static void send_timer_run(void *ptr) { struct send_timer *st = ptr; struct call *call = st->call; log_info_call(call); ilog(LOG_DEBUG, "running scheduled send_timer"); struct timeval next_send = {0,}; rwlock_lock_r(&call->master_lock); mutex_lock(&st->lock); while (st->packets.length) { struct codec_packet *cp = st->packets.head->data; // XXX this could be made lock-free if (!send_timer_send(st, cp)) { g_queue_pop_head(&st->packets); continue; } // couldn't send the last one. remember time to schedule next_send = cp->to_send; break; } mutex_unlock(&st->lock); rwlock_unlock_r(&call->master_lock); if (next_send.tv_sec) timerthread_obj_schedule_abs(&st->tt_obj, &next_send); log_info_clear(); }
void ice_thread_run(void *p) { struct ice_agent *ag; struct call *call; long long sleeptime; struct timeval tv; mutex_lock(&ice_agents_timers_lock); while (!g_shutdown) { gettimeofday(&g_now, NULL); /* lock our list and get the first element */ ag = g_tree_find_first(ice_agents_timers, NULL, NULL); /* scheduled to run? if not, we just go to sleep, otherwise we remove it from the tree, * steal the reference and run it */ if (!ag) goto sleep; if (timeval_cmp(&g_now, &ag->next_check) < 0) goto sleep; g_tree_remove(ice_agents_timers, ag); ZERO(ag->next_check); ag->last_run = g_now; mutex_unlock(&ice_agents_timers_lock); /* this agent is scheduled to run right now */ /* lock the call */ call = ag->call; log_info_ice_agent(ag); rwlock_lock_r(&call->master_lock); /* and run our checks */ __do_ice_checks(ag); /* finally, release our reference and start over */ log_info_clear(); rwlock_unlock_r(&call->master_lock); obj_put(ag); mutex_lock(&ice_agents_timers_lock); continue; sleep: /* figure out how long we should sleep */ sleeptime = ag ? timeval_diff(&ag->next_check, &g_now) : 100000; sleeptime = MIN(100000, sleeptime); /* 100 ms at the most */ tv = g_now; timeval_add_usec(&tv, sleeptime); cond_timedwait(&ice_agents_timers_cond, &ice_agents_timers_lock, &tv); continue; } mutex_unlock(&ice_agents_timers_lock); }
static int control_stream_parse(struct control_stream *s, char *line) { int ovec[60]; int ret; char **out; struct control_tcp *c = s->control; str *output = NULL; ret = pcre_exec(c->parse_re, c->parse_ree, line, strlen(line), 0, 0, ovec, G_N_ELEMENTS(ovec)); if (ret <= 0) { ilog(LOG_WARNING, "Unable to parse command line from " DF ": %s", DP(s->inaddr), line); return -1; } ilog(LOG_INFO, "Got valid command from " DF ": %s", DP(s->inaddr), line); pcre_get_substring_list(line, ovec, ret, (const char ***) &out); if (out[RE_TCP_RL_CALLID]) log_info_c_string(out[RE_TCP_RL_CALLID]); else if (out[RE_TCP_D_CALLID]) log_info_c_string(out[RE_TCP_D_CALLID]); if (!strcmp(out[RE_TCP_RL_CMD], "request")) output = call_request_tcp(out, c->callmaster); else if (!strcmp(out[RE_TCP_RL_CMD], "lookup")) output = call_lookup_tcp(out, c->callmaster); else if (!strcmp(out[RE_TCP_D_CMD], "delete")) call_delete_tcp(out, c->callmaster); else if (!strcmp(out[RE_TCP_DIV_CMD], "status")) calls_status_tcp(c->callmaster, s); else if (!strcmp(out[RE_TCP_DIV_CMD], "build") | !strcmp(out[RE_TCP_DIV_CMD], "version")) control_stream_printf(s, "Version: %s\n", RTPENGINE_VERSION); else if (!strcmp(out[RE_TCP_DIV_CMD], "controls")) control_list(c, s); else if (!strcmp(out[RE_TCP_DIV_CMD], "quit") || !strcmp(out[RE_TCP_DIV_CMD], "exit")) ; if (output) { mutex_lock(&s->lock); streambuf_write_str(s->outbuf, output); mutex_unlock(&s->lock); free(output); } pcre_free(out); log_info_clear(); return -1; }
static void media_player_run(void *ptr) { struct media_player *mp = ptr; struct call *call = mp->call; log_info_call(call); ilog(LOG_DEBUG, "running scheduled media_player"); rwlock_lock_r(&call->master_lock); mutex_lock(&mp->lock); media_player_read_packet(mp); mutex_unlock(&mp->lock); rwlock_unlock_r(&call->master_lock); log_info_clear(); }
static void control_udp_incoming(struct obj *obj, str *buf, const endpoint_t *sin, char *addr, struct udp_listener *ul) { struct control_udp *u = (void *) obj; int ret; int ovec[100]; char **out; struct iovec iov[10]; unsigned int iovlen; str cookie, *reply; ret = pcre_exec(u->parse_re, u->parse_ree, buf->s, buf->len, 0, 0, ovec, G_N_ELEMENTS(ovec)); if (ret <= 0) { ret = pcre_exec(u->fallback_re, NULL, buf->s, buf->len, 0, 0, ovec, G_N_ELEMENTS(ovec)); if (ret <= 0) { ilog(LOG_WARNING, "Unable to parse command line from udp:%s: %.*s", addr, STR_FMT(buf)); return; } ilog(LOG_WARNING, "Failed to properly parse UDP command line '%.*s' from %s, using fallback RE", STR_FMT(buf), addr); pcre_get_substring_list(buf->s, ovec, ret, (const char ***) &out); iov[0].iov_base = (void *) out[RE_UDP_COOKIE]; iov[0].iov_len = strlen(out[RE_UDP_COOKIE]); if (out[RE_UDP_UL_CMD] && (chrtoupper(out[RE_UDP_UL_CMD][0]) == 'U' || chrtoupper(out[RE_UDP_UL_CMD][0]) == 'L')) { iov[1].iov_base = (void *) out[4]; iov[1].iov_len = strlen(out[4]); iov[2].iov_base = (void *) out[3]; iov[2].iov_len = strlen(out[3]); iov[3].iov_base = "\n"; iov[3].iov_len = 1; iovlen = 4; } else { iov[1].iov_base = " E8\n"; iov[1].iov_len = 4; iovlen = 2; } socket_sendiov(&ul->sock, iov, iovlen, sin); pcre_free(out); return; } ilog(LOG_INFO, "Got valid command from udp:%s: %.*s", addr, STR_FMT(buf)); pcre_get_substring_list(buf->s, ovec, ret, (const char ***) &out); str_init(&cookie, (void *) out[RE_UDP_COOKIE]); reply = cookie_cache_lookup(&u->cookie_cache, &cookie); if (reply) { ilog(LOG_INFO, "Detected command from udp:%s as a duplicate", addr); socket_sendto(&ul->sock, reply->s, reply->len, sin); free(reply); goto out; } if (out[RE_UDP_UL_CALLID]) log_info_c_string(out[RE_UDP_UL_CALLID]); else if (out[RE_UDP_DQ_CALLID]) log_info_c_string(out[RE_UDP_DQ_CALLID]); if (chrtoupper(out[RE_UDP_UL_CMD][0]) == 'U') reply = call_update_udp(out, u->callmaster, addr, sin); else if (chrtoupper(out[RE_UDP_UL_CMD][0]) == 'L') reply = call_lookup_udp(out, u->callmaster); else if (chrtoupper(out[RE_UDP_DQ_CMD][0]) == 'D') reply = call_delete_udp(out, u->callmaster); else if (chrtoupper(out[RE_UDP_DQ_CMD][0]) == 'Q') reply = call_query_udp(out, u->callmaster); else if (chrtoupper(out[RE_UDP_V_CMD][0]) == 'V') { iovlen = 2; iov[0].iov_base = (void *) out[RE_UDP_COOKIE]; iov[0].iov_len = strlen(out[RE_UDP_COOKIE]); iov[1].iov_base = " "; iov[1].iov_len = 1; if (chrtoupper(out[RE_UDP_V_FLAGS][0]) == 'F') { ret = 0; if (!strcmp(out[RE_UDP_V_PARMS], "20040107")) ret = 1; else if (!strcmp(out[RE_UDP_V_PARMS], "20050322")) ret = 1; else if (!strcmp(out[RE_UDP_V_PARMS], "20060704")) ret = 1; iov[2].iov_base = ret ? "1\n" : "0\n"; iov[2].iov_len = 2; iovlen++; } else { iov[2].iov_base = "20040107\n"; iov[2].iov_len = 9; iovlen++; } socket_sendiov(&ul->sock, iov, iovlen, sin); } if (reply) { socket_sendto(&ul->sock, reply->s, reply->len, sin); cookie_cache_insert(&u->cookie_cache, &cookie, reply); free(reply); } else cookie_cache_remove(&u->cookie_cache, &cookie); out: pcre_free(out); log_info_clear(); }