void forwarder_deinit(forwarder_t *f) { su_root_unregister(f->f_pr->pr_root, f->f_wait, NULL, f); su_wait_destroy(f->f_wait); su_root_unregister(f->f_pr->pr_root, f->f_wait + 1, NULL, f); su_wait_destroy(f->f_wait + 1); if (f->f_socket != INVALID_SOCKET) su_close(f->f_socket), f->f_socket = INVALID_SOCKET; if (f->f_buf) su_free(f->f_pr->pr_home, f->f_buf), f->f_buf = NULL; }
int forwarder_shutdown(forwarder_t *f) { forwarder_t *f_peer = f->f_peer; su_sockaddr_t *su = f->f_dest; char buf[SU_ADDRSIZE]; SU_DEBUG_3(("forwarder_shutdown: shutdown from %s:%u\n", su_inet_ntop(su->su_family, SU_ADDR(su), buf, sizeof(buf)), ntohs(su->su_port))); if (su_root_unregister(f->f_pr->pr_root, f->f_wait, forwarder_recv, f) < 0) { SU_DEBUG_1(("%s: su_root_unregister failed\n", __func__)); } if (shutdown(f->f_socket, 0) < 0) { SU_DEBUG_1(("shutdown(0): %s\n", su_strerror(su_errno()))); } f_peer->f_shutdown = 1; if (!f_peer->f_buf) { if (shutdown(f_peer->f_socket, 1) < 0) { SU_DEBUG_1(("shutdown(1): %s\n", su_strerror(su_errno()))); } if (f->f_shutdown) { forwarder_close(f); } } return 0; }
/** 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; }
/** Unregister standard input. */ static void sofsip_deinit(cli_t *cli) { if (cli->cli_init) { cli->cli_init = 0; if (su_root_unregister(cli->cli_root, &cli->cli_input, sofsip_handle_input, NULL) == SOCKET_ERROR) { su_perror("su_root_unregister"); } su_wait_destroy(&cli->cli_input); ssc_input_remove_handler(); /* g_main_loop_quit(cli->cli_gmain); */ } }
/** 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; }
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(); }