/*! * \brief Parse the record-route parameter, to get dialog information back * \param p start of parameter string * \param end end of parameter string * \param h_entry found dialog hash entry * \param h_id found dialog hash id * \return 0 on success, -1 on failure */ static inline int parse_dlg_rr_param(char *p, char *end, int *h_entry, int *h_id) { char *s; /* sanity checks */ if (!p) { LM_ERR("NULL start of parameter string"); return -1; } if (!end) { LM_ERR("NULL end of parameter string"); return -1; } if (!h_entry) { LM_ERR("NULL h_entry"); return -1; } if (!h_id) { LM_ERR("NULL h_id"); return -1; } for ( s=p ; p<end && *p!=DLG_SEPARATOR ; p++ ); if (*p!=DLG_SEPARATOR) { LM_ERR("malformed rr param '%.*s'\n", (int)(long)(end-s), s); return -1; } if ( reverse_hex2int( s, p-s, (unsigned int*)h_entry)<0 ) { LM_ERR("invalid hash entry '%.*s'\n", (int)(long)(p-s), s); return -1; } if ( reverse_hex2int( p+1, end-(p+1), (unsigned int*)h_id)<0 ) { LM_ERR("invalid hash id '%.*s'\n", (int)(long)(end-(p+1)), p+1 ); return -1; } return 0; }
/*! * \brief Parse the record-route parameter, to get dialog information back * \param p start of parameter string * \param end end of parameter string * \param h_entry found dialog hash entry * \param h_id found dialog hash id * \return 0 on success, -1 on failure */ static inline int parse_dlg_rr_param(char *p, char *end, int *h_entry, int *h_id) { char *s; for (s = p; p < end && *p != DLG_SEPARATOR; p++); if (*p != DLG_SEPARATOR) { LM_ERR("malformed rr param '%.*s'\n", (int) (long) (end - s), s); return -1; } if (reverse_hex2int(s, p - s, (unsigned int*) h_entry) < 0) { LM_ERR("invalid hash entry '%.*s'\n", (int) (long) (p - s), s); return -1; } if (reverse_hex2int(p + 1, end - (p + 1), (unsigned int*) h_id) < 0) { LM_ERR("invalid hash id '%.*s'\n", (int) (long) (end - (p + 1)), p + 1); return -1; } return 0; }
int AmSession::acceptAudio(const string& body, const string& hdrs, string* sdp_reply) { try { try { // handle codec and send reply string str_msg_flags = getHeader(hdrs,"P-MsgFlags"); unsigned int msg_flags = 0; if(reverse_hex2int(str_msg_flags,msg_flags)){ ERROR("while parsing 'P-MsgFlags' header\n"); msg_flags = 0; } negotiate( body, msg_flags & FL_FORCE_ACTIVE, sdp_reply); // enable RTP stream lockAudio(); rtp_str.init(&payload); unlockAudio(); DBG("Sending Rtp data to %s/%i\n", rtp_str.getRHost().c_str(),rtp_str.getRPort()); return 0; } catch(const AmSession::Exception& e){ throw e; } catch(const string& str){ ERROR("%s\n",str.c_str()); throw AmSession::Exception(500,str); } catch(...){ throw AmSession::Exception(500,"unexpected exception."); } } catch(const AmSession::Exception& e){ ERROR("%i %s\n",e.code,e.reason.c_str()); throw; // if(dlg.reply(req,e.code,e.reason, "")){ // dlg.bye(); // } // setStopped(); } return -1; }
/** * Get last_status from current branch. Helper function. * @see selects select_tm_uac_last_status * @see select_tm_uac_response_retransmission */ static int get_last_status(struct sip_msg* msg, int *last_status) { unsigned int branch; char *bptr; int blen; struct cell *t; /* DBG("select_tm_uac_last_status: branch param name: '%.*s', value: '%.*s'\n", msg->via1->branch->name.len, msg->via1->branch->name.s, msg->via1->branch->value.len, msg->via1->branch->value.s); */ /* branch ID consist of MAGIC '.' HASHID '.' BRANCH_ID */ blen = 0; for (bptr = msg->via1->branch->value.s + msg->via1->branch->value.len - 1; bptr != msg->via1->branch->value.s; bptr--, blen++) { if (*bptr == '.') break; } bptr++; /* we have a pointer to the branch number */ /* DBG("branch number: '%.*s'\n", blen, bptr); */ if (reverse_hex2int(bptr, blen, &branch) < 0) { ERR("Wrong branch number in Via1 branch param\n"); return -1; } t = get_t(); if ( (t == NULL) || (t == T_UNDEFINED) ) { ERR("get_last_status: no transaction\n"); return -1; } /* DBG("select_tm_uac_last_status: branch = %d\n", branch); */ *last_status = t->uac[branch].last_received; return 1; }
/* removes first via & sends msg to the second */ int forward_reply(struct sip_msg* msg) { char* new_buf; struct dest_info dst; unsigned int new_len; int r; #ifdef USE_TCP char* s; int len; #endif init_dest_info(&dst); new_buf=0; /*check if first via host = us */ if (check_via){ if (check_self(&msg->via1->host, msg->via1->port?msg->via1->port:SIP_PORT, msg->via1->proto)!=1){ LOG(L_NOTICE, "ERROR: forward_reply: host in first via!=me :" " %.*s:%d\n", msg->via1->host.len, msg->via1->host.s, msg->via1->port); /* send error msg back? */ goto error; } } /* check modules response_f functions */ for (r=0; r<mod_response_cbk_no; r++) if (mod_response_cbks[r](msg)==0) goto skip; /* we have to forward the reply stateless, so we need second via -bogdan*/ if (parse_headers( msg, HDR_VIA2_F, 0 )==-1 || (msg->via2==0) || (msg->via2->error!=PARSE_OK)) { /* no second via => error */ LOG(L_DBG, "reply cannot be forwarded - no 2nd via\n"); goto error; } new_buf = build_res_buf_from_sip_res( msg, &new_len); if (!new_buf){ LOG(L_ERR, "ERROR: forward_reply: building failed\n"); goto error; } dst.proto=msg->via2->proto; SND_FLAGS_OR(&dst.send_flags, &msg->fwd_send_flags, &msg->rpl_send_flags); if (update_sock_struct_from_via( &dst.to, msg, msg->via2 )==-1) goto error; #ifdef USE_COMP dst.comp=msg->via2->comp_no; #endif #if defined USE_TCP || defined USE_SCTP if ( #ifdef USE_TCP dst.proto==PROTO_TCP || dst.proto==PROTO_WS #ifdef USE_TLS || dst.proto==PROTO_TLS || dst.proto==PROTO_WSS #endif #ifdef USE_SCTP || #endif /* USE_SCTP */ #endif /* USE_TCP */ #ifdef USE_SCTP dst.proto==PROTO_SCTP #endif /* USE_SCTP */ ){ /* find id in i param if it exists */ if (msg->via1->i && msg->via1->i->value.s){ s=msg->via1->i->value.s; len=msg->via1->i->value.len; DBG("forward_reply: i=%.*s\n",len, ZSW(s)); if (reverse_hex2int(s, len, (unsigned int*)&dst.id)<0){ LOG(L_ERR, "ERROR: forward_reply: bad via i param \"%.*s\"\n", len, ZSW(s)); dst.id=0; } } } #endif apply_force_send_socket(&dst, msg); if (msg_send(&dst, new_buf, new_len)<0) { STATS_RPL_FWD_DROP(); goto error; } #ifdef STATS STATS_TX_RESPONSE( (msg->first_line.u.reply.statuscode/100) ); #endif DBG(" reply forwarded to %.*s:%d\n", msg->via2->host.len, msg->via2->host.s, (unsigned short) msg->via2->port); STATS_RPL_FWD_OK(); pkg_free(new_buf); skip: return 0; error: if (new_buf) pkg_free(new_buf); return -1; }
/*! \brief removes first via & sends msg to the second */ int forward_reply(struct sip_msg* msg) { char* new_buf; union sockaddr_union* to; unsigned int new_len; struct sr_module *mod; int proto; int id; /* used only by tcp*/ struct socket_info *send_sock; #ifdef USE_TCP char* s; int len; #endif to=0; id=0; new_buf=0; /*check if first via host = us */ if (check_via){ if (check_self(&msg->via1->host, msg->via1->port?msg->via1->port:SIP_PORT, msg->via1->proto)!=1){ LM_ERR("host in first via!=me : %.*s:%d\n", msg->via1->host.len, msg->via1->host.s, msg->via1->port); /* send error msg back? */ goto error; } } /* quick hack, slower for multiple modules*/ for (mod=modules;mod;mod=mod->next){ if ((mod->exports) && (mod->exports->response_f)){ LM_DBG("found module %s, passing reply to it\n", mod->exports->name); if (mod->exports->response_f(msg)==0) goto skip; } } /* if stateless fwd was disabled, we cannot have stateless replies here*/ if (sl_fwd_disabled) goto skip; /* we have to forward the reply stateless, so we need second via -bogdan*/ if (parse_headers( msg, HDR_VIA2_F, 0 )==-1 || (msg->via2==0) || (msg->via2->error!=PARSE_OK)) { /* no second via => error */ LM_ERR("no 2nd via found in reply\n"); goto error; } to=(union sockaddr_union*)pkg_malloc(sizeof(union sockaddr_union)); if (to==0){ LM_ERR("out of pkg memory\n"); goto error; } new_buf = build_res_buf_from_sip_res( msg, &new_len); if (!new_buf){ LM_ERR("failed to build rpl from req failed\n"); goto error; } proto=msg->via2->proto; if (update_sock_struct_from_via( to, msg, msg->via2 )==-1) goto error; #ifdef USE_TCP if (proto==PROTO_TCP #ifdef USE_TLS || proto==PROTO_TLS #endif ){ /* find id in i param if it exists */ if (msg->via1->i&&msg->via1->i->value.s){ s=msg->via1->i->value.s; len=msg->via1->i->value.len; id=reverse_hex2int(s, len); } } #endif send_sock = get_send_socket(msg, to, proto); if (msg_send(send_sock, proto, to, id, new_buf, new_len)<0) { update_stat( drp_rpls, 1); goto error0; } update_stat( fwd_rpls, 1); /* * If no port is specified in the second via, then this * message output a wrong port number - zero. Despite that * the correct port is choosen in update_sock_struct_from_via, * as its visible with su_getport(to); . */ LM_DBG("reply forwarded to %.*s:%d\n", msg->via2->host.len, msg->via2->host.s, (unsigned short) msg->via2->port); pkg_free(new_buf); pkg_free(to); skip: return 0; error: update_stat( err_rpls, 1); error0: if (new_buf) pkg_free(new_buf); if (to) pkg_free(to); return -1; }
/** removes first via & sends msg to the second * - mode param controls if modules sip response callbacks are executed */ static int do_forward_reply(struct sip_msg* msg, int mode) { char* new_buf; struct dest_info dst; unsigned int new_len; int r; struct ip_addr ip; #ifdef USE_TCP char* s; int len; #endif init_dest_info(&dst); new_buf=0; /*check if first via host = us */ if (check_via){ if (check_self(&msg->via1->host, msg->via1->port?msg->via1->port:SIP_PORT, msg->via1->proto)!=1){ LM_ERR("host in first via!=me : %.*s:%d\n", msg->via1->host.len, msg->via1->host.s, msg->via1->port); /* send error msg back? */ goto error; } } /* check modules response_f functions */ if(likely(mode==0)) { for (r=0; r<mod_response_cbk_no; r++) if (mod_response_cbks[r](msg)==0) goto skip; } /* we have to forward the reply stateless, so we need second via -bogdan*/ if (parse_headers( msg, HDR_VIA2_F, 0 )==-1 || (msg->via2==0) || (msg->via2->error!=PARSE_OK)) { /* no second via => error */ LM_DBG("reply cannot be forwarded - no 2nd via\n"); goto error; } new_buf = build_res_buf_from_sip_res( msg, &new_len); if (!new_buf){ LM_ERR("building failed\n"); goto error; } dst.proto=msg->via2->proto; SND_FLAGS_OR(&dst.send_flags, &msg->fwd_send_flags, &msg->rpl_send_flags); if (update_sock_struct_from_via( &dst.to, msg, msg->via2 )==-1) goto error; #ifdef USE_COMP dst.comp=msg->via2->comp_no; #endif #if defined USE_TCP || defined USE_SCTP if ( #ifdef USE_TCP dst.proto==PROTO_TCP || dst.proto==PROTO_WS #ifdef USE_TLS || dst.proto==PROTO_TLS || dst.proto==PROTO_WSS #endif #ifdef USE_SCTP || #endif /* USE_SCTP */ #endif /* USE_TCP */ #ifdef USE_SCTP dst.proto==PROTO_SCTP #endif /* USE_SCTP */ ){ /* find id in i param if it exists */ if (msg->via1->i && msg->via1->i->value.s){ s=msg->via1->i->value.s; len=msg->via1->i->value.len; LM_DBG("i=%.*s\n",len, ZSW(s)); if (reverse_hex2int(s, len, (unsigned int*)&dst.id)<0){ LM_ERR("bad via i param \"%.*s\"\n", len, ZSW(s)); dst.id=0; } } } #endif apply_force_send_socket(&dst, msg); /* call onsend_route */ if(dst.send_sock == NULL) { dst.send_sock=get_send_socket(msg, &dst.to, dst.proto); if (dst.send_sock==0){ LM_ERR("cannot forward reply\n"); goto done; } } if (onsend_route_enabled(SIP_REPLY)){ if (run_onsend(msg, &dst, new_buf, new_len)==0){ su2ip_addr(&ip, &(dst.to)); LM_ERR("reply to %s:%d(%d) dropped (onsend_route)\n", ip_addr2a(&ip), su_getport(&(dst.to)), dst.proto); goto error; /* error ? */ } } if (msg_send(&dst, new_buf, new_len)<0) { STATS_RPL_FWD_DROP(); goto error; } done: #ifdef STATS STATS_TX_RESPONSE( (msg->first_line.u.reply.statuscode/100) ); #endif LM_DBG("reply forwarded to %.*s:%d\n", msg->via2->host.len, msg->via2->host.s, (unsigned short) msg->via2->port); STATS_RPL_FWD_OK(); pkg_free(new_buf); skip: return 0; error: if (new_buf) pkg_free(new_buf); return -1; }
/* Returns 0 - nothing found * 1 - T found */ int t_reply_matching( struct sip_msg *p_msg , int *p_branch ) { struct cell* p_cell; unsigned int hash_index = 0; unsigned int entry_label = 0; unsigned int branch_id = 0; char *hashi, *branchi, *p, *n; int hashl, branchl; int scan_space; str cseq_method; str req_method; char *loopi; int loopl; char *syni; int synl; short is_cancel; /* make compiler warnings happy */ loopi=0; loopl=0; syni=0; synl=0; /* split the branch into pieces: loop_detection_check(ignored), hash_table_id, synonym_id, branch_id */ if (!(p_msg->via1 && p_msg->via1->branch && p_msg->via1->branch->value.s)) goto nomatch2; /* we do RFC 3261 tid matching and want to see first if there is * magic cookie in branch */ if (p_msg->via1->branch->value.len<=MCOOKIE_LEN) goto nomatch2; if (memcmp(p_msg->via1->branch->value.s, MCOOKIE, MCOOKIE_LEN)!=0) goto nomatch2; p=p_msg->via1->branch->value.s+MCOOKIE_LEN; scan_space=p_msg->via1->branch->value.len-MCOOKIE_LEN; /* hash_id */ n=eat_token2_end( p, p+scan_space, BRANCH_SEPARATOR); hashl=n-p; scan_space-=hashl; if (!hashl || scan_space<2 || *n!=BRANCH_SEPARATOR) goto nomatch2; hashi=p; p=n+1;scan_space--; if (!syn_branch) { /* md5 value */ n=eat_token2_end( p, p+scan_space, BRANCH_SEPARATOR ); loopl = n-p; scan_space-= loopl; if (n==p || scan_space<2 || *n!=BRANCH_SEPARATOR) goto nomatch2; loopi=p; p=n+1; scan_space--; } else { /* synonym id */ n=eat_token2_end( p, p+scan_space, BRANCH_SEPARATOR); synl=n-p; scan_space-=synl; if (!synl || scan_space<2 || *n!=BRANCH_SEPARATOR) goto nomatch2; syni=p; p=n+1;scan_space--; } /* branch id - should exceed the scan_space */ n=eat_token_end( p, p+scan_space ); branchl=n-p; if (!branchl ) goto nomatch2; branchi=p; /* sanity check */ if (reverse_hex2int(hashi, hashl, &hash_index)<0 ||hash_index>=TABLE_ENTRIES || reverse_hex2int(branchi, branchl, &branch_id)<0 ||branch_id>=MAX_BRANCHES || (syn_branch ? (reverse_hex2int(syni, synl, &entry_label))<0 : loopl!=MD5_LEN ) ) { DBG("DEBUG: t_reply_matching: poor reply labels %d label %d " "branch %d\n", hash_index, entry_label, branch_id ); goto nomatch2; } DBG("DEBUG: t_reply_matching: hash %d label %d branch %d\n", hash_index, entry_label, branch_id ); /* search the hash table list at entry 'hash_index'; lock the entry first */ cseq_method=get_cseq(p_msg)->method; is_cancel=cseq_method.len==CANCEL_LEN && memcmp(cseq_method.s, CANCEL, CANCEL_LEN)==0; LOCK_HASH(hash_index); for (p_cell = get_tm_table()->entrys[hash_index].first_cell; p_cell; p_cell=p_cell->next_cell) { /* first look if branch matches */ if (syn_branch) { if (p_cell->label != entry_label) continue; } else { if ( memcmp(p_cell->md5, loopi,MD5_LEN)!=0) continue; } /* sanity check ... too high branch ? */ if ( branch_id>=p_cell->nr_of_outgoings ) continue; /* does method match ? (remember -- CANCELs have the same branch as canceled transactions) */ req_method=p_cell->method; if ( /* method match */ ! ((cseq_method.len==req_method.len && memcmp( cseq_method.s, req_method.s, cseq_method.len )==0) /* or it is a local cancel */ || (is_cancel && is_invite(p_cell) /* commented out -- should_cancel_branch set it to BUSY_BUFFER to avoid collisions with replies; thus, we test here by buffer size */ /* && p_cell->uac[branch_id].local_cancel.buffer ))) */ && p_cell->uac[branch_id].local_cancel.buffer_len ))) continue; /* we passed all disqualifying factors .... the transaction has been matched ! */ set_t(p_cell); *p_branch =(int) branch_id; REF_UNSAFE( T ); UNLOCK_HASH(hash_index); DBG("DEBUG: t_reply_matching: reply matched (T=%p)!\n",T); /* if this is a 200 for INVITE, we will wish to store to-tags to be * able to distinguish retransmissions later and not to call * TMCB_RESPONSE_OUT uselessly; we do it only if callbacks are * enabled -- except callback customers, nobody cares about * retransmissions of multiple 200/INV or ACK/200s */ if (is_invite(p_cell) && p_msg->REPLY_STATUS>=200 && p_msg->REPLY_STATUS<300 && ( (!is_local(p_cell) && has_tran_tmcbs(p_cell,TMCB_RESPONSE_OUT|TMCB_E2EACK_IN) ) || (is_local(p_cell)&&has_tran_tmcbs(p_cell,TMCB_LOCAL_COMPLETED)) )) { if (parse_headers(p_msg, HDR_TO_F, 0)==-1) { LOG(L_ERR, "ERROR: t_reply_matching: to parsing failed\n"); } } if (!is_local(p_cell)) { run_trans_callbacks( TMCB_RESPONSE_IN, T, T->uas.request, p_msg, p_msg->REPLY_STATUS); } return 1; } /* for cycle */ /* nothing found */ UNLOCK_HASH(hash_index); DBG("DEBUG: t_reply_matching: no matching transaction exists\n"); nomatch2: DBG("DEBUG: t_reply_matching: failure to match a transaction\n"); *p_branch = -1; set_t(0); return -1; }
/* Returns 0 - nothing found * 1 - T found */ int t_reply_matching( struct sip_msg *p_msg , int *p_branch ) { struct cell* p_cell; unsigned int hash_index = 0; unsigned int entry_label = 0; unsigned int branch_id = 0; char *hashi, *branchi, *p, *n; int hashl, branchl; int scan_space; struct cseq_body *cseq; char *loopi; int loopl; char *syni; int synl; /* make compiler warnings happy */ loopi=0; loopl=0; syni=0; synl=0; /* split the branch into pieces: loop_detection_check(ignored), hash_table_id, synonym_id, branch_id */ if (!(p_msg->via1 && p_msg->via1->branch && p_msg->via1->branch->value.s)) goto nomatch2; /* we do RFC 3261 tid matching and want to see first if there is * magic cookie in branch */ if (p_msg->via1->branch->value.len<=MCOOKIE_LEN) goto nomatch2; if (memcmp(p_msg->via1->branch->value.s, MCOOKIE, MCOOKIE_LEN)!=0) goto nomatch2; p=p_msg->via1->branch->value.s+MCOOKIE_LEN; scan_space=p_msg->via1->branch->value.len-MCOOKIE_LEN; /* hash_id */ n=eat_token2_end( p, p+scan_space, BRANCH_SEPARATOR); hashl=n-p; scan_space-=hashl; if (!hashl || scan_space<2 || *n!=BRANCH_SEPARATOR) goto nomatch2; hashi=p; p=n+1;scan_space--; if (!syn_branch) { /* md5 value */ n=eat_token2_end( p, p+scan_space, BRANCH_SEPARATOR ); loopl = n-p; scan_space-= loopl; if (n==p || scan_space<2 || *n!=BRANCH_SEPARATOR) goto nomatch2; loopi=p; p=n+1; scan_space--; } else { /* synonym id */ n=eat_token2_end( p, p+scan_space, BRANCH_SEPARATOR); synl=n-p; scan_space-=synl; if (!synl || scan_space<2 || *n!=BRANCH_SEPARATOR) goto nomatch2; syni=p; p=n+1;scan_space--; } /* branch id - should exceed the scan_space */ n=eat_token_end( p, p+scan_space ); branchl=n-p; if (!branchl ) goto nomatch2; branchi=p; /* sanity check */ if (reverse_hex2int(hashi, hashl, &hash_index)<0 ||hash_index>=TM_TABLE_ENTRIES || reverse_hex2int(branchi, branchl, &branch_id)<0 ||branch_id>=MAX_BRANCHES || (syn_branch ? reverse_hex2int(syni, synl, &entry_label)<0 : loopl!=MD5_LEN ) ) { LM_DBG("poor reply labels %u label %u branch %u\n", hash_index, entry_label, branch_id ); goto nomatch2; } LM_DBG("hash %u label %d branch %u\n",hash_index, entry_label, branch_id); cseq = get_cseq(p_msg); /* search the hash table list at entry 'hash_index'; lock the entry first */ LOCK_HASH(hash_index); for (p_cell = get_tm_table()->entrys[hash_index].first_cell; p_cell; p_cell=p_cell->next_cell) { /* first look if branch matches */ if (syn_branch) { if (p_cell->label != entry_label) continue; } else { if ( memcmp(p_cell->md5, loopi,MD5_LEN)!=0) continue; } /* sanity check ... too high branch ? */ if ( branch_id>=p_cell->nr_of_outgoings ) continue; /* does method match ? (remember -- CANCELs have the same branch as canceled transactions) */ if (!( /* it's a local cancel */ (cseq->method_id==METHOD_CANCEL && is_invite(p_cell) && p_cell->uac[branch_id].local_cancel.buffer.len ) /* method match */ || ((cseq->method_id!=METHOD_OTHER && p_cell->uas.request)? (cseq->method_id==REQ_LINE(p_cell->uas.request).method_value) :(EQ_STRS(cseq->method,p_cell->method))) )) continue; /* we passed all disqualifying factors .... the transaction has been matched ! */ set_t(p_cell); *p_branch = branch_id; REF_UNSAFE( T ); UNLOCK_HASH(hash_index); LM_DBG("reply matched (T=%p)!\n",T); /* if this is a 200 for INVITE, we will wish to store to-tags to be * able to distinguish retransmissions later and not to call * TMCB_RESPONSE_OUT uselessly; we do it only if callbacks are * enabled -- except callback customers, nobody cares about * retransmissions of multiple 200/INV or ACK/200s */ if (is_invite(p_cell) && p_msg->REPLY_STATUS>=200 && p_msg->REPLY_STATUS<300 && ( (!is_local(p_cell) && has_tran_tmcbs(p_cell, TMCB_RESPONSE_OUT|TMCB_RESPONSE_PRE_OUT) ) || (is_local(p_cell)&&has_tran_tmcbs(p_cell,TMCB_LOCAL_COMPLETED)) )) { if (parse_headers(p_msg, HDR_TO_F, 0)==-1) { LM_ERR("to parsing failed\n"); } } return 1; } /* for cycle */ /* nothing found */ UNLOCK_HASH(hash_index); LM_DBG("no matching transaction exists\n"); nomatch2: LM_DBG("failure to match a transaction\n"); *p_branch = -1; set_t(0); return -1; }
int AmZRTP::init() { zrtp_log_set_log_engine(zrtp_log); AmConfigReader cfg; string cfgname=add2path(AmConfig::ModConfigPath, 1, "zrtp.conf"); if(cfg.loadFile(cfgname)) { ERROR("No %s config file present.\n", cfgname.c_str()); return -1; } cache_path = cfg.getParameter("cache_path"); if (cfg.hasParameter("zid_hex")) { string zid_hex = cfg.getParameter("zid_hex"); if (zid_hex.size() != 2*sizeof(zrtp_instance_zid)) { ERROR("zid_hex config parameter in zrtp.conf must be %lu characters long.\n", sizeof(zrtp_zid_t)*2); return -1; } for (size_t i=0;i<sizeof(zrtp_instance_zid);i++) { unsigned int h; if (reverse_hex2int(zid_hex.substr(i*2, 2), h)) { ERROR("in zid_hex in zrtp.conf: '%s' is no hex number\n", zid_hex.substr(i*2, 2).c_str()); return -1; } zrtp_instance_zid[i]=h % 0xff; } } else if (cfg.hasParameter("zid")) { string zid = cfg.getParameter("zid"); WARN("zid parameter in zrtp.conf is only supported for backwards compatibility. Please use zid_hex\n"); if (zid.length() != sizeof(zrtp_zid_t)) { ERROR("zid config parameter in zrtp.conf must be %lu characters long.\n", sizeof(zrtp_zid_t)); return -1; } for (size_t i=0;i<zid.length();i++) zrtp_instance_zid[i]=zid[i]; } else { // generate one string zid_hex; for (size_t i=0;i<sizeof(zrtp_instance_zid);i++) { zrtp_instance_zid[i]=get_random() % 0xff; zid_hex+=char2hex(zrtp_instance_zid[i], true); } WARN("Generated random ZID. To support key continuity through key cache " "on the peers, add this to zrtp.conf: 'zid_hex=\"%s\"'", zid_hex.c_str()); } DBG("initializing ZRTP library with cache path '%s'.\n", cache_path.c_str()); zrtp_config_defaults(&zrtp_config); strcpy(zrtp_config.client_id, SEMS_CLIENT_ID); memcpy((char*)zrtp_config.zid, (char*)zrtp_instance_zid, sizeof(zrtp_zid_t)); zrtp_config.lic_mode = ZRTP_LICENSE_MODE_UNLIMITED; strncpy(zrtp_config.cache_file_cfg.cache_path, cache_path.c_str(), 256); zrtp_config.cb.misc_cb.on_send_packet = AmZRTP::on_send_packet; zrtp_config.cb.event_cb.on_zrtp_secure = AmZRTP::on_zrtp_secure; zrtp_config.cb.event_cb.on_zrtp_security_event = AmZRTP::on_zrtp_security_event; zrtp_config.cb.event_cb.on_zrtp_protocol_event = AmZRTP::on_zrtp_protocol_event; if ( zrtp_status_ok != zrtp_init(&zrtp_config, &zrtp_global) ) { ERROR("Error during ZRTP initialization\n"); return -1; } size_t rand_bytes = cfg.getParameterInt("random_entropy_bytes", 172); if (rand_bytes) { INFO("adding %zd bytes entropy from /dev/random to ZRTP entropy pool\n", rand_bytes); FILE* fd = fopen("/dev/random", "r"); if (!fd) { ERROR("opening /dev/random for adding entropy to the pool\n"); return -1; } void* p = malloc(rand_bytes); if (p==NULL) return -1; size_t read_bytes = fread(p, 1, rand_bytes, fd); if (read_bytes != rand_bytes) { ERROR("reading %zd bytes from /dev/random\n", rand_bytes); return -1; } zrtp_entropy_add(zrtp_global, (const unsigned char*)p, read_bytes); free(p); } // zrtp_add_entropy(zrtp_global, NULL, 0); // fixme DBG("ZRTP initialized ok.\n"); return 0; }