Example #1
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;

  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;
}
Example #2
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;
}