libpurple/protocols/ircv3/purpleircv3connection.c

changeset 42542
1407a0aac0bf
parent 42530
55b30ce86f17
child 42543
6dcf672547fe
equal deleted inserted replaced
42541:c5bcc44520c3 42542:1407a0aac0bf
25 #include "purpleircv3formatting.h" 25 #include "purpleircv3formatting.h"
26 #include "purpleircv3parser.h" 26 #include "purpleircv3parser.h"
27 27
28 enum { 28 enum {
29 PROP_0, 29 PROP_0,
30 PROP_CANCELLABLE,
31 PROP_CAPABILITIES, 30 PROP_CAPABILITIES,
32 PROP_REGISTERED, 31 PROP_REGISTERED,
33 N_PROPERTIES, 32 N_PROPERTIES,
34 }; 33 };
35 static GParamSpec *properties[N_PROPERTIES] = {NULL, }; 34 static GParamSpec *properties[N_PROPERTIES] = {NULL, };
42 }; 41 };
43 static guint signals[N_SIGNALS] = {0, }; 42 static guint signals[N_SIGNALS] = {0, };
44 43
45 typedef struct { 44 typedef struct {
46 GSocketConnection *connection; 45 GSocketConnection *connection;
47 GCancellable *cancellable;
48 46
49 gchar *server_name; 47 gchar *server_name;
50 gboolean registered; 48 gboolean registered;
51 49
52 GDataInputStream *input; 50 GDataInputStream *input;
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 }

mercurial