void fix_poll_method( enum poll_types *poll_method ) { char* poll_err; /* fix config variables */ /* they can have only positive values due the config parser so we can * ignore most of them */ poll_err=check_poll_method(*poll_method); /* set an appropiate poll method */ if (poll_err || (*poll_method==0)){ *poll_method=choose_poll_method(); if (poll_err){ LM_ERR("%s, using %s instead\n", poll_err, poll_method_name(*poll_method)); }else{ LM_INFO("using %s as the IO watch method" " (auto detected)\n", poll_method_name(*poll_method)); } }else{ LM_INFO("using %s as the IO watch method (config)\n", poll_method_name(*poll_method)); } return; }
/** * Set async I/O polling method. This function can also be called while the * program is running. * * @param method New polling method * * @return 0 if success, otherwise errorcode */ int poll_method_set(enum poll_method method) { struct re *re = re_get(); int err; err = fd_setsize(DEFAULT_MAXFDS); if (err) return err; switch (method) { #ifdef HAVE_POLL case METHOD_POLL: break; #endif #ifdef HAVE_SELECT case METHOD_SELECT: if (re->maxfds > (int)FD_SETSIZE) { DEBUG_WARNING("SELECT: maxfds > FD_SETSIZE\n"); return EMFILE; } break; #endif #ifdef HAVE_EPOLL case METHOD_EPOLL: if (!epoll_check()) return EINVAL; break; #endif #ifdef HAVE_ACTSCHED case METHOD_ACTSCHED: break; #endif #ifdef HAVE_KQUEUE case METHOD_KQUEUE: break; #endif default: DEBUG_WARNING("poll method not supported: '%s'\n", poll_method_name(method)); return EINVAL; } re->method = method; re->update = true; DEBUG_INFO("Setting async I/O polling method to `%s'\n", poll_method_name(re->method)); err = poll_init(re); if (err) return err; return rebuild_fds(re); }
static int poll_setup(struct re *re) { int err; err = fd_setsize(DEFAULT_MAXFDS); if (err) goto out; if (METHOD_NULL == re->method) { err = poll_method_set(poll_method_best()); if (err) goto out; DEBUG_INFO("poll setup: poll method not set - set to `%s'\n", poll_method_name(re->method)); } err = poll_init(re); out: if (err) poll_close(re); return err; }
/** * Debug the main polling loop * * @param pf Print handler where debug output is printed to * @param unused Unused parameter * * @return 0 if success, otherwise errorcode */ int re_debug(struct re_printf *pf, void *unused) { struct re *re = re_get(); int err = 0; (void)unused; err |= re_hprintf(pf, "re main loop:\n"); err |= re_hprintf(pf, " maxfds: %d\n", re->maxfds); err |= re_hprintf(pf, " nfds: %d\n", re->nfds); err |= re_hprintf(pf, " method: %d (%s)\n", re->method, poll_method_name(re->method)); return err; }
/** * Main polling loop for async I/O events. This function will only return when * re_cancel() is called or an error occured. * * @param signalh Optional Signal handler * * @return 0 if success, otherwise errorcode */ int re_main(re_signal_h *signalh) { struct re *re = re_get(); int err; #ifdef HAVE_SIGNAL if (signalh) { (void)signal(SIGINT, signal_handler); (void)signal(SIGALRM, signal_handler); (void)signal(SIGTERM, signal_handler); } #endif if (re->polling) { DEBUG_WARNING("main loop already polling\n"); return EALREADY; } err = poll_setup(re); if (err) goto out; DEBUG_INFO("Using async I/O polling method: `%s'\n", poll_method_name(re->method)); re->polling = true; #ifdef HAVE_ACTSCHED if (METHOD_ACTSCHED == re->method) { err = actsched_start(); goto out; } #endif re_lock(re); for (;;) { if (re->sig) { if (signalh) signalh(re->sig); re->sig = 0; } if (!re->polling) { err = 0; break; } err = fd_poll(re); if (err) { if (EINTR == err) continue; #ifdef DARWIN /* NOTE: workaround for Darwin */ if (EBADF == err) continue; #endif break; } tmr_poll(&re->tmrl); } re_unlock(re); out: re->polling = false; return err; }
int init_tcp(void) { char* poll_err; /* init lock */ tcpconn_lock=lock_alloc(); if (tcpconn_lock==0){ LM_CRIT("could not alloc lock\n"); goto error; } if (lock_init(tcpconn_lock)==0){ LM_CRIT("could not init lock\n"); lock_dealloc((void*)tcpconn_lock); tcpconn_lock=0; goto error; } /* init tcp children array */ tcp_children = (struct tcp_child*)pkg_malloc ( tcp_children_no*sizeof(struct tcp_child) ); if (tcp_children==0) { LM_CRIT("could not alloc tcp_children array in pkg memory\n"); goto error; } memset( tcp_children, 0, tcp_children_no*sizeof(struct tcp_child)); /* init globals */ connection_id=(int*)shm_malloc(sizeof(int)); if (connection_id==0){ LM_CRIT("could not alloc globals in shm memory\n"); goto error; } *connection_id=1; /* alloc hashtables*/ tcpconn_aliases_hash=(struct tcp_conn_alias**) shm_malloc(TCP_ALIAS_HASH_SIZE* sizeof(struct tcp_conn_alias*)); if (tcpconn_aliases_hash==0){ LM_CRIT("could not alloc address hashtable in shm memory\n"); goto error; } tcpconn_id_hash=(struct tcp_connection**)shm_malloc(TCP_ID_HASH_SIZE* sizeof(struct tcp_connection*)); if (tcpconn_id_hash==0){ LM_CRIT("could not alloc id hashtable in shm memory\n"); goto error; } /* init hashtables*/ memset((void*)tcpconn_aliases_hash, 0, TCP_ALIAS_HASH_SIZE * sizeof(struct tcp_conn_alias*)); memset((void*)tcpconn_id_hash, 0, TCP_ID_HASH_SIZE * sizeof(struct tcp_connection*)); /* fix config variables */ /* they can have only positive values due the config parser so we can * ignore most of them */ poll_err=check_poll_method(tcp_poll_method); /* set an appropiate poll method */ if (poll_err || (tcp_poll_method==0)){ tcp_poll_method=choose_poll_method(); if (poll_err){ LM_ERR("%s, using %s instead\n", poll_err, poll_method_name(tcp_poll_method)); }else{ LM_INFO("using %s as the TCP io watch method" " (auto detected)\n", poll_method_name(tcp_poll_method)); } }else{ LM_INFO("using %s as the TCP io watch method (config)\n", poll_method_name(tcp_poll_method)); } return 0; error: /* clean-up */ destroy_tcp(); return -1; }
/*! \brief tcp main loop */ void tcp_main_loop(void) { struct socket_info* si; int r; /* init io_wait (here because we want the memory allocated only in * the tcp_main process) */ /*! \todo FIXME: TODO: make tcp_max_fd_no a config param */ if (init_io_wait(&io_h, tcp_max_fd_no, tcp_poll_method)<0) goto error; /* init: start watching all the fds*/ /* add all the sockets we listens on for connections */ for (si=tcp_listen; si; si=si->next){ if ((si->proto==PROTO_TCP) &&(si->socket!=-1)){ if (io_watch_add(&io_h, si->socket, F_SOCKINFO, si)<0){ LM_CRIT("failed to add listen socket to the fd list\n"); goto error; } }else{ LM_CRIT("non tcp address in tcp_listen\n"); } } #ifdef USE_TLS if (!tls_disable){ for (si=tls_listen; si; si=si->next){ if ((si->proto==PROTO_TLS) && (si->socket!=-1)){ if (io_watch_add(&io_h, si->socket, F_SOCKINFO, si)<0){ LM_CRIT("failed to add tls listen socket to the fd list\n"); goto error; } }else{ LM_CRIT("non tls address in tls_listen\n"); } } } #endif /* add all the unix sockets used for communcation with other opensips * processes (get fd, new connection a.s.o) */ for (r=1; r<counted_processes; r++){ /* skip myslef (as process) and -1 socks (disabled) (we can't have 0, we never close it!) */ if (r!=process_no && pt[r].unix_sock>0) if (io_watch_add(&io_h, pt[r].unix_sock, F_PROC, &pt[r])<0){ LM_CRIT("failed to add process %d (%s) unix socket " "to the fd list\n", r, pt[r].desc); goto error; } } /* add all the unix sokets used for communication with the tcp childs */ for (r=0; r<tcp_children_no; r++){ if (tcp_children[r].unix_sock>0)/*we can't have 0, we never close it!*/ if (io_watch_add(&io_h, tcp_children[r].unix_sock, F_TCPCHILD, &tcp_children[r]) <0){ LM_CRIT("failed to add tcp child %d unix socket to " "the fd list\n", r); goto error; } } /* main loop */ switch(io_h.poll_method){ case POLL_POLL: while(1){ /* wait and process IO */ io_wait_loop_poll(&io_h, TCP_MAIN_SELECT_TIMEOUT, 0); /* remove old connections */ tcpconn_timeout(0); } break; #ifdef HAVE_SELECT case POLL_SELECT: while(1){ io_wait_loop_select(&io_h, TCP_MAIN_SELECT_TIMEOUT, 0); tcpconn_timeout(0); } break; #endif #ifdef HAVE_SIGIO_RT case POLL_SIGIO_RT: while(1){ io_wait_loop_sigio_rt(&io_h, TCP_MAIN_SELECT_TIMEOUT); tcpconn_timeout(0); } break; #endif #ifdef HAVE_EPOLL case POLL_EPOLL_LT: while(1){ io_wait_loop_epoll(&io_h, TCP_MAIN_SELECT_TIMEOUT, 0); tcpconn_timeout(0); } break; case POLL_EPOLL_ET: while(1){ io_wait_loop_epoll(&io_h, TCP_MAIN_SELECT_TIMEOUT, 1); tcpconn_timeout(0); } break; #endif #ifdef HAVE_KQUEUE case POLL_KQUEUE: while(1){ io_wait_loop_kqueue(&io_h, TCP_MAIN_SELECT_TIMEOUT, 0); tcpconn_timeout(0); } break; #endif #ifdef HAVE_DEVPOLL case POLL_DEVPOLL: while(1){ io_wait_loop_devpoll(&io_h, TCP_MAIN_SELECT_TIMEOUT, 0); tcpconn_timeout(0); } break; #endif default: LM_CRIT("no support for poll method %s (%d)\n", poll_method_name(io_h.poll_method), io_h.poll_method); goto error; } error: destroy_io_wait(&io_h); LM_CRIT("exiting..."); exit(-1); }
static int core_config_template(struct re_printf *pf, const struct config *cfg) { int err = 0; if (!cfg) return 0; err |= re_hprintf(pf, "\n# Core\n" "poll_method\t\t%s\t\t# poll, select" #ifdef HAVE_EPOLL ", epoll .." #endif #ifdef HAVE_KQUEUE ", kqueue .." #endif "\n" "\n# SIP\n" "sip_trans_bsize\t\t128\n" "#sip_listen\t\t0.0.0.0:5060\n" "#sip_certificate\tcert.pem\n" "\n" "# Call\n" "call_local_timeout\t%u\n" "\n" "# Audio\n" "#audio_path\t\t/usr/share/baresip\n" "audio_player\t\t%s\n" "audio_source\t\t%s\n" "audio_alert\t\t%s\n" "audio_srate\t\t%u-%u\n" "audio_channels\t\t%u-%u\n" "#ausrc_srate\t\t48000\n" "#auplay_srate\t\t48000\n" "#ausrc_channels\t\t0\n" "#auplay_channels\t\t0\n" , poll_method_name(poll_method_best()), cfg->call.local_timeout, default_audio_device(), default_audio_device(), default_audio_device(), cfg->audio.srate.min, cfg->audio.srate.max, cfg->audio.channels.min, cfg->audio.channels.max); #ifdef USE_VIDEO err |= re_hprintf(pf, "\n# Video\n" "#video_source\t\t%s\n" "#video_display\t\t%s\n" "video_size\t\t%dx%d\n" "video_bitrate\t\t%u\n" "video_fps\t\t%u\n", default_video_device(), default_video_display(), cfg->video.width, cfg->video.height, cfg->video.bitrate, cfg->video.fps); #endif err |= re_hprintf(pf, "\n# AVT - Audio/Video Transport\n" "rtp_tos\t\t\t184\n" "#rtp_ports\t\t10000-20000\n" "#rtp_bandwidth\t\t512-1024 # [kbit/s]\n" "rtcp_enable\t\tyes\n" "rtcp_mux\t\tno\n" "jitter_buffer_delay\t%u-%u\t\t# frames\n" "rtp_stats\t\tno\n" "\n# Network\n" "#dns_server\t\t10.0.0.1:53\n" "#net_interface\t\t%H\n", cfg->avt.jbuf_del.min, cfg->avt.jbuf_del.max, default_interface_print, NULL); #ifdef USE_VIDEO err |= re_hprintf(pf, "\n# BFCP\n" "#bfcp_proto\t\tudp\n"); #endif return err; }
void tcp_receive_loop(int unix_sock) { /* init */ tcpmain_sock=unix_sock; /* init com. socket */ if (init_io_wait(&io_w, tcp_max_fd_no, tcp_poll_method)<0) goto error; /* add the unix socket */ if (io_watch_add(&io_w, tcpmain_sock, F_TCPMAIN, 0)<0){ LM_CRIT("failed to add socket to the fd list\n"); goto error; } /* main loop */ switch(io_w.poll_method){ case POLL_POLL: while(1){ io_wait_loop_poll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0); tcp_receive_timeout(); } break; #ifdef HAVE_SELECT case POLL_SELECT: while(1){ io_wait_loop_select(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0); tcp_receive_timeout(); } break; #endif #ifdef HAVE_SIGIO_RT case POLL_SIGIO_RT: while(1){ io_wait_loop_sigio_rt(&io_w, TCP_CHILD_SELECT_TIMEOUT); tcp_receive_timeout(); } break; #endif #ifdef HAVE_EPOLL case POLL_EPOLL_LT: while(1){ io_wait_loop_epoll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0); tcp_receive_timeout(); } break; case POLL_EPOLL_ET: while(1){ io_wait_loop_epoll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 1); tcp_receive_timeout(); } break; #endif #ifdef HAVE_KQUEUE case POLL_KQUEUE: while(1){ io_wait_loop_kqueue(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0); tcp_receive_timeout(); } break; #endif #ifdef HAVE_DEVPOLL case POLL_DEVPOLL: while(1){ io_wait_loop_devpoll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0); tcp_receive_timeout(); } break; #endif default: LM_CRIT("no support for poll method %s (%d)\n", poll_method_name(io_w.poll_method), io_w.poll_method); goto error; } error: destroy_io_wait(&io_w); LM_CRIT("exiting..."); exit(-1); }
static int core_config_template(struct re_printf *pf, const struct config *cfg) { int err = 0; if (!cfg) return 0; err |= re_hprintf(pf, "\n# Core\n" "poll_method\t\t%s\t\t# poll, select" #ifdef HAVE_EPOLL ", epoll .." #endif #ifdef HAVE_KQUEUE ", kqueue .." #endif "\n" "\n# SIP\n" "#sip_listen\t\t0.0.0.0:5060\n" "#sip_certificate\tcert.pem\n" "#sip_cafile\t\t%s\n" "\n" "# Call\n" "call_local_timeout\t%u\n" "call_max_calls\t\t%u\n" "\n" "# Audio\n" #if defined (SHARE_PATH) "#audio_path\t\t" SHARE_PATH "\n" #elif defined (PREFIX) "#audio_path\t\t" PREFIX "/share/baresip\n" #else "#audio_path\t\t/usr/share/baresip\n" #endif "audio_player\t\t%s\n" "audio_source\t\t%s\n" "audio_alert\t\t%s\n" "#ausrc_srate\t\t48000\n" "#auplay_srate\t\t48000\n" "#ausrc_channels\t\t0\n" "#auplay_channels\t0\n" "#audio_txmode\t\tpoll\t\t# poll, thread\n" "audio_level\t\tno\n" "ausrc_format\t\ts16\t\t# s16, float, ..\n" "auplay_format\t\ts16\t\t# s16, float, ..\n" "auenc_format\t\ts16\t\t# s16, float, ..\n" "audec_format\t\ts16\t\t# s16, float, ..\n" , poll_method_name(poll_method_best()), default_cafile(), cfg->call.local_timeout, cfg->call.max_calls, default_audio_device(), default_audio_device(), default_audio_device()); err |= re_hprintf(pf, "\n# Video\n" "#video_source\t\t%s\n" "#video_display\t\t%s\n" "video_size\t\t%dx%d\n" "video_bitrate\t\t%u\n" "video_fps\t\t%.2f\n" "video_fullscreen\tyes\n" "videnc_format\t\t%s\n" , default_video_device(), default_video_display(), cfg->video.width, cfg->video.height, cfg->video.bitrate, cfg->video.fps, vidfmt_name(cfg->video.enc_fmt)); err |= re_hprintf(pf, "\n# AVT - Audio/Video Transport\n" "rtp_tos\t\t\t184\n" "#rtp_ports\t\t10000-20000\n" "#rtp_bandwidth\t\t512-1024 # [kbit/s]\n" "rtcp_mux\t\tno\n" "jitter_buffer_delay\t%u-%u\t\t# frames\n" "rtp_stats\t\tno\n" "#rtp_timeout\t\t60\n" "\n# Network\n" "prefer_ipv6\t\tno\n" "#dns_server\t\t10.0.0.1:53\n" "#net_interface\t\t%H\n", cfg->avt.jbuf_del.min, cfg->avt.jbuf_del.max, default_interface_print, NULL); err |= re_hprintf(pf, "\n# BFCP\n" "#bfcp_proto\t\tudp\n"); return err; }
void tcp_receive_loop(int unix_sock) { /* init */ tcpmain_sock=unix_sock; /* init com. socket */ if (init_io_wait(&io_w, get_max_open_fds(), tcp_poll_method)<0) goto error; tcp_reader_prev_ticks=get_ticks_raw(); if (init_local_timer(&tcp_reader_ltimer, get_ticks_raw())!=0) goto error; /* add the unix socket */ if (io_watch_add(&io_w, tcpmain_sock, POLLIN, F_TCPMAIN, 0)<0){ LM_CRIT("failed to add socket to the fd list\n"); goto error; } /* initialize the config framework */ if (cfg_child_init()) goto error; /* main loop */ switch(io_w.poll_method){ case POLL_POLL: while(1){ io_wait_loop_poll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0); tcp_reader_timer_run(); } break; #ifdef HAVE_SELECT case POLL_SELECT: while(1){ io_wait_loop_select(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0); tcp_reader_timer_run(); } break; #endif #ifdef HAVE_SIGIO_RT case POLL_SIGIO_RT: while(1){ io_wait_loop_sigio_rt(&io_w, TCP_CHILD_SELECT_TIMEOUT); tcp_reader_timer_run(); } break; #endif #ifdef HAVE_EPOLL case POLL_EPOLL_LT: while(1){ io_wait_loop_epoll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0); tcp_reader_timer_run(); } break; case POLL_EPOLL_ET: while(1){ io_wait_loop_epoll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 1); tcp_reader_timer_run(); } break; #endif #ifdef HAVE_KQUEUE case POLL_KQUEUE: while(1){ io_wait_loop_kqueue(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0); tcp_reader_timer_run(); } break; #endif #ifdef HAVE_DEVPOLL case POLL_DEVPOLL: while(1){ io_wait_loop_devpoll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0); tcp_reader_timer_run(); } break; #endif default: LM_CRIT("no support for poll method %s (%d)\n", poll_method_name(io_w.poll_method), io_w.poll_method); goto error; } error: destroy_io_wait(&io_w); LM_CRIT("exiting..."); exit(-1); }