/** Connection is complete. */ int forwarder_connected(proxy_t *pr, su_wait_t *w, forwarder_t *f) { int events, error; forwarder_t *f_peer; events = su_wait_events(w, f->f_socket); error = su_soerror(f->f_socket); if (error) { SU_DEBUG_1(("connect: %s\n", su_strerror(error))); forwarder_destroy(f); return 0; } su_root_unregister(pr->pr_root, f->f_wait + 1, forwarder_connected, f); /* Wait for data, forward it to peer */ assert(f->f_peer); f_peer = f->f_peer; su_root_register(pr->pr_root, f->f_wait, forwarder_recv, f, 0); su_root_register(pr->pr_root, f_peer->f_wait, forwarder_recv, f_peer, 0); return 0; }
/** Sofia poll/select wrapper, called by su_root_t object */ static int sres_sofia_poll(su_root_magic_t *magic, su_wait_t *w, sres_sofia_register_t *reg) { sres_sofia_t *srs = reg->reg_ptr; int retval = 0; su_socket_t socket = reg->reg_socket; int events = su_wait_events(w, socket); if (events & SU_WAIT_ERR) retval = sres_resolver_error(srs->srs_resolver, socket); if (events & SU_WAIT_IN) retval = sres_resolver_receive(srs->srs_resolver, socket); return retval; }
/** Receive data, forward it to peer */ int forwarder_recv(proxy_t *pr, su_wait_t *w, forwarder_t *f) { buffer_t b[1]; int n, events; events = su_wait_events(w, f->f_socket); n = recv(f->f_socket, b->b_data, sizeof(b->b_data), 0); if (n > 0) { b->b_sent = 0; b->b_used = n; if (f->f_peer->f_buf) { forwarder_append(f, b); return 0; } if (forwarder_send(pr, f->f_peer, b) >= 0) { if (b->b_sent < b->b_used) { su_root_unregister(pr->pr_root, w, forwarder_recv, f); su_root_register(pr->pr_root, f->f_peer->f_wait + 1, forwarder_empty, f->f_peer, 0); forwarder_append(f, b); } return 0; } else { /* Error when sending */ } } if (n < 0) { int error = su_errno(); SU_DEBUG_1(("recv: %s\n", su_strerror(error))); if (error == EINTR || error == EAGAIN || error == EWOULDBLOCK) { return 0; } /* XXX */ forwarder_destroy(f); } /* shutdown */ forwarder_shutdown(f); return 0; }
/** Empty forwarder buffers */ int forwarder_empty(proxy_t *pr, su_wait_t *w, forwarder_t *f) { buffer_t *b; int n, events; events = su_wait_events(w, f->f_socket); while ((b = f->f_buf)) { n = forwarder_send(f->f_pr, f, b); if (n == 0) { if ((f->f_buf = b->b_next)) b->b_next->b_prev = &f->f_buf; su_free(f->f_pr->pr_home, b); continue; } else if (n < 0) { /* XXX */ } break; } if (!f->f_buf) { forwarder_t *f_peer = f->f_peer; su_root_unregister(pr->pr_root, w, forwarder_empty, f); if (!f->f_shutdown) { /* Buffer is empty - start receiving */ su_root_register(pr->pr_root, f_peer->f_wait, forwarder_recv, f_peer, 0); } else { if (shutdown(f->f_socket, 1) < 0) { SU_DEBUG_1(("shutdown(1): %s\n", su_strerror(su_errno()))); } if (f_peer->f_shutdown) { forwarder_close(f); } } } return 0; }
int wakeup(root_test_t *rt, su_wait_t *w, test_ep_t *ep) { char buffer[64]; int n, error; su_wait_events(w, ep->s); n = recv(ep->s, buffer, sizeof(buffer), 0); error = su_errno(); if (n < 0) fprintf(stderr, "%s: %s\n", "recv", su_strerror(error)); TEST_1(n > 0); rt->rt_received = ep->i; return 0; }
/** Accept a connection. */ int forwarder_accept(proxy_t *pr, su_wait_t *w, forwarder_t *f0) { forwarder_t *f; su_sockaddr_t *su; socklen_t sulen; int events; events = su_wait_events(w, f0->f_socket); f = forwarder_create(pr); if (f) { su = f->f_dest; sulen = sizeof(f->f_dest); f->f_socket = accept(f0->f_socket, &su->su_sa, &sulen); f->f_upstream = 1; if (f->f_socket != INVALID_SOCKET) { char buf[SU_ADDRSIZE]; SU_DEBUG_3(("accept: connection from %s:%u\n", su_inet_ntop(su->su_family, SU_ADDR(su), buf, sizeof(buf)), ntohs(su->su_port))); if (!su_wait_create(f->f_wait, f->f_socket, SU_WAIT_IN) && !su_wait_create(f->f_wait + 1, f->f_socket, SU_WAIT_OUT)) { if (forwarder_stream_peer(pr, f) != SOCKET_ERROR) { /* success */ return 0; } } else { SU_DEBUG_1(("%s: cannot create wait objects\n", __func__)); } } } forwarder_destroy(f); return 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; }
int test_sendrecv(void) { su_socket_t s, l, a; ssize_t n; su_sockaddr_t su, csu; socklen_t sulen = sizeof su.su_sin, csulen = sizeof csu.su_sin; char b1[8], b2[8], b3[8]; su_iovec_t sv[3], rv[3]; sv[0].siv_base = "one!one!", sv[0].siv_len = 8; sv[1].siv_base = "two!two!", sv[1].siv_len = 8; sv[2].siv_base = "third!", sv[2].siv_len = 6; rv[0].siv_base = b1, rv[0].siv_len = 8; rv[1].siv_base = b2, rv[1].siv_len = 8; rv[2].siv_base = b3, rv[2].siv_len = 8; BEGIN(); s = su_socket(AF_INET, SOCK_DGRAM, 0); TEST_1(s != -1); su_setblocking(s, 1); memset(&su, 0, sulen); su.su_len = sulen; su.su_family = AF_INET; TEST(su_inet_pton(AF_INET, "127.0.0.1", &su.su_sin.sin_addr), 1); TEST(bind(s, &su.su_sa, sulen), 0); TEST(getsockname(s, &su.su_sa, &sulen), 0); n = su_vsend(s, sv, 3, 0, &su, sulen); TEST(n, 8 + 8 + 6); n = su_vrecv(s, rv, 3, 0, &su, &sulen); TEST(n, 8 + 8 + 6); TEST_M(rv[0].siv_base, sv[0].siv_base, sv[0].siv_len); TEST_M(rv[1].siv_base, sv[1].siv_base, sv[1].siv_len); TEST_M(rv[2].siv_base, sv[2].siv_base, sv[2].siv_len); su_close(s); l = su_socket(AF_INET, SOCK_STREAM, 0); TEST_1(l != -1); s = su_socket(AF_INET, SOCK_STREAM, 0); TEST_1(s != -1); memset(&su, 0, sulen); su.su_len = sulen; su.su_family = AF_INET; TEST(su_inet_pton(AF_INET, "127.0.0.1", &su.su_sin.sin_addr), 1); TEST(bind(l, &su.su_sa, sulen), 0); TEST(bind(s, &su.su_sa, sulen), 0); TEST(getsockname(l, &su.su_sa, &sulen), 0); TEST(listen(l, 5), 0); TEST(su_setblocking(s, 1), 0); TEST(connect(s, &su.su_sa, sulen), 0); a = accept(l, &csu.su_sa, &csulen); TEST_1(a != -1); TEST(su_setblocking(a, 1), 0); n = su_vsend(s, sv, 3, 0, NULL, 0); TEST(n, 8 + 8 + 6); n = su_vrecv(a, rv, 3, 0, NULL, NULL); TEST(n, 8 + 8 + 6); TEST_M(rv[0].siv_base, sv[0].siv_base, sv[0].siv_len); TEST_M(rv[1].siv_base, sv[1].siv_base, sv[1].siv_len); TEST_M(rv[2].siv_base, sv[2].siv_base, sv[2].siv_len); n = send(a, "", 0, 0); TEST(n, 0); n = su_vsend(a, sv, 3, 0, NULL, 0); TEST(n, 8 + 8 + 6); { su_wait_t w[1] = { SU_WAIT_INIT }; TEST(su_wait_create(w, s, SU_WAIT_IN | SU_WAIT_HUP), 0); TEST(su_wait(w, 0, 500), SU_WAIT_TIMEOUT); TEST(su_wait(w, 1, 500), 0); TEST(su_wait_events(w, s), SU_WAIT_IN); TEST_SIZE(su_getmsgsize(s), 8 + 8 + 6); n = su_vrecv(s, rv, 3, 0, NULL, NULL); TEST(n, 8 + 8 + 6); TEST(su_wait(w, 1, 100), SU_WAIT_TIMEOUT); shutdown(a, 2); TEST(su_wait(w, 1, 100), 0); #if SU_HAVE_WINSOCK TEST_1(su_wait_events(w, s) & SU_WAIT_HUP); #else TEST_1(su_wait_events(w, s)); n = su_vrecv(s, rv, 3, 0, NULL, NULL); TEST(n, 0); #endif su_wait_destroy(w); } su_close(a); su_close(l); su_close(s); END(); }