00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00037 #include <stdlib.h>
00038 #include "../../parser/parse_from.h"
00039 #include "../../modules/tm/ut.h"
00040 #include "../../lib/kmi/mi.h"
00041 #include "../../str_list.h"
00042 #include "tmx_mod.h"
00043
00044
00045
00055 static inline int uri2su(str *uri, union sockaddr_union *to_su, int proto)
00056 {
00057 struct proxy_l *proxy;
00058
00059 proxy = uri2proxy(uri, proto);
00060 if (!proxy) {
00061 ser_error = E_BAD_ADDRESS;
00062 LM_ERR("failed create a dst proxy\n");
00063 return -1;
00064 }
00065
00066 hostent2su(to_su, &proxy->host, proxy->addr_idx,
00067 (proxy->port) ? proxy->port : SIP_PORT);
00068 proto = proxy->proto;
00069
00070 free_proxy(proxy);
00071 pkg_free(proxy);
00072 return proto;
00073 }
00074
00075
00076 static inline struct socket_info *uri2sock(struct sip_msg* msg, str *uri,
00077 union sockaddr_union *to_su, int proto)
00078 {
00079 struct socket_info* send_sock;
00080
00081 if ( (proto=uri2su(uri, to_su, proto))==-1 )
00082 return 0;
00083
00084 send_sock = get_send_socket(msg, to_su, proto);
00085 if (!send_sock) {
00086 LM_ERR("no corresponding socket for af %d\n", to_su->s.sa_family);
00087 ser_error = E_NO_SOCKET;
00088 }
00089
00090 return send_sock;
00091 }
00092
00093
00094
00095
00109 static inline struct mi_root* mi_check_msg(struct sip_msg* msg, str* method,
00110 str* body, int* cseq, str* callid)
00111 {
00112 struct cseq_body *parsed_cseq;
00113
00114 if (body && body->len && !msg->content_type)
00115 return init_mi_tree( 400, "Content-Type missing", 19);
00116
00117 if (body && body->len && msg->content_length)
00118 return init_mi_tree( 400, "Content-Length disallowed", 24);
00119
00120 if (!msg->to)
00121 return init_mi_tree( 400, "To missing", 10);
00122
00123 if (!msg->from)
00124 return init_mi_tree( 400, "From missing", 12);
00125
00126
00127 if (parse_from_header(msg) < 0)
00128 return init_mi_tree( 400, "Error in From", 13);
00129
00130 if (msg->cseq && (parsed_cseq = get_cseq(msg))) {
00131 if (str2int( &parsed_cseq->number, (unsigned int*)cseq)!=0)
00132 return init_mi_tree( 400, "Bad CSeq number", 15);
00133
00134 if (parsed_cseq->method.len != method->len
00135 || memcmp(parsed_cseq->method.s, method->s, method->len) !=0 )
00136 return init_mi_tree( 400, "CSeq method mismatch", 20);
00137 } else {
00138 *cseq = -1;
00139 }
00140
00141 if (msg->callid) {
00142 callid->s = msg->callid->body.s;
00143 callid->len = msg->callid->body.len;
00144 } else {
00145 callid->s = 0;
00146 callid->len = 0;
00147 }
00148
00149 return 0;
00150 }
00151
00152
00164 static inline char *get_hfblock( str *uri, struct hdr_field *hf, int *l, struct socket_info** send_sock)
00165 {
00166 struct str_list sl, *last, *new, *i, *foo;
00167 int hf_avail, frag_len, total_len;
00168 char *begin, *needle, *dst, *ret, *d;
00169 str *sock_name, *portname;
00170 union sockaddr_union to_su;
00171
00172 ret=0;
00173 total_len=0;
00174 last=&sl;
00175 last->next=0;
00176 portname=sock_name=0;
00177
00178 for (; hf; hf=hf->next) {
00179 if (tm_skip_hf(hf)) continue;
00180
00181 begin=needle=hf->name.s;
00182 hf_avail=hf->len;
00183
00184
00185 while(hf_avail) {
00186 d=memchr(needle, SUBST_CHAR, hf_avail);
00187 if (!d || d+1>=needle+hf_avail) {
00188 new=append_str_list(begin, hf_avail, &last, &total_len);
00189 if (!new) goto error;
00190 break;
00191 } else {
00192 frag_len=d-begin;
00193 d++;
00194 switch(*d) {
00195 case SUBST_CHAR:
00196
00197 new=append_str_list(begin, frag_len, &last, &total_len);
00198 if (!new) goto error;
00199
00200 if (!sock_name) {
00201 if (*send_sock==0){
00202 *send_sock=uri2sock(0, uri, &to_su,PROTO_NONE);
00203 if (!*send_sock) {
00204 LM_ERR("send_sock failed\n");
00205 goto error;
00206 }
00207 }
00208 sock_name=&(*send_sock)->address_str;
00209 portname=&(*send_sock)->port_no_str;
00210 }
00211 new=append_str_list(sock_name->s, sock_name->len,
00212 &last, &total_len );
00213 if (!new) goto error;
00214
00215 new=append_str_list(":", 1, &last, &total_len);
00216 if (!new) goto error;
00217 new=append_str_list(portname->s, portname->len,
00218 &last, &total_len );
00219 if (!new) goto error;
00220
00221 begin=needle=d+1;hf_avail-=frag_len+2;
00222 continue;
00223 default:
00224
00225 hf_avail-=frag_len+1;
00226 needle=d;
00227 }
00228 }
00229 }
00230
00231
00232
00233 LM_DBG("one more hf processed\n");
00234 }
00235
00236
00237
00238 ret=pkg_malloc(total_len);
00239 if (!ret) {
00240 LM_ERR("no pkg mem for hf block\n");
00241 goto error;
00242 }
00243 i=sl.next;
00244 dst=ret;
00245 while(i) {
00246 foo=i;
00247 i=i->next;
00248 memcpy(dst, foo->s.s, foo->s.len);
00249 dst+=foo->s.len;
00250 pkg_free(foo);
00251 }
00252 *l=total_len;
00253 return ret;
00254
00255 error:
00256 i=sl.next;
00257 while(i) {
00258 foo=i;
00259 i=i->next;
00260 pkg_free(foo);
00261 }
00262 *l=0;
00263 return 0;
00264 }
00265
00266
00274 static inline void mi_print_routes( struct mi_node *node, dlg_t* dlg)
00275 {
00276 #define MI_ROUTE_PREFIX_S "Route: "
00277 #define MI_ROUTE_PREFIX_LEN (sizeof(MI_ROUTE_PREFIX_S)-1)
00278 #define MI_ROUTE_SEPARATOR_S ", "
00279 #define MI_ROUTE_SEPARATOR_LEN (sizeof(MI_ROUTE_SEPARATOR_S)-1)
00280 rr_t* ptr;
00281 int len;
00282 char *p, *s;
00283
00284 ptr = dlg->hooks.first_route;
00285
00286 if (ptr==NULL) {
00287 add_mi_node_child( node, 0, 0, 0, ".",1);
00288 return;
00289 }
00290
00291 len = MI_ROUTE_PREFIX_LEN;
00292 for( ; ptr ; ptr=ptr->next)
00293 len += ptr->len + MI_ROUTE_SEPARATOR_LEN*(ptr->next!=NULL);
00294 if (dlg->hooks.last_route)
00295 len += dlg->hooks.last_route->len + 2;
00296
00297
00298 s = pkg_malloc( len );
00299 if (s==0) {
00300 LM_ERR("no more pkg mem\n");
00301 return;
00302 }
00303
00304
00305 p = s;
00306 memcpy( p, MI_ROUTE_PREFIX_S, MI_ROUTE_PREFIX_LEN);
00307 p += MI_ROUTE_PREFIX_LEN;
00308
00309 for( ptr = dlg->hooks.first_route ; ptr ; ptr=ptr->next) {
00310 memcpy( p, ptr->nameaddr.name.s, ptr->len);
00311 p += ptr->len;
00312 if (ptr->next) {
00313 memcpy( p, MI_ROUTE_SEPARATOR_S, MI_ROUTE_SEPARATOR_LEN);
00314 p += MI_ROUTE_SEPARATOR_LEN;
00315 }
00316 }
00317
00318 if (dlg->hooks.last_route) {
00319 *(p++) = '<';
00320 memcpy( p, dlg->hooks.last_route->s, dlg->hooks.last_route->len);
00321 p += dlg->hooks.last_route->len;
00322 *(p++) = '>';
00323 }
00324
00325 add_mi_node_child( node, MI_DUP_VALUE, 0, 0, s, len);
00326 pkg_free(s);
00327 }
00328
00329
00338 static inline int mi_print_uris( struct mi_node *node, struct sip_msg* reply)
00339 {
00340 dlg_t* dlg;
00341
00342 if (reply==0)
00343 goto empty;
00344
00345 dlg = (dlg_t*)shm_malloc(sizeof(dlg_t));
00346 if (!dlg) {
00347 LM_ERR("no shm memory left\n");
00348 return -1;
00349 }
00350
00351 memset(dlg, 0, sizeof(dlg_t));
00352 if (_tmx_tmb.dlg_response_uac(dlg, reply, TARGET_REFRESH_UNKNOWN) < 0) {
00353 LM_ERR("failed to create dialog\n");
00354 _tmx_tmb.free_dlg(dlg);
00355 return -1;
00356 }
00357
00358 if (dlg->state != DLG_CONFIRMED) {
00359 _tmx_tmb.free_dlg(dlg);
00360 goto empty;
00361 }
00362
00363 if (dlg->hooks.request_uri->s) {
00364 add_mi_node_child( node, MI_DUP_VALUE, 0, 0,
00365 dlg->hooks.request_uri->s, dlg->hooks.request_uri->len);
00366 } else {
00367 add_mi_node_child( node, 0, 0, 0, ".",1);
00368 }
00369 if (dlg->hooks.next_hop->s) {
00370 add_mi_node_child( node, MI_DUP_VALUE, 0, 0,
00371 dlg->hooks.next_hop->s, dlg->hooks.next_hop->len);
00372 } else {
00373 add_mi_node_child( node, 0, 0, 0, ".",1);
00374 }
00375
00376 mi_print_routes( node, dlg);
00377
00378 _tmx_tmb.free_dlg(dlg);
00379 return 0;
00380 empty:
00381 add_mi_node_child( node, 0, 0, 0, ".",1);
00382 add_mi_node_child( node, 0, 0, 0, ".",1);
00383 add_mi_node_child( node, 0, 0, 0, ".",1);
00384 return 0;
00385 }
00386
00387
00388 static void mi_uac_dlg_hdl( struct cell *t, int type, struct tmcb_params *ps )
00389 {
00390 struct mi_handler *mi_hdl;
00391 struct mi_root *rpl_tree;
00392 str text;
00393
00394 LM_DBG("MI UAC generated status %d\n", ps->code);
00395 if (!*ps->param)
00396 return;
00397
00398 mi_hdl = (struct mi_handler *)(*ps->param);
00399
00400 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00401 if (rpl_tree==0)
00402 goto done;
00403
00404 if (ps->rpl==FAKED_REPLY) {
00405 get_reply_status( &text, ps->rpl, ps->code);
00406 if (text.s==0) {
00407 LM_ERR("get_reply_status failed\n");
00408 rpl_tree = 0;
00409 goto done;
00410 }
00411 add_mi_node_child( &rpl_tree->node, MI_DUP_VALUE, 0, 0,
00412 text.s, text.len);
00413 pkg_free(text.s);
00414 mi_print_uris( &rpl_tree->node, 0 );
00415 add_mi_node_child( &rpl_tree->node, 0, 0, 0, ".",1);
00416 } else {
00417 addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "%d %.*s",
00418 ps->rpl->first_line.u.reply.statuscode,
00419 ps->rpl->first_line.u.reply.reason.len,
00420 ps->rpl->first_line.u.reply.reason.s);
00421 mi_print_uris( &rpl_tree->node, ps->rpl);
00422 add_mi_node_child( &rpl_tree->node, MI_DUP_VALUE, 0, 0,
00423 ps->rpl->headers->name.s,
00424 ps->rpl->len-(ps->rpl->headers->name.s - ps->rpl->buf));
00425 }
00426
00427 LM_DBG("mi_callback successfully completed\n");
00428 done:
00429 if (ps->code >= 200) {
00430 mi_hdl->handler_f( rpl_tree, mi_hdl, 1 );
00431 *ps->param = 0;
00432 } else {
00433 mi_hdl->handler_f( rpl_tree, mi_hdl, 0 );
00434 }
00435 }
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 struct mi_root* mi_tm_uac_dlg(struct mi_root* cmd_tree, void* param)
00452 {
00453 static char err_buf[MAX_REASON_LEN];
00454 static struct sip_msg tmp_msg;
00455 static dlg_t dlg;
00456 struct mi_root *rpl_tree;
00457 struct mi_node *node;
00458 struct sip_uri pruri;
00459 struct sip_uri pnexthop;
00460 struct socket_info* sock;
00461 str *method;
00462 str *ruri;
00463 str *nexthop;
00464 str *socket;
00465 str *hdrs;
00466 str *body;
00467 str s;
00468 str callid = {0,0};
00469 int sip_error;
00470 int proto;
00471 int port;
00472 int cseq;
00473 int n;
00474 uac_req_t uac_r;
00475
00476 for( n=0,node = cmd_tree->node.kids; n<6 && node ; n++,node=node->next );
00477 if ( !(n==5 || n==6) || node!=0)
00478 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00479
00480 cseq = -1;
00481
00482
00483 node = cmd_tree->node.kids;
00484 method = &node->value;
00485
00486
00487 node = node->next;
00488 ruri = &node->value;
00489 if (parse_uri( ruri->s, ruri->len, &pruri) < 0 )
00490 return init_mi_tree( 400, "Invalid RURI", 12);
00491
00492
00493 node = node->next;
00494 nexthop = &node->value;
00495 if (nexthop->len==1 && nexthop->s[0]=='.') {
00496 nexthop = 0;
00497 } else {
00498 if (parse_uri( nexthop->s, nexthop->len, &pnexthop) < 0 )
00499 return init_mi_tree( 400, "Invalid NEXTHOP", 15);
00500 }
00501
00502
00503 node = node->next;
00504 socket = &node->value;
00505 if (socket->len==1 && socket->s[0]=='.' ) {
00506 sock = 0;
00507 } else {
00508 if (parse_phostport( socket->s, &s.s, &s.len,
00509 &port,&proto)!=0)
00510 return init_mi_tree( 404, "Invalid local socket", 20);
00511 sock = grep_sock_info( &s, (unsigned short)port, proto);
00512 if (sock==0)
00513 return init_mi_tree( 404, "Local socket not found", 22);
00514 }
00515
00516
00517 node = node->next;
00518 if (node->value.len==1 && node->value.s[0]=='.')
00519 hdrs = 0;
00520 else {
00521 hdrs = &node->value;
00522
00523 memset( &tmp_msg, 0, sizeof(struct sip_msg));
00524 tmp_msg.len = hdrs->len;
00525 tmp_msg.buf = tmp_msg.unparsed = hdrs->s;
00526 if (parse_headers( &tmp_msg, HDR_EOH_F, 0) == -1 )
00527 return init_mi_tree( 400, "Bad headers", 11);
00528 }
00529
00530
00531 node = node->next;
00532 if (node)
00533 body = &node->value;
00534 else
00535 body = 0;
00536
00537
00538
00539 rpl_tree = mi_check_msg( &tmp_msg, method, body, &cseq, &callid);
00540 if (rpl_tree) {
00541 if (tmp_msg.headers) free_hdr_field_lst(tmp_msg.headers);
00542 return rpl_tree;
00543 }
00544
00545 s.s = get_hfblock( nexthop ? nexthop : ruri,
00546 tmp_msg.headers, &s.len, &sock);
00547 if (s.s==0) {
00548 if (tmp_msg.headers) free_hdr_field_lst(tmp_msg.headers);
00549 return 0;
00550 }
00551
00552 memset( &dlg, 0, sizeof(dlg_t));
00553
00554
00555 if (callid.s && callid.len)
00556 dlg.id.call_id = callid;
00557 else
00558 _tmx_tmb.generate_callid(&dlg.id.call_id);
00559
00560
00561
00562
00563
00564 if (!(get_from(&tmp_msg)->tag_value.len&&get_from(&tmp_msg)->tag_value.s))
00565 _tmx_tmb.generate_fromtag(&dlg.id.loc_tag, &dlg.id.call_id);
00566
00567
00568 if (cseq!=-1)
00569 dlg.loc_seq.value = cseq;
00570 else
00571 dlg.loc_seq.value = DEFAULT_CSEQ;
00572 dlg.loc_seq.is_set = 1;
00573
00574 dlg.loc_uri = tmp_msg.from->body;
00575 dlg.rem_uri = tmp_msg.to->body;
00576 dlg.rem_target = *ruri;
00577 if (nexthop)
00578 dlg.dst_uri = *nexthop;
00579 dlg.send_sock = sock;
00580
00581 memset(&uac_r, 0, sizeof(uac_req_t));
00582 uac_r.method = method;
00583 uac_r.body = body;
00584 uac_r.headers = &s;
00585 uac_r.dialog = &dlg;
00586 if (cmd_tree->async_hdl!=NULL)
00587 {
00588 uac_r.cb = mi_uac_dlg_hdl;
00589 uac_r.cbp = (void*)cmd_tree->async_hdl;
00590 uac_r.cb_flags = TMCB_LOCAL_COMPLETED;
00591 }
00592 n = _tmx_tmb.t_uac(&uac_r);
00593
00594 pkg_free(s.s);
00595 if (tmp_msg.headers) free_hdr_field_lst(tmp_msg.headers);
00596
00597 if (n<=0) {
00598
00599 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00600 if (rpl_tree==0)
00601 return 0;
00602
00603 n = err2reason_phrase( n, &sip_error, err_buf, sizeof(err_buf),
00604 "MI/UAC") ;
00605 if (n > 0 )
00606 addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "%d %.*s",
00607 sip_error, n, err_buf);
00608 else
00609 add_mi_node_child( &rpl_tree->node, 0, 0, 0,
00610 "500 MI/UAC failed", 17);
00611
00612 return rpl_tree;
00613 } else {
00614 if (cmd_tree->async_hdl==NULL)
00615 return init_mi_tree( 202, "Accepted", 8);
00616 else
00617 return MI_ROOT_ASYNC_RPL;
00618 }
00619 }
00620
00621
00622
00623
00624
00625
00626
00627 struct mi_root* mi_tm_cancel(struct mi_root* cmd_tree, void* param)
00628 {
00629 struct cancel_info cancel_data;
00630 struct mi_node *node;
00631 struct cell *trans;
00632
00633 node = cmd_tree->node.kids;
00634 if ( !node || !node->next || node->next->next)
00635 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00636
00637 if( _tmx_tmb.t_lookup_callid( &trans, node->value, node->next->value) < 0 )
00638 return init_mi_tree( 481, "No such transaction", 19);
00639
00640
00641 LM_DBG("cancelling transaction %p\n",trans);
00642
00643 init_cancel_info(&cancel_data);
00644 cancel_data.cancel_bitmap = ~0;
00645 _tmx_tmb.cancel_uacs(trans, &cancel_data, 0);
00646
00647 _tmx_tmb.unref_cell(trans);
00648
00649 return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00650 }
00651
00652
00653
00654
00655
00656
00657 struct mi_root* mi_tm_hash(struct mi_root* cmd_tree, void* param)
00658 {
00659 #ifndef TM_HASH_STATS
00660 return init_mi_tree( 500, "No TM hash stats", 16);
00661 #else
00662 struct mi_root* rpl_tree= NULL;
00663 struct mi_node* rpl;
00664 struct mi_node* node;
00665 struct mi_attr* attr;
00666 struct s_table* tm_t;
00667 char *p;
00668 int i;
00669 int len;
00670
00671 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00672 if (rpl_tree==0)
00673 return 0;
00674 rpl = &rpl_tree->node;
00675 tm_t = _tmx_tmb.get_table();
00676
00677 for (i=0; i<TABLE_ENTRIES; i++) {
00678 if(tm_t->entries[i].cur_entries==0
00679 && tm_t->entries[i].acc_entries==0)
00680 continue;
00681
00682 p = int2str((unsigned long)i, &len );
00683 node = add_mi_node_child(rpl, MI_DUP_VALUE , 0, 0, p, len);
00684 if(node == NULL)
00685 goto error;
00686
00687 p = int2str((unsigned long)tm_t->entries[i].cur_entries, &len );
00688 attr = add_mi_attr(node, MI_DUP_VALUE, "Current", 7, p, len );
00689 if(attr == NULL)
00690 goto error;
00691
00692 p = int2str((unsigned long)tm_t->entries[i].acc_entries, &len );
00693 attr = add_mi_attr(node, MI_DUP_VALUE, "Total", 5, p, len );
00694 if(attr == NULL)
00695 goto error;
00696 }
00697
00698 return rpl_tree;
00699 error:
00700 free_mi_tree(rpl_tree);
00701 return init_mi_tree( 500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
00702 #endif
00703 }
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715 struct mi_root* mi_tm_reply(struct mi_root* cmd_tree, void* param)
00716 {
00717 struct mi_node* node;
00718 unsigned int hash_index;
00719 unsigned int hash_label;
00720 unsigned int rpl_code;
00721 struct cell *trans;
00722 str reason = {0, 0};
00723 str totag = {0, 0};
00724 str new_hdrs = {0, 0};
00725 str body = {0, 0};
00726 str tmp = {0, 0};
00727 char *p;
00728 int n;
00729
00730 for( n=0,node = cmd_tree->node.kids; n<6 && node ; n++,node=node->next );
00731 if ( !(n==5 || n==6) || node!=0)
00732 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00733
00734
00735
00736
00737 node = cmd_tree->node.kids;
00738 if (str2int( &node->value, &rpl_code)!=0 || rpl_code>=700)
00739 return init_mi_tree( 400, "Invalid reply code", 18);
00740
00741
00742 node = node->next;
00743 reason = node->value;
00744
00745
00746 node = node->next;
00747 tmp = node->value;
00748 p = memchr( tmp.s, ':', tmp.len);
00749 if(p==NULL)
00750 return init_mi_tree( 400, "Invalid trans_id", 16);
00751
00752 tmp.len = p-tmp.s;
00753 if(str2int(&tmp, &hash_index)!=0)
00754 return init_mi_tree( 400, "Invalid index in trans_id", 25);
00755
00756 tmp.s = p+1;
00757 tmp.len = (node->value.s+node->value.len) - tmp.s;
00758 if(str2int(&tmp, &hash_label)!=0)
00759 return init_mi_tree( 400, "Invalid label in trans_id", 25);
00760
00761 if(_tmx_tmb.t_lookup_ident( &trans, hash_index, hash_label)<0)
00762 return init_mi_tree( 404, "Transaction not found", 21);
00763
00764
00765 node = node->next;
00766 totag = node->value;
00767
00768
00769 node = node->next;
00770 if (!(node->value.len==1 && node->value.s[0]=='.'))
00771 new_hdrs = node->value;
00772
00773
00774 node = node->next;
00775 if (node)
00776 body = node->value;
00777
00778
00779
00780 n = _tmx_tmb.t_reply_with_body(trans, rpl_code, &reason, &body,
00781 &new_hdrs, &totag);
00782
00783 if (n<0)
00784 return init_mi_tree( 500, "Reply failed", 12);
00785
00786 return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00787 }
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799 struct mi_root* mi_tm_reply_callid(struct mi_root* cmd_tree, void* param)
00800 {
00801 struct mi_node* node;
00802 unsigned int rpl_code;
00803 struct cell *trans;
00804 str reason = {0, 0};
00805 str totag = {0, 0};
00806 str new_hdrs = {0, 0};
00807 str body = {0, 0};
00808 str callid = {0, 0};
00809 str cseq = {0, 0};
00810 int n;
00811
00812 for( n=0,node = cmd_tree->node.kids; n<7 && node ; n++,node=node->next );
00813 if ( !(n==6 || n==7) || node!=0)
00814 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00815
00816
00817
00818
00819 node = cmd_tree->node.kids;
00820 if (str2int( &node->value, &rpl_code)!=0 || rpl_code>=700)
00821 return init_mi_tree( 400, "Invalid reply code", 18);
00822
00823
00824 node = node->next;
00825 reason = node->value;
00826
00827
00828 node = node->next;
00829 callid = node->value;
00830
00831
00832 node = node->next;
00833 cseq = node->value;
00834
00835 if(_tmx_tmb.t_lookup_callid( &trans, callid, cseq) < 0 )
00836 return init_mi_tree( 400, "Lookup failed - no transaction", 30);
00837
00838
00839 node = node->next;
00840 totag = node->value;
00841
00842
00843 node = node->next;
00844 if (!(node->value.len==1 && node->value.s[0]=='.'))
00845 new_hdrs = node->value;
00846
00847
00848 node = node->next;
00849 if (node)
00850 body = node->value;
00851
00852
00853
00854 n = _tmx_tmb.t_reply_with_body(trans, rpl_code, &reason, &body,
00855 &new_hdrs, &totag);
00856
00857 if (n<0)
00858 return init_mi_tree( 500, "Reply failed", 12);
00859
00860 return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00861 }
00862