/* * Send a transactional request, no dialogs involved * WARNING: writes uac_r->dialog */ int request(uac_req_t *uac_r, str* ruri, str* to, str* from, str *next_hop) { str callid, fromtag; dlg_t* dialog; int res; if (check_params(uac_r, to, from) < 0) goto err; if (uac_r->callid == NULL || uac_r->callid->len <= 0) generate_callid(&callid); else callid = *uac_r->callid; generate_fromtag(&fromtag, &callid); if (new_dlg_uac(&callid, &fromtag, DEFAULT_CSEQ, from, to, &dialog) < 0) { LOG(L_ERR, "request(): Error while creating temporary dialog\n"); goto err; } if (ruri) { dialog->rem_target.s = ruri->s; dialog->rem_target.len = ruri->len; /* hooks will be set from w_calculate_hooks */ } if (next_hop) dialog->dst_uri = *next_hop; w_calculate_hooks(dialog); /* WARNING: * to be clean it should be called * set_dlg_target(dialog, ruri, next_hop); * which sets both uris if given [but it duplicates them in shm!] * * but in this case the _ruri parameter in set_dlg_target * must be optional (it is needed now) and following hacks * dialog->rem_target.s = 0; * dialog->dst_uri.s = 0; * before freeing dialog here must be removed */ uac_r->dialog = dialog; if(uac_r->ssock!=NULL && uac_r->ssock->len>0 && uac_r->dialog->send_sock==NULL) { /* set local send socket */ uac_r->dialog->send_sock = lookup_local_socket(uac_r->ssock); } res = t_uac(uac_r); dialog->rem_target.s = 0; dialog->dst_uri.s = 0; free_dlg(dialog); uac_r->dialog = 0; return res; err: /* callback parameter must be freed outside of tm module if (cp) shm_free(cp); */ return -1; }
/** * @brief config file function for replicating SIP message to all nodes (wraps t_replicate) */ int cfg_dmq_t_replicate(struct sip_msg* msg, char* s) { dmq_node_t* node; struct socket_info* sock; int i = 0; int first = 1; /* avoid loops - do not replicate if message has come from another node * (override if optional parameter is set) */ if ((!s || (get_int_fparam(&i, msg, (fparam_t*)s)==0 && !i)) && (is_from_remote_node(msg) > 0)) { LM_DBG("message is from another node - skipping replication\n"); return -1; } /* TODO - backup/restore original send socket */ sock = lookup_local_socket(&dmq_server_socket); if (sock) { set_force_socket(msg, sock); } lock_get(&node_list->lock); node = node_list->nodes; while(node) { /* we do not send the message to the following: * - ourself * - any inactive nodes */ if(node->local || node->status != DMQ_NODE_ACTIVE) { LM_DBG("skipping node %.*s\n", STR_FMT(&node->orig_uri)); node = node->next; continue; } if (!first) { if (append_branch(msg, 0, 0, 0, Q_UNSPECIFIED, 0, sock, 0, 0, 0, 0) == -1) { LM_ERR("failed to append a branch\n"); node = node->next; continue; } } else { first = 0; } if(tmb.t_replicate(msg, &node->orig_uri) < 0) { LM_ERR("error calling t_replicate\n"); goto error; } node = node->next; } lock_release(&node_list->lock); return 0; error: lock_release(&node_list->lock); return -1; }
int rtjson_append_branch(sip_msg_t *msg, srjson_doc_t *jdoc, srjson_t *nj) { srjson_t *rj = NULL; str uri = {0}; str duri = {0}; str path = {0}; str socket = {0}; struct socket_info* fsocket = NULL; unsigned int bflags = 0; rj = srjson_GetObjectItem(jdoc, nj, "uri"); if(rj==NULL || rj->type!=srjson_String || rj->valuestring==NULL) { return -1; } uri.s = rj->valuestring; uri.len = strlen(uri.s); rj = srjson_GetObjectItem(jdoc, nj, "dst_uri"); if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) { duri.s = rj->valuestring; duri.len = strlen(duri.s); } rj = srjson_GetObjectItem(jdoc, nj, "path"); if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) { path.s = rj->valuestring; path.len = strlen(path.s); } rj = srjson_GetObjectItem(jdoc, nj, "socket"); if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) { socket.s = rj->valuestring; socket.len = strlen(socket.s); fsocket = lookup_local_socket(&socket); } if (append_branch(msg, &uri, &duri, &path, 0, bflags, fsocket, 0 /*instance*/, 0, 0, 0) <0) { LM_ERR("failed to append branch\n"); goto error; } return 0; error: return -1; }
/* * Send an initial request that will start a dialog * WARNING: writes uac_r->dialog */ int req_outside(uac_req_t *uac_r, str* ruri, str* to, str* from, str *next_hop) { str callid, fromtag; if (check_params(uac_r, to, from) < 0) goto err; generate_callid(&callid); generate_fromtag(&fromtag, &callid); if (new_dlg_uac(&callid, &fromtag, DEFAULT_CSEQ, from, to, &uac_r->dialog) < 0) { LOG(L_ERR, "req_outside(): Error while creating new dialog\n"); goto err; } if (ruri) { uac_r->dialog->rem_target.s = ruri->s; uac_r->dialog->rem_target.len = ruri->len; /* hooks will be set from w_calculate_hooks */ } if (next_hop) uac_r->dialog->dst_uri = *next_hop; w_calculate_hooks(uac_r->dialog); if(uac_r->ssock!=NULL && uac_r->ssock->len>0 && uac_r->dialog->send_sock==NULL) { /* set local send socket */ uac_r->dialog->send_sock = lookup_local_socket(uac_r->ssock); } return t_uac(uac_r); err: /* callback parameter must be freed outside of tm module if (cbp) shm_free(cbp); */ return -1; }
/* * Send a message within a dialog */ int req_within(uac_req_t *uac_r) { if (!uac_r || !uac_r->method || !uac_r->dialog) { LOG(L_ERR, "req_within: Invalid parameter value\n"); goto err; } if(uac_r->ssock!=NULL && uac_r->ssock->len>0 && uac_r->dialog->send_sock==NULL) { /* set local send socket */ uac_r->dialog->send_sock = lookup_local_socket(uac_r->ssock); } if ((uac_r->method->len == 3) && (!memcmp("ACK", uac_r->method->s, 3))) goto send; if ((uac_r->method->len == 6) && (!memcmp("CANCEL", uac_r->method->s, 6))) goto send; uac_r->dialog->loc_seq.value++; /* Increment CSeq */ send: return t_uac(uac_r); err: /* callback parameter must be freed outside of tm module if (cbp) shm_free(cbp); */ return -1; }
/** * init module function */ static int mod_init(void) { if(register_mi_mod(exports.name, mi_cmds)!=0) { LM_ERR("failed to register MI commands\n"); return -1; } /* bind the SL API */ if (sl_load_api(&slb)!=0) { LM_ERR("cannot bind to SL API\n"); return -1; } /* load all TM stuff */ if(load_tm_api(&tmb)==-1) { LM_ERR("can't load tm functions. TM module probably not loaded\n"); return -1; } /* load peer list - the list containing the module callbacks for dmq */ peer_list = init_peer_list(); if(peer_list==NULL) { LM_ERR("cannot initialize peer list\n"); return -1; } /* load the dmq node list - the list containing the dmq servers */ node_list = init_dmq_node_list(); if(node_list==NULL) { LM_ERR("cannot initialize node list\n"); return -1; } if (rpc_register_array(rpc_methods)!=0) { LM_ERR("failed to register RPC commands\n"); return -1; } /* register worker processes - add one because of the ping process */ register_procs(num_workers); /* check server_address and notification_address are not empty and correct */ if(parse_uri(dmq_server_address.s, dmq_server_address.len, &dmq_server_uri) < 0) { LM_ERR("server address invalid\n"); return -1; } if(parse_uri(dmq_notification_address.s, dmq_notification_address.len, &dmq_notification_uri) < 0) { LM_ERR("notification address invalid\n"); return -1; } /* create socket string out of the server_uri */ if(make_socket_str_from_uri(&dmq_server_uri, &dmq_server_socket) < 0) { LM_ERR("failed to create socket out of server_uri\n"); return -1; } if (lookup_local_socket(&dmq_server_socket) == NULL) { LM_ERR("server_uri is not a socket the proxy is listening on\n"); return -1; } /* allocate workers array */ workers = shm_malloc(num_workers * sizeof(*workers)); if(workers == NULL) { LM_ERR("error in shm_malloc\n"); return -1; } dmq_init_callback_done = shm_malloc(sizeof(int)); if (!dmq_init_callback_done) { LM_ERR("no more shm\n"); return -1; } *dmq_init_callback_done = 0; /** * add the dmq notification peer. * the dmq is a peer itself so that it can receive node notifications */ if(add_notification_peer()<0) { LM_ERR("cannot add notification peer\n"); return -1; } startup_time = (int) time(NULL); /** * add the ping timer * it pings the servers once in a while so that we know which failed */ if(ping_interval < MIN_PING_INTERVAL) { ping_interval = MIN_PING_INTERVAL; } if(register_timer(ping_servers, 0, ping_interval)<0) { LM_ERR("cannot register timer callback\n"); return -1; } return 0; }
int rtjson_init_serial(sip_msg_t *msg, srjson_doc_t *jdoc, sr_xavp_t *iavp) { srjson_t *tj = NULL; srjson_t *nj = NULL; srjson_t *rj = NULL; str val; unsigned int bflags = 0; unsigned int old_bflags = 0; struct socket_info* fsocket = NULL; tj = srjson_GetObjectItem(jdoc, jdoc->root, "routes"); if(tj==NULL || tj->type!=srjson_Array || tj->child==NULL) { LM_ERR("missing or invalid routes field\n"); goto error; } nj = tj->child; clear_branches(); rj = srjson_GetObjectItem(jdoc, nj, "uri"); if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) { val.s = rj->valuestring; val.len = strlen(val.s); LM_DBG("rewrite r-uri to: [%.*s]\n", val.len, val.s); if (rewrite_uri(msg, &val) < 0) { LM_ERR("unable to rewrite Request-URI\n"); goto error; } } reset_dst_uri(msg); reset_path_vector(msg); reset_instance(msg); reset_ruid(msg); reset_ua(msg); reset_force_socket(msg); msg->reg_id = 0; set_ruri_q(0); rj = srjson_GetObjectItem(jdoc, nj, "dst_uri"); if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) { val.s = rj->valuestring; val.len = strlen(val.s); LM_DBG("rewrite dst-uri to: [%.*s]\n", val.len, val.s); if (set_dst_uri(msg, &val) < 0) { LM_ERR("unable to set destination uri\n"); goto error; } } rj = srjson_GetObjectItem(jdoc, nj, "path"); if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) { val.s = rj->valuestring; val.len = strlen(val.s); LM_DBG("rewrite path to: [%.*s]\n", val.len, val.s); if (set_path_vector(msg, &val) < 0) { LM_ERR("unable to set path\n"); goto error; } } rj = srjson_GetObjectItem(jdoc, nj, "socket"); if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) { val.s = rj->valuestring; val.len = strlen(val.s); LM_DBG("trying to set send socket to: [%.*s]\n", val.len, val.s); fsocket = lookup_local_socket(&val); if(fsocket) { set_force_socket(msg, fsocket); } } rj = srjson_GetObjectItem(jdoc, nj, "branch_flags"); if(rj!=NULL && rj->type==srjson_Number && SRJSON_GET_UINT(rj)!=0) { bflags = SRJSON_GET_UINT(rj); old_bflags = 0; getbflagsval(0, &old_bflags); setbflagsval(0, old_bflags|bflags); } iavp->val.v.i++; return 0; error: return -1; }