struct rtpp_pcount * rtpp_pcount_ctor(void) { struct rtpp_pcount_priv *pvt; struct rtpp_refcnt *rcnt; pvt = rtpp_rzmalloc(sizeof(struct rtpp_pcount_priv), &rcnt); if (pvt == NULL) { goto e0; } pvt->pub.rcnt = rcnt; if (pthread_mutex_init(&pvt->lock, NULL) != 0) { goto e1; } pvt->pub.reg_reld = &rtpp_pcount_reg_reld; pvt->pub.reg_drop = &rtpp_pcount_reg_drop; pvt->pub.reg_ignr = &rtpp_pcount_reg_ignr; pvt->pub.get_stats = &rtpp_pcount_get_stats; CALL_SMETHOD(pvt->pub.rcnt, attach, (rtpp_refcnt_dtor_t)&rtpp_pcount_dtor, pvt); return ((&pvt->pub)); e1: CALL_SMETHOD(pvt->pub.rcnt, decref); free(pvt); e0: return (NULL); }
void rtpp_pcount_fintest() { int naborts_s; struct { struct rtpp_pcount pub; } *tp; naborts_s = _naborts; tp = rtpp_rzmalloc(sizeof(*tp), offsetof(typeof(*tp), pub.rcnt)); assert(tp != NULL); assert(tp->pub.rcnt != NULL); tp->pub.get_stats = (rtpp_pcount_get_stats_t)((void *)0x1); tp->pub.reg_drop = (rtpp_pcount_reg_drop_t)((void *)0x1); tp->pub.reg_ignr = (rtpp_pcount_reg_ignr_t)((void *)0x1); tp->pub.reg_reld = (rtpp_pcount_reg_reld_t)((void *)0x1); CALL_SMETHOD(tp->pub.rcnt, attach, (rtpp_refcnt_dtor_t)&rtpp_pcount_fin, &tp->pub); CALL_SMETHOD(tp->pub.rcnt, decref); CALL_TFIN(&tp->pub, get_stats); CALL_TFIN(&tp->pub, reg_drop); CALL_TFIN(&tp->pub, reg_ignr); CALL_TFIN(&tp->pub, reg_reld); assert((_naborts - naborts_s) == 4); }
struct rtpp_acct_rtcp * rtpp_acct_rtcp_ctor(const char *call_id, const struct rtp_packet *pp) { struct rtpp_acct_rtcp_priv *pvt; pvt = rtpp_rzmalloc(sizeof(struct rtpp_acct_rtcp_priv), PVT_RCOFFS(pvt)); if (pvt == NULL) { goto e0; } pvt->pub.pkt = rtp_packet_alloc(); if (pvt->pub.pkt == NULL) { goto e1; } rtp_packet_dup(pvt->pub.pkt, pp, 0); pvt->pub.call_id = strdup(call_id); if (pvt->pub.call_id == NULL) { goto e2; } pvt->pub.jt = &pvt->_jt; CALL_SMETHOD(pvt->pub.rcnt, attach, (rtpp_refcnt_dtor_t)&rtpp_acct_rtcp_dtor, pvt); return ((&pvt->pub)); e2: rtp_packet_free(pvt->pub.pkt); e1: CALL_SMETHOD(pvt->pub.rcnt, decref); free(pvt); e0: return (NULL); }
void rtpp_wi_free(struct rtpp_wi *wi) { if (wi->sock_rcnt != NULL) { CALL_SMETHOD(wi->sock_rcnt, decref); } if (wi->log != NULL) { CALL_SMETHOD(wi->log->rcnt, decref); } free(wi->free_ptr); }
static int rtpp_proc_ttl_foreach(void *dp, void *ap) { struct foreach_args *fap; struct rtpp_session *sp; fap = (struct foreach_args *)ap; /* * This method does not need us to bump ref, since we are in the * locked context of the rtpp_hash_table, which holds its own ref. */ sp = (struct rtpp_session *)dp; if (CALL_METHOD(sp->rtp, get_ttl) == 0) { RTPP_LOG(sp->log, RTPP_LOG_INFO, "session timeout"); if (sp->timeout_data.notify_target != NULL) { CALL_METHOD(fap->rtpp_notify_cf, schedule, sp->timeout_data.notify_target, sp->timeout_data.notify_tag); } CALL_SMETHOD(fap->rtpp_stats, updatebyname, "nsess_timeout", 1); CALL_METHOD(fap->sessions_wrt, unreg, sp->seuid); return (RTPP_HT_MATCH_DEL); } else { CALL_METHOD(sp->rtp, decr_ttl); } return (RTPP_HT_MATCH_CONT); }
void rtpp_timed_task_fintest() { int naborts_s; struct { struct rtpp_timed_task pub; } *tp; naborts_s = _naborts; tp = rtpp_rzmalloc(sizeof(*tp), offsetof(typeof(*tp), pub.rcnt)); assert(tp != NULL); assert(tp->pub.rcnt != NULL); tp->pub.cancel = (rtpp_timed_task_cancel_t)((void *)0x1); CALL_SMETHOD(tp->pub.rcnt, attach, (rtpp_refcnt_dtor_t)&rtpp_timed_task_fin, &tp->pub); CALL_SMETHOD(tp->pub.rcnt, decref); CALL_TFIN(&tp->pub, cancel); assert((_naborts - naborts_s) == 1); }
struct rtpp_socket * rtpp_socket_ctor(int domain, int type) { struct rtpp_socket_priv *pvt; pvt = rtpp_rzmalloc(sizeof(struct rtpp_socket_priv), PVT_RCOFFS(pvt)); if (pvt == NULL) { goto e0; } pvt->fd = socket(domain, type, 0); if (pvt->fd < 0) { goto e1; } if (domain == AF_INET6) { /* Disable any automatic IPv4->IPv6 gatewaying */ int yes = 1; setsockopt(pvt->fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes)); } pvt->pub.bind = &rtpp_socket_bind; pvt->pub.settos = &rtpp_socket_settos; pvt->pub.setrbuf = &rtpp_socket_setrbuf; pvt->pub.setnonblock = &rtpp_socket_setnonblock; pvt->pub.settimestamp = &rtpp_socket_settimestamp; #if 0 pvt->pub.send_pkt = &rtpp_socket_send_pkt; #endif pvt->pub.send_pkt_na = &rtpp_socket_send_pkt_na; pvt->pub.rtp_recv = &rtpp_socket_rtp_recv_simple; pvt->pub.getfd = &rtpp_socket_getfd; CALL_SMETHOD(pvt->pub.rcnt, attach, (rtpp_refcnt_dtor_t)&rtpp_socket_dtor, pvt); return (&pvt->pub); e1: CALL_SMETHOD(pvt->pub.rcnt, decref); free(pvt); e0: return (NULL); }
void rtpp_netaddr_fintest() { int naborts_s; struct { struct rtpp_netaddr pub; } *tp; naborts_s = _naborts; tp = rtpp_rzmalloc(sizeof(*tp), offsetof(typeof(*tp), pub.rcnt)); assert(tp != NULL); assert(tp->pub.rcnt != NULL); static const struct rtpp_netaddr_smethods dummy = { .cmp = (rtpp_netaddr_cmp_t)((void *)0x1), .cmphost = (rtpp_netaddr_cmphost_t)((void *)0x1), .copy = (rtpp_netaddr_copy_t)((void *)0x1), .get = (rtpp_netaddr_get_t)((void *)0x1), .isaddrseq = (rtpp_netaddr_isaddrseq_t)((void *)0x1), .isempty = (rtpp_netaddr_isempty_t)((void *)0x1), .set = (rtpp_netaddr_set_t)((void *)0x1), .sip_print = (rtpp_netaddr_sip_print_t)((void *)0x1), }; tp->pub.smethods = &dummy; CALL_SMETHOD(tp->pub.rcnt, attach, (rtpp_refcnt_dtor_t)&rtpp_netaddr_fin, &tp->pub); CALL_SMETHOD(tp->pub.rcnt, decref); CALL_TFIN(&tp->pub, cmp); CALL_TFIN(&tp->pub, cmphost); CALL_TFIN(&tp->pub, copy); CALL_TFIN(&tp->pub, get); CALL_TFIN(&tp->pub, isaddrseq); CALL_TFIN(&tp->pub, isempty); CALL_TFIN(&tp->pub, set); CALL_TFIN(&tp->pub, sip_print); assert((_naborts - naborts_s) == 8); } const static void *_rtpp_netaddr_ftp = (void *)&rtpp_netaddr_fintest; DATA_SET(rtpp_fintests, _rtpp_netaddr_ftp);
static void rtp_analyze_jt_destroy(struct rtp_analyze_jitter *jp) { struct rtp_analyze_jdata *jdp, *jdp_next; for (jdp = jp->first; jdp != NULL; jdp = jdp_next) { jdp_next = jdp->next; CALL_SMETHOD(jdp->ts_dedup->rcnt, decref); free(jdp); jp->jdlen -= 1; } RTPP_DBG_ASSERT(jp->jdlen == 0); free(jp); }
struct rtpp_wi * rtpp_wi_malloc_pkt_na(int sock, struct rtp_packet *pkt, struct rtpp_netaddr *sendto, int nsend, struct rtpp_refcnt *sock_rcnt) { struct rtpp_wi *wi; wi = pkt->wi; wi->free_ptr = (struct rtpp_wi *)pkt; wi->wi_type = RTPP_WI_TYPE_OPKT; wi->sock = sock; if (sock_rcnt != NULL) { CALL_SMETHOD(sock_rcnt, incref); } wi->sock_rcnt = sock_rcnt; wi->flags = 0; wi->msg = pkt->data.buf; wi->msg_len = pkt->size; wi->sendto = sstosa(&pkt->sendto); wi->tolen = CALL_SMETHOD(sendto, get, wi->sendto, sizeof(pkt->raddr)); wi->nsend = nsend; return (wi); }
void rtpp_netio_async_destroy(struct rtpp_anetio_cf *netio_cf) { int i; for (i = 0; i < SEND_THREADS; i++) { rtpp_queue_put_item(netio_cf->args[i].sigterm, netio_cf->args[i].out_q); } for (i = 0; i < SEND_THREADS; i++) { pthread_join(netio_cf->thread_id[i], NULL); rtpp_queue_destroy(netio_cf->args[i].out_q); CALL_SMETHOD(netio_cf->args[i].glog->rcnt, decref); } free(netio_cf); }
struct rtpp_log * rtpp_log_ctor(struct rtpp_cfg_stable *cfs, const char *app, const char *call_id, int flags) { struct rtpp_log_priv *pvt; struct rtpp_refcnt *rcnt; pvt = rtpp_rzmalloc(sizeof(struct rtpp_log_priv), &rcnt); if (pvt == NULL) { return (NULL); } pvt->pub.rcnt = rcnt; pvt->log = rtpp_log_open(cfs, app, call_id, flags); rtpp_gen_uid(&pvt->pub.lguid); pvt->pub.setlevel = &rtpp_log_obj_setlevel; pvt->pub.write = rtpp_log_obj_write; pvt->pub.ewrite = rtpp_log_obj_ewrite; CALL_SMETHOD(pvt->pub.rcnt, attach, (rtpp_refcnt_dtor_t)&rtpp_log_obj_dtor, pvt); return (&pvt->pub); }
int rtpp_anetio_sendto(struct rtpp_anetio_cf *netio_cf, int sock, const void *msg, \ size_t msg_len, int flags, const struct sockaddr *sendto, socklen_t tolen) { struct rtpp_wi *wi; wi = rtpp_wi_malloc(sock, msg, msg_len, flags, sendto, tolen); if (wi == NULL) { return (-1); } #if RTPP_DEBUG_netio >= 1 wi->debug = 1; wi->log = netio_cf->args[0].glog; CALL_SMETHOD(wi->log->rcnt, incref); #if RTPP_DEBUG_netio >= 2 RTPP_LOG(netio_cf->args[0].glog, RTPP_LOG_DBUG, "malloc(%d, %p, %d, %d, %p, %d) = %p", sock, msg, msg_len, flags, sendto, tolen, wi); RTPP_LOG(netio_cf->args[0].glog, RTPP_LOG_DBUG, "sendto(%d, %p, %d, %d, %p, %d)", wi->sock, wi->msg, wi->msg_len, wi->flags, wi->sendto, wi->tolen); #endif #endif rtpp_queue_put_item(wi, netio_cf->args[0].out_q); return (0); }
struct rtpp_wi * rtpp_wi_malloc_pkt(int sock, struct rtp_packet *pkt, const struct sockaddr *sendto, size_t tolen, int nsend, struct rtpp_refcnt *sock_rcnt) { struct rtpp_wi *wi; wi = pkt->wi; wi->free_ptr = (struct rtpp_wi *)pkt; wi->wi_type = RTPP_WI_TYPE_OPKT; wi->sock = sock; if (sock_rcnt != NULL) { CALL_SMETHOD(sock_rcnt, incref); } wi->sock_rcnt = sock_rcnt; wi->flags = 0; wi->msg = pkt->data.buf; wi->msg_len = pkt->size; wi->sendto = sstosa(&pkt->sendto); wi->tolen = tolen; memcpy(wi->sendto, sendto, tolen); wi->nsend = nsend; return (wi); }
int rtpp_anetio_send_pkt_na(struct sthread_args *sender, int sock, \ struct rtpp_netaddr *sendto, struct rtp_packet *pkt, struct rtpp_refcnt *sock_rcnt, struct rtpp_log *plog) { struct rtpp_wi *wi; int nsend; if (sender->dmode != 0 && pkt->size < LBR_THRS) { nsend = 2; } else { nsend = 1; } wi = rtpp_wi_malloc_pkt_na(sock, pkt, sendto, nsend, sock_rcnt); if (wi == NULL) { rtp_packet_free(pkt); return (-1); } /* * rtpp_wi_malloc_pkt() consumes pkt and returns wi, so no need to * call rtp_packet_free() here. */ #if RTPP_DEBUG_netio >= 2 wi->debug = 1; if (plog == NULL) { plog = sender->glog; } CALL_SMETHOD(plog->rcnt, incref); wi->log = plog; RTPP_LOG(plog, RTPP_LOG_DBUG, "send_pkt(%d, %p, %d, %d, %p, %d)", wi->sock, wi->msg, wi->msg_len, wi->flags, wi->sendto, wi->tolen); #endif rtpp_queue_put_item(wi, sender->out_q); return (0); }
static int process_rtp_servers_foreach(void *dp, void *ap) { struct foreach_args *fap; struct rtpp_server *rsrv; struct rtp_packet *pkt; int len; struct rtpp_stream *rsop; fap = (struct foreach_args *)ap; /* * This method does not need us to bump ref, since we are in the * locked context of the rtpp_hash_table, which holds its own ref. */ rsrv = (struct rtpp_server *)dp; rsop = CALL_METHOD(fap->rtp_streams_wrt, get_by_idx, rsrv->stuid); if (rsop == NULL) { return (RTPP_WR_MATCH_CONT); } for (;;) { pkt = CALL_SMETHOD(rsrv, get, fap->dtime, &len); if (pkt == NULL) { if (len == RTPS_EOF) { CALL_SMETHOD(rsop, finish_playback, rsrv->sruid); CALL_SMETHOD(rsop->rcnt, decref); return (RTPP_WR_MATCH_DEL); } else if (len != RTPS_LATER) { /* XXX some error, brag to logs */ } break; } if (CALL_SMETHOD(rsop, issendable) == 0) { /* We have a packet, but nowhere to send it, drop */ rtp_packet_free(pkt); continue; } CALL_SMETHOD(rsop, send_pkt, fap->sender, pkt); fap->rsp->npkts_played.cnt++; } CALL_SMETHOD(rsop->rcnt, decref); return (RTPP_WR_MATCH_CONT); }
static int parse_modules(struct rtpp_cfg_stable *csp, const ucl_object_t *wop) { ucl_object_iter_t it_conf; const ucl_object_t *obj_file; const char *cf_key; const ucl_object_t *obj_key; int ecode, success; void *confp; const conf_helper_map *fent, *map; struct rtpp_module_conf *mcp; char mpath[PATH_MAX + 1]; const char *cp, *mp; struct rtpp_module_if *mif; it_conf = ucl_object_iterate_new(wop); if (it_conf == NULL) return (-1); ecode = 0; while ((obj_file = ucl_object_iterate_safe(it_conf, true)) != NULL) { cf_key = ucl_object_key(obj_file); RTPP_LOG(csp->glog, RTPP_LOG_DBUG, "\tmodule: %s", cf_key); obj_key = ucl_object_find_key(obj_file, "load"); if (obj_key == NULL) { cp = rtpp_module_dsop_canonic(cf_key, mpath, sizeof(mpath)); if (cp == NULL) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "Error: Unable to find load parameter in module: %s", cf_key); ecode = -1; goto e0; } } else { if (obj_key->type != UCL_STRING) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "Error: \"load\" parameter in %s has a wrong type, string is expected", cf_key); ecode = -1; goto e0; } mp = ucl_object_tostring(obj_key); cp = realpath(mp, mpath); if (cp == NULL) { RTPP_ELOG(csp->glog, RTPP_LOG_ERR, "realpath() failed: %s", mp); ecode = -1; goto e0; } } mif = rtpp_module_if_ctor(cp); if (mif == NULL) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "dymanic module constructor has failed: %s", cp); ecode = -1; goto e0; } if (CALL_METHOD(mif, load, csp, csp->glog) != 0) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "%p->load() method has failed: %s", mif, cp); goto e1; } if (CALL_METHOD(mif, get_mconf, &mcp) < 0) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "%p->get_mconf() method has failed: %s", mif, cp); goto e1; } fent = NULL; if (mcp != NULL) { map = mcp->conf_map; confp = mcp->conf_data; } else { map = default_module_map; confp = NULL; } success = conf_helper_mapper(csp->glog, obj_file, map, confp, &fent); if (!success) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "Config parsing issue in section %s", cf_key); if (fent != NULL && fent->conf_key != NULL) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "\tparameter %s", fent->conf_key); } goto e1; } if (CALL_METHOD(mif, config) < 0) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "%p->config() method has failed: %s", mif, cp); goto e1; } rtpp_list_append(csp->modules_cf, mif); continue; e1: ecode = -1; CALL_SMETHOD(mif->rcnt, decref); goto e0; } e0: if (ucl_object_iter_chk_excpn(it_conf)) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "UCL has failed with an internal error"); ecode = -1; } ucl_object_iterate_free(it_conf); return (ecode); }
static int fill_cmd_props(struct cfg *cf, struct rtpp_command *cmd, struct cmd_props *cpp) { cpp->has_call_id = 1; cpp->fpos = -1; cpp->tpos = -1; cpp->cmods = &(cmd->argv[0][1]); switch (cmd->argv[0][0]) { case 'u': case 'U': cmd->cca.op = UPDATE; cmd->cca.rname = "update/create"; cmd->cca.hint = "U[opts] callid remote_ip remote_port from_tag [to_tag] [notify_socket notify_tag]"; cpp->max_argc = 8; cpp->min_argc = 5; cpp->has_cmods = 1; cpp->fpos = 4; cpp->tpos = 5; break; case 'l': case 'L': cmd->cca.op = LOOKUP; cmd->cca.rname = "lookup"; cmd->cca.hint = "L[opts] callid remote_ip remote_port from_tag [to_tag]"; cpp->max_argc = 6; cpp->min_argc = 5; cpp->has_cmods = 1; cpp->fpos = 4; cpp->tpos = 5; break; case 'd': case 'D': cmd->cca.op = DELETE; cmd->cca.rname = "delete"; cmd->cca.hint = "D[w] callid from_tag [to_tag]"; cpp->max_argc = 4; cpp->min_argc = 3; cpp->has_cmods = 1; cpp->fpos = 2; cpp->tpos = 3; break; case 'p': case 'P': cmd->cca.op = PLAY; cmd->cca.rname = "play"; cmd->cca.hint = "P[n] callid pname codecs from_tag [to_tag]"; cpp->max_argc = 6; cpp->min_argc = 5; cpp->has_cmods = 1; cpp->fpos = 4; cpp->tpos = 5; break; case 'r': case 'R': cmd->cca.op = RECORD; cmd->cca.rname = "record"; if (cf->stable->record_pcap != 0) { cmd->cca.hint = "R[s] call_id from_tag [to_tag]"; } else { cmd->cca.hint = "R call_id from_tag [to_tag]"; } cpp->max_argc = 4; cpp->min_argc = 3; cpp->has_cmods = 1; cpp->fpos = 2; cpp->tpos = 3; break; case 'c': case 'C': cmd->cca.op = COPY; cmd->cca.rname = "copy"; cmd->cca.hint = "C[-xxx-] call_id -XXX- from_tag [to_tag]"; cpp->max_argc = 5; cpp->min_argc = 4; cpp->has_cmods = 1; cpp->fpos = 3; cpp->tpos = 4; break; case 's': case 'S': cmd->cca.op = NOPLAY; cmd->cca.rname = "noplay"; cmd->cca.hint = "S call_id from_tag [to_tag]"; cpp->max_argc = 4; cpp->min_argc = 3; cpp->has_cmods = 0; cpp->fpos = 2; cpp->tpos = 3; break; case 'v': case 'V': if (cpp->cmods[0] == 'F' || cpp->cmods[0] == 'f') { cpp->cmods += 1; cmd->cca.op = VER_FEATURE; cmd->cca.rname = "feature_check"; cmd->cca.hint = "VF feature_num"; cmd->no_glock = 1; cpp->max_argc = 2; cpp->min_argc = 2; cpp->has_cmods = 0; cpp->has_call_id = 0; break; } cmd->cca.op = GET_VER; cmd->cca.rname = "get_version"; cmd->cca.hint = "V"; cmd->no_glock = 1; cpp->max_argc = 1; cpp->min_argc = 1; cpp->has_cmods = 0; cpp->has_call_id = 0; break; case 'i': case 'I': cmd->cca.op = INFO; cmd->cca.rname = "get_info"; cmd->cca.hint = "I[b]"; cpp->max_argc = 1; cpp->min_argc = 1; cpp->has_cmods = 1; cpp->has_call_id = 0; break; case 'q': case 'Q': cmd->cca.op = QUERY; cmd->cca.rname = "query"; cmd->cca.hint = "Q[v] call_id from_tag [to_tag [stat_name1 ...[stat_nameN]]]"; cpp->max_argc = 4 + RTPP_QUERY_NSTATS; cpp->min_argc = 3; cpp->has_cmods = 1; cpp->fpos = 2; cpp->tpos = 3; break; case 'x': case 'X': cmd->cca.op = DELETE_ALL; cmd->cca.rname = "delete_all"; cmd->cca.hint = "X"; cpp->max_argc = 1; cpp->min_argc = 1; cpp->has_cmods = 0; cpp->has_call_id = 0; break; case 'g': case 'G': cmd->cca.op = GET_STATS; cmd->cca.rname = "get_stats"; cmd->cca.hint = "G[v] [stat_name1 [stat_name2 [stat_name3 ...[stat_nameN]]]]"; cmd->no_glock = 1; cpp->max_argc = CALL_SMETHOD(cf->stable->rtpp_stats, getnstats) + 1; cpp->min_argc = 1; cpp->has_cmods = 1; cpp->has_call_id = 0; break; default: return (-1); } return (0); }
struct rtpp_anetio_cf * rtpp_netio_async_init(struct cfg *cf, int qlen) { struct rtpp_anetio_cf *netio_cf; int i, ri; netio_cf = rtpp_zmalloc(sizeof(*netio_cf)); if (netio_cf == NULL) return (NULL); for (i = 0; i < SEND_THREADS; i++) { netio_cf->args[i].out_q = rtpp_queue_init(qlen, "RTPP->NET%.2d", i); if (netio_cf->args[i].out_q == NULL) { for (ri = i - 1; ri >= 0; ri--) { rtpp_queue_destroy(netio_cf->args[ri].out_q); CALL_SMETHOD(netio_cf->args[ri].glog->rcnt, decref); } goto e0; } CALL_SMETHOD(cf->stable->glog->rcnt, incref); netio_cf->args[i].glog = cf->stable->glog; netio_cf->args[i].dmode = cf->stable->dmode; #if RTPP_DEBUG_timers recfilter_init(&netio_cf->args[i].average_load, 0.9, 0.0, 0); #endif } for (i = 0; i < SEND_THREADS; i++) { netio_cf->args[i].sigterm = rtpp_wi_malloc_sgnl(SIGTERM, NULL, 0); if (netio_cf->args[i].sigterm == NULL) { for (ri = i - 1; ri >= 0; ri--) { rtpp_wi_free(netio_cf->args[ri].sigterm); } goto e1; } } cf->stable->rtpp_netio_cf = netio_cf; for (i = 0; i < SEND_THREADS; i++) { if (pthread_create(&(netio_cf->thread_id[i]), NULL, (void *(*)(void *))&rtpp_anetio_sthread, &netio_cf->args[i]) != 0) { for (ri = i - 1; ri >= 0; ri--) { rtpp_queue_put_item(netio_cf->args[ri].sigterm, netio_cf->args[ri].out_q); pthread_join(netio_cf->thread_id[ri], NULL); } for (ri = i; ri < SEND_THREADS; ri++) { rtpp_wi_free(netio_cf->args[ri].sigterm); } goto e1; } } return (netio_cf); #if 0 e2: for (i = 0; i < SEND_THREADS; i++) { rtpp_wi_free(netio_cf->args[i].sigterm); } #endif e1: for (i = 0; i < SEND_THREADS; i++) { rtpp_queue_destroy(netio_cf->args[i].out_q); CALL_SMETHOD(netio_cf->args[i].glog->rcnt, decref); } e0: free(netio_cf); return (NULL); }