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;