コード例 #1
0
/** Receive from stream.
 *
 * @retval -1 error
 * @retval 0  end-of-stream
 * @retval 1  normal receive
 * @retval 2  incomplete recv, recv again
 *
 */
int tport_recv_stream_ws(tport_t *self)
{
  msg_t *msg;
  ssize_t n, N, veclen, i, m;
  int err;
  msg_iovec_t iovec[msg_n_fragments] = {{ 0 }};
  tport_ws_t *wstp = (tport_ws_t *)self;
  uint8_t *data;
  ws_opcode_t oc;

  if (wstp->ws_initialized < 0) {
	  return -1;
  }

  N = ws_read_frame(&wstp->ws, &oc, &data);

  if (N == -2) {
	  return 2;
  }

  if ((N == -1000) || (N == 0)) {
	  if (self->tp_msg) {
		  msg_recv_commit(self->tp_msg, 0, 1);
	  }
	  return 0;    /* End of stream */
  }
  if (N < 0) {
	  err = errno = EHOSTDOWN;
	  SU_DEBUG_1(("%s(%p): su_getmsgsize(): %s (%d)\n", __func__, (void *)self,
				  su_strerror(err), err));
	  return 0;
  }

  veclen = tport_recv_iovec(self, &self->tp_msg, iovec, N, 0);
  if (veclen < 0)
    return -1;

  msg = self->tp_msg;

  msg_set_address(msg, self->tp_addr, self->tp_addrlen);

  for (i = 0, n = 0; i < veclen; i++) {
    m = iovec[i].mv_len; assert(N >= n + m);
    memcpy(iovec[i].mv_base, data + n, m);
    n += m;
  }

  assert(N == n);

  /* Write the received data to the message dump file */
  if (self->tp_master->mr_dump_file)
	  tport_dump_iovec(self, msg, n, iovec, veclen, "recv", "from");

  /* Mark buffer as used */
  msg_recv_commit(msg, N, 0);

  return 1;
}
コード例 #2
0
/** Receive from stream.
 *
 * @retval -1 error
 * @retval 0  end-of-stream
 * @retval 1  normal receive
 * @retval 2  incomplete recv, recv again
 *
 */
int tport_recv_stream(tport_t *self)
{
  msg_t *msg;
  ssize_t n, N, veclen;
  int err, initial;
  msg_iovec_t iovec[msg_n_fragments] = {{ 0 }};

  N = su_getmsgsize(self->tp_socket);
  if (N == 0) {
    if (self->tp_msg)
      msg_recv_commit(self->tp_msg, 0, 1);
    return 0;    /* End of stream */
  }
  if (N == -1) {
    err = su_errno();
    SU_DEBUG_1(("%s(%p): su_getmsgsize(): %s (%d)\n", __func__, (void *)self,
		su_strerror(err), err));
    return -1;
  }

  initial = self->tp_msg == NULL;
  memset(&self->tp_ptime, 0, sizeof self->tp_ptime);

  while (initial && N <= 8) {	/* Check for whitespace */
    char crlf[9];
    size_t i;

    n = su_recv(self->tp_socket, crlf, N, MSG_PEEK);

    i = ws_span(crlf, n);
    if (i == 0)
      break;

    n = su_recv(self->tp_socket, crlf, i, 0);
    if (n <= 0)
      return (int)n;

    SU_DEBUG_7(("%s(%p): received keepalive (total %u)\n", __func__,
		(void *)self, self->tp_ping));

    N -= n, self->tp_ping += n;

    tport_recv_bytes(self, n, n);

    if (N == 0) {
      /* outbound-10 section 3.5.1  - send pong */
      if (self->tp_ping >= 4)
	tport_tcp_pong(self);

      return 1;
    }
  }

  veclen = tport_recv_iovec(self, &self->tp_msg, iovec, N, 0);
  if (veclen == -1)
    return -1;

  msg = self->tp_msg;

  msg_set_address(msg, self->tp_addr, (socklen_t)(self->tp_addrlen));

  n = su_vrecv(self->tp_socket, iovec, veclen, 0, NULL, NULL);

  if (n == SOCKET_ERROR)
    return tport_recv_error_report(self);

  assert(n <= N);

  tport_recv_bytes(self, n, n);

  /* Check if message contains only whitespace */
  /* This can happen if multiple PINGs are received at once */
  if (initial) {
    size_t i = ws_span(iovec->siv_base, iovec->siv_len);

    if (i + self->tp_ping >= 4)
      tport_tcp_pong(self);
    else

      self->tp_ping += (unsigned short)i;

    if (i == iovec->siv_len && veclen == 1) {
      SU_DEBUG_7(("%s(%p): received %u bytes of keepalive\n",
		  __func__, (void *)self, (unsigned)i));
      msg_destroy(self->tp_msg), self->tp_msg = NULL;
      return 1;
    }
  }

  /* Write the received data to the message dump file */
  if (self->tp_master->mr_dump_file)
    tport_dump_iovec(self, msg, n, iovec, veclen, "recv", "from");
    
  if (self->tp_master->mr_capt_sock)
      tport_capt_msg(self, msg, n, iovec, veclen, "recv");
         

  /* Mark buffer as used */
  msg_recv_commit(msg, n, n == 0);

  if (n > 0)
    self->tp_ping = 0;

  return n != 0;
}