static struct tcp_sock *tcp_listen_child_sock(struct tcp_sock *tsk, struct tcp_segment *seg) { struct sock *newsk = tcp_alloc_sock(tsk->sk.protocol); struct tcp_sock *newtsk = tcpsk(newsk); tcp_set_state(newtsk, TCP_SYN_RECV); newsk->sk_saddr = seg->iphdr->ip_dst; newsk->sk_daddr = seg->iphdr->ip_src; newsk->sk_sport = seg->tcphdr->dst; newsk->sk_dport = seg->tcphdr->src; /* add to establish hash table for third ACK */ if (tcp_hash(&newtsk->sk) < 0) { free(newsk); return NULL; } /* * Why to get parent reference? * To avoid parent accidental release. * e.g: Parent is interrupted by user * when child is pending in three-way handshake. */ newtsk->parent = get_tcp_sock(tsk); /* FIXME: add limit to listen queue */ list_add(&newtsk->list, &tsk->listen_queue); /* reference for being listed into parent queue */ return get_tcp_sock(newtsk); }
static void *bridge_channel_media(void *channel_data) { unsigned char readframe[MEDIA_BUFFER_SIZE]; unsigned char writeframe[MEDIA_BUFFER_SIZE]; char trace_file_name[255]; char *trace_prefix = NULL; wanpipe_tdm_api_t tdm_api; sbridge_chan_t *chan = channel_data; sangoma_pri_t *spri = &chan->span->spri; int32_t channo = chan->channo; memset(readframe, 0, sizeof(readframe)); memset(writeframe, 0, sizeof(writeframe)); /* need to disable cancellation while registering the cleanup handler * if we get cancelled before registering, no harm done * once the cleanup handler gets registered, it does not matter * at which point of this thread we get cancelled, the cleanup routine * will take care of closing sockets or any other resource we eventually allocate * */ if (!sbridge_thread_setcancelstate(SBRIDGE_THREAD_CANCEL_DISABLE, NULL)) { sbridge_log(SBRIDGE_LOG_ERROR, "Failed to disable thread cancellation in chanel %d\n", channo); sbridge_thread_exit(NULL); } if (!sbridge_thread_setcanceltype(SBRIDGE_THREAD_CANCEL_DEFERRED, NULL)) { sbridge_log(SBRIDGE_LOG_ERROR, "Failed to set deferred cancel type in chanel %d\n", channo); sbridge_thread_exit(NULL); } /* just grab the lock to start once the thread that launched us is done using the channel * channel manipulations in this routine do not require the channel lock because the signaling * thread does not access the channel once the media thread is launched * */ sbridge_mutex_lock(&chan->lock); chan->running = SBRIDGE_TRUE; sbridge_mutex_unlock(&chan->lock); /* register the cleanup handler */ sbridge_thread_cleanup_push(clean_thread_data, chan); /* restore the cancellation state */ sbridge_thread_setcancelstate(SBRIDGE_THREAD_CANCEL_ENABLE, NULL); /* open sangoma media channel */ if ((chan->sangoma_sock = sangoma_open_tdmapi_span_chan(spri->span, channo)) < 0) { sbridge_log(SBRIDGE_LOG_ERROR, "Failed to open TDM API descriptor for sangoma channel %d\n", channo); sbridge_thread_exit(NULL); } if (!get_tcp_sock(chan)) { sbridge_log(SBRIDGE_LOG_ERROR, "Failed to get TCP socket for channel %d\n", channo); sbridge_thread_exit(NULL); } /* open the traces */ trace_prefix = chan->span->config->trace_prefix; if (strlen(trace_prefix)) { CHAN_MEDIA_TRACE_OPEN(trace_raw_in); CHAN_MEDIA_TRACE_OPEN(trace_raw_out); } /* set the channel read period */ if (sangoma_tdm_set_usr_period(chan->sangoma_sock, &tdm_api, SBRIDGE_MEDIA_PERIOD) < 0) { sbridge_log(SBRIDGE_LOG_ERROR, "Failed to set sangoma channel read period to %d\n", SBRIDGE_MEDIA_PERIOD); sbridge_thread_exit(NULL); } /* everything will be passed thru as received, WP_NONE */ if ((sangoma_tdm_set_codec(chan->sangoma_sock, &tdm_api, WP_NONE)) < 0) { sbridge_log(SBRIDGE_LOG_ERROR, "Failed to set native driver codec for sangoma channel %d\n", channo); sbridge_thread_exit(NULL); } chan->mtu = sangoma_tdm_get_usr_mtu_mru(chan->sangoma_sock, &tdm_api); if (chan->mtu != SBRIDGE_ALAW_MTU) { sbridge_log(SBRIDGE_LOG_ERROR, "Unexpected MTU of size %d, cannot handle media\n", chan->mtu); sbridge_thread_exit(NULL); } sbridge_log(SBRIDGE_LOG_NOTICE, "Sangoma socket MTU is %d\n", chan->mtu); /* run the proper application depending on the chan mode */ chan->app_func(chan); /* done, let's clean up our mess and notify the signaling thread */ sbridge_log(SBRIDGE_LOG_NOTICE, "Media thread for channel %d completed application execution\n", channo); if (!sbridge_thread_setcancelstate(SBRIDGE_THREAD_CANCEL_DISABLE, NULL)) { sbridge_log(SBRIDGE_LOG_ERROR, "Failed to disable thread cancellation when terminating media thread for channel %d\n", channo); sbridge_thread_exit(NULL); } /* this calls the cleanup handler to free resources */ sbridge_thread_cleanup_pop(SBRIDGE_THREAD_CLEANUP_EXECUTE); sbridge_thread_exit(NULL); return NULL; }