static void servconn_write_cb(gpointer data, gint source, PurpleInputCondition cond) { MsnServConn *servconn = data; gssize ret; int writelen; writelen = purple_circ_buffer_get_max_read(servconn->tx_buf); if (writelen == 0) { purple_input_remove(servconn->tx_handler); servconn->tx_handler = 0; return; } ret = write(servconn->fd, servconn->tx_buf->outptr, writelen); if (ret < 0 && errno == EAGAIN) return; else if (ret <= 0) { msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_WRITE, NULL); return; } purple_circ_buffer_mark_read(servconn->tx_buf, ret); servconn_timeout_renew(servconn); }
static void http_connection_send_cb(gpointer data, gint source, PurpleInputCondition cond) { PurpleHTTPConnection *conn = data; int ret; int writelen = purple_circ_buffer_get_max_read(conn->write_buf); if (writelen == 0) { purple_input_remove(conn->writeh); conn->writeh = 0; return; } ret = http_connection_do_send(conn, conn->write_buf->outptr, writelen); if (ret < 0 && errno == EAGAIN) return; else if (ret <= 0) { /* * TODO: Handle this better. Probably requires a PurpleBOSHConnection * buffer that stores what is "being sent" until the * PurpleHTTPConnection reports it is fully sent. */ gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); purple_connection_error_reason(conn->bosh->js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return; } purple_circ_buffer_mark_read(conn->write_buf, ret); }
void UploadPortrait_cb(gpointer data, gint source, const gchar * error_message) { struct fetion_account_data *sip = data; gsize max_write; gssize written; max_write = purple_circ_buffer_get_max_read(sip->icon_buf); if (max_write == 0) { purple_input_remove(sip->icon_handler); sip->icon_handler = 0; return; } written = write(source, sip->icon_buf->outptr, max_write); purple_debug_info("fetion:", "UploadPortrait[%d][%d]", max_write, written); if (written < 0 && errno == EAGAIN) written = 0; else if (written <= 0) { /*TODO: do we really want to disconnect on a failure to write? */ purple_connection_error_reason(sip->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Could not write")); return; } purple_circ_buffer_mark_read(sip->icon_buf, written); }
static void irc_send_cb(gpointer data, gint source, PurpleInputCondition cond) { struct irc_conn *irc = data; int ret, writelen; writelen = purple_circ_buffer_get_max_read(irc->outbuf); if (writelen == 0) { purple_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) { purple_connection_error(purple_account_get_connection(irc->account), _("Server has disconnected")); return; } purple_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 }
static void httpconn_write_cb(gpointer data, gint source, PurpleInputCondition cond) { MsnHttpConn *httpconn; gssize ret; int writelen; httpconn = data; writelen = purple_circ_buffer_get_max_read(httpconn->tx_buf); if (writelen == 0) { purple_input_remove(httpconn->tx_handler); httpconn->tx_handler = 0; return; } ret = write(httpconn->fd, httpconn->tx_buf->outptr, writelen); if (ret <= 0) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) /* No worries */ return; /* Error! */ msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_WRITE); return; } purple_circ_buffer_mark_read(httpconn->tx_buf, ret); /* TODO: I don't think these 2 lines are needed. Remove them? */ if (ret == writelen) httpconn_write_cb(data, source, cond); }
static void fetion_canwrite_cb(gpointer data, gint source, PurpleInputCondition cond) { PurpleConnection *gc = data; struct fetion_account_data *sip = gc->proto_data; gsize max_write; gssize written; max_write = purple_circ_buffer_get_max_read(sip->txbuf); if (max_write == 0) { purple_input_remove(sip->tx_handler); sip->tx_handler = 0; return; } written = write(sip->fd, sip->txbuf->outptr, max_write); if (written < 0 && errno == EAGAIN) written = 0; else if (written <= 0) { /*TODO: do we really want to disconnect on a failure to write? */ purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Could not write")); return; } purple_circ_buffer_mark_read(sip->txbuf, written); }
static void yahoo_packet_send_can_write(gpointer data, gint source, PurpleInputCondition cond) { YahooData *yd = data; int ret, writelen; writelen = purple_circ_buffer_get_max_read(yd->txbuf); if (writelen == 0) { purple_input_remove(yd->txhandler); yd->txhandler = 0; 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? */ purple_connection_error_reason(yd->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Write Error")); return; } purple_circ_buffer_mark_read(yd->txbuf, ret); }
static void send_cb(gpointer data, gint source, PurpleInputCondition cond) { PeerConnection *conn; gsize writelen; ssize_t wrotelen; conn = data; writelen = purple_circ_buffer_get_max_read(conn->buffer_outgoing); if (writelen == 0) { purple_input_remove(conn->watcher_outgoing); conn->watcher_outgoing = 0; return; } wrotelen = send(conn->fd, conn->buffer_outgoing->outptr, writelen, 0); if (wrotelen <= 0) { if (wrotelen < 0 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) /* No worries */ return; if (conn->ready) { purple_input_remove(conn->watcher_outgoing); conn->watcher_outgoing = 0; close(conn->fd); conn->fd = -1; peer_connection_schedule_destroy(conn, OSCAR_DISCONNECT_LOST_CONNECTION, NULL); } else { /* * This could happen when unable to send a negotiation * frame to a peer proxy server. */ peer_connection_trynext(conn); } return; } purple_circ_buffer_mark_read(conn->buffer_outgoing, wrotelen); conn->lastactivity = time(NULL); }
/** * @param source When this function is called as a callback source is * set to the fd that triggered the callback. But this function * is also called directly from flap_connection_send_byte_stream(), * in which case source will be -1. So don't use source--use * conn->gsc or conn->fd instead. */ static void send_cb(gpointer data, gint source, PurpleInputCondition cond) { FlapConnection *conn; int writelen, ret; conn = data; writelen = purple_circ_buffer_get_max_read(conn->buffer_outgoing); if (writelen == 0) { purple_input_remove(conn->watcher_outgoing); conn->watcher_outgoing = 0; return; } if (conn->gsc) ret = purple_ssl_write(conn->gsc, conn->buffer_outgoing->outptr, writelen); else ret = send(conn->fd, conn->buffer_outgoing->outptr, writelen, 0); if (ret <= 0) { if (ret < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) /* No worries */ return; /* Error! */ purple_input_remove(conn->watcher_outgoing); conn->watcher_outgoing = 0; if (conn->gsc) { purple_ssl_close(conn->gsc); conn->gsc = NULL; } else { close(conn->fd); conn->fd = -1; } flap_connection_schedule_destroy(conn, OSCAR_DISCONNECT_LOST_CONNECTION, g_strerror(errno)); return; } purple_circ_buffer_mark_read(conn->buffer_outgoing, ret); }
static void _send_data_write_cb(gpointer data, gint source, PurpleInputCondition cond) { PurpleBuddy *pb = data; BonjourBuddy *bb = purple_buddy_get_protocol_data(pb); BonjourJabberConversation *bconv = bb->conversation; int ret, writelen; writelen = purple_circ_buffer_get_max_read(bconv->tx_buf); if (writelen == 0) { purple_input_remove(bconv->tx_handler); bconv->tx_handler = 0; return; } ret = send(bconv->socket, bconv->tx_buf->outptr, writelen, 0); if (ret < 0 && errno == EAGAIN) return; else if (ret <= 0) { PurpleConversation *conv = NULL; PurpleAccount *account = NULL; const char *error = g_strerror(errno); purple_debug_error("bonjour", "Error sending message to buddy %s error: %s\n", purple_buddy_get_name(pb), error ? error : "(null)"); account = purple_buddy_get_account(pb); conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bb->name, account); if (conv != NULL) purple_conversation_write(conv, NULL, _("Unable to send message."), PURPLE_MESSAGE_SYSTEM, time(NULL)); bonjour_jabber_close_conversation(bb->conversation); bb->conversation = NULL; return; } purple_circ_buffer_mark_read(bconv->tx_buf, ret); }
static void tcp_can_write(gpointer data, gint source, PurpleInputCondition cond) { PurpleConnection *gc = (PurpleConnection *) data; qq_data *qd; qq_connection *conn; int ret, writelen; g_return_if_fail(gc != NULL && gc->proto_data != NULL); qd = (qq_data *) gc->proto_data; conn = connection_find(qd, source); g_return_if_fail(conn != NULL); writelen = purple_circ_buffer_get_max_read(conn->tcp_txbuf); if (writelen == 0) { purple_input_remove(conn->can_write_handler); conn->can_write_handler = 0; return; } ret = write(source, conn->tcp_txbuf->outptr, writelen); purple_debug_info("TCP_CAN_WRITE", "total %d bytes is sent %d\n", writelen, ret); if (ret < 0 && errno == EAGAIN) return; else if (ret < 0) { /* TODO: what to do here - do we really have to disconnect? */ gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return; } purple_circ_buffer_mark_read(conn->tcp_txbuf, ret); }
static void irc_send_cb(gpointer data, gint source, PurpleInputCondition cond) { struct irc_conn *irc = data; int ret, writelen; writelen = purple_circ_buffer_get_max_read(irc->outbuf); if (writelen == 0) { purple_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) { PurpleConnection *gc = purple_account_get_connection(irc->account); gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); purple_connection_error_reason (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return; } purple_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 }
static void jabber_bosh_connection_send(PurpleBOSHConnection *conn, const PurpleBOSHPacketType type, const char *data) { PurpleHTTPConnection *chosen; GString *packet = NULL; if (type != PACKET_FLUSH && type != PACKET_TERMINATE) { /* * Unless this is a flush (or session terminate, which needs to be * sent immediately), queue up the data and start a timer to flush * the buffer. */ if (data) { int len = data ? strlen(data) : 0; purple_circ_buffer_append(conn->pending, data, len); } if (purple_debug_is_verbose()) purple_debug_misc("jabber", "bosh: %p has %" G_GSIZE_FORMAT " bytes in " "the buffer.\n", conn, conn->pending->bufused); if (conn->send_timer == 0) conn->send_timer = purple_timeout_add_seconds(BUFFER_SEND_IN_SECS, send_timer_cb, conn); return; } chosen = find_available_http_connection(conn); if (!chosen) { if (type == PACKET_FLUSH) return; /* * For non-ordinary traffic, we can't 'buffer' it, so use the * first connection. */ chosen = conn->connections[0]; if (chosen->state != HTTP_CONN_CONNECTED) { purple_debug_warning("jabber", "Unable to find a ready BOSH " "connection. Ignoring send of type 0x%02x.\n", type); return; } } /* We're flushing the send buffer, so remove the send timer */ if (conn->send_timer != 0) { purple_timeout_remove(conn->send_timer); conn->send_timer = 0; } packet = g_string_new(NULL); g_string_printf(packet, "<body " "rid='%" G_GUINT64_FORMAT "' " "sid='%s' " "to='%s' " "xml:lang='en' " "xmlns='" NS_BOSH "' " "xmlns:xmpp='" NS_XMPP_BOSH "'", ++conn->rid, conn->sid, conn->js->user->domain); if (conn->js->reinit) { packet = g_string_append(packet, " xmpp:restart='true'/>"); /* TODO: Do we need to wait for a response? */ conn->js->reinit = FALSE; } else { gsize read_amt; if (type == PACKET_TERMINATE) packet = g_string_append(packet, " type='terminate'"); packet = g_string_append_c(packet, '>'); while ((read_amt = purple_circ_buffer_get_max_read(conn->pending)) > 0) { packet = g_string_append_len(packet, conn->pending->outptr, read_amt); purple_circ_buffer_mark_read(conn->pending, read_amt); } if (data) packet = g_string_append(packet, data); packet = g_string_append(packet, "</body>"); } http_connection_send_request(chosen, packet); }
static void send_cb(gpointer data, gint source, PurpleInputCondition cond) { PeerConnection *conn; gsize writelen; gssize wrotelen; conn = data; writelen = purple_circ_buffer_get_max_read(conn->buffer_outgoing); if (writelen == 0) { purple_input_remove(conn->watcher_outgoing); conn->watcher_outgoing = 0; /* * The buffer is currently empty, so reset the current input * and output positions to the start of the buffer. We do * this so that the next chunk of data that we put into the * buffer can be read back out of the buffer in one fell swoop. * Otherwise it gets fragmented and we have to read from the * second half of the buffer than go back and read the rest of * the chunk from the first half. * * We're using TCP, which is a stream based protocol, so this * isn't supposed to matter. However, experience has shown * that at least the proxy file transfer code in AIM 6.1.41.2 * requires that the entire OFT frame arrive all at once. If * the frame is fragmented then AIM freaks out and aborts the * file transfer. Somebody should teach those guys how to * write good TCP code. */ conn->buffer_outgoing->inptr = conn->buffer_outgoing->buffer; conn->buffer_outgoing->outptr = conn->buffer_outgoing->buffer; return; } wrotelen = send(conn->fd, conn->buffer_outgoing->outptr, writelen, 0); if (wrotelen <= 0) { if (wrotelen < 0 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) /* No worries */ return; if (conn->ready) { purple_input_remove(conn->watcher_outgoing); conn->watcher_outgoing = 0; close(conn->fd); conn->fd = -1; peer_connection_schedule_destroy(conn, OSCAR_DISCONNECT_LOST_CONNECTION, NULL); } else { /* * This could happen when unable to send a negotiation * frame to a peer proxy server. */ peer_connection_trynext(conn); } return; } purple_circ_buffer_mark_read(conn->buffer_outgoing, wrotelen); conn->lastactivity = time(NULL); }