/**Update registered socket. * * @retval 0 if success * @retval -1 upon failure */ static int sres_sofia_update(sres_sofia_t *srs, su_socket_t new_socket, su_socket_t old_socket) { char const *what = NULL; su_wait_t wait[1]; sres_sofia_register_t *reg = NULL; sres_sofia_register_t *old_reg = NULL; int i, index = -1, error = 0; int N = SRES_MAX_NAMESERVERS; SU_DEBUG_9(("sres_sofia_update(%p, %d, %d)\n", (void *)srs, (int)new_socket, (int)old_socket)); if (srs == NULL) return 0; if (srs->srs_root == NULL) return -1; if (old_socket == new_socket) { if (old_socket == INVALID_SOCKET) { sres_resolver_set_async(srs->srs_resolver, sres_sofia_update, NULL, 0); /* Destroy srs */ for (i = 0; i < N; i++) { if (!srs->srs_reg[i].reg_index) continue; su_root_deregister(srs->srs_root, srs->srs_reg[i].reg_index); memset(&srs->srs_reg[i], 0, sizeof(srs->srs_reg[i])); } su_timer_destroy(srs->srs_timer), srs->srs_timer = NULL; su_free(NULL, srs); } return 0; } if (old_socket != INVALID_SOCKET) for (i = 0; i < N; i++) if ((srs->srs_reg + i)->reg_socket == old_socket) { old_reg = srs->srs_reg + i; break; } if (new_socket != INVALID_SOCKET) { if (old_reg == NULL) { for (i = 0; i < N; i++) { if (!(srs->srs_reg + i)->reg_ptr) break; } if (i > N) return su_seterrno(ENOMEM); reg = srs->srs_reg + i; } else reg = old_reg; } if (reg) { if (su_wait_create(wait, new_socket, SU_WAIT_IN | SU_WAIT_ERR) == -1) { reg = NULL; what = "su_wait_create"; error = su_errno(); } if (reg) index = su_root_register(srs->srs_root, wait, sres_sofia_poll, reg, 0); if (index < 0) { reg = NULL; what = "su_root_register"; error = su_errno(); su_wait_destroy(wait); } } if (old_reg) { if (old_socket == srs->srs_socket) srs->srs_socket = INVALID_SOCKET; su_root_deregister(srs->srs_root, old_reg->reg_index); memset(old_reg, 0, sizeof *old_reg); } if (reg) { srs->srs_socket = new_socket; reg->reg_ptr = srs; reg->reg_socket = new_socket; reg->reg_index = index; } if (!what) return 0; /* success */ SU_DEBUG_3(("sres: %s: %s\n", what, su_strerror(error))); return su_seterrno(error); }
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; }
static int register_test(root_test_t *rt) { int i; int s; char msg[3] = "foo"; BEGIN(); TEST_1((s = su_socket(rt->rt_family, SOCK_DGRAM, 0)) != -1); for (i = 0; i < 5; i++) { rt->rt_ep[i]->registered = su_root_register(rt->rt_root, rt->rt_ep[i]->wait, wakeups[i], rt->rt_ep[i], 0); TEST(rt->rt_ep[i]->registered, i + 1 + SU_HAVE_PTHREADS); } for (i = 0; i < 5; i++) { test_ep_t *ep = rt->rt_ep[i]; TEST(su_sendto(s, msg, sizeof(msg), 0, ep->addr, ep->addrlen), sizeof(msg)); test_run(rt); TEST(rt->rt_received, i); TEST(rt->rt_wakeup, i); } for (i = 0; i < 5; i++) { TEST(su_root_unregister(rt->rt_root, rt->rt_ep[i]->wait, wakeups[i], rt->rt_ep[i]), rt->rt_ep[i]->registered); } for (i = 0; i < 5; i++) { rt->rt_ep[i]->registered = su_root_register(rt->rt_root, rt->rt_ep[i]->wait, wakeups[i], rt->rt_ep[i], 1); TEST_1(rt->rt_ep[i]->registered > 0); } for (i = 0; i < 5; i++) { test_ep_t *ep = rt->rt_ep[i]; TEST(su_sendto(s, msg, sizeof(msg), 0, ep->addr, ep->addrlen), sizeof(msg)); test_run(rt); TEST(rt->rt_received, i); TEST(rt->rt_wakeup, i); } for (i = 0; i < 5; i++) { TEST(su_root_deregister(rt->rt_root, rt->rt_ep[i]->registered), rt->rt_ep[i]->registered); } for (i = 0; i < 5; i++) { test_ep_t *ep = rt->rt_ep[i]; TEST_1(su_wait_create(ep->wait, ep->s, SU_WAIT_IN|SU_WAIT_ERR) != -1); ep->registered = su_root_register(rt->rt_root, ep->wait, wakeups[i], ep, 1); TEST_1(ep->registered > 0); } for (i = 0; i < 5; i++) { test_ep_t *ep = rt->rt_ep[i]; TEST(su_sendto(s, msg, sizeof(msg), 0, ep->addr, ep->addrlen), sizeof(msg)); test_run(rt); TEST(rt->rt_received, i); TEST(rt->rt_wakeup, i); } for (i = 0; i < 5; i++) { TEST(su_root_unregister(rt->rt_root, rt->rt_ep[i]->wait, wakeups[i], rt->rt_ep[i]), rt->rt_ep[i]->registered); } END(); }