📄 uac_fifo.c
字号:
dst EOL // ("." if no outbound server used) // must be used with dialogs/lr <EOL separated HFs>+ // From and To must be present at least; // dialog-apps must include tag in From // (an ephemeral is appended otherwise) // and supply CSeq/CallId .[EOL] [body] .EOL there is also the possibility to have server placed its hostname:portnumber in header fields -- just put double exclamation mark in any of the optional header fields (i.e., any but From/To/CallID,CSeq), they will be substituted hn:pnExample:sc fifo t_uac_dlg MESSAGE sip:joe@192.168.2.1 \ . \ # no outbound proxy 'From:sender@iptel.org;tagd=123' \ # no to-tag -> ephemeral 'To:sender@iptel.org' \ 'Foo: sip:user@!! ' \ # expansion here 'CSEQ: 11 MESSAGE ' \ . \ # EoH . # empty body---U 192.168.2.16:5060 -> 192.168.2.1:5060MESSAGE sip:joe@192.168.2.1 SIP/2.0..Via: SIP/2.0/UDP 192.168.2.16;branch=z9hG4bK760c.922ea6a1.0..To: sender@iptel.org..From: sender@iptel.org;tagd=123;tag=5405e669bc2980663aed2624dc31396f-fa77..CSeq: 11 MESSAGE..Call-ID: e863bf56-22255@192.168.2.16..Content-Length: 0..User-Agent: Sip EXpress router (0.8.11pre4-tcp1-locking (i386/linux))..Foo: sip:user@192.168.2.16:5060....*//* * Make sure that the FIFO user created the message * correctly */static inline int fifo_check_msg(struct sip_msg* msg, str* method, char* resp, str* body, int* fromtag, int *cseq_is, int* cseq, str* callid){ struct to_body* parsed_from; struct cseq_body *parsed_cseq; int i; char c; if (body->len && !msg->content_type) { fifo_uac_error(resp, 400, "Content-Type missing"); return -1; } if (body->len && msg->content_length) { fifo_uac_error(resp, 400, "Content-Length disallowed"); return -2; } if (!msg->to) { fifo_uac_error(resp, 400, "To missing"); return -3; } if (!msg->from) { fifo_uac_error(resp, 400, "From missing"); return -4; } /* we also need to know if there is from-tag and add it otherwise */ if (parse_from_header(msg) < 0) { fifo_uac_error(resp, 400, "Error in From"); return -5; } parsed_from = (struct to_body*)msg->from->parsed; *fromtag = parsed_from->tag_value.s && parsed_from->tag_value.len; *cseq = 0; if (msg->cseq && (parsed_cseq = get_cseq(msg))) { *cseq_is = 1; for (i = 0; i < parsed_cseq->number.len; i++) { c = parsed_cseq->number.s[i]; if (c >= '0' && c <= '9' ) *cseq = (*cseq) * 10 + c - '0'; else { DBG("found non-numerical in CSeq: <%i>='%c'\n",(unsigned int)c,c); fifo_uac_error(resp, 400, "non-numerical CSeq"); return -6; } } if (parsed_cseq->method.len != method->len || memcmp(parsed_cseq->method.s, method->s, method->len) !=0 ) { fifo_uac_error(resp, 400, "CSeq method mismatch"); return -7; } } else { *cseq_is = 0; } if (msg->callid) { callid->s = msg->callid->body.s; callid->len = msg->callid->body.len; } else { callid->s = 0; callid->len = 0; } return 0;}#define FIFO_ROUTE_PREFIX "Route: "#define FIFO_ROUTE_SEPARATOR ", "static inline void print_routes(FILE* out, dlg_t* _d){ rr_t* ptr; ptr = _d->hooks.first_route; if (ptr) { fprintf(out, FIFO_ROUTE_PREFIX); } else { fprintf(out, ".\n"); return; } while(ptr) { fprintf(out, "%.*s", ptr->len, ptr->nameaddr.name.s); ptr = ptr->next; if (ptr) { fprintf(out, FIFO_ROUTE_SEPARATOR); } } if (_d->hooks.last_route) { fprintf(out, FIFO_ROUTE_SEPARATOR "<"); fprintf(out, "%.*s", _d->hooks.last_route->len, _d->hooks.last_route->s); fprintf(out, ">"); } if (_d->hooks.first_route) { fprintf(out, CRLF); }}static inline int print_uris(FILE* out, struct sip_msg* reply){ dlg_t* dlg; dlg = (dlg_t*)shm_malloc(sizeof(dlg_t)); if (!dlg) { LOG(L_ERR, "print_uris(): No memory left\n"); return -1; } memset(dlg, 0, sizeof(dlg_t)); if (dlg_response_uac(dlg, reply) < 0) { LOG(L_ERR, "print_uris(): Error while creating dialog structure\n"); free_dlg(dlg); return -2; } if (dlg->state != DLG_CONFIRMED) { fprintf(out, ".\n.\n.\n"); free_dlg(dlg); return 0; } if (dlg->hooks.request_uri->s) { fprintf(out, "%.*s\n", dlg->hooks.request_uri->len, dlg->hooks.request_uri->s); } else { fprintf(out, ".\n"); } if (dlg->hooks.next_hop->s) { fprintf(out, "%.*s\n", dlg->hooks.next_hop->len, dlg->hooks.next_hop->s); } else { fprintf(out, ".\n"); } print_routes(out, dlg); free_dlg(dlg); return 0;}static void fifo_callback( struct cell *t, int type, struct tmcb_params *ps ){ char *filename; FILE* f; str text; DBG("!!!!! ref_counter: %d\n", t->ref_count); DBG("DEBUG: fifo UAC completed with status %d\n", ps->code); if (!*ps->param) { LOG(L_INFO, "INFO: fifo UAC completed with status %d\n", ps->code); return; } filename=(char *)(*ps->param); if (ps->rpl==FAKED_REPLY) { get_reply_status( &text, ps->rpl, ps->code); if (text.s==0) { LOG(L_ERR, "ERROR: fifo_callback: get_reply_status failed\n"); fifo_reply( filename, "500 fifo_callback: get_reply_status failed\n"); goto done; } fifo_reply(filename, "%.*s\n", text.len, text.s ); pkg_free(text.s); } else { text.s = ps->rpl->first_line.u.reply.reason.s; text.len = ps->rpl->first_line.u.reply.reason.len; f = open_reply_pipe(filename); if (!f) return; fprintf(f, "%d %.*s\n", ps->rpl->first_line.u.reply.statuscode, text.len, text.s); print_uris(f, ps->rpl); fprintf(f, "%s\n", ps->rpl->headers->name.s); fclose(f); } DBG("DEBUG: fifo_callback successfully completed\n");done: shm_free(filename);}int fifo_uac(FILE *stream, char *response_file){ str method, ruri, nexthop, headers, body, hfb, callid; struct sip_uri puri, pnexthop; struct sip_msg faked_msg; int ret, sip_error, err_ret; int fromtag, cseq_is, cseq; struct cb_data; char err_buf[MAX_REASON_LEN]; char* shm_file; dlg_t dlg; if (fifo_get_method(stream, response_file, &method) < 0) return 1; if (fifo_get_ruri(stream, response_file, &ruri, &puri) < 0) return 1; if (fifo_get_nexthop(stream, response_file, &nexthop, &pnexthop) < 0) return 1; if (fifo_get_headers(stream, response_file, &headers) < 0) return 1; /* use SIP parser to look at what is in the FIFO request */ memset(&faked_msg, 0, sizeof(struct sip_msg)); faked_msg.len = headers.len; faked_msg.buf = faked_msg.unparsed = headers.s; if (parse_headers(&faked_msg, HDR_EOH, 0) == -1 ) { DBG("DEBUG: fifo_uac: parse_headers failed\n"); fifo_uac_error(response_file, 400, "HFs unparseable"); goto error; } DBG("DEBUG: fifo_uac: parse_headers succeeded\n"); if (fifo_get_body(stream, response_file, &body) < 0) goto error; /* at this moment, we collected all the things we got, let's * verify user has not forgotten something */ if (fifo_check_msg(&faked_msg, &method, response_file, &body, &fromtag, &cseq_is, &cseq, &callid) < 0) goto error; hfb.s = get_hfblock(nexthop.len ? &nexthop : &ruri, faked_msg.headers, &hfb.len, PROTO_UDP); if (!hfb.s) { fifo_uac_error(response_file, 500, "no mem for hf block"); goto error; } DBG("DEBUG: fifo_uac: EoL -- proceeding to transaction creation\n"); memset(&dlg, 0, sizeof(dlg_t)); /* Fill in Call-ID, use given Call-ID if * present and generate it if not present */ if (callid.s && callid.len) dlg.id.call_id = callid; else generate_callid(&dlg.id.call_id); /* We will not fill in dlg->id.rem_tag because * if present it will be printed within To HF */ /* Generate fromtag if not present */ if (!fromtag) { generate_fromtag(&dlg.id.loc_tag, &dlg.id.call_id); } /* Fill in CSeq */ if (cseq_is) dlg.loc_seq.value = cseq; else dlg.loc_seq.value = DEFAULT_CSEQ; dlg.loc_seq.is_set = 1; dlg.loc_uri = faked_msg.from->body; dlg.rem_uri = faked_msg.to->body; dlg.hooks.request_uri = &ruri; dlg.hooks.next_hop = (nexthop.len ? &nexthop : &ruri);#ifdef XL_DEBUG print_dlg(stderr, &dlg);#endif /* we got it all, initiate transaction now! */ if (fifo_cbp(&shm_file, response_file) < 0) goto error01; ret = t_uac(&method, &hfb, &body, &dlg, fifo_callback, shm_file); if (ret <= 0) { err_ret = err2reason_phrase(ret, &sip_error, err_buf, sizeof(err_buf), "FIFO/UAC") ; if (err_ret > 0 ) { fifo_uac_error(response_file, sip_error, err_buf); } else { fifo_uac_error(response_file, 500, "FIFO/UAC error"); } } error01: pkg_free(hfb.s); error: /* free_sip_msg(&faked_msg); */ if (faked_msg.headers) free_hdr_field_lst(faked_msg.headers); return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -