t_fifo.c
来自「性能优秀的SIP Proxy」· C语言 代码 · 共 821 行 · 第 1/2 页
C
821 行
goto error; } else { goto repeat; } } close(fd_fifo); DBG("DEBUG:tm:write_to_fifo: write completed\n"); return 1; /* OK */error: return -1;}static inline char* add2buf(char *buf, char *end, str *name, str *value){ if (buf+name->len+value->len+2+1>=end) return 0; memcpy( buf, name->s, name->len); buf += name->len; *(buf++) = ':'; *(buf++) = ' '; memcpy( buf, value->s, value->len); buf += value->len; *(buf++) = '\n'; return buf;}static inline char* append2buf( char *buf, int len, struct sip_msg *req, struct append_elem *elem){ xl_value_t value; char *end; end = buf+len; while (elem) { /* get the value */ if (xl_get_spec_value(req, &elem->spec, &value, 0)!=0) { LOG(L_ERR,"ERROR:tm:append2buf: failed to get '%.*s'\n", elem->name.len,elem->name.s); } /* empty element? */ if ( !(value.flags&XL_VAL_NULL) ) { /* write the value into the buffer */ buf = add2buf( buf, end, &elem->name, &value.rs); if (!buf) { LOG(L_ERR,"ERROR:tm:append2buf: overflow -> append " "exceeded %d len\n",len); return 0; } } elem = elem->next; } return buf;}static int assemble_msg(struct sip_msg* msg, struct tw_info *twi){ static char id_buf[IDBUF_LEN]; static char route_buffer[ROUTE_BUFFER_MAX]; static char append_buf[APPEND_BUFFER_MAX]; static char cmd_buf[CMD_BUFFER_MAX]; static str empty_param = {".",1}; unsigned int hash_index, label; contact_body_t* cb=0; contact_t* c=0; name_addr_t na; rr_t* record_route; struct hdr_field* p_hdr; param_hooks_t hooks; int l; char* s, fproxy_lr; str route, next_hop, append, tmp_s, body, str_uri; if(msg->first_line.type != SIP_REQUEST){ LOG(L_ERR,"ERROR:tm:assemble_msg: called for something else then" "a SIP request\n"); goto error; } /* parse all -- we will need every header field for a UAS */ if ( parse_headers(msg, HDR_EOH_F, 0)==-1) { LOG(L_ERR,"ERROR:tm:assemble_msg: parse_headers failed\n"); goto error; } /* find index and hash; (the transaction can be safely used due * to refcounting till script completes) */ if( t_get_trans_ident(msg,&hash_index,&label) == -1 ) { LOG(L_ERR,"ERROR:tm:assemble_msg: t_get_trans_ident failed\n"); goto error; } /* parse from header */ if (msg->from->parsed==0 && parse_from_header(msg)<0 ) { LOG(L_ERR,"ERROR:tm:assemble_msg: while parsing <From:> header\n"); goto error; } /* parse the RURI (doesn't make any malloc) */ msg->parsed_uri_ok = 0; /* force parsing */ if (parse_sip_msg_uri(msg)<0) { LOG(L_ERR,"ERROR:tm:assemble_msg: uri has not been parsed\n"); goto error; } /* parse contact header */ str_uri.s = 0; str_uri.len = 0; if(msg->contact) { if (msg->contact->parsed==0 && parse_contact(msg->contact)<0) { LOG(L_ERR,"ERROR:tm:assemble_msg: error while parsing " "<Contact:> header\n"); goto error; } cb = (contact_body_t*)msg->contact->parsed; if(cb && (c=cb->contacts)) { str_uri = c->uri; if (find_not_quoted(&str_uri,'<')) { parse_nameaddr(&str_uri,&na); str_uri = na.uri; } } } /* str_uri is taken from caller's contact or from header * for backwards compatibility with pre-3261 (from is already parsed)*/ if(!str_uri.len || !str_uri.s) str_uri = get_from(msg)->uri; /* parse Record-Route headers */ route.s = s = route_buffer; route.len = 0; fproxy_lr = 0; next_hop = empty_param; p_hdr = msg->record_route; if(p_hdr) { if (p_hdr->parsed==0 && parse_rr(p_hdr)!=0 ) { LOG(L_ERR,"ERROR:tm:assemble_msg: failed to parse " "'Record-Route:' header\n"); goto error; } record_route = (rr_t*)p_hdr->parsed; } else { record_route = 0; } if( record_route ) { if ( (tmp_s.s=find_not_quoted(&record_route->nameaddr.uri,';'))!=0 && tmp_s.s+1!=record_route->nameaddr.uri.s+ record_route->nameaddr.uri.len) { /* Parse all parameters */ tmp_s.len = record_route->nameaddr.uri.len - (tmp_s.s- record_route->nameaddr.uri.s); if (parse_params( &tmp_s, CLASS_URI, &hooks, &record_route->params) < 0) { LOG(L_ERR,"ERROR:tm:assemble_msg: failed to parse " "record route uri params\n"); goto error; } fproxy_lr = (hooks.uri.lr != 0); DBG("DEBUG:tm:assemble_msg: record_route->nameaddr.uri: %.*s\n", record_route->nameaddr.uri.len,record_route->nameaddr.uri.s); if(fproxy_lr){ DBG("DEBUG:tm:assemble_msg: first proxy has loose routing\n"); copy_route(s,route.len,record_route->nameaddr.uri.s, record_route->nameaddr.uri.len); } } for(p_hdr = p_hdr->next;p_hdr;p_hdr = p_hdr->next) { /* filter out non-RR hdr and empty hdrs */ if( (p_hdr->type!=HDR_RECORDROUTE_T) || p_hdr->body.len==0) continue; if(p_hdr->parsed==0 && parse_rr(p_hdr)!=0 ){ LOG(L_ERR,"ERROR:tm:assemble_msg: " "failed to parse <Record-route:> header\n"); goto error; } for(record_route=p_hdr->parsed; record_route; record_route=record_route->next){ DBG("DEBUG:tm:assemble_msg: record_route->nameaddr.uri: " "<%.*s>\n", record_route->nameaddr.uri.len, record_route->nameaddr.uri.s); copy_route(s,route.len,record_route->nameaddr.uri.s, record_route->nameaddr.uri.len); } } if(!fproxy_lr){ copy_route(s,route.len,str_uri.s,str_uri.len); str_uri = ((rr_t*)msg->record_route->parsed)->nameaddr.uri; } else { next_hop = ((rr_t*)msg->record_route->parsed)->nameaddr.uri; } } DBG("DEBUG:tm:assemble_msg: calculated route: %.*s\n", route.len,route.len ? route.s : ""); DBG("DEBUG:tm:assemble_msg: next r-uri: %.*s\n", str_uri.len,str_uri.len ? str_uri.s : ""); if ( REQ_LINE(msg).method_value==METHOD_INVITE || (twi->append && twi->append->add_body) ) { /* get body */ if( (body.s = get_body(msg)) == 0 ){ LOG(L_ERR, "ERROR:tm:assemble_msg: get_body failed\n"); goto error; } body.len = msg->len - (body.s - msg->buf); } else { body = empty_param; } /* flags & additional headers */ append.s = s = append_buf; if (sizeof(flag_t)*2+12+1 >= APPEND_BUFFER_MAX) { LOG(L_ERR,"ERROR:tm:assemble_msg: buffer overflow " "while copying flags\n"); goto error; } append_str(s,"P-MsgFlags: ",12); l = APPEND_BUFFER_MAX - (12+1); /* include trailing `\n'*/ if (int2reverse_hex(&s, &l, (int)msg->msg_flags) == -1) { LOG(L_ERR,"ERROR:tm:assemble_msg: buffer overflow " "while copying optional header\n"); goto error; } append_chr(s,'\n'); if ( twi->append && ((s=append2buf( s, APPEND_BUFFER_MAX-(s-append.s), msg, twi->append->elems))==0) ) goto error; /* body separator */ append_chr(s,'.'); append.len = s-append.s; eol_line(1).s = s = cmd_buf; if(twi->action.len+12 >= CMD_BUFFER_MAX){ LOG(L_ERR,"ERROR:tm:assemble_msg: buffer overflow while " "copying command name\n"); goto error; } append_str(s,"sip_request.",12); append_str(s,twi->action.s,twi->action.len); eol_line(1).len = s-eol_line(1).s; eol_line(2)=REQ_LINE(msg).method; /* method type */ eol_line(3)=msg->parsed_uri.user; /* user from r-uri */ eol_line(4)=msg->parsed_uri.host; /* domain */ eol_line(5)=msg->rcv.bind_address->address_str; /* dst ip */ eol_line(6)=msg->rcv.dst_port==SIP_PORT ? empty_param : msg->rcv.bind_address->port_no_str; /* port */ /* r_uri ('Contact:' for next requests) */ eol_line(7)=*GET_RURI(msg); /* r_uri for subsequent requests */ eol_line(8)=str_uri.len?str_uri:empty_param; eol_line(9)=get_from(msg)->body; /* from */ eol_line(10)=msg->to->body; /* to */ eol_line(11)=msg->callid->body; /* callid */ eol_line(12)=get_from(msg)->tag_value; /* from tag */ eol_line(13)=get_to(msg)->tag_value; /* to tag */ eol_line(14)=get_cseq(msg)->number; /* cseq number */ eol_line(15).s=id_buf; /* hash:label */ s = int2str(hash_index, &l); if (l+1>=IDBUF_LEN) { LOG(L_ERR, "ERROR:tm:assemble_msg: too big hash\n"); goto error; } memcpy(id_buf, s, l); id_buf[l]=':'; eol_line(15).len=l+1; s = int2str(label, &l); if (l+1+eol_line(15).len>=IDBUF_LEN) { LOG(L_ERR, "ERROR:tm:assemble_msg: too big label\n"); goto error; } memcpy(id_buf+eol_line(15).len, s, l); eol_line(15).len+=l; eol_line(16) = route.len ? route : empty_param; eol_line(17) = next_hop; eol_line(18) = append; eol_line(19) = body; /* success */ return 1;error: /* 0 would lead to immediate script exit -- -1 returns * with 'false' to script processing */ return -1;}static int write_to_unixsock(char* sockname, int cnt){ int len, e; struct sockaddr_un dest; if (!sockname) { LOG(L_ERR, "ERROR:tm:write_to_unixsock: Invalid parameter\n"); return E_UNSPEC; } len = strlen(sockname); if (len == 0) { DBG("DEBUG:tm:write_to_unixsock: Error - empty socket name\n"); return -1; } else if (len > 107) { LOG(L_ERR, "ERROR:tm:write_to_unixsock: Socket name too long\n"); return -1; } memset(&dest, 0, sizeof(dest)); dest.sun_family = PF_LOCAL; memcpy(dest.sun_path, sockname, len);#ifdef HAVE_SOCKADDR_SA_LEN dest.sun_len = len;#endif e = connect(sock, (struct sockaddr*)&dest, SUN_LEN(&dest));#ifdef HAVE_CONNECT_ECONNRESET_BUG /* * Workaround for a nasty bug in BSD kernels dated back * to the Berkeley days, so that can be found in many modern * BSD-derived kernels. Workaround should be pretty harmless since * in normal conditions connect(2) can never return ECONNRESET. */ if ((e == -1) && (errno == ECONNRESET)) e = 0;#endif if (e == -1) { LOG(L_ERR, "ERROR:tm:write_to_unixsock: Error in connect: %s\n", strerror(errno)); return -1; } if (tsend_dgram_ev(sock, (struct iovec*)lines_eol, 2 * cnt, tm_unix_tx_timeout * 1000) < 0) { LOG(L_ERR, "ERROR:tm:write_to_unixsock: writev failed: %s\n", strerror(errno)); return -1; } return 0;}int t_write_req(struct sip_msg* msg, char* vm_fifo, char* info){ if (assemble_msg(msg, (struct tw_info*)info) < 0) { LOG(L_ERR, "ERROR:tm:t_write_req: Error int assemble_msg\n"); return -1; } if (write_to_fifo(vm_fifo, TWRITE_PARAMS) == -1) { LOG(L_ERR, "ERROR:tm:t_write_req: write_to_fifo failed\n"); return -1; } /* make sure that if voicemail does not initiate a reply * timely, a SIP timeout will be sent out */ if (add_blind_uac() == -1) { LOG(L_ERR, "ERROR:tm:t_write_req: add_blind failed\n"); return -1; } return 1;}int t_write_unix(struct sip_msg* msg, char* socket, char* info){ if (assemble_msg(msg, (struct tw_info*)info) < 0) { LOG(L_ERR, "ERROR:tm:t_write_unix: Error in assemble_msg\n"); return -1; } if (write_to_unixsock(socket, TWRITE_PARAMS) == -1) { LOG(L_ERR, "ERROR:tm:t_write_unix: write_to_unixsock failed\n"); return -1; } /* make sure that if voicemail does not initiate a reply * timely, a SIP timeout will be sent out */ if (add_blind_uac() == -1) { LOG(L_ERR, "ERROR:tm:t_write_unix: add_blind failed\n"); return -1; } return 1;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?