| 153 purple_ircv3_connection_read_cb(GObject *source, GAsyncResult *result, |
151 purple_ircv3_connection_read_cb(GObject *source, GAsyncResult *result, |
| 154 gpointer data) |
152 gpointer data) |
| 155 { |
153 { |
| 156 PurpleIRCv3Connection *connection = data; |
154 PurpleIRCv3Connection *connection = data; |
| 157 PurpleIRCv3ConnectionPrivate *priv = NULL; |
155 PurpleIRCv3ConnectionPrivate *priv = NULL; |
| |
156 GCancellable *cancellable = NULL; |
| 158 GDataInputStream *istream = G_DATA_INPUT_STREAM(source); |
157 GDataInputStream *istream = G_DATA_INPUT_STREAM(source); |
| 159 GError *error = NULL; |
158 GError *error = NULL; |
| 160 gchar *line = NULL; |
159 gchar *line = NULL; |
| 161 gsize length; |
160 gsize length; |
| 162 gboolean parsed = FALSE; |
161 gboolean parsed = FALSE; |
| 193 g_clear_error(&error); |
192 g_clear_error(&error); |
| 194 |
193 |
| 195 g_free(line); |
194 g_free(line); |
| 196 |
195 |
| 197 /* Call read_line_async again to continue reading lines. */ |
196 /* Call read_line_async again to continue reading lines. */ |
| |
197 cancellable = purple_connection_get_cancellable(PURPLE_CONNECTION(connection)); |
| 198 g_data_input_stream_read_line_async(priv->input, |
198 g_data_input_stream_read_line_async(priv->input, |
| 199 G_PRIORITY_DEFAULT, |
199 G_PRIORITY_DEFAULT, |
| 200 priv->cancellable, |
200 cancellable, |
| 201 purple_ircv3_connection_read_cb, |
201 purple_ircv3_connection_read_cb, |
| 202 connection); |
202 connection); |
| 203 } |
203 } |
| 204 |
204 |
| 205 static void |
205 static void |
| 229 purple_ircv3_connection_connected_cb(GObject *source, GAsyncResult *result, |
229 purple_ircv3_connection_connected_cb(GObject *source, GAsyncResult *result, |
| 230 gpointer data) |
230 gpointer data) |
| 231 { |
231 { |
| 232 PurpleIRCv3Connection *connection = data; |
232 PurpleIRCv3Connection *connection = data; |
| 233 PurpleIRCv3ConnectionPrivate *priv = NULL; |
233 PurpleIRCv3ConnectionPrivate *priv = NULL; |
| |
234 GCancellable *cancellable = NULL; |
| 234 GError *error = NULL; |
235 GError *error = NULL; |
| 235 GInputStream *istream = NULL; |
236 GInputStream *istream = NULL; |
| 236 GOutputStream *ostream = NULL; |
237 GOutputStream *ostream = NULL; |
| 237 GSocketClient *client = G_SOCKET_CLIENT(source); |
238 GSocketClient *client = G_SOCKET_CLIENT(source); |
| 238 GSocketConnection *conn = NULL; |
239 GSocketConnection *conn = NULL; |
| 264 istream = g_io_stream_get_input_stream(G_IO_STREAM(conn)); |
265 istream = g_io_stream_get_input_stream(G_IO_STREAM(conn)); |
| 265 priv->input = g_data_input_stream_new(istream); |
266 priv->input = g_data_input_stream_new(istream); |
| 266 g_data_input_stream_set_newline_type(G_DATA_INPUT_STREAM(priv->input), |
267 g_data_input_stream_set_newline_type(G_DATA_INPUT_STREAM(priv->input), |
| 267 G_DATA_STREAM_NEWLINE_TYPE_CR_LF); |
268 G_DATA_STREAM_NEWLINE_TYPE_CR_LF); |
| 268 |
269 |
| |
270 cancellable = purple_connection_get_cancellable(PURPLE_CONNECTION(connection)); |
| |
271 |
| 269 /* Add our read callback. */ |
272 /* Add our read callback. */ |
| 270 g_data_input_stream_read_line_async(priv->input, |
273 g_data_input_stream_read_line_async(priv->input, |
| 271 G_PRIORITY_DEFAULT, |
274 G_PRIORITY_DEFAULT, |
| 272 priv->cancellable, |
275 cancellable, |
| 273 purple_ircv3_connection_read_cb, |
276 purple_ircv3_connection_read_cb, |
| 274 connection); |
277 connection); |
| 275 |
278 |
| 276 /* Send our registration commands. */ |
279 /* Send our registration commands. */ |
| 277 purple_ircv3_capabilities_start(priv->capabilities); |
280 purple_ircv3_capabilities_start(priv->capabilities); |
| 307 GError **error) |
310 GError **error) |
| 308 { |
311 { |
| 309 PurpleIRCv3Connection *connection = NULL; |
312 PurpleIRCv3Connection *connection = NULL; |
| 310 PurpleIRCv3ConnectionPrivate *priv = NULL; |
313 PurpleIRCv3ConnectionPrivate *priv = NULL; |
| 311 PurpleAccount *account = NULL; |
314 PurpleAccount *account = NULL; |
| |
315 GCancellable *cancellable = NULL; |
| 312 GSocketClient *client = NULL; |
316 GSocketClient *client = NULL; |
| 313 gint default_port = PURPLE_IRCV3_DEFAULT_TLS_PORT; |
317 gint default_port = PURPLE_IRCV3_DEFAULT_TLS_PORT; |
| 314 gint port = 0; |
318 gint port = 0; |
| 315 gboolean use_tls = TRUE; |
319 gboolean use_tls = TRUE; |
| 316 |
320 |
| 337 if(!use_tls) { |
341 if(!use_tls) { |
| 338 default_port = PURPLE_IRCV3_DEFAULT_PLAIN_PORT; |
342 default_port = PURPLE_IRCV3_DEFAULT_PLAIN_PORT; |
| 339 } |
343 } |
| 340 port = purple_account_get_int(account, "port", default_port); |
344 port = purple_account_get_int(account, "port", default_port); |
| 341 |
345 |
| |
346 cancellable = purple_connection_get_cancellable(purple_connection); |
| |
347 |
| 342 /* Finally start the async connection. */ |
348 /* Finally start the async connection. */ |
| 343 g_socket_client_connect_to_host_async(client, priv->server_name, |
349 g_socket_client_connect_to_host_async(client, priv->server_name, |
| 344 port, priv->cancellable, |
350 port, cancellable, |
| 345 purple_ircv3_connection_connected_cb, |
351 purple_ircv3_connection_connected_cb, |
| 346 connection); |
352 connection); |
| 347 |
353 |
| 348 g_clear_object(&client); |
354 g_clear_object(&client); |
| 349 |
355 |
| 350 return TRUE; |
356 return TRUE; |
| 351 } |
357 } |
| 352 |
358 |
| 353 static gboolean |
359 static gboolean |
| 354 purple_ircv3_connection_disconnect(PurpleConnection *purple_connection, |
360 purple_ircv3_connection_disconnect(PurpleConnection *purple_connection, |
| 355 G_GNUC_UNUSED GError **error) |
361 GError **error) |
| 356 { |
362 { |
| 357 PurpleIRCv3Connection *connection = NULL; |
363 PurpleIRCv3Connection *connection = NULL; |
| 358 PurpleIRCv3ConnectionPrivate *priv = NULL; |
364 PurpleIRCv3ConnectionPrivate *priv = NULL; |
| |
365 PurpleConnectionClass *parent_class = NULL; |
| 359 |
366 |
| 360 g_return_val_if_fail(PURPLE_IRCV3_IS_CONNECTION(purple_connection), FALSE); |
367 g_return_val_if_fail(PURPLE_IRCV3_IS_CONNECTION(purple_connection), FALSE); |
| 361 |
368 |
| |
369 /* Chain up to our parent's disconnect to do initial clean up. */ |
| |
370 parent_class = PURPLE_CONNECTION_CLASS(purple_ircv3_connection_parent_class); |
| |
371 parent_class->disconnect(purple_connection, error); |
| |
372 |
| 362 connection = PURPLE_IRCV3_CONNECTION(purple_connection); |
373 connection = PURPLE_IRCV3_CONNECTION(purple_connection); |
| 363 priv = purple_ircv3_connection_get_instance_private(connection); |
374 priv = purple_ircv3_connection_get_instance_private(connection); |
| 364 |
375 |
| 365 /* TODO: send QUIT command. */ |
376 /* TODO: send QUIT command. */ |
| 366 |
|
| 367 /* Cancel the cancellable to tell everyone we're shutting down. */ |
|
| 368 if(G_IS_CANCELLABLE(priv->cancellable)) { |
|
| 369 g_cancellable_cancel(priv->cancellable); |
|
| 370 |
|
| 371 g_clear_object(&priv->cancellable); |
|
| 372 } |
|
| 373 |
377 |
| 374 if(G_IS_SOCKET_CONNECTION(priv->connection)) { |
378 if(G_IS_SOCKET_CONNECTION(priv->connection)) { |
| 375 GInputStream *istream = G_INPUT_STREAM(priv->input); |
379 GInputStream *istream = G_INPUT_STREAM(priv->input); |
| 376 GOutputStream *ostream = G_OUTPUT_STREAM(priv->output); |
380 GOutputStream *ostream = G_OUTPUT_STREAM(priv->output); |
| 377 |
381 |
| 404 GValue *value, GParamSpec *pspec) |
408 GValue *value, GParamSpec *pspec) |
| 405 { |
409 { |
| 406 PurpleIRCv3Connection *connection = PURPLE_IRCV3_CONNECTION(obj); |
410 PurpleIRCv3Connection *connection = PURPLE_IRCV3_CONNECTION(obj); |
| 407 |
411 |
| 408 switch(param_id) { |
412 switch(param_id) { |
| 409 case PROP_CANCELLABLE: |
|
| 410 g_value_set_object(value, |
|
| 411 purple_ircv3_connection_get_cancellable(connection)); |
|
| 412 break; |
|
| 413 case PROP_CAPABILITIES: |
413 case PROP_CAPABILITIES: |
| 414 g_value_set_object(value, |
414 g_value_set_object(value, |
| 415 purple_ircv3_connection_get_capabilities(connection)); |
415 purple_ircv3_connection_get_capabilities(connection)); |
| 416 break; |
416 break; |
| 417 case PROP_REGISTERED: |
417 case PROP_REGISTERED: |
| 429 PurpleIRCv3Connection *connection = PURPLE_IRCV3_CONNECTION(obj); |
429 PurpleIRCv3Connection *connection = PURPLE_IRCV3_CONNECTION(obj); |
| 430 PurpleIRCv3ConnectionPrivate *priv = NULL; |
430 PurpleIRCv3ConnectionPrivate *priv = NULL; |
| 431 |
431 |
| 432 priv = purple_ircv3_connection_get_instance_private(connection); |
432 priv = purple_ircv3_connection_get_instance_private(connection); |
| 433 |
433 |
| 434 g_clear_object(&priv->cancellable); |
|
| 435 |
|
| 436 g_clear_object(&priv->input); |
434 g_clear_object(&priv->input); |
| 437 g_clear_object(&priv->output); |
435 g_clear_object(&priv->output); |
| 438 g_clear_object(&priv->connection); |
436 g_clear_object(&priv->connection); |
| 439 |
437 |
| 440 g_clear_object(&priv->capabilities); |
438 g_clear_object(&priv->capabilities); |
| 510 } |
508 } |
| 511 |
509 |
| 512 g_clear_pointer(&title, g_free); |
510 g_clear_pointer(&title, g_free); |
| 513 |
511 |
| 514 /* Finally create our objects. */ |
512 /* Finally create our objects. */ |
| 515 priv->cancellable = g_cancellable_new(); |
|
| 516 |
|
| 517 priv->capabilities = purple_ircv3_capabilities_new(connection); |
513 priv->capabilities = purple_ircv3_capabilities_new(connection); |
| 518 g_signal_connect_object(priv->capabilities, "done", |
514 g_signal_connect_object(priv->capabilities, "done", |
| 519 G_CALLBACK(purple_ircv3_connection_caps_done_cb), |
515 G_CALLBACK(purple_ircv3_connection_caps_done_cb), |
| 520 connection, 0); |
516 connection, 0); |
| 521 } |
517 } |
| 538 obj_class->dispose = purple_ircv3_connection_dispose; |
534 obj_class->dispose = purple_ircv3_connection_dispose; |
| 539 obj_class->finalize = purple_ircv3_connection_finalize; |
535 obj_class->finalize = purple_ircv3_connection_finalize; |
| 540 |
536 |
| 541 connection_class->connect = purple_ircv3_connection_connect; |
537 connection_class->connect = purple_ircv3_connection_connect; |
| 542 connection_class->disconnect = purple_ircv3_connection_disconnect; |
538 connection_class->disconnect = purple_ircv3_connection_disconnect; |
| 543 |
|
| 544 /** |
|
| 545 * PurpleIRCv3Connection:cancellable: |
|
| 546 * |
|
| 547 * The [class@Gio.Cancellable] for this connection. |
|
| 548 * |
|
| 549 * Since: 3.0.0 |
|
| 550 */ |
|
| 551 properties[PROP_CANCELLABLE] = g_param_spec_object( |
|
| 552 "cancellable", "cancellable", |
|
| 553 "The cancellable for this connection", |
|
| 554 G_TYPE_CANCELLABLE, |
|
| 555 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); |
|
| 556 |
539 |
| 557 /** |
540 /** |
| 558 * PurpleIRCv3Connection:capabilities: |
541 * PurpleIRCv3Connection:capabilities: |
| 559 * |
542 * |
| 560 * The capabilities that the server supports. |
543 * The capabilities that the server supports. |
| 674 */ |
657 */ |
| 675 hack = g_type_class_ref(purple_ircv3_connection_get_type()); |
658 hack = g_type_class_ref(purple_ircv3_connection_get_type()); |
| 676 g_type_class_unref(hack); |
659 g_type_class_unref(hack); |
| 677 } |
660 } |
| 678 |
661 |
| 679 GCancellable * |
|
| 680 purple_ircv3_connection_get_cancellable(PurpleIRCv3Connection *connection) { |
|
| 681 PurpleIRCv3ConnectionPrivate *priv = NULL; |
|
| 682 |
|
| 683 g_return_val_if_fail(PURPLE_IRCV3_IS_CONNECTION(connection), NULL); |
|
| 684 |
|
| 685 priv = purple_ircv3_connection_get_instance_private(connection); |
|
| 686 |
|
| 687 return priv->cancellable; |
|
| 688 } |
|
| 689 |
|
| 690 void |
662 void |
| 691 purple_ircv3_connection_emit_ctcp_request(PurpleIRCv3Connection *connection, |
663 purple_ircv3_connection_emit_ctcp_request(PurpleIRCv3Connection *connection, |
| 692 const char *command, |
664 const char *command, |
| 693 const char *parameters) |
665 const char *parameters) |
| 694 { |
666 { |
| 718 purple_ircv3_connection_writef(PurpleIRCv3Connection *connection, |
690 purple_ircv3_connection_writef(PurpleIRCv3Connection *connection, |
| 719 const char *format, ...) |
691 const char *format, ...) |
| 720 { |
692 { |
| 721 PurpleIRCv3ConnectionPrivate *priv = NULL; |
693 PurpleIRCv3ConnectionPrivate *priv = NULL; |
| 722 GBytes *bytes = NULL; |
694 GBytes *bytes = NULL; |
| |
695 GCancellable *cancellable = NULL; |
| 723 GString *msg = NULL; |
696 GString *msg = NULL; |
| 724 va_list vargs; |
697 va_list vargs; |
| 725 |
698 |
| 726 g_return_if_fail(PURPLE_IRCV3_IS_CONNECTION(connection)); |
699 g_return_if_fail(PURPLE_IRCV3_IS_CONNECTION(connection)); |
| 727 g_return_if_fail(format != NULL); |
700 g_return_if_fail(format != NULL); |
| 738 /* Next add the trailing carriage return line feed. */ |
711 /* Next add the trailing carriage return line feed. */ |
| 739 g_string_append(msg, "\r\n"); |
712 g_string_append(msg, "\r\n"); |
| 740 |
713 |
| 741 /* Finally turn the string into bytes and send it! */ |
714 /* Finally turn the string into bytes and send it! */ |
| 742 bytes = g_string_free_to_bytes(msg); |
715 bytes = g_string_free_to_bytes(msg); |
| |
716 |
| |
717 cancellable = purple_connection_get_cancellable(PURPLE_CONNECTION(connection)); |
| 743 purple_queued_output_stream_push_bytes_async(priv->output, bytes, |
718 purple_queued_output_stream_push_bytes_async(priv->output, bytes, |
| 744 G_PRIORITY_DEFAULT, |
719 G_PRIORITY_DEFAULT, |
| 745 priv->cancellable, |
720 cancellable, |
| 746 purple_ircv3_connection_write_cb, |
721 purple_ircv3_connection_write_cb, |
| 747 connection); |
722 connection); |
| 748 |
723 |
| 749 g_bytes_unref(bytes); |
724 g_bytes_unref(bytes); |
| 750 } |
725 } |