Mercurial > pidgin
diff 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 |
line wrap: on
line diff
--- a/src/protocols/irc/irc.c Thu Feb 09 04:14:54 2006 +0000 +++ b/src/protocols/irc/irc.c Thu Feb 09 04:17:56 2006 +0000 @@ -83,23 +83,79 @@ gaim_notify_formatted(gc, title, title, NULL, irc->motd->str, NULL, NULL); } -int irc_send(struct irc_conn *irc, const char *buf) +static int do_send(struct irc_conn *irc, const char *buf, gsize len) { int ret; if (irc->gsc) { - ret = gaim_ssl_write(irc->gsc, buf, strlen(buf)); + ret = gaim_ssl_write(irc->gsc, buf, len); } else { - if (irc->fd < 0) - return -1; - ret = write(irc->fd, buf, strlen(buf)); + ret = write(irc->fd, buf, len); + } + + return ret; +} + +static void +irc_send_cb(gpointer data, gint source, GaimInputCondition cond) +{ + struct irc_conn *irc = data; + int ret, writelen; + + writelen = gaim_circ_buffer_get_max_read(irc->outbuf); + + if (writelen == 0) { + gaim_input_remove(irc->writeh); + irc->writeh = 0; + return; + } + + ret = do_send(irc, irc->outbuf->outptr, writelen); + + if (ret < 0 && errno == EAGAIN) + return; + else if (ret <= 0) { + gaim_connection_error(gaim_account_get_connection(irc->account), + _("Server has disconnected")); + return; + } + + gaim_circ_buffer_mark_read(irc->outbuf, ret); + +#if 0 + /* We *could* try to write more if we wrote it all */ + if (ret == write_len) { + irc_send_cb(data, source, cond); + } +#endif +} + +int irc_send(struct irc_conn *irc, const char *buf) +{ + int ret, buflen = strlen(buf); + + /* If we're not buffering writes, try to send immediately */ + if (!irc->writeh) + ret = do_send(irc, buf, buflen); + else { + ret = -1; + errno = EAGAIN; } /* gaim_debug(GAIM_DEBUG_MISC, "irc", "sent%s: %s", irc->gsc ? " (ssl)" : "", buf); */ - if (ret < 0) { + if (ret <= 0 && errno != EAGAIN) { gaim_connection_error(gaim_account_get_connection(irc->account), _("Server has disconnected")); + } else if (ret < buflen) { + if (ret < 0) + ret = 0; + if (!irc->writeh) + irc->writeh = gaim_input_add( + irc->gsc ? irc->gsc->fd : irc->fd, + GAIM_INPUT_WRITE, irc_send_cb, irc); + gaim_circ_buffer_append(irc->outbuf, buf + ret, + buflen - ret); } return ret; @@ -240,6 +296,7 @@ gc->proto_data = irc = g_new0(struct irc_conn, 1); irc->fd = -1; irc->account = account; + irc->outbuf = gaim_circ_buffer_new(512); userparts = g_strsplit(username, "@", 2); gaim_connection_set_display_name(gc, userparts[0]); @@ -262,6 +319,7 @@ irc_login_cb_ssl, irc_ssl_connect_failure, gc); } else { gaim_connection_error(gc, _("SSL support unavailable")); + return; } } @@ -288,7 +346,7 @@ if (pass && *pass) { buf = irc_format(irc, "vv", "PASS", pass); if (irc_send(irc, buf) < 0) { - gaim_connection_error(gc, "Error sending password"); +/* gaim_connection_error(gc, "Error sending password"); */ g_free(buf); return FALSE; } @@ -302,14 +360,14 @@ buf = irc_format(irc, "vvvv:", "USER", strlen(username) ? username : g_get_user_name(), hostname, irc->server, strlen(realname) ? realname : IRC_DEFAULT_ALIAS); if (irc_send(irc, buf) < 0) { - gaim_connection_error(gc, "Error registering with server"); +/* gaim_connection_error(gc, "Error registering with server");*/ g_free(buf); return FALSE; } g_free(buf); buf = irc_format(irc, "vn", "NICK", gaim_connection_get_display_name(gc)); if (irc_send(irc, buf) < 0) { - gaim_connection_error(gc, "Error sending nickname"); +/* gaim_connection_error(gc, "Error sending nickname");*/ g_free(buf); return FALSE; } @@ -404,6 +462,12 @@ if (irc->motd) g_string_free(irc->motd, TRUE); g_free(irc->server); + + if (irc->writeh) + gaim_input_remove(irc->writeh); + + gaim_circ_buffer_destroy(irc->outbuf); + g_free(irc); } @@ -443,7 +507,7 @@ const char *status_id = gaim_status_get_id(status); if (gc) - irc = gc->proto_data; + irc = gc->proto_data; if (!gaim_status_is_active(status)) return; @@ -527,8 +591,13 @@ irc->inbuflen += IRC_INITIAL_BUFSIZE; irc->inbuf = g_realloc(irc->inbuf, irc->inbuflen); } - - if ((len = gaim_ssl_read(gsc, irc->inbuf + irc->inbufused, IRC_INITIAL_BUFSIZE - 1)) < 0) { + + len = gaim_ssl_read(gsc, irc->inbuf + irc->inbufused, IRC_INITIAL_BUFSIZE - 1); + + if (len < 0 && errno == EAGAIN) { + /* Try again later */ + return; + } else if (len < 0) { gaim_connection_error(gc, _("Read error")); return; } else if (len == 0) { @@ -550,7 +619,10 @@ irc->inbuf = g_realloc(irc->inbuf, irc->inbuflen); } - if ((len = read(irc->fd, irc->inbuf + irc->inbufused, IRC_INITIAL_BUFSIZE - 1)) < 0) { + len = read(irc->fd, irc->inbuf + irc->inbufused, IRC_INITIAL_BUFSIZE - 1); + if (len < 0 && errno == EAGAIN) { + return; + } else if (len < 0) { gaim_connection_error(gc, _("Read error")); return; } else if (len == 0) {