static void sendlater(PurpleConnection * gc, const char *buf) { struct fetion_account_data *sip = gc->proto_data; if (!sip->connecting) { purple_debug_info("fetion", "connecting to %s port %d\n", sip-> realhostname ? sip->realhostname : "{NULL}", sip->realport); if (purple_proxy_connect (gc, sip->account, sip->realhostname, sip->realport, send_later_cb, gc) == NULL) { purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _ ("Couldn't create socket")); } sip->connecting = TRUE; } if (purple_circ_buffer_get_max_read(sip->txbuf) > 0) purple_circ_buffer_append(sip->txbuf, "\r\n", 2); purple_circ_buffer_append(sip->txbuf, buf, strlen(buf)); }
static void http_connection_send_request(PurpleHTTPConnection *conn, const GString *req) { char *data; int ret; size_t len; /* Sending something to the server, restart the inactivity timer */ jabber_stream_restart_inactivity_timer(conn->bosh->js); data = g_strdup_printf("POST %s HTTP/1.1\r\n" "Host: %s\r\n" "User-Agent: %s\r\n" "Content-Encoding: text/xml; charset=utf-8\r\n" "Content-Length: %" G_GSIZE_FORMAT "\r\n\r\n" "%s", conn->bosh->path, conn->bosh->host, bosh_useragent, req->len, req->str); len = strlen(data); ++conn->requests; ++conn->bosh->requests; if (purple_debug_is_unsafe() && purple_debug_is_verbose()) /* Will contain passwords for SASL PLAIN and is verbose */ purple_debug_misc("jabber", "BOSH (%p): Sending %s\n", conn, data); else if (purple_debug_is_verbose()) purple_debug_misc("jabber", "BOSH (%p): Sending request of " "%" G_GSIZE_FORMAT " bytes.\n", conn, len); if (conn->writeh == 0) ret = http_connection_do_send(conn, data, len); else { ret = -1; errno = EAGAIN; } if (ret < 0 && errno != EAGAIN) { /* * 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; } else if (ret < len) { if (ret < 0) ret = 0; if (conn->writeh == 0) conn->writeh = purple_input_add(conn->psc ? conn->psc->fd : conn->fd, PURPLE_INPUT_WRITE, http_connection_send_cb, conn); purple_circ_buffer_append(conn->write_buf, data + ret, len - ret); } }
static void flap_connection_send_byte_stream(ByteStream *bs, FlapConnection *conn, size_t count) { if (conn == NULL) return; /* Make sure we don't send past the end of the bs */ if (count > byte_stream_bytes_left(bs)) count = byte_stream_bytes_left(bs); /* truncate to remaining space */ if (count == 0) return; /* Add everything to our outgoing buffer */ purple_circ_buffer_append(conn->buffer_outgoing, bs->data, count); /* If we haven't already started writing stuff, then start the cycle */ if (conn->watcher_outgoing == 0) { if (conn->gsc) { conn->watcher_outgoing = purple_input_add(conn->gsc->fd, PURPLE_INPUT_WRITE, send_cb, conn); send_cb(conn, -1, 0); } else if (conn->fd >= 0) { conn->watcher_outgoing = purple_input_add(conn->fd, PURPLE_INPUT_WRITE, send_cb, conn); send_cb(conn, -1, 0); } } }
static gboolean write_raw(MsnHttpConn *httpconn, const char *data, size_t data_len) { gssize res; /* result of the write operation */ if (httpconn->tx_handler == 0) res = write(httpconn->fd, data, data_len); else { res = -1; errno = EAGAIN; } if ((res <= 0) && ((errno != EAGAIN) && (errno != EWOULDBLOCK))) { msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_WRITE); return FALSE; } if (res < 0 || res < data_len) { if (res < 0) res = 0; if (httpconn->tx_handler == 0 && httpconn->fd) httpconn->tx_handler = purple_input_add(httpconn->fd, PURPLE_INPUT_WRITE, httpconn_write_cb, httpconn); purple_circ_buffer_append(httpconn->tx_buf, data + res, data_len - res); } return TRUE; }
static void sendout_pkt(PurpleConnection * gc, const gchar * buf) { struct fetion_account_data *sip = gc->proto_data; time_t currtime = time(NULL); gint writelen = strlen(buf); gint ret; purple_debug(PURPLE_DEBUG_MISC, "fetion", "\n\nsending - %s\n######\n%s\n######\n\n", ctime(&currtime), buf); if (sip->fd < 0) { sendlater(gc, buf); return; } if (sip->tx_handler) { ret = -1; errno = EAGAIN; } else ret = write(sip->fd, buf, writelen); if (ret < 0 && errno == EAGAIN) ret = 0; else if (ret <= 0) { /* XXX: When does this happen legitimately? */ sendlater(gc, buf); return; } if (ret < writelen) { if (!sip->tx_handler) sip->tx_handler = purple_input_add(sip->fd, PURPLE_INPUT_WRITE, fetion_canwrite_cb, gc); /* XXX: is it OK to do this? You might get part of a request sent with part of another. */ if (sip->txbuf->bufused > 0) purple_circ_buffer_append(sip->txbuf, "\r\n", 2); purple_circ_buffer_append(sip->txbuf, buf + ret, writelen - ret); } }
static gint tcp_send_out(PurpleConnection *gc, guint8 *data, gint data_len) { qq_data *qd; qq_connection *conn; gint ret; g_return_val_if_fail(data != NULL && data_len > 0, -1); g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); qd = (qq_data *) gc->proto_data; conn = connection_find(qd, qd->fd); g_return_val_if_fail(conn, -1); #if 0 purple_debug_info("TCP_SEND_OUT", "Send %d bytes to socket %d\n", data_len, qd->fd); #endif if (conn->can_write_handler == 0) { ret = write(qd->fd, data, data_len); } else { ret = -1; errno = EAGAIN; } /* purple_debug_info("TCP_SEND_OUT", "Socket %d, total %d bytes is sent %d\n", qd->fd, data_len, ret); */ if (ret < 0 && errno == EAGAIN) { /* socket is busy, send later */ purple_debug_info("TCP_SEND_OUT", "Socket is busy and send later\n"); ret = 0; } 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_debug_error("TCP_SEND_OUT", "Send to socket %d failed: %d, %s\n", qd->fd, errno, g_strerror(errno)); purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return ret; } if (ret < data_len) { purple_debug_info("TCP_SEND_OUT", "Add %d bytes to buffer\n", data_len - ret); if (conn->can_write_handler == 0) { conn->can_write_handler = purple_input_add(qd->fd, PURPLE_INPUT_WRITE, tcp_can_write, gc); } if (conn->tcp_txbuf == NULL) { conn->tcp_txbuf = purple_circ_buffer_new(4096); } purple_circ_buffer_append(conn->tcp_txbuf, data + ret, data_len - ret); } return ret; }
gssize msn_servconn_write(MsnServConn *servconn, const char *buf, size_t len) { gssize ret = 0; g_return_val_if_fail(servconn != NULL, 0); if (!servconn->session->http_method) { if (servconn->tx_handler == 0) { switch (servconn->type) { case MSN_SERVCONN_NS: case MSN_SERVCONN_SB: ret = write(servconn->fd, buf, len); break; #if 0 case MSN_SERVCONN_DC: ret = write(servconn->fd, &buf, sizeof(len)); ret = write(servconn->fd, buf, len); break; #endif default: ret = write(servconn->fd, buf, len); break; } } else { ret = -1; errno = EAGAIN; } if (ret < 0 && errno == EAGAIN) ret = 0; if (ret >= 0 && ret < len) { if (servconn->tx_handler == 0) servconn->tx_handler = purple_input_add( servconn->fd, PURPLE_INPUT_WRITE, servconn_write_cb, servconn); purple_circ_buffer_append(servconn->tx_buf, buf + ret, len - ret); } } else { ret = msn_httpconn_write(servconn->httpconn, buf, len); } if (ret == -1) { msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_WRITE, NULL); } servconn_timeout_renew(servconn); return ret; }
static gint _send_data(PurpleBuddy *pb, char *message) { gint ret; int len = strlen(message); BonjourBuddy *bb = purple_buddy_get_protocol_data(pb); BonjourJabberConversation *bconv = bb->conversation; /* If we're not ready to actually send, append it to the buffer */ if (bconv->tx_handler != 0 || bconv->connect_data != NULL || bconv->sent_stream_start != FULLY_SENT || !bconv->recv_stream_start || purple_circ_buffer_get_max_read(bconv->tx_buf) > 0) { ret = -1; errno = EAGAIN; } else { ret = send(bconv->socket, message, len, 0); } if (ret == -1 && errno == EAGAIN) ret = 0; else if (ret <= 0) { PurpleConversation *conv; PurpleAccount *account; 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 -1; } if (ret < len) { /* Don't interfere with the stream starting */ if (bconv->sent_stream_start == FULLY_SENT && bconv->recv_stream_start && bconv->tx_handler == 0) bconv->tx_handler = purple_input_add(bconv->socket, PURPLE_INPUT_WRITE, _send_data_write_cb, pb); purple_circ_buffer_append(bconv->tx_buf, message + ret, len - ret); } return ret; }
int irc_send_len(struct irc_conn *irc, const char *buf, int buflen) { int ret; char *tosend = g_strdup(buf); purple_signal_emit(_irc_plugin, "irc-sending-text", purple_account_get_connection(irc->account), &tosend); if (tosend == NULL) return 0; if (!purple_strequal(tosend, buf)) { buflen = strlen(tosend); } if (purple_debug_is_verbose()) { char *clean = purple_utf8_salvage(tosend); clean = g_strstrip(clean); purple_debug_misc("irc", "<< %s\n", clean); g_free(clean); } /* If we're not buffering writes, try to send immediately */ if (!irc->writeh) ret = do_send(irc, tosend, buflen); else { ret = -1; errno = EAGAIN; } /* purple_debug(PURPLE_DEBUG_MISC, "irc", "sent%s: %s", irc->gsc ? " (ssl)" : "", tosend); */ if (ret <= 0 && errno != EAGAIN) { 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); } else if (ret < buflen) { if (ret < 0) ret = 0; if (!irc->writeh) irc->writeh = purple_input_add( irc->gsc ? irc->gsc->fd : irc->fd, PURPLE_INPUT_WRITE, irc_send_cb, irc); purple_circ_buffer_append(irc->outbuf, tosend + ret, buflen - ret); } g_free(tosend); return ret; }
/** * This should be called by OFT/ODC code to send a standard OFT or ODC * frame across the peer connection along with some payload data. Or * maybe a file. Anything, really. */ void peer_connection_send(PeerConnection *conn, ByteStream *bs) { /* Add everything to our outgoing buffer */ purple_circ_buffer_append(conn->buffer_outgoing, bs->data, bs->len); /* If we haven't already started writing stuff, then start the cycle */ if ((conn->watcher_outgoing == 0) && (conn->fd >= 0)) { conn->watcher_outgoing = purple_input_add(conn->fd, PURPLE_INPUT_WRITE, send_cb, conn); send_cb(conn, conn->fd, 0); } }
void UploadPortrait(gpointer data, gint source, const gchar * error_message) { struct fetion_account_data *sip = data; PurpleStoredImage *img = sip->icon; gchar *head; gchar *buf; gint head_len; gint ret, lenth, writed; gconstpointer img_data = purple_imgstore_get_data(img); size_t size = purple_imgstore_get_size(img); head = g_strdup_printf("POST /%s/setportrait.aspx HTTP/1.1\r\n" "User-Agent: IIC2.0/PC 3.3.0370\r\n" "Content-Type: image/jpeg\r\n" "Host: %s\r\n" "Cookie: ssic=%s\r\n" "Content-Length: %d\r\n\r\n", sip->UploadPrefix, sip->UploadServer, sip->ssic, size); purple_debug_info("fetion:", "UploadPortrait:head[%s][%d]\n", head, size); head_len = strlen(head); buf = g_malloc(head_len + size); memcpy(buf, head, head_len); memcpy(buf + head_len, img_data, size); lenth = size + strlen(head); writed = 0; ret = write(source, buf, lenth); if (ret < 0 && errno == EAGAIN) ret = 0; g_return_if_fail(ret >= 0); if (ret < lenth) { purple_circ_buffer_append(sip->icon_buf, buf + ret, lenth - ret); sip->icon_handler = purple_input_add(source, PURPLE_INPUT_WRITE, (PurpleInputFunction) UploadPortrait_cb, sip); } g_free(head); sip->icon = NULL; purple_imgstore_unref(img); }
int yahoo_packet_send(struct yahoo_packet *pkt, YahooData *yd) { size_t len; gssize ret; guchar *data; if (yd->fd < 0) return -1; len = yahoo_packet_build(pkt, 0, yd->wm, yd->jp, &data); yahoo_packet_dump(data, len); if (yd->txhandler == 0) ret = write(yd->fd, data, len); else { ret = -1; errno = EAGAIN; } if (ret < 0 && errno == EAGAIN) ret = 0; else if (ret <= 0) { purple_debug_warning("yahoo", "Only wrote %" G_GSSIZE_FORMAT " of %" G_GSIZE_FORMAT " bytes!\n", ret, len); g_free(data); return ret; } if ((gsize)ret < len) { if (yd->txhandler == 0) yd->txhandler = purple_input_add(yd->fd, PURPLE_INPUT_WRITE, yahoo_packet_send_can_write, yd); purple_circ_buffer_append(yd->txbuf, data + ret, len - ret); } g_free(data); return ret; }
int irc_send(struct irc_conn *irc, const char *buf) { int ret, buflen; char *tosend= g_strdup(buf); purple_signal_emit(_irc_plugin, "irc-sending-text", purple_account_get_connection(irc->account), &tosend); if (tosend == NULL) return 0; buflen = strlen(tosend); /* If we're not buffering writes, try to send immediately */ if (!irc->writeh) ret = do_send(irc, tosend, buflen); else { ret = -1; errno = EAGAIN; } /* purple_debug(PURPLE_DEBUG_MISC, "irc", "sent%s: %s", irc->gsc ? " (ssl)" : "", tosend); */ if (ret <= 0 && errno != EAGAIN) { purple_connection_error(purple_account_get_connection(irc->account), _("Server has disconnected")); } else if (ret < buflen) { if (ret < 0) ret = 0; if (!irc->writeh) irc->writeh = purple_input_add( irc->gsc ? irc->gsc->fd : irc->fd, PURPLE_INPUT_WRITE, irc_send_cb, irc); purple_circ_buffer_append(irc->outbuf, tosend + ret, buflen - ret); } g_free(tosend); return ret; }
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); }