Exemplo n.º 1
0
/** Calculate next timeout for keepalive */
int tport_next_keepalive(tport_t *self,
			 su_time_t *return_target,
			 char const **return_why)
{
  /* Keepalive timer */
  unsigned timeout = self->tp_params->tpp_keepalive;

  if (timeout != 0 && timeout != UINT_MAX) {
    if (!tport_has_queued(self)) {
      su_time_t ntime = su_time_add(self->tp_ktime, timeout);
      if (su_time_cmp(ntime, *return_target) < 0)
	*return_target = ntime, *return_why = "keepalive";
    }
  }

  timeout = self->tp_params->tpp_pingpong;
  if (timeout != 0) {
    if (self->tp_ptime.tv_sec && !self->tp_recv_close) {
      su_time_t ntime = su_time_add(self->tp_ptime, timeout);
      if (su_time_cmp(ntime, *return_target) < 0)
	*return_target = ntime, *return_why = "waiting for pong";
    }
  }

  return 0;
}
Exemplo n.º 2
0
/** Timeout timer if receive is incomplete */
void tport_recv_timeout_timer(tport_t *self, su_time_t now)
{
  unsigned timeout = self->tp_params->tpp_timeout;

  if (timeout < INT_MAX) {
    if (self->tp_msg &&
	su_time_cmp(su_time_add(self->tp_rtime, timeout), now) < 0) {
      msg_t *msg = self->tp_msg;
      msg_set_streaming(msg, (enum msg_streaming_status)0);
      msg_set_flags(msg, MSG_FLG_ERROR | MSG_FLG_TRUNC | MSG_FLG_TIMEOUT);
      tport_deliver(self, msg, NULL, NULL, now);
      self->tp_msg = NULL;
    }

#if 0
    /* Send timeout */
    if (tport_has_queued(self) &&
	su_time_cmp(su_time_add(self->tp_stime, timeout), now) < 0) {
      stime = su_time_add(self->tp_stime, self->tp_params->tpp_timeout);
      if (su_time_cmp(stime, target) < 0)
	target = stime;
    }
#endif
  }
}
Exemplo n.º 3
0
/** Calculate timeout if receive is incomplete. */
int tport_next_recv_timeout(tport_t *self,
			    su_time_t *return_target,
			    char const **return_why)
{
  unsigned timeout = self->tp_params->tpp_timeout;

  if (timeout < INT_MAX) {
    /* Recv timeout */
    if (self->tp_msg) {
      su_time_t ntime = su_time_add(self->tp_rtime, timeout);
      if (su_time_cmp(ntime, *return_target) < 0)
	*return_target = ntime, *return_why = "recv timeout";
    }

#if 0
    /* Send timeout */
    if (tport_has_queued(self)) {
      su_time_t ntime = su_time_add(self->tp_stime, timeout);
      if (su_time_cmp(ntime, *return_target) < 0)
	*return_target = ntime, *return_why = "send timeout";
    }
#endif
  }

  return 0;
}
Exemplo n.º 4
0
/** Send pong */
int tport_ws_pong(tport_t *self)
{
  self->tp_ping = 0;

  if (tport_has_queued(self) || !self->tp_params->tpp_pong2ping)
    return 0;

  SU_DEBUG_7(("%s(%p): %s to " TPN_FORMAT "%s\n",
	      __func__, (void *)self,
	      "sending PONG", TPN_ARGS(self->tp_name), ""));

  return send(self->tp_socket, "\r\n", 2, 0);
}
Exemplo n.º 5
0
/** Send PING */
int tport_ws_ping(tport_t *self, su_time_t now)
{
  ssize_t n;
  char *why = "";

  if (tport_has_queued(self))
    return 0;

  n = send(self->tp_socket, "\r\n\r\n", 4, 0);

  if (n > 0)
    self->tp_ktime = now;

  if (n == 4) {
    if (self->tp_ptime.tv_sec == 0)
      self->tp_ptime = now;
  }
  else if (n == -1) {
    int error = su_errno();

    why = " failed";

    if (!su_is_blocking(error))
      tport_error_report(self, error, NULL);
    else
      why = " blocking";

    return -1;
  }

  SU_DEBUG_7(("%s(%p): %s to " TPN_FORMAT "%s\n",
	      __func__, (void *)self,
	      "sending PING", TPN_ARGS(self->tp_name), why));

  return n == -1 ? -1 : 0;
}
Exemplo n.º 6
0
int tls_connect(su_root_magic_t *magic, su_wait_t *w, tport_t *self)
{
  tport_master_t *mr = self->tp_master;
  tport_tls_t *tlstp = (tport_tls_t *)self;
  tls_t *tls;
  int events = su_wait_events(w, self->tp_socket);
  int error;

  SU_DEBUG_7(("%s(%p): events%s%s%s%s\n", __func__, (void *)self,
              events & (SU_WAIT_CONNECT) ? " CONNECTING" : "",
              events & SU_WAIT_IN  ? " NEGOTIATING" : "",
              events & SU_WAIT_ERR ? " ERROR" : "",
              events & SU_WAIT_HUP ? " HANGUP" : ""));

#if HAVE_POLL
  assert(w->fd == self->tp_socket);
#endif

  if (events & SU_WAIT_ERR)
    tport_error_event(self);

  if (events & SU_WAIT_HUP && !self->tp_closed)
    tport_hup_event(self);

  if (self->tp_closed)
    return 0;

  error = su_soerror(self->tp_socket);
  if (error) {
    tport_error_report(self, error, NULL);
    return 0;
  }

  if ((tls = tlstp->tlstp_context) == NULL) {
    SU_DEBUG_3(("%s(%p): Error: no TLS context data for connected socket.\n",
                __func__, (void *)tlstp));
    tport_close(self);
    tport_set_secondary_timer(self);
    return 0;
  }

  if (self->tp_is_connected == 0) {
    int ret, status;

    ret = self->tp_accepted ? SSL_accept(tls->con) : SSL_connect(tls->con);
    status = SSL_get_error(tls->con, ret);

    switch (status) {
      case SSL_ERROR_WANT_READ:
        /* OpenSSL is waiting for the peer to send handshake data */
        self->tp_events = SU_WAIT_IN | SU_WAIT_ERR | SU_WAIT_HUP;
        su_root_eventmask(mr->mr_root, self->tp_index,
		          self->tp_socket, self->tp_events);
        return 0;

      case SSL_ERROR_WANT_WRITE:
        /* OpenSSL is waiting for the peer to receive handshake data */
        self->tp_events = SU_WAIT_IN | SU_WAIT_ERR | SU_WAIT_HUP | SU_WAIT_OUT;
        su_root_eventmask(mr->mr_root, self->tp_index,
                           self->tp_socket, self->tp_events);
        return 0;

      case SSL_ERROR_NONE:
        /* TLS Handshake complete */
	status = tls_post_connection_check(self, tls);
        if ( status == X509_V_OK ) {
          su_wait_t wait[1] = {SU_WAIT_INIT};
          tport_master_t *mr = self->tp_master;

          su_root_deregister(mr->mr_root, self->tp_index);
          self->tp_index = -1;
          self->tp_events = SU_WAIT_IN | SU_WAIT_ERR | SU_WAIT_HUP;

          if ((su_wait_create(wait, self->tp_socket, self->tp_events) == -1) ||
             ((self->tp_index = su_root_register(mr->mr_root, wait, tport_wakeup,
                                                           self, 0)) == -1)) {
            tport_close(self);
            tport_set_secondary_timer(self);
	    return 0;
          }

          tls->read_events = SU_WAIT_IN;
          tls->write_events = 0;
          self->tp_is_connected = 1;
	  self->tp_verified = tls->x509_verified;
	  self->tp_subjects = tls->subjects;

	  if (tport_has_queued(self))
            tport_send_event(self);
          else
            tport_set_secondary_timer(self);

          return 0;
	}
	break;

      default:
        {
	  char errbuf[64];
	  ERR_error_string_n(status, errbuf, 64);
          SU_DEBUG_3(("%s(%p): TLS setup failed (%s)\n",
					  __func__, (void *)self, errbuf));
        }
        break;
    }
  }

  /* TLS Handshake Failed or Peer Certificate did not Verify */
  tport_close(self);
  tport_set_secondary_timer(self);

  return 0;
}