static gssize socket_recv_message (NiceSocket *sock, NiceInputMessage *recv_message) { TurnTcpPriv *priv = sock->priv; gssize ret; guint padlen; GInputVector local_recv_buf; NiceInputMessage local_recv_message; if (priv->expecting_len == 0) { guint headerlen = 0; if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 || priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) headerlen = 4; else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) headerlen = 2; else return -1; local_recv_buf.buffer = priv->recv_buf.u8 + priv->recv_buf_len; local_recv_buf.size = headerlen - priv->recv_buf_len; local_recv_message.buffers = &local_recv_buf; local_recv_message.n_buffers = 1; local_recv_message.from = recv_message->from; local_recv_message.length = 0; ret = nice_socket_recv_messages (priv->base_socket, &local_recv_message, 1); if (ret < 0) return ret; priv->recv_buf_len += local_recv_message.length; if (priv->recv_buf_len < headerlen) return 0; if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 || priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) { guint16 magic = ntohs (*priv->recv_buf.u16); guint16 packetlen = ntohs (*(priv->recv_buf.u16 + 1)); if (magic < 0x4000) { /* Its STUN */ priv->expecting_len = 20 + packetlen; } else { /* Channel data */ priv->expecting_len = 4 + packetlen; } } else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) { guint compat_len = ntohs (*priv->recv_buf.u16); priv->expecting_len = compat_len; priv->recv_buf_len = 0; } } if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 || priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) padlen = (priv->expecting_len % 4) ? 4 - (priv->expecting_len % 4) : 0; else padlen = 0; local_recv_buf.buffer = priv->recv_buf.u8 + priv->recv_buf_len; local_recv_buf.size = priv->expecting_len + padlen - priv->recv_buf_len; local_recv_message.buffers = &local_recv_buf; local_recv_message.n_buffers = 1; local_recv_message.from = recv_message->from; local_recv_message.length = 0; ret = nice_socket_recv_messages (priv->base_socket, &local_recv_message, 1); if (ret < 0) return ret; priv->recv_buf_len += local_recv_message.length; if (priv->recv_buf_len == priv->expecting_len + padlen) { /* FIXME: Eliminate this memcpy(). */ ret = memcpy_buffer_to_input_message (recv_message, priv->recv_buf.u8, priv->recv_buf_len); priv->expecting_len = 0; priv->recv_buf_len = 0; return ret; } return 0; }
static gssize socket_recv_message (NiceSocket *sock, NiceInputMessage *recv_message) { TurnTcpPriv *priv = sock->priv; gssize ret; guint padlen; GInputVector local_recv_buf; NiceInputMessage local_recv_message; /* Socket has been closed: */ if (sock->priv == NULL) return 0; if (priv->expecting_len == 0) { guint headerlen = 0; if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 || priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766 || priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_OC2007) headerlen = 4; else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) headerlen = 2; else return -1; local_recv_buf.buffer = priv->recv_buf.u8 + priv->recv_buf_len; local_recv_buf.size = headerlen - priv->recv_buf_len; local_recv_message.buffers = &local_recv_buf; local_recv_message.n_buffers = 1; local_recv_message.from = recv_message->from; local_recv_message.length = 0; ret = nice_socket_recv_messages (priv->base_socket, &local_recv_message, 1); if (ret < 0) return ret; priv->recv_buf_len += local_recv_message.length; if (priv->recv_buf_len < headerlen) return 0; if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 || priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) { guint16 magic = ntohs (*priv->recv_buf.u16); guint16 packetlen = ntohs (*(priv->recv_buf.u16 + 1)); if (magic < 0x4000) { /* Its STUN */ priv->expecting_len = 20 + packetlen; } else { /* Channel data */ priv->expecting_len = 4 + packetlen; } } else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) { guint compat_len = ntohs (*priv->recv_buf.u16); priv->expecting_len = compat_len; priv->recv_buf_len = 0; } else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_OC2007) { guint8 pt = *priv->recv_buf.u8; guint16 packetlen = ntohs (priv->recv_buf.u16[1]); if (pt != MS_TURN_CONTROL_MESSAGE && pt != MS_TURN_END_TO_END_DATA) { /* Unexpected data, error in stream */ return -1; } /* Keep the RFC4571 framing for the NiceAgent to unframe */ priv->expecting_len = packetlen + sizeof(guint16); priv->recv_buf_len = sizeof(guint16); priv->recv_buf.u16[0] = priv->recv_buf.u16[1]; } } if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 || priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) padlen = (priv->expecting_len % 4) ? 4 - (priv->expecting_len % 4) : 0; else padlen = 0; local_recv_buf.buffer = priv->recv_buf.u8 + priv->recv_buf_len; local_recv_buf.size = priv->expecting_len + padlen - priv->recv_buf_len; local_recv_message.buffers = &local_recv_buf; local_recv_message.n_buffers = 1; local_recv_message.from = recv_message->from; local_recv_message.length = 0; ret = nice_socket_recv_messages (priv->base_socket, &local_recv_message, 1); if (ret < 0) return ret; priv->recv_buf_len += local_recv_message.length; if (priv->recv_buf_len == priv->expecting_len + padlen) { /* FIXME: Eliminate this memcpy(). */ ret = memcpy_buffer_to_input_message (recv_message, priv->recv_buf.u8, priv->recv_buf_len); priv->expecting_len = 0; priv->recv_buf_len = 0; return ret; } return 0; }