Mercurial > pidgin
comparison src/protocols/irc/irc.c @ 13200:33bef17125c2
[gaim-migrate @ 15563]
This is the soon-to-be-infamous nonblocking network activity patch that I've been working on. Feel free to yell at me if this makes you unhappy.
committer: Tailor Script <tailor@pidgin.im>
author | Daniel Atallah <daniel.atallah@gmail.com> |
---|---|
date | Thu, 09 Feb 2006 04:17:56 +0000 |
parents | 91424393b70b |
children | 263c2db78f77 |
comparison
equal
deleted
inserted
replaced
13199:d8f238864c88 | 13200:33bef17125c2 |
---|---|
81 } | 81 } |
82 title = g_strdup_printf(_("MOTD for %s"), irc->server); | 82 title = g_strdup_printf(_("MOTD for %s"), irc->server); |
83 gaim_notify_formatted(gc, title, title, NULL, irc->motd->str, NULL, NULL); | 83 gaim_notify_formatted(gc, title, title, NULL, irc->motd->str, NULL, NULL); |
84 } | 84 } |
85 | 85 |
86 static int do_send(struct irc_conn *irc, const char *buf, gsize len) | |
87 { | |
88 int ret; | |
89 | |
90 if (irc->gsc) { | |
91 ret = gaim_ssl_write(irc->gsc, buf, len); | |
92 } else { | |
93 ret = write(irc->fd, buf, len); | |
94 } | |
95 | |
96 return ret; | |
97 } | |
98 | |
99 static void | |
100 irc_send_cb(gpointer data, gint source, GaimInputCondition cond) | |
101 { | |
102 struct irc_conn *irc = data; | |
103 int ret, writelen; | |
104 | |
105 writelen = gaim_circ_buffer_get_max_read(irc->outbuf); | |
106 | |
107 if (writelen == 0) { | |
108 gaim_input_remove(irc->writeh); | |
109 irc->writeh = 0; | |
110 return; | |
111 } | |
112 | |
113 ret = do_send(irc, irc->outbuf->outptr, writelen); | |
114 | |
115 if (ret < 0 && errno == EAGAIN) | |
116 return; | |
117 else if (ret <= 0) { | |
118 gaim_connection_error(gaim_account_get_connection(irc->account), | |
119 _("Server has disconnected")); | |
120 return; | |
121 } | |
122 | |
123 gaim_circ_buffer_mark_read(irc->outbuf, ret); | |
124 | |
125 #if 0 | |
126 /* We *could* try to write more if we wrote it all */ | |
127 if (ret == write_len) { | |
128 irc_send_cb(data, source, cond); | |
129 } | |
130 #endif | |
131 } | |
132 | |
86 int irc_send(struct irc_conn *irc, const char *buf) | 133 int irc_send(struct irc_conn *irc, const char *buf) |
87 { | 134 { |
88 int ret; | 135 int ret, buflen = strlen(buf); |
89 | 136 |
90 if (irc->gsc) { | 137 /* If we're not buffering writes, try to send immediately */ |
91 ret = gaim_ssl_write(irc->gsc, buf, strlen(buf)); | 138 if (!irc->writeh) |
92 } else { | 139 ret = do_send(irc, buf, buflen); |
93 if (irc->fd < 0) | 140 else { |
94 return -1; | 141 ret = -1; |
95 ret = write(irc->fd, buf, strlen(buf)); | 142 errno = EAGAIN; |
96 } | 143 } |
97 | 144 |
98 /* gaim_debug(GAIM_DEBUG_MISC, "irc", "sent%s: %s", | 145 /* gaim_debug(GAIM_DEBUG_MISC, "irc", "sent%s: %s", |
99 irc->gsc ? " (ssl)" : "", buf); */ | 146 irc->gsc ? " (ssl)" : "", buf); */ |
100 if (ret < 0) { | 147 if (ret <= 0 && errno != EAGAIN) { |
101 gaim_connection_error(gaim_account_get_connection(irc->account), | 148 gaim_connection_error(gaim_account_get_connection(irc->account), |
102 _("Server has disconnected")); | 149 _("Server has disconnected")); |
150 } else if (ret < buflen) { | |
151 if (ret < 0) | |
152 ret = 0; | |
153 if (!irc->writeh) | |
154 irc->writeh = gaim_input_add( | |
155 irc->gsc ? irc->gsc->fd : irc->fd, | |
156 GAIM_INPUT_WRITE, irc_send_cb, irc); | |
157 gaim_circ_buffer_append(irc->outbuf, buf + ret, | |
158 buflen - ret); | |
103 } | 159 } |
104 | 160 |
105 return ret; | 161 return ret; |
106 } | 162 } |
107 | 163 |
238 } | 294 } |
239 | 295 |
240 gc->proto_data = irc = g_new0(struct irc_conn, 1); | 296 gc->proto_data = irc = g_new0(struct irc_conn, 1); |
241 irc->fd = -1; | 297 irc->fd = -1; |
242 irc->account = account; | 298 irc->account = account; |
299 irc->outbuf = gaim_circ_buffer_new(512); | |
243 | 300 |
244 userparts = g_strsplit(username, "@", 2); | 301 userparts = g_strsplit(username, "@", 2); |
245 gaim_connection_set_display_name(gc, userparts[0]); | 302 gaim_connection_set_display_name(gc, userparts[0]); |
246 irc->server = g_strdup(userparts[1]); | 303 irc->server = g_strdup(userparts[1]); |
247 g_strfreev(userparts); | 304 g_strfreev(userparts); |
260 irc->gsc = gaim_ssl_connect(account, irc->server, | 317 irc->gsc = gaim_ssl_connect(account, irc->server, |
261 gaim_account_get_int(account, "port", IRC_DEFAULT_SSL_PORT), | 318 gaim_account_get_int(account, "port", IRC_DEFAULT_SSL_PORT), |
262 irc_login_cb_ssl, irc_ssl_connect_failure, gc); | 319 irc_login_cb_ssl, irc_ssl_connect_failure, gc); |
263 } else { | 320 } else { |
264 gaim_connection_error(gc, _("SSL support unavailable")); | 321 gaim_connection_error(gc, _("SSL support unavailable")); |
322 return; | |
265 } | 323 } |
266 } | 324 } |
267 | 325 |
268 if (!irc->gsc) { | 326 if (!irc->gsc) { |
269 | 327 |
286 const char *pass = gaim_connection_get_password(gc); | 344 const char *pass = gaim_connection_get_password(gc); |
287 | 345 |
288 if (pass && *pass) { | 346 if (pass && *pass) { |
289 buf = irc_format(irc, "vv", "PASS", pass); | 347 buf = irc_format(irc, "vv", "PASS", pass); |
290 if (irc_send(irc, buf) < 0) { | 348 if (irc_send(irc, buf) < 0) { |
291 gaim_connection_error(gc, "Error sending password"); | 349 /* gaim_connection_error(gc, "Error sending password"); */ |
292 g_free(buf); | 350 g_free(buf); |
293 return FALSE; | 351 return FALSE; |
294 } | 352 } |
295 g_free(buf); | 353 g_free(buf); |
296 } | 354 } |
300 username = gaim_account_get_string(irc->account, "username", ""); | 358 username = gaim_account_get_string(irc->account, "username", ""); |
301 realname = gaim_account_get_string(irc->account, "realname", ""); | 359 realname = gaim_account_get_string(irc->account, "realname", ""); |
302 buf = irc_format(irc, "vvvv:", "USER", strlen(username) ? username : g_get_user_name(), hostname, irc->server, | 360 buf = irc_format(irc, "vvvv:", "USER", strlen(username) ? username : g_get_user_name(), hostname, irc->server, |
303 strlen(realname) ? realname : IRC_DEFAULT_ALIAS); | 361 strlen(realname) ? realname : IRC_DEFAULT_ALIAS); |
304 if (irc_send(irc, buf) < 0) { | 362 if (irc_send(irc, buf) < 0) { |
305 gaim_connection_error(gc, "Error registering with server"); | 363 /* gaim_connection_error(gc, "Error registering with server");*/ |
306 g_free(buf); | 364 g_free(buf); |
307 return FALSE; | 365 return FALSE; |
308 } | 366 } |
309 g_free(buf); | 367 g_free(buf); |
310 buf = irc_format(irc, "vn", "NICK", gaim_connection_get_display_name(gc)); | 368 buf = irc_format(irc, "vn", "NICK", gaim_connection_get_display_name(gc)); |
311 if (irc_send(irc, buf) < 0) { | 369 if (irc_send(irc, buf) < 0) { |
312 gaim_connection_error(gc, "Error sending nickname"); | 370 /* gaim_connection_error(gc, "Error sending nickname");*/ |
313 g_free(buf); | 371 g_free(buf); |
314 return FALSE; | 372 return FALSE; |
315 } | 373 } |
316 g_free(buf); | 374 g_free(buf); |
317 | 375 |
402 g_hash_table_destroy(irc->msgs); | 460 g_hash_table_destroy(irc->msgs); |
403 g_hash_table_destroy(irc->buddies); | 461 g_hash_table_destroy(irc->buddies); |
404 if (irc->motd) | 462 if (irc->motd) |
405 g_string_free(irc->motd, TRUE); | 463 g_string_free(irc->motd, TRUE); |
406 g_free(irc->server); | 464 g_free(irc->server); |
465 | |
466 if (irc->writeh) | |
467 gaim_input_remove(irc->writeh); | |
468 | |
469 gaim_circ_buffer_destroy(irc->outbuf); | |
470 | |
407 g_free(irc); | 471 g_free(irc); |
408 } | 472 } |
409 | 473 |
410 static int irc_im_send(GaimConnection *gc, const char *who, const char *what, GaimMessageFlags flags) | 474 static int irc_im_send(GaimConnection *gc, const char *who, const char *what, GaimMessageFlags flags) |
411 { | 475 { |
441 struct irc_conn *irc = NULL; | 505 struct irc_conn *irc = NULL; |
442 const char *args[1]; | 506 const char *args[1]; |
443 const char *status_id = gaim_status_get_id(status); | 507 const char *status_id = gaim_status_get_id(status); |
444 | 508 |
445 if (gc) | 509 if (gc) |
446 irc = gc->proto_data; | 510 irc = gc->proto_data; |
447 | 511 |
448 if (!gaim_status_is_active(status)) | 512 if (!gaim_status_is_active(status)) |
449 return; | 513 return; |
450 | 514 |
451 args[0] = NULL; | 515 args[0] = NULL; |
525 | 589 |
526 if (irc->inbuflen < irc->inbufused + IRC_INITIAL_BUFSIZE) { | 590 if (irc->inbuflen < irc->inbufused + IRC_INITIAL_BUFSIZE) { |
527 irc->inbuflen += IRC_INITIAL_BUFSIZE; | 591 irc->inbuflen += IRC_INITIAL_BUFSIZE; |
528 irc->inbuf = g_realloc(irc->inbuf, irc->inbuflen); | 592 irc->inbuf = g_realloc(irc->inbuf, irc->inbuflen); |
529 } | 593 } |
530 | 594 |
531 if ((len = gaim_ssl_read(gsc, irc->inbuf + irc->inbufused, IRC_INITIAL_BUFSIZE - 1)) < 0) { | 595 len = gaim_ssl_read(gsc, irc->inbuf + irc->inbufused, IRC_INITIAL_BUFSIZE - 1); |
596 | |
597 if (len < 0 && errno == EAGAIN) { | |
598 /* Try again later */ | |
599 return; | |
600 } else if (len < 0) { | |
532 gaim_connection_error(gc, _("Read error")); | 601 gaim_connection_error(gc, _("Read error")); |
533 return; | 602 return; |
534 } else if (len == 0) { | 603 } else if (len == 0) { |
535 gaim_connection_error(gc, _("Server has disconnected")); | 604 gaim_connection_error(gc, _("Server has disconnected")); |
536 return; | 605 return; |
548 if (irc->inbuflen < irc->inbufused + IRC_INITIAL_BUFSIZE) { | 617 if (irc->inbuflen < irc->inbufused + IRC_INITIAL_BUFSIZE) { |
549 irc->inbuflen += IRC_INITIAL_BUFSIZE; | 618 irc->inbuflen += IRC_INITIAL_BUFSIZE; |
550 irc->inbuf = g_realloc(irc->inbuf, irc->inbuflen); | 619 irc->inbuf = g_realloc(irc->inbuf, irc->inbuflen); |
551 } | 620 } |
552 | 621 |
553 if ((len = read(irc->fd, irc->inbuf + irc->inbufused, IRC_INITIAL_BUFSIZE - 1)) < 0) { | 622 len = read(irc->fd, irc->inbuf + irc->inbufused, IRC_INITIAL_BUFSIZE - 1); |
623 if (len < 0 && errno == EAGAIN) { | |
624 return; | |
625 } else if (len < 0) { | |
554 gaim_connection_error(gc, _("Read error")); | 626 gaim_connection_error(gc, _("Read error")); |
555 return; | 627 return; |
556 } else if (len == 0) { | 628 } else if (len == 0) { |
557 gaim_connection_error(gc, _("Server has disconnected")); | 629 gaim_connection_error(gc, _("Server has disconnected")); |
558 return; | 630 return; |