// Get fds and store them into user allocated memory. // sender_fd is from pgm_transport->send_sock. // receive_fd_ is from transport->recv_sock. int zmq::pgm_socket_t::get_sender_fds (int *send_fd_, int *receive_fd_) { // Preallocate pollfds array. int fds_array_size = pgm_sender_fd_count; pollfd *fds = new pollfd [fds_array_size]; memset (fds, '\0', fds_array_size * sizeof (fds)); // Retrieve pollfds from pgm_transport int rc = pgm_transport_poll_info (g_transport, fds, &fds_array_size, POLLOUT | POLLIN); // pgm_transport_poll_info has to return one pollfds for POLLOUT and // second for POLLIN. // Note that fds_array_size parameter can be // changed inside pgm_transport_poll_info call. assert (rc == pgm_sender_fd_count); // Store pfds into user allocated space. *receive_fd_ = fds [0].fd; *send_fd_ = fds [1].fd; delete [] fds; return pgm_sender_fd_count; }
// Get receiver fds. recv_fd is from transport->recv_sock // waiting_pipe_fd is from transport->waiting_pipe [0] int zmq::pgm_socket_t::get_receiver_fds (int *recv_fd_, int *waiting_pipe_fd_) { // For POLLIN there are 2 pollfds in pgm_transport. int fds_array_size = pgm_receiver_fd_count; pollfd *fds = new pollfd [fds_array_size]; memset (fds, '\0', fds_array_size * sizeof (fds)); // Retrieve pollfds from pgm_transport. int rc = pgm_transport_poll_info (g_transport, fds, &fds_array_size, POLLIN); // pgm_transport_poll_info has to return 2 pollfds for POLLIN. // Note that fds_array_size parameter can be // changed inside pgm_transport_poll_info call. assert (rc == pgm_receiver_fd_count); // Store pfds into user allocated space. *recv_fd_ = fds [0].fd; *waiting_pipe_fd_ = fds [1].fd; delete [] fds; return pgm_receiver_fd_count; }
int main ( int argc, char* argv[] ) { int e; pgm_error_t* pgm_err = NULL; setlocale (LC_ALL, ""); log_init (); g_message ("syncrecv"); if (!pgm_init (&pgm_err)) { g_error ("Unable to start PGM engine: %s", pgm_err->message); pgm_error_free (pgm_err); return EXIT_FAILURE; } /* parse program arguments */ const char* binary_name = strrchr (argv[0], '/'); int c; while ((c = getopt (argc, argv, "s:n:p:lh")) != -1) { switch (c) { case 'n': g_network = optarg; break; case 's': g_port = atoi (optarg); break; case 'p': g_udp_encap_port = atoi (optarg); break; case 'l': g_multicast_loop = TRUE; break; case 'h': case '?': usage (binary_name); } } g_quit = FALSE; #ifdef G_OS_UNIX e = pipe (g_quit_pipe); #else e = _pipe (g_quit_pipe, 4096, _O_BINARY | _O_NOINHERIT); #endif g_assert (0 == e); /* setup signal handlers */ signal(SIGSEGV, on_sigsegv); signal(SIGINT, on_signal); signal(SIGTERM, on_signal); #ifdef SIGHUP signal(SIGHUP, SIG_IGN); #endif if (!on_startup()) { g_error ("startup failed"); exit(1); } /* dispatch loop */ g_message ("entering PGM message loop ... "); do { struct timeval tv; int timeout; int n_fds = 2; struct pollfd fds[ 1 + n_fds ]; char buffer[4096]; gsize len; pgm_tsi_t from; const int status = pgm_recvfrom (g_transport, buffer, sizeof(buffer), 0, &len, &from, &pgm_err); switch (status) { case PGM_IO_STATUS_NORMAL: on_data (buffer, len, &from); break; case PGM_IO_STATUS_TIMER_PENDING: pgm_transport_get_timer_pending (g_transport, &tv); goto block; case PGM_IO_STATUS_RATE_LIMITED: pgm_transport_get_rate_remaining (g_transport, &tv); case PGM_IO_STATUS_WOULD_BLOCK: /* poll for next event */ block: timeout = PGM_IO_STATUS_WOULD_BLOCK == status ? -1 : ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)); memset (fds, 0, sizeof(fds)); fds[0].fd = g_quit_pipe[0]; fds[0].events = POLLIN; pgm_transport_poll_info (g_transport, &fds[1], &n_fds, POLLIN); poll (fds, 1 + n_fds, timeout /* ms */); break; default: if (pgm_err) { g_warning ("%s", pgm_err->message); pgm_error_free (pgm_err); pgm_err = NULL; } if (PGM_IO_STATUS_ERROR == status) break; } } while (!g_quit); g_message ("message loop terminated, cleaning up."); /* cleanup */ close (g_quit_pipe[0]); close (g_quit_pipe[1]); if (g_transport) { g_message ("destroying transport."); pgm_transport_destroy (g_transport, TRUE); g_transport = NULL; } g_message ("PGM engine shutdown."); pgm_shutdown (); g_message ("finished."); return EXIT_SUCCESS; }
static gpointer receiver_thread ( gpointer data ) { pgm_transport_t* transport = (pgm_transport_t*)data; long iov_max = sysconf( SC_IOV_MAX ); pgm_msgv_t msgv[iov_max]; #ifdef CONFIG_HAVE_EPOLL int efd = epoll_create (IP_MAX_MEMBERSHIPS); if (efd < 0) { g_error ("epoll_create failed errno %i: \"%s\"", errno, strerror(errno)); g_main_loop_quit(g_loop); return NULL; } int retval = pgm_transport_epoll_ctl (g_transport, efd, EPOLL_CTL_ADD, EPOLLIN); if (retval < 0) { g_error ("pgm_epoll_ctl failed errno %i: \"%s\"", errno, strerror(errno)); g_main_loop_quit(g_loop); return NULL; } #else int n_fds = 2; struct pollfd fds[ n_fds ]; #endif /* !CONFIG_HAVE_EPOLL */ do { gssize len = pgm_transport_recvmsgv (transport, msgv, iov_max, MSG_DONTWAIT /* non-blocking */); if (len >= 0) { on_msgv (msgv, len, NULL); } else if (errno == EAGAIN) /* len == -1, an error occured */ { #ifdef CONFIG_HAVE_EPOLL struct epoll_event events[1]; /* wait for maximum 1 event */ epoll_wait (efd, events, G_N_ELEMENTS(events), 1000 /* ms */); #else memset (fds, 0, sizeof(fds)); pgm_transport_poll_info (g_transport, fds, &n_fds, POLLIN); poll (fds, n_fds, 1000 /* ms */); #endif /* !CONFIG_HAVE_EPOLL */ } else if (errno == ECONNRESET) { pgm_sock_err_t* pgm_sock_err = (pgm_sock_err_t*)msgv[0].msgv_iov->iov_base; g_warning ("pgm socket lost %" G_GUINT32_FORMAT " packets detected from %s", pgm_sock_err->lost_count, pgm_print_tsi(&pgm_sock_err->tsi)); continue; } else if (errno == ENOTCONN) /* socket(s) closed */ { g_error ("pgm socket closed."); g_main_loop_quit(g_loop); break; } else { g_error ("pgm socket failed errno %i: \"%s\"", errno, strerror(errno)); g_main_loop_quit(g_loop); break; } } while (!g_quit); #ifdef CONFIG_HAVE_EPOLL close (efd); #endif return NULL; }