static gint socket_send_messages_reliable (NiceSocket *sock, const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages) { TcpPassivePriv *priv = sock->priv; if (to) { NiceSocket *peer_socket = g_hash_table_lookup (priv->connections, to); if (peer_socket) return nice_socket_send_messages_reliable (peer_socket, to, messages, n_messages); } return -1; }
static gint socket_send_messages_reliable (NiceSocket *sock, const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages) { PseudoSSLPriv *priv = sock->priv; if (priv->handshaken) { /* Fast path: pass directly through to the base socket once the handshake is * complete. */ if (priv->base_socket == NULL) return -1; return nice_socket_send_messages_reliable (priv->base_socket, to, messages, n_messages); } else { nice_socket_queue_send (&priv->send_queue, to, messages, n_messages); } return n_messages; }
static gint socket_send_messages_reliable (NiceSocket *sock, const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages) { HttpPriv *priv = sock->priv; if (priv->state == HTTP_STATE_CONNECTED) { /* Fast path. */ if (!priv->base_socket) return -1; return nice_socket_send_messages_reliable (priv->base_socket, to, messages, n_messages); } else if (priv->state == HTTP_STATE_ERROR) { return -1; } else { nice_socket_queue_send (&priv->send_queue, to, messages, n_messages); } return n_messages; }
NiceSocket * nice_http_socket_new (NiceSocket *base_socket, NiceAddress *addr, gchar *username, gchar *password) { HttpPriv *priv; NiceSocket *sock = NULL; if (addr) { sock = g_slice_new0 (NiceSocket); sock->priv = priv = g_slice_new0 (HttpPriv); priv->base_socket = base_socket; priv->addr = *addr; priv->username = g_strdup (username); priv->password = g_strdup (password); priv->recv_buf = NULL; priv->recv_buf_length = 0; priv->recv_buf_pos = 0; priv->recv_buf_fill = 0; priv->content_length = 0; sock->type = NICE_SOCKET_TYPE_HTTP; sock->fileno = priv->base_socket->fileno; sock->addr = priv->base_socket->addr; sock->send_messages = socket_send_messages; sock->send_messages_reliable = socket_send_messages_reliable; sock->recv_messages = socket_recv_messages; sock->is_reliable = socket_is_reliable; sock->can_send = socket_can_send; sock->set_writable_callback = socket_set_writable_callback; sock->close = socket_close; /* Send HTTP CONNECT */ { gchar *msg = NULL; gchar *credential = NULL; gchar host[INET6_ADDRSTRLEN]; gint port = nice_address_get_port (&priv->addr); GOutputVector local_bufs; NiceOutputMessage local_messages; nice_address_to_string (&priv->addr, host); if (username) { gchar * userpass = g_strdup_printf ("%s:%s", username, password ? password : ""); gchar * auth = g_base64_encode ((guchar *)userpass, strlen (userpass)); credential = g_strdup_printf ("Proxy-Authorization: Basic %s\r\n", auth); g_free (auth); g_free (userpass); } msg = g_strdup_printf ("CONNECT %s:%d HTTP/1.0\r\n" "Host: %s\r\n" "User-Agent: %s\r\n" "Content-Length: 0\r\n" "Proxy-Connection: Keep-Alive\r\n" "Connection: Keep-Alive\r\n" "Cache-Control: no-cache\r\n" "Pragma: no-cache\r\n" "%s\r\n", host, port, host, HTTP_USER_AGENT, credential? credential : "" ); g_free (credential); local_bufs.buffer = msg; local_bufs.size = strlen (msg); local_messages.buffers = &local_bufs; local_messages.n_buffers = 1; nice_socket_send_messages_reliable (priv->base_socket, NULL, &local_messages, 1); priv->state = HTTP_STATE_INIT; g_free (msg); } } return sock; }
static gssize socket_send_message (NiceSocket *sock, const NiceAddress *to, const NiceOutputMessage *message, gboolean reliable) { TurnTcpPriv *priv = sock->priv; guint8 padbuf[3] = {0, 0, 0}; GOutputVector *local_bufs; NiceOutputMessage local_message; guint j; gint ret; guint n_bufs; union { guint16 google_len; struct { guint8 pt; guint8 zero; } msoc; } header_buf; guint offset = 0; /* Socket has been closed: */ if (sock->priv == NULL) return -1; /* Count the number of buffers. */ if (message->n_buffers == -1) { n_bufs = 0; for (j = 0; message->buffers[j].buffer != NULL; j++) n_bufs++; } else { n_bufs = message->n_buffers; } /* Allocate a new array of buffers, covering all the buffers in the input * @message, but with an additional one for a header and one for a footer. */ local_bufs = g_malloc_n (n_bufs + 1, sizeof (GOutputVector)); local_message.buffers = local_bufs; local_message.n_buffers = n_bufs + 1; if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) { header_buf.google_len = htons (output_message_get_size (message)); local_bufs[0].buffer = &header_buf; local_bufs[0].size = sizeof (guint16); offset = 1; } else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 || priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) { gsize message_len = output_message_get_size (message); gsize padlen = (message_len % 4) ? 4 - (message_len % 4) : 0; local_bufs[n_bufs].buffer = &padbuf; local_bufs[n_bufs].size = padlen; } else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_OC2007) { union { guint32 u32; guint8 u8[4]; } cookie; guint16 len = output_message_get_size (message); /* Copy the cookie from possibly split messages */ cookie.u32 = 0; if (len > sizeof (TURN_MAGIC_COOKIE) + MAGIC_COOKIE_OFFSET) { guint16 buf_offset = 0; guint i; for (i = 0; i < n_bufs; i++) { if (message->buffers[i].size > (gsize) (MAGIC_COOKIE_OFFSET - buf_offset)) { /* If the cookie is split, we assume it's data */ if (message->buffers[i].size > sizeof (TURN_MAGIC_COOKIE) + MAGIC_COOKIE_OFFSET - buf_offset) { const guint8 *buf = message->buffers[i].buffer; memcpy (&cookie.u8, buf + MAGIC_COOKIE_OFFSET - buf_offset, sizeof (TURN_MAGIC_COOKIE)); } break; } else { buf_offset += message->buffers[i].size; } } } cookie.u32 = ntohl(cookie.u32); header_buf.msoc.zero = 0; if (cookie.u32 == TURN_MAGIC_COOKIE) header_buf.msoc.pt = MS_TURN_CONTROL_MESSAGE; else header_buf.msoc.pt = MS_TURN_END_TO_END_DATA; local_bufs[0].buffer = &header_buf; local_bufs[0].size = sizeof(header_buf.msoc); offset = 1; } else { local_message.n_buffers = n_bufs; } /* Copy the existing buffers across. */ for (j = 0; j < n_bufs; j++) { local_bufs[j + offset].buffer = message->buffers[j].buffer; local_bufs[j + offset].size = message->buffers[j].size; } if (reliable) ret = nice_socket_send_messages_reliable (priv->base_socket, to, &local_message, 1); else ret = nice_socket_send_messages (priv->base_socket, to, &local_message, 1); if (ret == 1) ret = output_message_get_size (&local_message); g_free (local_bufs); return ret; }