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(); }
static void control_ng_incoming(struct obj *obj, str *buf, const endpoint_t *sin, char *addr, struct udp_listener *ul) { struct control_ng *c = (void *) obj; bencode_buffer_t bencbuf; bencode_item_t *dict, *resp; str cmd, cookie, data, reply, *to_send, callid; const char *errstr; struct iovec iov[3]; unsigned int iovlen; GString *log_str; struct control_ng_stats* cur = get_control_ng_stats(c,&sin->address); str_chr_str(&data, buf, ' '); if (!data.s || data.s == buf->s) { ilog(LOG_WARNING, "Received invalid data on NG port (no cookie) from %s: "STR_FORMAT, addr, STR_FMT(buf)); return; } bencode_buffer_init(&bencbuf); resp = bencode_dictionary(&bencbuf); cookie = *buf; cookie.len -= data.len; *data.s++ = '\0'; data.len--; errstr = "Invalid data (no payload)"; if (data.len <= 0) goto err_send; to_send = cookie_cache_lookup(&c->cookie_cache, &cookie); if (to_send) { ilog(LOG_INFO, "Detected command from %s as a duplicate", addr); resp = NULL; goto send_only; } dict = bencode_decode_expect_str(&bencbuf, &data, BENCODE_DICTIONARY); errstr = "Could not decode dictionary"; if (!dict) goto err_send; bencode_dictionary_get_str(dict, "command", &cmd); errstr = "Dictionary contains no key \"command\""; if (!cmd.s) goto err_send; bencode_dictionary_get_str(dict, "call-id", &callid); log_info_str(&callid); ilog(LOG_INFO, "Received command '"STR_FORMAT"' from %s", STR_FMT(&cmd), addr); if (get_log_level() >= LOG_DEBUG) { log_str = g_string_sized_new(256); g_string_append_printf(log_str, "Dump for '"STR_FORMAT"' from %s: ", STR_FMT(&cmd), addr); pretty_print(dict, log_str); ilog(LOG_DEBUG, "%.*s", (int) log_str->len, log_str->str); g_string_free(log_str, TRUE); } errstr = NULL; if (!str_cmp(&cmd, "ping")) { bencode_dictionary_add_string(resp, "result", "pong"); g_atomic_int_inc(&cur->ping); } else if (!str_cmp(&cmd, "offer")) { errstr = call_offer_ng(dict, c->callmaster, resp, addr, sin); g_atomic_int_inc(&cur->offer); } else if (!str_cmp(&cmd, "answer")) { errstr = call_answer_ng(dict, c->callmaster, resp); g_atomic_int_inc(&cur->answer); } else if (!str_cmp(&cmd, "delete")) { errstr = call_delete_ng(dict, c->callmaster, resp); g_atomic_int_inc(&cur->delete); }