static int sca_bind_srdb1( sca_mod *scam, db_func_t *db_api ) { db1_con_t *db_con = NULL; int rc = -1; if ( db_bind_mod( scam->cfg->db_url, db_api ) != 0 ) { LM_ERR( "Failed to initialize required DB API - %.*s\n", STR_FMT( scam->cfg->db_url)); goto done; } scam->db_api = db_api; if ( !DB_CAPABILITY( (*db_api), DB_CAP_ALL )) { LM_ERR( "Selected database %.*s lacks required capabilities\n", STR_FMT( scam->cfg->db_url )); goto done; } /* ensure database exists and table schemas are correct */ db_con = db_api->init( scam->cfg->db_url ); if ( db_con == NULL ) { LM_ERR( "sca_bind_srdb1: failed to connect to DB %.*s\n", STR_FMT( scam->cfg->db_url )); goto done; } if ( db_check_table_version( db_api, db_con, scam->cfg->subs_table, SCA_DB_SUBSCRIPTIONS_TABLE_VERSION ) < 0 ) { LM_ERR( "Version check of %.*s table in DB %.*s failed\n", STR_FMT( scam->cfg->subs_table ), STR_FMT( scam->cfg->db_url )); LM_ERR( "%.*s table version %d required\n", STR_FMT( scam->cfg->subs_table ), SCA_DB_SUBSCRIPTIONS_TABLE_VERSION ); goto done; } /* DB and tables are OK, close DB handle. reopen in each child. */ rc = 0; done: if ( db_con != NULL ) { db_api->close( db_con ); db_con = NULL; } return( rc ); }
str *call_query_udp(char **out, struct callmaster *m) { struct call *c; str *ret, callid, fromtag, totag; struct call_stats stats; __C_DBG("got query for callid '%s'", out[RE_UDP_DQ_CALLID]); str_init(&callid, out[RE_UDP_DQ_CALLID]); str_init(&fromtag, out[RE_UDP_DQ_FROMTAG]); str_init(&totag, out[RE_UDP_DQ_TOTAG]); c = call_get_opmode(&callid, m, OP_OTHER); if (!c) { ilog(LOG_INFO, "["STR_FORMAT"] Call-ID to query not found", STR_FMT(&callid)); goto err; } ng_call_stats(c, &fromtag, &totag, NULL, &stats); rwlock_unlock_w(&c->master_lock); ret = str_sprintf("%s %lld "UINT64F" "UINT64F" "UINT64F" "UINT64F"\n", out[RE_UDP_COOKIE], (long long int) m->conf.silent_timeout - (poller_now - stats.last_packet), stats.totals[0].packets, stats.totals[1].packets, stats.totals[2].packets, stats.totals[3].packets); goto out; err: if (c) rwlock_unlock_w(&c->master_lock); ret = str_sprintf("%s E8\n", out[RE_UDP_COOKIE]); goto out; out: if (c) obj_put(c); return ret; }
/** * @brief pings the servers in the nodelist * * if the server does not reply to the ping, it is removed from the list * the ping messages are actualy notification requests * this way the ping will have two uses: * - checks if the servers in the list are up and running * - updates the list of servers from the other nodes */ void ping_servers(unsigned int ticks, void *param) { str *body; int ret; LM_DBG("ping_servers\n"); if(!node_list->nodes || (node_list->nodes->local && !node_list->nodes->next)) { LM_DBG("node list is empty - attempt to rebuild from notification " "address\n"); *dmq_init_callback_done = 0; if(dmq_notification_address.s) { notification_node = add_server_and_notify(&dmq_notification_address); if(!notification_node) { LM_ERR("cannot retrieve initial nodelist from %.*s\n", STR_FMT(&dmq_notification_address)); } } else { LM_ERR("no notification address"); } return; } body = build_notification_body(); if(!body) { LM_ERR("could not build notification body\n"); return; } ret = bcast_dmq_message1(dmq_notification_peer, body, NULL, ¬ification_callback, 1, ¬ification_content_type, 1); pkg_free(body->s); pkg_free(body); if(ret < 0) { LM_ERR("error broadcasting message\n"); } }
/** * @brief set the parameters for the node */ int set_dmq_node_params(dmq_node_t* node, param_t* params) { str* status; if(!params) { LM_DBG("no parameters given\n"); return 0; } status = get_param_value(params, &dmq_node_status_str); if(status) { if(STR_EQ(*status, dmq_node_active_str)) { node->status = DMQ_NODE_ACTIVE; } else if(STR_EQ(*status, dmq_node_timeout_str)) { node->status = DMQ_NODE_TIMEOUT; } else if(STR_EQ(*status, dmq_node_disabled_str)) { node->status = DMQ_NODE_DISABLED; } else { LM_ERR("invalid status parameter: %.*s\n", STR_FMT(status)); goto error; } } return 0; error: return -1; }
static dlg_t * sca_notify_dlg_for_subscription( sca_subscription *sub ) { dlg_t *dlg; dlg = (dlg_t *)pkg_malloc( sizeof( dlg_t )); if ( dlg == NULL ) { LM_ERR( "pkg_malloc dlg_t for %.*s failed: out of memory", STR_FMT( &sub->subscriber )); return( NULL ); } memset( dlg, 0, sizeof( dlg_t )); dlg->loc_seq.value = sub->dialog.notify_cseq; dlg->loc_seq.is_set = 1; dlg->id.call_id = sub->dialog.call_id; dlg->id.rem_tag = sub->dialog.from_tag; dlg->id.loc_tag = sub->dialog.to_tag; /* RURI */ dlg->rem_target = sub->subscriber; /* To and From URIs are both the SCA AoR in an SCA NOTIFY */ dlg->loc_uri = sub->target_aor; dlg->rem_uri = sub->target_aor; /* * the dialog state in an SCA NOTIFY should always be confirmed, * since we generated the dialog to-tag in our response to the * subscriber's SUBSCRIBE request. */ dlg->state = DLG_CONFIRMED; return( dlg ); }
int worker_reg_send_impl(ei_cnode *ec, int s,int wpid) { str server = STR_NULL; ei_x_buff emsg; struct msghdr msgh; struct iovec cnt[6]; int rc; memset((void*)&emsg,0,sizeof(emsg)); memset((void*)&msgh,0,sizeof(msgh)); /* server name length */ cnt[0].iov_base = &server.len; cnt[0].iov_len = sizeof(int); /* Erlang args size */ cnt[1].iov_base = &emsg.buffsz; cnt[1].iov_len = sizeof(int); /* get data size */ msgh.msg_iov = cnt; msgh.msg_iovlen = 2; while ((rc = recvmsg(s, &msgh, MSG_PEEK)) == -1 && errno == EAGAIN) ; if (rc == -1){ LM_ERR("recvmsg failed (socket=%d): %s\n",s,strerror(errno)); return -1; } /* allocate space */ server.s = (char*)pkg_malloc(server.len+1); if (!server.s) { LM_ERR("not enough memory\n"); goto err; } emsg.buff = (char*)malloc(emsg.buffsz); if (!emsg.buff) { LM_ERR("malloc: not enough memory\n"); goto err; } /* buffers */ cnt[2].iov_base = server.s; cnt[2].iov_len = server.len; cnt[3].iov_base = emsg.buff; cnt[3].iov_len = emsg.buffsz; /* get whole data */ msgh.msg_iovlen = 4; while ((rc = recvmsg(s, &msgh, MSG_WAITALL)) == -1 && errno == EAGAIN) ; if (rc == -1){ LM_ERR("recvmsg failed (socket=%d): %s\n",s,strerror(errno)); goto err; } /* fix str */ server.s[server.len] = 0; if(!enode) { LM_NOTICE("there is no connected Erlang node\n"); goto err; } LM_DBG(">> {%.*s,'%s'} ! emsg\n",STR_FMT(&server),enode->conn.nodename); EI_X_BUFF_PRINT(&emsg); /* do ERL_REG_SEND */ if ((rc = ei_reg_send(ec,enode->sockfd,server.s,emsg.buff,emsg.buffsz)) == ERL_ERROR) { if (erl_errno) { LM_ERR("ei_rpc failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(erl_errno)); } else if (errno) { LM_ERR("ei_rpc failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(errno)); } else { LM_ERR("ei_rpc failed on node=<%s> socket=<%d>, Unknown error.\n",ec->thisalivename,enode->sockfd); } } pkg_free(server.s); free(emsg.buff); return 0; err: pkg_free(server.s); free(emsg.buff); return -1; }
/** * @brief build a dmq node */ dmq_node_t *build_dmq_node(str *uri, int shm) { dmq_node_t *ret = NULL; param_hooks_t hooks; param_t *params; /* For DNS-Lookups */ static char hn[256]; struct hostent *he; LM_DBG("build_dmq_node %.*s with %s memory\n", STR_FMT(uri), shm ? "shm" : "private"); if(shm) { ret = shm_malloc(sizeof(dmq_node_t)); if(ret == NULL) { LM_ERR("no more shm\n"); goto error; } memset(ret, 0, sizeof(dmq_node_t)); if(shm_str_dup(&ret->orig_uri, uri) < 0) { goto error; } } else { ret = pkg_malloc(sizeof(dmq_node_t)); if(ret == NULL) { LM_ERR("no more pkg\n"); goto error; } memset(ret, 0, sizeof(dmq_node_t)); if(pkg_str_dup(&ret->orig_uri, uri) < 0) { goto error; } } set_default_dmq_node_params(ret); if(parse_uri(ret->orig_uri.s, ret->orig_uri.len, &ret->uri) < 0 || ret->uri.host.len > 254) { LM_ERR("error parsing uri\n"); goto error; } /* if any parameters found, parse them */ if(parse_params(&ret->uri.params, CLASS_ANY, &hooks, ¶ms) < 0) { LM_ERR("error parsing params\n"); goto error; } /* if any params found */ if(params) { if(set_dmq_node_params(ret, params) < 0) { free_params(params); LM_ERR("error setting parameters\n"); goto error; } free_params(params); } else { LM_DBG("no dmqnode params found\n"); } /* resolve hostname */ strncpy(hn, ret->uri.host.s, ret->uri.host.len); hn[ret->uri.host.len] = '\0'; he = resolvehost(hn); if(he == 0) { LM_ERR("could not resolve %.*s\n", ret->uri.host.len, ret->uri.host.s); goto error; } hostent2ip_addr(&ret->ip_address, he, 0); return ret; error: if(ret != NULL) { destroy_dmq_node(ret, shm); } return NULL; }
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(); }
/* * Loads contacts in destination set into contacts_avp in reverse * priority order and associated each contact with Q_FLAG telling if * contact is the last one in its priority class. Finally, removes * all branches from destination set. */ int t_load_contacts(struct sip_msg* msg, char* key, char* value) { str uri, tmp, dst_uri, path, branch_info, *ruri; qvalue_t first_q, q; struct contact *contacts, *next, *prev, *curr; int_str val; int first_idx, idx; struct socket_info* sock; unsigned int flags; /* Check if contacts_avp has been defined */ if (contacts_avp.n == 0) { LM_ERR("feature has been disabled - " "to enable define contacts_avp module parameter"); return -1; } /* Check if anything needs to be done */ if (nr_branches == 0) { LM_DBG("t_load_contacts(): nothing to do - no branches!\n"); return 1; } ruri = (str *)0; /* Take first q from Request-URI */ ruri = GET_RURI(msg); if (!ruri) { LM_ERR("no Request-URI found\n"); return -1; } first_q = get_ruri_q(); first_idx = 0; /* Check if all q values are equal */ for(idx = first_idx; (tmp.s = get_branch(idx, &tmp.len, &q, 0, 0, 0, 0)) != 0; idx++) { if (q != first_q) { goto rest; } } LM_DBG("t_load_contacts(): nothing to do - all contacts have same q!\n"); return 1; rest: /* Allocate memory for first contact */ contacts = (struct contact *)pkg_malloc(sizeof(struct contact)); if (!contacts) { LM_ERR("no memory for contact info\n"); return -1; } /* Insert Request-URI branch to first contact */ contacts->uri.s = ruri->s; contacts->uri.len = ruri->len; contacts->dst_uri = msg->dst_uri; contacts->sock = msg->force_send_socket; getbflagsval(0, &contacts->flags); contacts->path = msg->path_vec; contacts->q = first_q; contacts->next = (struct contact *)0; /* Insert (remaining) branches to contact list in increasing q order */ for(idx = first_idx; (uri.s = get_branch(idx,&uri.len,&q,&dst_uri,&path,&flags,&sock)) != 0; idx++ ) { next = (struct contact *)pkg_malloc(sizeof(struct contact)); if (!next) { LM_ERR("no memory for contact info\n"); free_contact_list(contacts); return -1; } next->uri = uri; next->q = q; next->dst_uri = dst_uri; next->path = path; next->flags = flags; next->sock = sock; next->next = (struct contact *)0; prev = (struct contact *)0; curr = contacts; while (curr && (curr->q < q)) { prev = curr; curr = curr->next; } if (!curr) { next->next = (struct contact *)0; prev->next = next; } else { next->next = curr; if (prev) { prev->next = next; } else { contacts = next; } } } /* Assign values for q_flags */ curr = contacts; curr->q_flag = 0; while (curr->next) { if (curr->q < curr->next->q) { curr->next->q_flag = Q_FLAG; } else { curr->next->q_flag = 0; } curr = curr->next; } /* Add contacts to contacts_avp */ curr = contacts; while (curr) { if (encode_branch_info(&branch_info, curr) == 0) { LM_ERR("encoding of branch info failed\n"); free_contact_list(contacts); if (branch_info.s) pkg_free(branch_info.s); return -1; } val.s = branch_info; add_avp(contacts_avp_type|AVP_VAL_STR|(curr->q_flag), contacts_avp, val); pkg_free(branch_info.s); LM_DBG("loaded contact <%.*s> with q_flag <%d>\n", STR_FMT(&val.s), curr->q_flag); curr = curr->next; } /* Clear all branches */ clear_branches(); /* Free contact list */ free_contact_list(contacts); return 1; }
static int get_str(str *str_ptr, erl_rpc_ctx_t *ctx, int reads, int autoconvert) { int type, size; char *p; double d; long n; if (ei_get_type(ctx->request->buff,&ctx->request_index,&type,&size)) { erl_rpc_fault(ctx,400,"Can't determine data type of parameter #%d",reads); return -1; } switch(type) { case ERL_FLOAT_EXT: if (autoconvert == 0) { erl_rpc_fault(ctx,400,"Bad type of parameter #%d",reads); return -1; } if (ei_decode_double(ctx->request->buff,&ctx->request_index,&d)) { erl_rpc_fault(ctx,400, "Bad value of parameter #%d.",reads); return -1; } p=(char*)pkg_malloc(MAX_DIGITS); if (!p) { erl_rpc_fault(ctx,500, "Internal Server Error (No memory left)"); LM_ERR("Not enough memory\n"); return -1; } if (add_to_recycle_bin(JUNK_PKGCHAR, p, ctx)) { pkg_free(p); return -1; } str_ptr->len=snprintf(p, MAX_DIGITS, "%f", d); str_ptr->s = p; break; case ERL_STRING_EXT: case ERL_LIST_EXT: case ERL_BINARY_EXT: /* allocate buffer */ p = (char*)pkg_malloc(size+1); if (!p) { erl_rpc_fault(ctx,500, "Internal Server Error (No memory left)"); LM_ERR("Not enough memory\n"); return -1; } if (add_to_recycle_bin(JUNK_PKGCHAR, p, ctx)) { pkg_free(p); return -1; } if(ei_decode_strorbin(ctx->request->buff,&ctx->request_index,size+1,p)) { erl_rpc_fault(ctx,400, "Can't read parameter #%d",reads); return -1; } str_ptr->s=p; str_ptr->len=size; break; case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: if (autoconvert == 0) { erl_rpc_fault(ctx,400,"Bad type of parameter #%d",reads); return -1; } if (ei_decode_long(ctx->request->buff,&ctx->request_index,&n)) { erl_rpc_fault(ctx,400, "Bad value of parameter #%d.",reads); return -1; } p=(char*)pkg_malloc(MAX_DIGITS); if (!p) { erl_rpc_fault(ctx,500, "Internal Server Error (No memory left)"); LM_ERR("Not enough memory\n"); return -1; } if (add_to_recycle_bin(JUNK_PKGCHAR, p, ctx)) { pkg_free(p); return -1; } str_ptr->len=snprintf(p, MAX_DIGITS, "%ld", n); str_ptr->s = p; break; default: erl_rpc_fault(ctx,400,"Can't convert to string parameter #%d.",reads); return -1; } LM_ERR("parameter #%d:<%.*s>\n",reads,STR_FMT(str_ptr)); return 0; }
/* called with the call lock held in W, hence agent doesn't need to be locked */ void ice_update(struct ice_agent *ag, struct stream_params *sp) { GList *l, *k; struct ice_candidate *cand, *dup; struct call_media *media; struct call *call; int recalc = 0; unsigned int comps; struct packet_stream *components[MAX_COMPONENTS], *ps; GQueue *candidates; if (!ag) return; atomic64_set(&ag->last_activity, poller_now); media = ag->media; call = media->call; __role_change(ag, MEDIA_ISSET(media, ICE_CONTROLLING)); if (sp) { /* check for ICE restarts */ if (ag->ufrag[0].s && sp->ice_ufrag.s && str_cmp_str(&ag->ufrag[0], &sp->ice_ufrag)) __ice_restart(ag); else if (ag->pwd[0].s && sp->ice_pwd.s && str_cmp_str(&ag->pwd[0], &sp->ice_pwd)) __ice_restart(ag); else if (ag->local_interface != media->interface) __ice_restart(ag); /* update remote info */ if (sp->ice_ufrag.s) call_str_cpy(call, &ag->ufrag[0], &sp->ice_ufrag); if (sp->ice_pwd.s) call_str_cpy(call, &ag->pwd[0], &sp->ice_pwd); candidates = &sp->ice_candidates; } else /* this is a dummy update in case rtcp-mux has changed */ candidates = &ag->remote_candidates; /* get our component streams */ ZERO(components); comps = 0; for (l = media->streams.head; l; l = l->next) components[comps++] = l->data; if (comps == 2 && MEDIA_ISSET(media, RTCP_MUX)) components[1] = NULL; comps = 0; for (l = candidates->head; l; l = l->next) { if (ag->remote_candidates.length >= MAX_ICE_CANDIDATES) { ilog(LOG_WARNING, "Maxmimum number of ICE candidates exceeded"); break; } cand = l->data; /* skip invalid */ if (!cand->component_id || cand->component_id > G_N_ELEMENTS(components)) continue; ps = components[cand->component_id - 1]; if (ps) /* only count active components */ comps = MAX(comps, cand->component_id); dup = g_hash_table_lookup(ag->candidate_hash, cand); if (!sp && dup) /* this isn't a real update, so only check pairings */ goto pair; /* check for duplicates */ if (dup) { /* if this is peer reflexive, we've learned it through STUN. * otherwise it's simply one we've seen before. */ if (dup->type == ICT_PRFLX) { ilog(LOG_DEBUG, "Replacing previously learned prflx ICE candidate with " STR_FORMAT":%lu", STR_FMT(&cand->foundation), cand->component_id); } else { /* if the new one has higher priority then the old one, then we * update it, otherwise we just drop it */ if (cand->priority <= dup->priority) { ilog(LOG_DEBUG, "Dropping new ICE candidate "STR_FORMAT" in favour of " STR_FORMAT":%lu", STR_FMT(&cand->foundation), STR_FMT(&dup->foundation), cand->component_id); continue; } ilog(LOG_DEBUG, "Replacing known ICE candidate "STR_FORMAT" with higher " "priority " STR_FORMAT":%lu", STR_FMT(&dup->foundation), STR_FMT(&cand->foundation), cand->component_id); } /* priority and foundation may change */ g_hash_table_remove(ag->foundation_hash, dup); recalc += __copy_cand(call, dup, cand); } else { ilog(LOG_DEBUG, "Learning new ICE candidate "STR_FORMAT":%lu", STR_FMT(&cand->foundation), cand->component_id); dup = g_slice_alloc(sizeof(*dup)); __copy_cand(call, dup, cand); g_hash_table_insert(ag->candidate_hash, dup, dup); g_queue_push_tail(&ag->remote_candidates, dup); } g_hash_table_insert(ag->foundation_hash, dup, dup); pair: if (!ps) continue; for (k = ag->local_interface->list.head; k; k = k->next) { /* skip duplicates here also */ if (__pair_lookup(ag, dup, k->data)) continue; __pair_candidate(k->data, ag, dup, ps); } } if (comps) ag->active_components = comps; if (!ag->active_components) { /* determine components for tricke-ice case */ comps = 2; if (!components[1]) comps = 1; ag->active_components = comps; } /* if we're here, we can start our ICE checks */ if (recalc) __recalc_pair_prios(ag); else __all_pairs_list(ag); if (comps) __do_ice_checks(ag); else __agent_shutdown(ag); }
/* Encode branch info from str */ static inline int decode_branch_info(char *info, str *uri, str *dst, str *path, struct socket_info **sock, unsigned int *flags) { str s, host; int port, proto; char *pos, *at, *tmp; if (info == NULL) { ERR("decode_branch_info: Invalid input string.\n"); return 0; } /* Reset or return arguments to sane defaults */ uri->s = 0; uri->len = 0; dst->s = 0; dst->len = 0; path->s = 0; path->len = 0; *sock = NULL; *flags = 0; /* Make sure that we have at least a non-empty URI string, it is fine if * everything else is missing, but we need at least the URI. */ uri->s = info; if ((pos = strchr(info, '\n')) == NULL) { uri->len = strlen(info); /* We don't even have the URI string, this is bad, report an * error. */ if (uri->len == 0) goto uri_missing; return 1; } uri->len = pos - info; if (uri->len == 0) goto uri_missing; /* If we get here we have at least the branch URI, now try to parse as * much as you can. All output variable have been initialized above, so it * is OK if any of the fields are missing from now on. */ dst->s = at = pos + 1; if ((pos = strchr(at, '\n')) == NULL) { dst->len = strlen(dst->s); return 1; } dst->len = pos - at; path->s = at = pos + 1; if ((pos = strchr(at, '\n')) == NULL) { path->len = strlen(path->s); return 1; } path->len = pos - at; s.s = at = pos + 1; if ((pos = strchr(at, '\n')) == NULL) { /* No LF found, that means we take the string till the final zero * termination character and pass it directly to parse_phostport * without making a zero-terminated copy. */ tmp = s.s; s.len = strlen(s.s); } else { /* Our string is terminated by LF, so we need to make a * zero-terminated copy of the string before we pass it to * parse_phostport. */ s.len = pos - at; if ((tmp = as_asciiz(&s)) == NULL) { ERR("No memory left\n"); return 0; } } if (s.len) { if (parse_phostport(tmp, &host.s, &host.len, &port, &proto) != 0) { LM_ERR("parsing of socket info <%s> failed\n", tmp); if (pos) pkg_free(tmp); return 0; } *sock = grep_sock_info(&host, (unsigned short)port, (unsigned short)proto); if (*sock == 0) { LM_ERR("invalid socket <%s>\n", tmp); if (pos) pkg_free(tmp); return 0; } } if (pos) pkg_free(tmp); else return 1; s.s = at = pos + 1; if ((pos = strchr(at, '\n')) == NULL) s.len = strlen(s.s); else s.len = pos - s.s; if (s.len) { if (str2int(&s, flags) != 0) { LM_ERR("failed to decode flags <%.*s>\n", STR_FMT(&s)); return 0; } } return 1; uri_missing: ERR("decode_branch_info: Cannot decode branch URI.\n"); return 0; }
/** * @brief send a dmq message * * peer - the peer structure on behalf of which we are sending * body - the body of the message * node - we send the message to this node * resp_cback - a response callback that gets called when the transaction is complete */ int dmq_send_message(dmq_peer_t *peer, str *body, dmq_node_t *node, dmq_resp_cback_t *resp_cback, int max_forwards, str *content_type) { uac_req_t uac_r; str str_hdr = {0, 0}; str from = {0, 0}, to = {0, 0}; dmq_cback_param_t *cb_param = NULL; int result = 0; int len = 0; if(!content_type) { LM_ERR("content-type is null\n"); return -1; } /* add Max-Forwards and Content-Type headers */ str_hdr.len = 34 + content_type->len + (CRLF_LEN * 2); str_hdr.s = pkg_malloc(str_hdr.len); if(str_hdr.s == NULL) { LM_ERR("no more pkg\n"); return -1; } len += sprintf(str_hdr.s, "Max-Forwards: %d" CRLF "Content-Type: %.*s" CRLF, max_forwards, content_type->len, content_type->s); str_hdr.len = len; cb_param = shm_malloc(sizeof(*cb_param)); if(cb_param == NULL) { LM_ERR("no more shm for building callback parameter\n"); goto error; } memset(cb_param, 0, sizeof(*cb_param)); cb_param->resp_cback = *resp_cback; cb_param->node = shm_dup_node(node); if(cb_param->node == NULL) { LM_ERR("error building callback parameter\n"); goto error; } if(build_uri_str(&peer->peer_id, &dmq_server_uri, &from) < 0) { LM_ERR("error building from string [username %.*s]\n", STR_FMT(&peer->peer_id)); goto error; } if(build_uri_str(&peer->peer_id, &node->uri, &to) < 0) { LM_ERR("error building to string\n"); goto error; } set_uac_req(&uac_r, &dmq_request_method, &str_hdr, body, NULL, TMCB_LOCAL_COMPLETED, dmq_tm_callback, (void *)cb_param); uac_r.ssock = &dmq_server_socket; result = tmb.t_request(&uac_r, &to, &to, &from, NULL); if(result < 0) { LM_ERR("error in tmb.t_request_within\n"); goto error; } pkg_free(str_hdr.s); pkg_free(from.s); pkg_free(to.s); return 0; error: pkg_free(str_hdr.s); if(from.s != NULL) pkg_free(from.s); if(to.s != NULL) pkg_free(to.s); if(cb_param) { if(cb_param->node) destroy_dmq_node(cb_param->node, 1); shm_free(cb_param); } return -1; }
static int parse_domain(void* param, cfg_parser_t* st, unsigned int flags) { cfg_token_t t; int ret; cfg_option_t* opt; int type; struct ip_addr ip; unsigned int port; memset(&ip, 0, sizeof(struct ip_addr)); ret = cfg_get_token(&t, st, 0); if (ret < 0) return -1; if (ret > 0) { ERR("%s:%d:%d: TLS domain type missing\n", st->file, st->line, st->col); return -1; } if (t.type != CFG_TOKEN_ALPHA || ((opt = cfg_lookup_token(domain_types, &t.val)) == NULL)) { ERR("%s:%d:%d: Invalid TLS domain type %d:'%.*s'\n", st->file, t.start.line, t.start.col, t.type, STR_FMT(&t.val)); return -1; } ret = cfg_get_token(&t, st, 0); if (ret < 0) return -1; if (ret > 0) { ERR("%s:%d:%d: TLS domain IP address missing\n", st->file, st->line, st->col); return -1; } if (t.type != ':') { ERR("%s:%d:%d: Syntax error, ':' expected\n", st->file, t.start.line, t.start.col); return -1; } port = 0; if (parse_hostport(&type, &ip, &port, &t, st) < 0) return -1; ret = cfg_get_token(&t, st, 0); if (ret < 0) return -1; if (ret > 0) { ERR("%s:%d:%d: Closing ']' missing\n", st->file, st->line, st->col); return -1; } if (t.type != ']') { ERR("%s:%d:%d: Syntax error, ']' expected\n", st->file, t.start.line, t.start.col); return -1; } if (cfg_eat_eol(st, flags)) return -1; if ((domain = tls_new_domain(opt->val | type, &ip, port)) == NULL) { ERR("%s:%d: Cannot create TLS domain structure\n", st->file, st->line); return -1; } ret = tls_add_domain(cfg, domain); if (ret < 0) { ERR("%s:%d: Error while creating TLS domain structure\n", st->file, st->line); tls_free_domain(domain); return -1; } else if (ret == 1) { ERR("%s:%d: Duplicate TLS domain (appears earlier in the config file)\n", st->file, st->line); tls_free_domain(domain); return -1; } update_opt_variables(); cfg_set_options(st, options); return 0; }
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); }
static int parse_hostport(int* type, struct ip_addr* ip, unsigned int* port, cfg_token_t* token, cfg_parser_t* st) { int ret; cfg_token_t t; cfg_option_t* opt; ret = cfg_get_token(&t, st, 0); if (ret < 0) return -1; if (ret > 0) { ERR("%s:%d:%d: Missing IP address\n", st->file, token->start.line, token->start.col); return -1; } if (t.type == '[') { if (parse_ipv6(ip, &t, st) < 0) return -1; } else if (t.type == CFG_TOKEN_ALPHA) { opt = cfg_lookup_token(token_default, &t.val); if (opt) { *type = TLS_DOMAIN_DEF; /* Default domain */ return 0; } else { if (parse_ipv4(ip, &t, st) < 0) return -1; } } else { ERR("%s:%d:%d: Syntax error, IP address expected\n", st->file, t.start.line, t.start.col); return -1; } *type = 0; /* Parse port */ ret = cfg_get_token(&t, st, 0); if (ret < 0) return -1; if (ret > 0) { ERR("%s:%d:%d: Syntax error, ':' expected\n", st->file, st->line, st->col); return -1; } if (t.type != ':') { ERR("%s:%d:%d: Syntax error, ':' expected\n", st->file, t.start.line, t.start.col); return -1; } ret = cfg_get_token(&t, st, 0); if (ret < 0) return -1; if (ret > 0) { ERR("%s:%d:%d: Premature end of file, port number missing\n", st->file, t.start.line, t.start.col); return -1; } if (t.type != CFG_TOKEN_ALPHA || (str2int(&t.val, port) < 0)) { ERR("%s:%d:%d: Invalid port number '%.*s'\n", st->file, t.start.line, t.start.col, STR_FMT(&t.val)); return -1; } return 0; }
int ld_cmd(db_cmd_t* cmd) { struct ld_cmd* lcmd; struct ld_cfg* cfg; struct ld_fld* lfld; int i, j; lcmd = (struct ld_cmd*)pkg_malloc(sizeof(struct ld_cmd)); if (lcmd == NULL) { ERR("ldap: No memory left\n"); goto error; } memset(lcmd, '\0', sizeof(struct ld_cmd)); if (db_drv_init(&lcmd->gen, ld_cmd_free) < 0) goto error; switch(cmd->type) { case DB_PUT: case DB_DEL: case DB_UPD: ERR("ldap: The driver does not support directory modifications yet.\n"); goto error; break; case DB_GET: break; case DB_SQL: ERR("ldap: The driver does not support raw queries yet.\n"); goto error; } cfg = ld_find_cfg(&cmd->table); if (cfg == NULL) { ERR("ldap: Cannot find configuration for '%.*s', giving up\n", STR_FMT(&cmd->table)); goto error; } lcmd->base = cfg->base.s; lcmd->scope = cfg->scope; lcmd->sizelimit = cfg->sizelimit; if (cfg->timelimit) { lcmd->timelimit.tv_sec = cfg->timelimit; lcmd->timelimit.tv_usec = 0; } if (cfg->filter.s) { lcmd->filter = cfg->filter; } lcmd->chase_references = cfg->chase_references; lcmd->chase_referrals = cfg->chase_referrals; if (ld_resolve_fld(cmd->match, cfg) < 0) goto error; if (ld_resolve_fld(cmd->result, cfg) < 0) goto error; /* prepare filter for each result field */ for(i = 0; !DB_FLD_EMPTY(cmd->result) && !DB_FLD_LAST(cmd->result[i]); i++) { int n; lfld = DB_GET_PAYLOAD(cmd->result + i); lfld->filter = NULL; for(j = 0, n = 0; !DB_FLD_EMPTY(cmd->match) && !DB_FLD_LAST(cmd->match[j]); j++) { if (strcmp(cmd->result[i].name, cmd->match[j].name) == 0) n++; } if (n > 0) { lfld->filter = pkg_malloc((n+1)*sizeof(*(lfld->filter))); if (!lfld->filter) return -1 /* E_OUT_OF_MEM*/; for(j = 0, n = 0; !DB_FLD_EMPTY(cmd->match) && !DB_FLD_LAST(cmd->match[j]); j++) { if (strcmp(cmd->result[i].name, cmd->match[j].name) == 0) { lfld->filter[n] = cmd->match+j; n++; } } lfld->filter[n] = NULL; } } if (build_result_array(&lcmd->result, cmd) < 0) goto error; DB_SET_PAYLOAD(cmd, lcmd); return 0; error: if (lcmd) { DB_SET_PAYLOAD(cmd, NULL); db_drv_free(&lcmd->gen); if (lcmd->result) pkg_free(lcmd->result); pkg_free(lcmd); } return -1; }
int sca_create_canonical_aor_for_ua( sip_msg_t *msg, str *c_aor, int ua_opts ) { struct to_body *tf = NULL; sip_uri_t c_uri; str tf_aor = STR_NULL; str contact_uri = STR_NULL; int rc = -1; assert( msg != NULL ); assert( c_aor != NULL ); memset( c_aor, 0, sizeof( str )); if (( ua_opts & SCA_AOR_TYPE_AUTO )) { if ( msg->first_line.type == SIP_REQUEST ) { ua_opts = SCA_AOR_TYPE_UAC; } else { ua_opts = SCA_AOR_TYPE_UAS; } } if (( ua_opts & SCA_AOR_TYPE_UAC )) { if ( sca_get_msg_from_header( msg, &tf ) < 0 ) { LM_ERR( "sca_create_canonical_aor: failed to get From header" ); goto done; } } else { if ( sca_get_msg_to_header( msg, &tf ) < 0 ) { LM_ERR( "sca_create_canonical_aor: failed to get To header" ); goto done; } } if ( sca_uri_extract_aor( &tf->uri, &tf_aor ) < 0 ) { LM_ERR( "sca_create_canonical_aor: failed to extract AoR from " "URI <%.*s>", STR_FMT( &tf->uri )); goto done; } memset( &c_uri, 0, sizeof( sip_uri_t )); if (( rc = sca_get_msg_contact_uri( msg, &contact_uri )) < 0 ) { LM_ERR( "sca_create_canonical_aor: failed to get contact URI from " "Contact <%.*s>", STR_FMT( &msg->contact->body )); goto done; } if ( rc > 0 ) { if ( parse_uri( contact_uri.s, contact_uri.len, &c_uri ) < 0 ) { LM_ERR( "sca_create_canonical_aor: failed to parse Contact URI " "<%.*s>", STR_FMT( &contact_uri )); rc = -1; goto done; } } if ( SCA_STR_EMPTY( &c_uri.user ) || SCA_STR_EQ( &c_uri.user, &tf->parsed_uri.user )) { /* empty contact header or Contact user matches To/From AoR */ c_aor->s = (char *)pkg_malloc( tf_aor.len ); c_aor->len = tf_aor.len; memcpy( c_aor->s, tf_aor.s, tf_aor.len ); } else { /* Contact user and To/From user mismatch */ if ( sca_aor_create_from_info( c_aor, c_uri.type, &c_uri.user, &tf->parsed_uri.host, &tf->parsed_uri.port ) < 0 ) { LM_ERR( "sca_create_canonical_aor: failed to create AoR from " "Contact <%.*s> and URI <%.*s>", STR_FMT( &contact_uri ), STR_FMT( &tf_aor )); goto done; } } rc = 1; done: return( rc ); }
/* * The function creates an ACK to 200 OK. Route set will be created * and parsed and the dst parameter will contain the destination to which * the request should be send. The function is used by tm when it * generates local ACK to 200 OK (on behalf of applications using uac) */ char *build_dlg_ack(struct sip_msg* rpl, struct cell *Trans, unsigned int branch, str *hdrs, str *body, unsigned int *len, struct dest_info* dst) { char *req_buf, *p, *via; unsigned int via_len; char branch_buf[MAX_BRANCH_PARAM_LEN]; int branch_len; str branch_str; struct hostport hp; struct rte* list; str contact, ruri, *cont; str next_hop; str body_len; str _to, *to = &_to; #ifdef USE_DNS_FAILOVER struct dns_srv_handle dns_h; #endif #ifdef WITH_AS_SUPPORT /* With AS support, TM allows for external modules to generate building of * the ACK; in this case, the ACK's retransmission buffer is built once * and kept in memory (to help when retransmitted 2xx are received and ACK * must be resent). * Allocation of the string raw buffer that holds the ACK is piggy-backed * with allocation of the retransmission buffer (since both have the same * life-cycle): both the string buffer and retransm. buffer are placed * into the same allocated chunk of memory (retr. buffer first, string * buffer follows).In this case, the 'len' param is used as in-out * parameter: 'in' to give the extra space needed by the retr. buffer, * 'out' to return the lenght of the allocated string buffer. */ unsigned offset = *len; #endif if (parse_headers(rpl, HDR_EOH_F, 0) == -1 || !rpl->to) { LM_ERR("Error while parsing headers.\n"); return 0; } else { _to.s = rpl->to->name.s; _to.len = rpl->to->len; } if (get_contact_uri(rpl, &contact) < 0) { return 0; } if (eval_uac_routing(rpl, &Trans->uac[branch].request, &contact, &list, &ruri, &next_hop) < 0) { LM_ERR("failed to evaluate routing elements.\n"); return 0; } LM_DBG("ACK RURI: `%.*s', NH: `%.*s'.\n", STR_FMT(&ruri), STR_FMT(&next_hop)); if ((contact.s != ruri.s) || (contact.len != ruri.len)) { /* contact != ruri means that the next * hop is a strict router, cont will be non-zero * and print_routeset will append it at the end * of the route set */ cont = &contact; } else { /* Next hop is a loose router, nothing to append */ cont = 0; } /* method, separators, version: "ACK sip:[email protected] SIP/2.0" */ *len = SIP_VERSION_LEN + ACK_LEN + 2 /* spaces */ + CRLF_LEN; *len += ruri.len; /* dst */ switch(cfg_get(tm, tm_cfg, local_ack_mode)){ case 1: /* send the local 200 ack to the same dst as the corresp. invite*/ *dst=Trans->uac[branch].request.dst; break; case 2: /* send the local 200 ack to the same dst as the 200 reply source*/ init_dst_from_rcv(dst, &rpl->rcv); dst->send_flags=rpl->fwd_send_flags; break; case 0: default: /* rfc conformant behaviour: use the next_hop determined from the * contact and the route set */ #ifdef USE_DNS_FAILOVER if (cfg_get(core, core_cfg, use_dns_failover)){ dns_srv_handle_init(&dns_h); if ((uri2dst(&dns_h , dst, rpl, &next_hop, PROTO_NONE)==0) || (dst->send_sock==0)){ dns_srv_handle_put(&dns_h); LM_ERR("no socket found\n"); goto error; } dns_srv_handle_put(&dns_h); /* not needed any more */ }else{ if ((uri2dst(0 , dst, rpl, &next_hop, PROTO_NONE)==0) || (dst->send_sock==0)){ LM_ERR("no socket found\n"); goto error; } } #else /* USE_DNS_FAILOVER */ if ( (uri2dst( dst, rpl, &next_hop, PROTO_NONE)==0) || (dst->send_sock==0)){ LM_ERR("no socket found\n"); goto error; } #endif /* USE_DNS_FAILOVER */ break; } /* via */ if (!t_calc_branch(Trans, branch, branch_buf, &branch_len)) goto error; branch_str.s = branch_buf; branch_str.len = branch_len; set_hostport(&hp, 0); via = via_builder(&via_len, NULL, dst, &branch_str, 0, &hp); if (!via) { LM_ERR("No via header got from builder\n"); goto error; } *len+= via_len; /* headers */ *len += Trans->from.len + Trans->callid.len + to->len + Trans->cseq_n.len + 1 + ACK_LEN + CRLF_LEN; /* copy'n'paste Route headers */ *len += calc_routeset_len(list, cont); /* User Agent */ if (server_signature) *len += user_agent_hdr.len + CRLF_LEN; /* extra headers */ if (hdrs) *len += hdrs->len; /* body */ if (body) { body_len.s = int2str(body->len, &body_len.len); *len += body->len; } else { body_len.len = 0; body_len.s = NULL; /*4gcc*/ *len += 1; /* for the (Cont-Len:) `0' */ } /* Content Length, EoM */ *len += CONTENT_LENGTH_LEN + body_len.len + CRLF_LEN + CRLF_LEN; #if WITH_AS_SUPPORT req_buf = shm_malloc(offset + *len + 1); req_buf += offset; #else req_buf = shm_malloc(*len + 1); #endif if (!req_buf) { LM_ERR("Cannot allocate memory (%u+1)\n", *len); goto error01; } p = req_buf; append_str( p, ACK, ACK_LEN ); append_str( p, " ", 1 ); append_str(p, ruri.s, ruri.len); append_str( p, " " SIP_VERSION CRLF, 1 + SIP_VERSION_LEN + CRLF_LEN); /* insert our via */ append_str(p, via, via_len); /*other headers*/ append_str(p, Trans->from.s, Trans->from.len); append_str(p, Trans->callid.s, Trans->callid.len); append_str(p, to->s, to->len); append_str(p, Trans->cseq_n.s, Trans->cseq_n.len); append_str( p, " ", 1 ); append_str( p, ACK, ACK_LEN); append_str(p, CRLF, CRLF_LEN); /* Routeset */ p = print_rs(p, list, cont); /* User Agent header */ if (server_signature) { append_str(p, user_agent_hdr.s, user_agent_hdr.len); append_str(p, CRLF, CRLF_LEN); } /* extra headers */ if (hdrs) append_str(p, hdrs->s, hdrs->len); /* Content Length, EoH, (body) */ if (body) { append_str(p, CONTENT_LENGTH, CONTENT_LENGTH_LEN); append_str(p, body_len.s, body_len.len); append_str(p, /*end crr. header*/CRLF /*EoH*/CRLF, CRLF_LEN + CRLF_LEN); append_str(p, body->s, body->len); } else { append_str(p, CONTENT_LENGTH "0" CRLF CRLF, CONTENT_LENGTH_LEN + 1 + CRLF_LEN + CRLF_LEN); } /* EoM */ *p = 0; pkg_free(via); free_rte_list(list); return req_buf; error01: pkg_free(via); error: free_rte_list(list); return 0; }
static void call_ng_process_flags(struct sdp_ng_flags *out, bencode_item_t *input) { bencode_item_t *list, *it; int diridx; str s; ZERO(*out); if ((list = bencode_dictionary_get_expect(input, "flags", BENCODE_LIST))) { for (it = list->child; it; it = it->sibling) { str_hyphenate(it); if (!bencode_strcmp(it, "trust-address")) out->trust_address = 1; else if (!bencode_strcmp(it, "asymmetric")) out->asymmetric = 1; else if (!bencode_strcmp(it, "strict-source")) out->strict_source = 1; else if (!bencode_strcmp(it, "media-handover")) out->media_handover = 1; else ilog(LOG_WARN, "Unknown flag encountered: '"BENCODE_FORMAT"'", BENCODE_FMT(it)); } } if ((list = bencode_dictionary_get_expect(input, "replace", BENCODE_LIST))) { for (it = list->child; it; it = it->sibling) { str_hyphenate(it); if (!bencode_strcmp(it, "origin")) out->replace_origin = 1; else if (!bencode_strcmp(it, "session-connection")) out->replace_sess_conn = 1; else ilog(LOG_WARN, "Unknown 'replace' flag encountered: '"BENCODE_FORMAT"'", BENCODE_FMT(it)); } } diridx = 0; if ((list = bencode_dictionary_get_expect(input, "direction", BENCODE_LIST))) { for (it = list->child; it && diridx < 2; it = it->sibling) bencode_get_str(it, &out->direction[diridx++]); } list = bencode_dictionary_get_expect(input, "received from", BENCODE_LIST); if (!list) list = bencode_dictionary_get_expect(input, "received-from", BENCODE_LIST); if (list && (it = list->child)) { bencode_get_str(it, &out->received_from_family); bencode_get_str(it->sibling, &out->received_from_address); } if (bencode_dictionary_get_str(input, "ICE", &s)) { if (!str_cmp(&s, "remove")) out->ice_remove = 1; else if (!str_cmp(&s, "force")) out->ice_force = 1; else if (!str_cmp(&s, "force_relay") || !str_cmp(&s, "force-relay")) out->ice_force_relay = 1; else ilog(LOG_WARN, "Unknown 'ICE' flag encountered: '"STR_FORMAT"'", STR_FMT(&s)); } if ((list = bencode_dictionary_get_expect(input, "rtcp-mux", BENCODE_LIST))) { for (it = list->child; it; it = it->sibling) { if (!bencode_strcmp(it, "offer")) out->rtcp_mux_offer = 1; else if (!bencode_strcmp(it, "demux")) out->rtcp_mux_demux = 1; else if (!bencode_strcmp(it, "accept")) out->rtcp_mux_accept = 1; else if (!bencode_strcmp(it, "reject")) out->rtcp_mux_reject = 1; else ilog(LOG_WARN, "Unknown 'rtcp-mux' flag encountered: '"BENCODE_FORMAT"'", BENCODE_FMT(it)); } } bencode_get_alt(input, "transport-protocol", "transport protocol", &out->transport_protocol_str); out->transport_protocol = transport_protocol(&out->transport_protocol_str); bencode_get_alt(input, "media-address", "media address", &out->media_address); if (bencode_get_alt(input, "address-family", "address family", &out->address_family_str)) out->address_family = address_family(&out->address_family_str); out->tos = bencode_dictionary_get_integer(input, "TOS", 256); }
/** * Evaluate if next hop is a strict or loose router, by looking at the * retr. buffer of the original INVITE. * Assumes: * orig_inv is a parsed SIP message; * rtset is not NULL. * @return: * F_RB_NH_LOOSE : next hop was loose router; * F_RB_NH_STRICT: nh is strict; * 0 on error. */ static unsigned long nhop_type(sip_msg_t *orig_inv, rte_t *rtset, const struct dest_info *dst_inv, str *contact) { struct sip_uri puri, topr_uri, lastr_uri, inv_ruri, cont_uri; struct ip_addr *uri_ia; union sockaddr_union uri_sau; unsigned int uri_port, dst_port, inv_port, cont_port, lastr_port; rte_t *last_r; #ifdef TM_LOC_ACK_DO_REV_DNS struct ip_addr ia; struct hostent *he; char **alias; #endif #define PARSE_URI(_str_, _uri_) \ do { \ /* parse_uri() 0z the puri */ \ if (parse_uri((_str_)->s, \ (_str_)->len, _uri_) < 0) { \ LM_ERR("failed to parse route body '%.*s'.\n", STR_FMT(_str_)); \ return 0; \ } \ } while (0) #define HAS_LR(_rte_) \ ({ \ PARSE_URI(&(_rte_)->ptr->nameaddr.uri, &puri); \ puri.lr.s; \ }) #define URI_PORT(_puri_, _port) \ do { \ if (! (_port = uri2port(_puri_))) \ return 0; \ } while (0) /* examine the easy/fast & positive cases foremost */ /* [1] check if 1st route lacks ;lr */ LM_DBG("checking lack of ';lr' in 1st route.\n"); if (! HAS_LR(rtset)) return F_RB_NH_STRICT; topr_uri = puri; /* save 1st route's URI */ /* [2] check if last route shows ;lr */ LM_DBG("checking presence of ';lr' in last route.\n"); for (last_r = rtset; last_r->next; last_r = last_r->next) /* scroll down to last route */ ; if (HAS_LR(last_r)) return F_RB_NH_LOOSE; /* [3] 1st route has ;lr -> check if the destination of original INV * equals the address provided by this route; if does -> loose */ LM_DBG("checking INVITE's destination against its first route.\n"); URI_PORT(&topr_uri, uri_port); if (! (dst_port = su_getport(&dst_inv->to))) return 0; /* not really expected */ if (dst_port != uri_port) return F_RB_NH_STRICT; /* if 1st route contains an IP address, comparing it against .dst */ if ((uri_ia = str2ip(&topr_uri.host)) || (uri_ia = str2ip6(&topr_uri.host)) ) { /* we have an IP address in route -> comparison can go swiftly */ if (init_su(&uri_sau, uri_ia, uri_port) < 0) return 0; /* not really expected */ if (su_cmp(&uri_sau, &dst_inv->to)) /* ;lr and sent there */ return F_RB_NH_LOOSE; else /* ;lr and NOT sent there (probably sent to RURI address) */ return F_RB_NH_STRICT; } else { /*if 1st route contains a name, rev resolve the .dst and compare*/ LM_INFO("Failed to decode string '%.*s' in route set element as IP" " address. Trying name resolution.\n",STR_FMT(&topr_uri.host)); /* TODO: alternatively, rev name and compare against dest. IP. */ #ifdef TM_LOC_ACK_DO_REV_DNS ia.af = 0; su2ip_addr(&ia, (void *)&dst_inv->to); if (! ia.af) return 0; /* not really expected */ if ((he = rev_resolvehost(&ia))) { if ((strlen(he->h_name) == topr_uri.host.len) && (memcmp(he->h_name, topr_uri.host.s, topr_uri.host.len) == 0)) return F_RB_NH_LOOSE; for (alias = he->h_aliases; *alias; alias ++) if ((strlen(*alias) == topr_uri.host.len) && (memcmp(*alias, topr_uri.host.s, topr_uri.host.len) == 0)) return F_RB_NH_LOOSE; return F_RB_NH_STRICT; } else { LM_INFO("failed to resolve address '%s' to a name.\n", ip_addr2a(&ia)); } #endif } LM_WARN("failed to establish with certainty the type of next hop;" " trying an educated guess.\n"); /* [4] compare (possibly updated) remote target to original RURI; if * equal, a strict router's address wasn't filled in as RURI -> loose */ LM_DBG("checking remote target against INVITE's RURI.\n"); PARSE_URI(contact, &cont_uri); PARSE_URI(GET_RURI(orig_inv), &inv_ruri); URI_PORT(&cont_uri, cont_port); URI_PORT(&inv_ruri, inv_port); if ((cont_port == inv_port) && (cont_uri.host.len == inv_ruri.host.len) && (memcmp(cont_uri.host.s, inv_ruri.host.s, cont_uri.host.len) == 0)) return F_RB_NH_LOOSE; /* [5] compare (possibly updated) remote target to last route; if equal, * strict router's address might have been filled as RURI and remote * target appended to route set -> strict */ LM_DBG("checking remote target against INVITE's last route.\n"); PARSE_URI(&last_r->ptr->nameaddr.uri, &lastr_uri); URI_PORT(&lastr_uri, lastr_port); if ((cont_port == lastr_port) && (cont_uri.host.len == lastr_uri.host.len) && (memcmp(cont_uri.host.s, lastr_uri.host.s, lastr_uri.host.len) == 0)) return F_RB_NH_STRICT; LM_WARN("failed to establish the type of next hop;" " assuming loose router.\n"); return F_RB_NH_LOOSE; #undef PARSE_URI #undef HAS_LR #undef URI_PORT }
/* * send a call-info NOTIFY to all subscribers to a given SCA AoR. */ int sca_notify_call_info_subscribers(sca_mod *scam, str *subscription_aor) { sca_hash_slot *slot; sca_hash_entry *e; sca_subscription *sub; str headers = STR_NULL; str hash_key = STR_NULL; char hdrbuf[SCA_HEADERS_MAX_LEN]; char keybuf[512]; char *event_name; int slot_idx; int rc = -1; assert(scam->subscriptions != NULL); assert(!SCA_STR_EMPTY(subscription_aor)); LM_DBG("Notifying ALL subscribers of AOR %.*s due to a SUBSCRIBTION request\n", STR_FMT(subscription_aor)); event_name = sca_event_name_from_type(SCA_EVENT_TYPE_CALL_INFO); if (subscription_aor->len + strlen(event_name) >= sizeof(keybuf)) { LM_ERR("Hash key %.*s + %s is too long\n", STR_FMT(subscription_aor), event_name); return (-1); } hash_key.s = keybuf; SCA_STR_COPY(&hash_key, subscription_aor); SCA_STR_APPEND_CSTR(&hash_key, event_name); slot_idx = sca_hash_table_index_for_key(scam->subscriptions, &hash_key); slot = sca_hash_table_slot_for_index(scam->subscriptions, slot_idx); sca_hash_table_lock_index(scam->subscriptions, slot_idx); for (e = slot->entries; e != NULL; e = e->next) { sub = (sca_subscription *) e->value; if (!SCA_STR_EQ(subscription_aor, &sub->target_aor)) { continue; } if (headers.len == 0) { headers.s = hdrbuf; if (sca_notify_build_headers_from_info(&headers, sizeof(hdrbuf), scam, sub, SCA_CALL_INFO_APPEARANCE_INDEX_ANY) < 0) { LM_ERR("Failed to build NOTIFY headers\n"); goto done; } } // XXX would like this to be wrapped in one location sub->dialog.notify_cseq += 1; if (sca_notify_subscriber_internal(scam, sub, &headers) < 0) { goto done; } } rc = 1; done: sca_hash_table_unlock_index(scam->subscriptions, slot_idx); return (rc); }
/** * extract the node list from the body of a notification request SIP message * the SIP request will look something like: * KDMQ sip:10.0.0.0:5062 * To: ... * From: ... * Max-Forwards: ... * Content-Length: 22 * * sip:host1:port1;param1=value1 * sip:host2:port2;param2=value2 * ... */ int extract_node_list(dmq_node_list_t* update_list, struct sip_msg* msg) { int content_length, total_nodes = 0; str body; str tmp_uri; dmq_node_t *cur = NULL; dmq_node_t *ret, *find; char *tmp, *end, *match; if(!msg->content_length && (parse_headers(msg,HDR_CONTENTLENGTH_F,0)<0 || !msg->content_length)) { LM_ERR("no content length header found\n"); return -1; } content_length = get_content_length(msg); if(!content_length) { LM_DBG("content length is 0\n"); return total_nodes; } body.s = get_body(msg); body.len = content_length; tmp = body.s; end = body.s + body.len; /* acquire big list lock */ lock_get(&update_list->lock); while(tmp < end) { match = q_memchr(tmp, '\n', end - tmp); if(match) { match++; } else { /* for the last line - take all of it */ match = end; } /* create the orig_uri from the parsed uri line and trim it */ tmp_uri.s = tmp; tmp_uri.len = match - tmp - 1; tmp = match; /* trim the \r, \n and \0's */ trim_r(tmp_uri); find = build_dmq_node(&tmp_uri, 0); if(find==NULL) return -1; ret = find_dmq_node(update_list, find); if (!ret) { LM_DBG("found new node %.*s\n", STR_FMT(&tmp_uri)); cur = build_dmq_node(&tmp_uri, 1); if(!cur) { LM_ERR("error creating new dmq node\n"); goto error; } cur->next = update_list->nodes; update_list->nodes = cur; update_list->count++; total_nodes++; } else if (find->params && ret->status != find->status) { LM_DBG("updating status on %.*s from %d to %d\n", STR_FMT(&tmp_uri), ret->status, find->status); ret->status = find->status; total_nodes++; } destroy_dmq_node(find, 0); } /* release big list lock */ lock_release(&update_list->lock); return total_nodes; error: lock_release(&update_list->lock); return -1; }
int pv_xbuff_parse_name(pv_spec_t *sp, str *in) { char *p; str idx; str name; str attr; int l; if (in->s == NULL || in->len <= 0) return -1; p = in->s; name.s = p; while (is_in_str(p, in)) { if (*p == '[' || *p== '=') break; if (!is_pv_xbuff_valid_char(*p)) { l = p-in->s; LM_ERR("invalid character in var name %.*s at %d\n",STR_FMT(in),l); goto error; } p++; } /* from in->s to p */ name.len = p - in->s; if (pv_parse_avp_name(sp,&name)) goto error; if (is_in_str(p,in) && *p =='[') { idx.s=++p; while (is_in_str(p,in)) { if (*p == ']' || *p == '=') break; p++; } if (is_in_str(p,in) && *p==']') { idx.len = p - idx.s; if (pv_parse_index(sp,&idx)) goto error; } p++; } else { xbuff_set_attr_flag(sp->pvp.pvi.type,XBUFF_NO_IDX); } if (is_in_str(p,in) && *p =='=') { p++; if (!is_in_str(p,in) || *p!='>') { l = p-in->s; LM_ERR("invalid operator (expected =>) for accessing attribute in token %.*s at position %d\n",STR_FMT(in),l); goto error; } attr.s = ++p; while (is_in_str(p,in)) { if (!is_pv_xbuff_valid_char(*p)) { l = p-in->s; LM_ERR("invalid character in attribute name in token %.*s at %d\n",STR_FMT(in),l); goto error; } p++; } attr.len = p - attr.s; if (attr.len > 0 ) { if (STR_EQ(attr,xbuff_attr_name(XBUFF_ATTR_TYPE))) { xbuff_set_attr_flag(sp->pvp.pvi.type,XBUFF_ATTR_TYPE); } else if (STR_EQ(attr,xbuff_attr_name(XBUFF_ATTR_FORMAT))) { xbuff_set_attr_flag(sp->pvp.pvi.type,XBUFF_ATTR_FORMAT); } else if (STR_EQ(attr,xbuff_attr_name(XBUFF_ATTR_LENGTH))) { xbuff_set_attr_flag(sp->pvp.pvi.type,XBUFF_ATTR_LENGTH); } else { LM_ERR("unknown attribute %.*s\n",STR_FMT(&attr)); goto error; } if (sp->pvp.pvi.type & PV_IDX_ALL) { LM_ERR("index [*] (all) isn't compatible with attribute %.*s\n",STR_FMT(&attr)); goto error; } } } if (p < in->s + in->len) { l = p-in->s; LM_ERR("unexpected token in %.*s at %d\n",STR_FMT(in),l); goto error; } return 0; error: return -1; }
/* * Function returns always success - we uses EPMD for transport */ int erl_rpc_send(erl_rpc_ctx_t *ctx, int depth) { if (ctx->response_sent) return 0; ctx->response_sent = 1; erl_rpc_ctx_t *handler; erl_rpc_param_t *fault = *(ctx->fault_p); if (fault) { LM_ERR("fault: %d %.*s\n",fault->type, STR_FMT(&fault->value.S)); /* restore clear point */ ctx->response->index = ctx->response_index; /* {error,{struct,[ {"code", 400}, {"error","Error message"}]}}*/ if (ei_x_encode_tuple_header(ctx->response,1)) goto error; /* {error,{_,_}} */ if (rpc_reply_with_struct && ei_x_encode_atom(ctx->response,"struct")) goto error; /* {error,{struct,_}} */ if (ei_x_encode_list_header(ctx->response,2)) goto error; /* {error,{struct,[_,_]}} */ if (ei_x_encode_tuple_header(ctx->response,2)) goto error; /* {error,{struct,[{_,_},_]}} */ if (ei_x_encode_atom(ctx->response,"code")) goto error; /* {error,{struct,[{code,_},_]}} */ if (ei_x_encode_long(ctx->response,fault->type)) goto error;/* {error,{struct,[{code,400},_]}} */ if (ei_x_encode_tuple_header(ctx->response,2)) goto error; /* {error,{struct,[{code,400},{_,_}]}} */ if (ei_x_encode_binary(ctx->response,"error",sizeof("error")-1)) goto error; /* {error,{struct,[{code,400},{<<"error">>,_}]}} */ if (ei_x_encode_binary(ctx->response,(void*)fault->value.S.s,fault->value.S.len)) /* {error,{struct,[{code,400},{<<"error">>,<<Msg>>}]}} */ goto error; if (ei_x_encode_empty_list(ctx->response)) goto error; } else if (ctx->reply_params) { while(ctx->reply_params) { if (ctx->reply_params->member_name) { /* {"member_name", _} */ if (ei_x_encode_tuple_header(ctx->response,2)) goto error; if (ei_x_encode_binary(ctx->response,ctx->reply_params->member_name, strlen(ctx->reply_params->member_name))) goto error; } /* {"member_name", MemberValue} */ switch (ctx->reply_params->type) { case ERL_INTEGER_EXT: if(ei_x_encode_long(ctx->response,ctx->reply_params->value.n)) goto error; break; case ERL_FLOAT_EXT: if(ei_x_encode_double(ctx->response,ctx->reply_params->value.d)) goto error; break; case ERL_STRING_EXT: if(ei_x_encode_binary(ctx->response,ctx->reply_params->value.S.s,ctx->reply_params->value.S.len)) goto error; break; case ERL_SMALL_TUPLE_EXT: /* add as {struct,list(no_params)} */ handler = (erl_rpc_ctx_t*)ctx->reply_params->value.handler; if (ei_x_encode_tuple_header(ctx->response,1)) goto error; if (rpc_reply_with_struct && ei_x_encode_atom(ctx->response,"struct")) goto error; if (ei_x_encode_list_header(ctx->response,handler->no_params)) goto error; if (erl_rpc_send(handler, depth++)) goto error; if (ei_x_encode_empty_list(ctx->response)) goto error; break; case ERL_LIST_EXT: /* add as [list(no_params)] */ handler = (erl_rpc_ctx_t*)ctx->reply_params->value.handler; if (ei_x_encode_list_header(ctx->response,handler->no_params)) goto error; if (erl_rpc_send(handler, depth++)) goto error; if (handler->no_params) if (ei_x_encode_empty_list(ctx->response)) goto error; break; default: LM_ERR("Unknown type '%c' for encoding RPC reply\n",ctx->reply_params->type); break; } ctx->reply_params=ctx->reply_params->next; } } else if (!depth) { /* restore start point */ LM_WARN("encode empty response -> ok"); ctx->response->index = ctx->response_index; if (ei_x_encode_atom(ctx->response,"ok")) goto error; } return 0; error: LM_ERR("error while encoding response\n"); return -1; }
static int __ensure_codec_handler(struct media_player *mp, AVStream *avs) { if (mp->handler) return 0; // synthesise rtp payload type struct rtp_payload_type src_pt = { .payload_type = -1 }; // src_pt.codec_def = codec_find_by_av(avs->codec->codec_id); `codec` is deprecated src_pt.codec_def = codec_find_by_av(avs->CODECPAR->codec_id); if (!src_pt.codec_def) { ilog(LOG_ERR, "Attempting to play media from an unsupported file format/codec"); return -1; } src_pt.encoding = src_pt.codec_def->rtpname_str; src_pt.channels = avs->CODECPAR->channels; src_pt.clock_rate = avs->CODECPAR->sample_rate; codec_init_payload_type(&src_pt, mp->media); // find suitable output payload type struct rtp_payload_type *dst_pt; for (GList *l = mp->media->codecs_prefs_send.head; l; l = l->next) { dst_pt = l->data; if (dst_pt->codec_def && !dst_pt->codec_def->supplemental) goto found; } dst_pt = NULL; found: if (!dst_pt) { ilog(LOG_ERR, "No supported output codec found in SDP"); return -1; } ilog(LOG_DEBUG, "Output codec for media playback is " STR_FORMAT, STR_FMT(&dst_pt->encoding_with_params)); // if we played anything before, scale our sync TS according to the time // that has passed if (mp->sync_ts_tv.tv_sec) { long long ts_diff_us = timeval_diff(&rtpe_now, &mp->sync_ts_tv); mp->sync_ts += ts_diff_us * dst_pt->clock_rate / 1000000 / dst_pt->codec_def->clockrate_mult; } mp->handler = codec_handler_make_playback(&src_pt, dst_pt, mp->sync_ts); if (!mp->handler) return -1; mp->duration = avs->duration * 1000 * avs->time_base.num / avs->time_base.den; return 0; } // appropriate lock must be held static void media_player_read_packet(struct media_player *mp) { if (!mp->fmtctx) return; int ret = av_read_frame(mp->fmtctx, &mp->pkt); if (ret < 0) { if (ret == AVERROR_EOF) { ilog(LOG_DEBUG, "EOF reading from media stream"); return; } ilog(LOG_ERR, "Error while reading from media stream"); return; } if (!mp->fmtctx->streams) { ilog(LOG_ERR, "No AVStream present in format context"); goto out; } AVStream *avs = mp->fmtctx->streams[0]; if (!avs) { ilog(LOG_ERR, "No AVStream present in format context"); goto out; } if (__ensure_codec_handler(mp, avs)) goto out; // scale pts and duration according to sample rate long long duration_scaled = mp->pkt.duration * avs->CODECPAR->sample_rate * avs->time_base.num / avs->time_base.den; unsigned long long pts_scaled = mp->pkt.pts * avs->CODECPAR->sample_rate * avs->time_base.num / avs->time_base.den; long long us_dur = mp->pkt.duration * 1000000LL * avs->time_base.num / avs->time_base.den; ilog(LOG_DEBUG, "read media packet: pts %llu duration %lli (scaled %llu/%lli, %lli us), " "sample rate %i, time_base %i/%i", (unsigned long long) mp->pkt.pts, (long long) mp->pkt.duration, pts_scaled, duration_scaled, us_dur, avs->CODECPAR->sample_rate, avs->time_base.num, avs->time_base.den); // synthesise fake RTP header and media_packet context struct rtp_header rtp = { .timestamp = pts_scaled, // taken verbatim by handler_func_playback w/o byte swap .seq_num = htons(mp->seq), }; struct media_packet packet = { .tv = rtpe_now, .call = mp->call, .media = mp->media, .rtp = &rtp, .ssrc_out = mp->ssrc_out, }; str_init_len(&packet.raw, (char *) mp->pkt.data, mp->pkt.size); packet.payload = packet.raw; mp->handler->func(mp->handler, &packet); // as this is timing sensitive and we may have spent some time decoding, // update our global "now" timestamp gettimeofday(&rtpe_now, NULL); // keep track of RTP timestamps and real clock. look at the last packet we received // and update our sync TS. if (packet.packets_out.head) { struct codec_packet *p = packet.packets_out.head->data; if (p->rtp) { mp->sync_ts = ntohl(p->rtp->timestamp); mp->sync_ts_tv = p->to_send; } } media_packet_encrypt(mp->crypt_handler->out->rtp_crypt, mp->sink, &packet); mutex_lock(&mp->sink->out_lock); if (media_socket_dequeue(&packet, mp->sink)) ilog(LOG_ERR, "Error sending playback media to RTP sink"); mutex_unlock(&mp->sink->out_lock); timeval_add_usec(&mp->next_run, us_dur); timerthread_obj_schedule_abs(&mp->tt_obj, &mp->next_run); out: av_packet_unref(&mp->pkt); } // call->master_lock held in W static int media_player_play_init(struct media_player *mp) { media_player_shutdown(mp); // find call media suitable for playback struct call_media *media; for (GList *l = mp->ml->medias.head; l; l = l->next) { media = l->data; if (media->type_id != MT_AUDIO) continue; if (!MEDIA_ISSET(media, SEND)) continue; if (media->streams.length == 0) continue; goto found; } media = NULL; found: if (!media) { ilog(LOG_ERR, "No suitable SDP section for media playback"); return -1; } mp->media = media; mp->sink = media->streams.head->data; mp->crypt_handler = determine_handler(&transport_protocols[PROTO_RTP_AVP], media, 1); return 0; } // call->master_lock held in W static void media_player_play_start(struct media_player *mp) { // needed to have usable duration for some formats. ignore errors. avformat_find_stream_info(mp->fmtctx, NULL); mp->next_run = rtpe_now; // give ourselves a bit of a head start with decoding timeval_add_usec(&mp->next_run, -50000); media_player_read_packet(mp); } #endif // call->master_lock held in W int media_player_play_file(struct media_player *mp, const str *file) { #ifdef WITH_TRANSCODING if (media_player_play_init(mp)) return -1; char file_s[PATH_MAX]; snprintf(file_s, sizeof(file_s), STR_FORMAT, STR_FMT(file)); int ret = avformat_open_input(&mp->fmtctx, file_s, NULL, NULL); if (ret < 0) { ilog(LOG_ERR, "Failed to open media file for playback: %s", av_error(ret)); return -1; } media_player_play_start(mp); return 0; #else return -1; #endif } #ifdef WITH_TRANSCODING static int __mp_avio_read_wrap(void *opaque, uint8_t *buf, int buf_size) { struct media_player *mp = opaque; if (buf_size < 0) return AVERROR(EINVAL); if (buf_size == 0) return 0; if (!mp->read_pos.len) return AVERROR_EOF; int len = buf_size; if (len > mp->read_pos.len) len = mp->read_pos.len; memcpy(buf, mp->read_pos.s, len); str_shift(&mp->read_pos, len); return len; } static int __mp_avio_read(void *opaque, uint8_t *buf, int buf_size) { ilog(LOG_DEBUG, "__mp_avio_read(%i)", buf_size); int ret = __mp_avio_read_wrap(opaque, buf, buf_size); ilog(LOG_DEBUG, "__mp_avio_read(%i) = %i", buf_size, ret); return ret; }
/* call must be locked R or W, agent must not be locked */ static void __do_ice_checks(struct ice_agent *ag) { GList *l; struct ice_candidate_pair *pair, *highest = NULL, *frozen = NULL, *valid; struct packet_stream *ps; GQueue retransmits = G_QUEUE_INIT; struct timeval next_run = {0,0}; int have_more = 0; if (!ag) { ilog(LOG_ERR, "ice ag is NULL"); return; } if (!ag->pwd[0].s) return; atomic64_set(&ag->last_activity, poller_now); __DBG("running checks, call "STR_FORMAT" tag "STR_FORMAT"", STR_FMT(&ag->call->callid), STR_FMT(&ag->media->monologue->tag)); mutex_lock(&ag->lock); /* check if we're done and should start nominating pairs */ if (AGENT_ISSET(ag, CONTROLLING) && !AGENT_ISSET(ag, NOMINATING) && ag->start_nominating.tv_sec) { if (timeval_cmp(&g_now, &ag->start_nominating) >= 0) __nominate_pairs(ag); timeval_lowest(&next_run, &ag->start_nominating); } /* triggered checks are preferred */ pair = g_queue_pop_head(&ag->triggered); if (pair) { PAIR_CLEAR(pair, TRIGGERED); next_run = g_now; goto check; } /* find the highest-priority non-frozen non-in-progress pair */ for (l = ag->all_pairs_list.head; l; l = l->next) { pair = l->data; /* skip dead streams */ ps = pair->packet_stream; if (!ps || !ps->sfd) continue; if (PAIR_ISSET(pair, FAILED)) continue; if (PAIR_ISSET(pair, SUCCEEDED) && !PAIR_ISSET(pair, TO_USE)) continue; valid = __get_pair_by_component(ag->valid_pairs, pair->remote_candidate->component_id); if (PAIR_ISSET(pair, IN_PROGRESS)) { /* handle retransmits */ /* but only if our priority is lower than any valid pair */ if (valid && valid->pair_priority > pair->pair_priority) continue; if (timeval_cmp(&pair->retransmit, &g_now) <= 0) g_queue_push_tail(&retransmits, pair); /* can't run check directly due to locks */ else timeval_lowest(&next_run, &pair->retransmit); continue; } /* don't do anything else if we already have a valid pair */ if (valid) continue; /* or if we're in or past the final phase */ if (AGENT_ISSET2(ag, NOMINATING, COMPLETED)) continue; have_more = 1; /* remember the first frozen pair in case we find nothing else */ if (PAIR_ISSET(pair, FROZEN)) { if (!frozen) frozen = pair; continue; } if (!highest) highest = pair; } if (highest) pair = highest; else if (frozen) pair = frozen; else pair = NULL; check: mutex_unlock(&ag->lock); if (pair) __do_ice_check(pair); while ((pair = g_queue_pop_head(&retransmits))) __do_ice_check(pair); /* determine when to run next */ if (have_more) __agent_schedule(ag, 0); else if (next_run.tv_sec) __agent_schedule_abs(ag, &next_run); /* for retransmits */ }
/** * internal implementation */ int worker_rpc_impl(ei_cnode *ec, int s,int wpid) { str module = STR_NULL; str function = STR_NULL; ei_x_buff args; ei_x_buff reply; struct msghdr msgh; struct iovec cnt[6]; int rc; memset((void*)&args,0,sizeof(args)); memset((void*)&reply,0,sizeof(reply)); memset((void*)&msgh,0,sizeof(msgh)); /* module name length */ cnt[0].iov_base = &module.len; cnt[0].iov_len = sizeof(int); /* function name length */ cnt[1].iov_base = &function.len; cnt[1].iov_len = sizeof(int); /* Erlang args size */ cnt[2].iov_base = &args.buffsz; cnt[2].iov_len = sizeof(int); /* get data size */ msgh.msg_iov = cnt; msgh.msg_iovlen = 3; while ((rc = recvmsg(s, &msgh, MSG_PEEK)) == -1 && errno == EAGAIN) ; if (rc == -1){ LM_ERR("recvmsg failed (socket=%d): %s\n",s,strerror(errno)); goto err; } /* allocate space */ module.s = (char*)pkg_malloc(module.len+1); if (!module.s) { LM_ERR("not enough memory\n"); goto err; } function.s = (char*)pkg_malloc(function.len+1); if (!function.s) { LM_ERR("not enough memory\n"); goto err; } args.buff = (char*)malloc(args.buffsz); if (!args.buff) { LM_ERR("malloc: not enough memory\n"); goto err; } /* buffers */ cnt[3].iov_base = module.s; cnt[3].iov_len = module.len; cnt[4].iov_base = function.s; cnt[4].iov_len = function.len; cnt[5].iov_base = args.buff; cnt[5].iov_len = args.buffsz; /* get whole data */ msgh.msg_iovlen = 6; while ((rc = recvmsg(s, &msgh, MSG_WAITALL)) == -1 && errno == EAGAIN) ; if (rc == -1){ LM_ERR("recvmsg failed (socket=%d): %s\n",s,strerror(errno)); goto err; } /* fix str */ module.s[module.len] = 0; function.s[function.len] = 0; LM_DBG("rpc: %.*s:%.*s(args)\n",STR_FMT(&module),STR_FMT(&function)); EI_X_BUFF_PRINT(&args); if(!enode) { LM_NOTICE("there is no connected Erlang node\n"); /* reply up with error */ ei_x_format(&reply, "{error,cnode,~a}", "no_erlang_node"); goto reply; } /* do RPC */ if ((rc = ei_rpc(ec,enode->sockfd,module.s,function.s,args.buff,args.buffsz,&reply)) == ERL_ERROR) { reply.index = 0; /* re-use reply buffer */ if (erl_errno) { ei_x_format(&reply, "{error,cnode,~s}", strerror(erl_errno)); LM_ERR("ei_rpc failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(erl_errno)); } else if (errno) { ei_x_format(&reply, "{error,cnode,~s}", strerror(errno)); LM_ERR("ei_rpc failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(errno)); } else { ei_x_format(&reply, "{error,cnode,~s}", "Unknown error."); LM_ERR("ei_rpc failed on node=<%s> socket=<%d>, Unknown error.\n",ec->thisalivename,enode->sockfd); } } reply: EI_X_BUFF_PRINT(&reply); cnt[0].iov_base = (void*)&wpid; cnt[0].iov_len = sizeof(int); /* send reply to Kamailio worker */ cnt[1].iov_base = (void*)&reply.buffsz; cnt[1].iov_len = sizeof(int); cnt[2].iov_base = (void*)reply.buff; cnt[2].iov_len = reply.buffsz; msgh.msg_iovlen = 3; while ((rc = sendmsg(s, &msgh, 0)) == -1 && errno == EAGAIN) ; if (rc == -1) { LM_ERR("sendmsg failed on socket=%d rpid_no=%d; %s\n",s, wpid, strerror(errno)); goto err; }; pkg_free(module.s); pkg_free(function.s); free(args.buff); ei_x_free(&reply); return 0; err: pkg_free(module.s); pkg_free(function.s); free(args.buff); ei_x_free(&reply); abort(); /* cant't recover */ return -1; }
static bool read_config(const char *file_path, Context *ctx) { Variable *last_var = NULL; GList *itr; FILE *f; char line[LINE_SIZE]; char name[NAME_SIZE]; int tmp; // default values ctx->read_freq = READ_FREQ; ctx->days = DAYS; ctx->time_blocks = TIME_BLOCKS; ctx->read_counter = 0; ctx->enable_time_input = 1; ctx->enable_weekday_input = 1; ctx->inputs = NULL; ctx->outputs = NULL; ctx->expectations = NULL; ctx->expectation_blocks = NULL; ctx->time = NULL; ctx->weekday = NULL; f = fopen(file_path, "r"); if (!f) { fprintf(stderr, "Failed to open %s\n", file_path); return false; } while (fgets(line, LINE_SIZE, f)) { float min = 0, max = 0; int ret; // empty or comment line if ((line[0] == '\n') || (line[0] == '#')) continue; ret = sscanf(line, "TIME_BLOCKS %d\n", &ctx->time_blocks); if (ret > 0) { last_var = NULL; continue; } ret = sscanf(line, "DAYS %d\n", &ctx->days); if (ret > 0) { last_var = NULL; continue; } ret = sscanf(line, "READ_FREQ %d\n", &ctx->read_freq); if (ret > 0) { last_var = NULL; continue; } ret = sscanf(line, "ENABLE_TIME_INPUT %d\n", &tmp); if (ret > 0) { ctx->enable_time_input = !!tmp; last_var = NULL; continue; } ret = sscanf(line, "ENABLE_WEEKDAY_INPUT %d\n", &tmp); if (ret > 0) { ctx->enable_weekday_input = !!tmp; last_var = NULL; continue; } ret = sscanf(line, "INPUT " STR_FMT(NAME_SIZE) " %f %f\n", name, &min, &max); if (ret > 0) { last_var = add_input(ctx, name, min, max); continue; } ret = sscanf(line, "OUTPUT " STR_FMT(NAME_SIZE) " %f %f\n", name, &min, &max); if (ret > 0) { last_var = add_output(ctx, name, min, max); add_expectation(ctx, last_var, name); continue; } ret = sscanf(line, "TERM " STR_FMT(NAME_SIZE) " %f %f\n", name, &min, &max); if (ret > 0) { if (!last_var) { fprintf(stderr, "Failed to find var for term %s\n", line); goto error; } add_term(ctx, last_var, name, min, max); continue; } fprintf(stderr, "Unknow configuration %s\n", line); goto error; } ctx->reads = 24 * 60 / ctx->read_freq * ctx->days; for (itr = ctx->inputs; itr; itr = itr->next) { Variable *var = itr->data; if (!var->terms) variable_add_terms(ctx, var); } for (itr = ctx->outputs; itr; itr = itr->next) { Variable *var = itr->data; if (!var->terms) variable_add_terms(ctx, var); } fclose(f); return true; error: fclose(f); return false; }
/* * Adds to request a new destination set that includes all highest * priority class contacts in contacts_avp. Request URI is rewritten with * first contact and the remaining contacts (if any) are added as branches. * Removes used contacts from contacts_avp. Returns 1, if contacts_avp * was not empty and a destination set was successfully added. Returns -2, * if contacts_avp was empty and thus there was nothing to do. * Returns -1 in case of an error. */ int t_next_contacts(struct sip_msg* msg, char* key, char* value) { struct usr_avp *avp, *prev; int_str val; str uri, dst, path; struct socket_info *sock; unsigned int flags; struct search_state st; /* Check if contacts_avp has been defined */ if (contacts_avp.n == 0) { LM_ERR("feature has been disabled - " "to enable define contacts_avp module parameter"); return -1; } /* Load Request-URI and branches */ /* Find first contacts_avp value */ avp = search_first_avp(contacts_avp_type, contacts_avp, &val, &st); if (!avp) { LM_DBG("no AVPs - we are done!\n"); return -2; } LM_DBG("next contact is <%.*s>\n", STR_FMT(&val.s)); if (decode_branch_info(val.s.s, &uri, &dst, &path, &sock, &flags) == 0) { LM_ERR("decoding of branch info <%.*s> failed\n", STR_FMT(&val.s)); destroy_avp(avp); return -1; } /* Rewrite Request-URI */ rewrite_uri(msg, &uri); if (dst.s && dst.len) set_dst_uri(msg, &dst); else reset_dst_uri(msg); if (path.s && path.len) set_path_vector(msg, &path); else reset_path_vector(msg); set_force_socket(msg, sock); setbflagsval(0, flags); if (avp->flags & Q_FLAG) { destroy_avp(avp); return 1; } /* Append branches until out of branches or Q_FLAG is set */ prev = avp; while ((avp = search_next_avp(&st, &val))) { destroy_avp(prev); LM_DBG("next contact is <%.*s>\n", STR_FMT(&val.s)); if (decode_branch_info(val.s.s, &uri, &dst, &path, &sock, &flags) == 0) { LM_ERR("decoding of branch info <%.*s> failed\n", STR_FMT(&val.s)); destroy_avp(avp); return -1; } if (append_branch(msg, &uri, &dst, &path, 0, flags, sock) != 1) { LM_ERR("appending branch failed\n"); destroy_avp(avp); return -1; } if (avp->flags & Q_FLAG) { destroy_avp(avp); return 1; } prev = avp; } destroy_avp(prev); return 1; }