static void ycht_packet_send_write_cb(gpointer data, gint source, PurpleInputCondition cond) { YchtConn *ycht = data; int ret, writelen; const gchar *output = NULL; writelen = purple_circular_buffer_get_max_read(ycht->txbuf); if (writelen == 0) { purple_input_remove(ycht->tx_handler); ycht->tx_handler = 0; return; } output = purple_circular_buffer_get_output(ycht->txbuf); ret = write(ycht->fd, output, writelen); if (ret < 0 && errno == EAGAIN) return; else if (ret <= 0) { /* TODO: error handling */ /* gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); purple_connection_error(purple_account_get_connection(irc->account), PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); */ return; } purple_circular_buffer_mark_read(ycht->txbuf, ret); }
static void purple_circular_buffer_get_property(GObject *obj, guint param_id, GValue *value, GParamSpec *pspec) { PurpleCircularBuffer *buffer = PURPLE_CIRCULAR_BUFFER(obj); switch(param_id) { case PROP_GROW_SIZE: g_value_set_ulong(value, purple_circular_buffer_get_grow_size(buffer)); break; case PROP_BUFFER_USED: g_value_set_ulong(value, purple_circular_buffer_get_used(buffer)); break; case PROP_INPUT: g_value_set_pointer(value, (void*) purple_circular_buffer_get_input(buffer)); break; case PROP_OUTPUT: g_value_set_pointer(value, (void*) purple_circular_buffer_get_output(buffer)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); break; } }
/** * @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; const gchar *output = NULL; conn = data; writelen = purple_circular_buffer_get_max_read(conn->buffer_outgoing); output = purple_circular_buffer_get_output(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, output, writelen); else ret = send(conn->fd, output, 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_circular_buffer_mark_read(conn->buffer_outgoing, ret); }
static void send_cb(gpointer data, gint source, PurpleInputCondition cond) { PeerConnection *conn; gsize writelen; gssize wrotelen; const gchar *output = NULL; conn = data; writelen = purple_circular_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. */ purple_circular_buffer_reset(conn->buffer_outgoing); return; } output = purple_circular_buffer_get_output(conn->buffer_outgoing); wrotelen = send(conn->fd, output, 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_circular_buffer_mark_read(conn->buffer_outgoing, wrotelen); conn->lastactivity = time(NULL); }