Mercurial > pidgin.yaz
diff src/protocols/yahoo/yahoo_packet.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 | f4e58e94ced3 |
children | 4f8c85836b41 |
line wrap: on
line diff
--- a/src/protocols/yahoo/yahoo_packet.c Thu Feb 09 04:14:54 2006 +0000 +++ b/src/protocols/yahoo/yahoo_packet.c Thu Feb 09 04:17:56 2006 +0000 @@ -242,39 +242,97 @@ #endif } -int yahoo_packet_send(struct yahoo_packet *pkt, struct yahoo_data *yd) +static void +yahoo_packet_send_can_write(gpointer data, gint source, GaimInputCondition cond) +{ + struct yahoo_data *yd = data; + int ret, writelen; + + writelen = gaim_circ_buffer_get_max_read(yd->txbuf); + + if (writelen == 0) { + gaim_input_remove(yd->txhandler); + yd->txhandler = -1; + return; + } + + ret = write(yd->fd, yd->txbuf->outptr, writelen); + + if (ret < 0 && errno == EAGAIN) + return; + else if (ret < 0) { + /* TODO: what to do here - do we really have to disconnect? */ + gaim_connection_error(yd->gc, _("Write Error")); + return; + } + + gaim_circ_buffer_mark_read(yd->txbuf, ret); +} + + +gsize yahoo_packet_build(struct yahoo_packet *pkt, int pad, gboolean wm, + guchar **buf) { int pktlen = yahoo_packet_length(pkt); int len = YAHOO_PACKET_HDRLEN + pktlen; - int ret; - guchar *data; int pos = 0; - if (yd->fd < 0) - return -1; - data = g_malloc0(len + 1); memcpy(data + pos, "YMSG", 4); pos += 4; - if (yd->wm) + if (wm) pos += yahoo_put16(data + pos, YAHOO_WEBMESSENGER_PROTO_VER); else pos += yahoo_put16(data + pos, YAHOO_PROTO_VER); - pos += yahoo_put16(data + pos, 0x0000); - pos += yahoo_put16(data + pos, pktlen); + pos += yahoo_put16(data + pos, pktlen + pad); pos += yahoo_put16(data + pos, pkt->service); pos += yahoo_put32(data + pos, pkt->status); pos += yahoo_put32(data + pos, pkt->id); yahoo_packet_write(pkt, data + pos); + *buf = data; + + return len; +} + +int yahoo_packet_send(struct yahoo_packet *pkt, struct yahoo_data *yd) +{ + gsize len; + int ret; + guchar *data; + + if (yd->fd < 0) + return -1; + + len = yahoo_packet_build(pkt, 0, yd->wm, &data); + yahoo_packet_dump(data, len); - ret = write(yd->fd, data, len); - if (ret != len) + if (yd->txhandler == -1) + ret = write(yd->fd, data, len); + else { + ret = -1; + errno = EAGAIN; + } + + if (ret < 0 && errno == EAGAIN) + ret = 0; + else if (ret <= 0) { gaim_debug_warning("yahoo", "Only wrote %d of %d bytes!", ret, len); + g_free(data); + return ret; + } + + if (ret < len) { + if (yd->txhandler == -1) + yd->txhandler = gaim_input_add(yd->fd, GAIM_INPUT_WRITE, + yahoo_packet_send_can_write, yd); + gaim_circ_buffer_append(yd->txbuf, data + ret, len - ret); + } + g_free(data); return ret; @@ -289,37 +347,6 @@ return ret; } -int yahoo_packet_send_special(struct yahoo_packet *pkt, int fd, int pad) -{ - int pktlen = yahoo_packet_length(pkt); - int len = YAHOO_PACKET_HDRLEN + pktlen; - int ret; - - guchar *data; - int pos = 0; - - if (fd < 0) - return -1; - - data = g_malloc0(len + 1); - - memcpy(data + pos, "YMSG", 4); pos += 4; - - pos += yahoo_put16(data + pos, YAHOO_PROTO_VER); - pos += yahoo_put16(data + pos, 0x0000); - pos += yahoo_put16(data + pos, pktlen + pad); - pos += yahoo_put16(data + pos, pkt->service); - pos += yahoo_put32(data + pos, pkt->status); - pos += yahoo_put32(data + pos, pkt->id); - - yahoo_packet_write(pkt, data + pos); - - ret = write(fd, data, len); - g_free(data); - - return ret; -} - void yahoo_packet_free(struct yahoo_packet *pkt) { while (pkt->hash) {