int e2e_cancel_branch( struct sip_msg *cancel_msg, struct cell *t_cancel, struct cell *t_invite, int branch ) { int ret; char *shbuf; unsigned int len; if (t_cancel->uac[branch].request.buffer) { LOG(L_CRIT, "ERROR: e2e_cancel_branch: buffer rewrite attempt\n"); ret=ser_error=E_BUG; goto error; } /* note -- there is a gap in proxy stats -- we don't update proxy stats with CANCEL (proxy->ok, proxy->tx, etc.) */ /* print */ shbuf=print_uac_request( t_cancel, cancel_msg, branch, &t_invite->uac[branch].uri, &len, t_invite->uac[branch].request.dst.send_sock, t_invite->uac[branch].request.dst.proto); if (!shbuf) { LOG(L_ERR, "ERROR: e2e_cancel_branch: printing e2e cancel failed\n"); ret=ser_error=E_OUT_OF_MEM; goto error; } /* install buffer */ t_cancel->uac[branch].request.dst=t_invite->uac[branch].request.dst; t_cancel->uac[branch].request.buffer=shbuf; t_cancel->uac[branch].request.buffer_len=len; t_cancel->uac[branch].uri.s=t_cancel->uac[branch].request.buffer+ cancel_msg->first_line.u.request.method.len+1; t_cancel->uac[branch].uri.len=t_invite->uac[branch].uri.len; /* success */ ret=1; error: return ret; }
static inline int update_uac_dst( struct sip_msg *request, struct ua_client *uac ) { struct socket_info* send_sock; char *shbuf; unsigned int len; send_sock = get_send_socket( request, &uac->request.dst.to , uac->request.dst.proto ); if (send_sock==0) { LM_ERR("failed to fwd to af %d, proto %d " " (no corresponding listening socket)\n", uac->request.dst.to.s.sa_family, uac->request.dst.proto ); ser_error=E_NO_SOCKET; return -1; } if (send_sock!=uac->request.dst.send_sock) { /* rebuild */ shbuf = print_uac_request( request, &len, send_sock, uac->request.dst.proto); if (!shbuf) { ser_error=E_OUT_OF_MEM; return -1; } if (uac->request.buffer.s) shm_free(uac->request.buffer.s); /* things went well, move ahead and install new buffer! */ uac->request.dst.send_sock = send_sock; uac->request.dst.proto_reserved1 = 0; uac->request.buffer.s = shbuf; uac->request.buffer.len = len; } return 0; }
int e2e_cancel_branch( struct sip_msg *cancel_msg, struct cell *t_cancel, struct cell *t_invite, int branch ) { int ret; char *shbuf; unsigned int len; str bk_dst_uri; str bk_path_vec; if (t_cancel->uac[branch].request.buffer.s) { LM_CRIT("buffer rewrite attempt\n"); ret=ser_error=E_BUG; goto error; } cancel_msg->new_uri = t_invite->uac[branch].uri; cancel_msg->parsed_uri_ok=0; bk_dst_uri = cancel_msg->dst_uri; bk_path_vec = cancel_msg->path_vec; /* force same path as for request */ cancel_msg->path_vec = t_invite->uac[branch].path_vec; if ( pre_print_uac_request( t_cancel, branch, cancel_msg)!= 0 ) { ret = -1; goto error01; } /* force same uri as in INVITE */ if (cancel_msg->new_uri.s!=t_invite->uac[branch].uri.s) { pkg_free(cancel_msg->new_uri.s); cancel_msg->new_uri = t_invite->uac[branch].uri; /* and just to be sure */ cancel_msg->parsed_uri_ok = 0; } /* print */ shbuf=print_uac_request( cancel_msg, &len, t_invite->uac[branch].request.dst.send_sock, t_invite->uac[branch].request.dst.proto); if (!shbuf) { LM_ERR("printing e2e cancel failed\n"); ret=ser_error=E_OUT_OF_MEM; goto error01; } /* install buffer */ t_cancel->uac[branch].request.dst=t_invite->uac[branch].request.dst; t_cancel->uac[branch].request.buffer.s=shbuf; t_cancel->uac[branch].request.buffer.len=len; t_cancel->uac[branch].uri.s=t_cancel->uac[branch].request.buffer.s+ cancel_msg->first_line.u.request.method.len+1; t_cancel->uac[branch].uri.len=t_invite->uac[branch].uri.len; t_cancel->uac[branch].br_flags = cancel_msg->flags; /* success */ ret=1; error01: post_print_uac_request( cancel_msg, &t_invite->uac[branch].uri, &bk_dst_uri); cancel_msg->dst_uri = bk_dst_uri; cancel_msg->path_vec = bk_path_vec; error: return ret; }
/* introduce a new uac to transaction; returns its branch id (>=0) or error (<0); it doesn't send a message yet -- a reply to it might interfere with the processes of adding multiple branches */ int add_uac( struct cell *t, struct sip_msg *request, str *uri, str* next_hop, struct proxy_l *proxy, int proto ) { int ret; short temp_proxy; union sockaddr_union to; unsigned short branch; struct socket_info* send_sock; char *shbuf; unsigned int len; branch=t->nr_of_outgoings; if (branch==MAX_BRANCHES) { LOG(L_ERR, "ERROR: add_uac: maximum number of branches exceeded\n"); ret=E_CFG; goto error; } /* check existing buffer -- rewriting should never occur */ if (t->uac[branch].request.buffer) { LOG(L_CRIT, "ERROR: add_uac: buffer rewrite attempt\n"); ret=ser_error=E_BUG; goto error; } /* check DNS resolution */ if (proxy) { temp_proxy=0; proto=get_proto(proto, proxy->proto); } else { proxy=uri2proxy( next_hop ? next_hop : uri, proto ); if (proxy==0) { ret=E_BAD_ADDRESS; goto error; } proto=proxy->proto; /* uri2proxy will fix it for us */ temp_proxy=1; } if (proxy->ok==0) { if (proxy->host.h_addr_list[proxy->addr_idx+1]) proxy->addr_idx++; else proxy->addr_idx=0; proxy->ok=1; } hostent2su( &to, &proxy->host, proxy->addr_idx, proxy->port ? proxy->port:SIP_PORT); send_sock=get_send_socket( request, &to , proto); if (send_sock==0) { LOG(L_ERR, "ERROR: add_uac: can't fwd to af %d, proto %d " " (no corresponding listening socket)\n", to.s.sa_family, proto ); ret=ser_error=E_NO_SOCKET; goto error01; } /* now message printing starts ... */ shbuf=print_uac_request( t, request, branch, uri, &len, send_sock, proto ); if (!shbuf) { ret=ser_error=E_OUT_OF_MEM; goto error01; } /* things went well, move ahead and install new buffer! */ t->uac[branch].request.dst.to=to; t->uac[branch].request.dst.send_sock=send_sock; t->uac[branch].request.dst.proto=proto; t->uac[branch].request.dst.proto_reserved1=0; t->uac[branch].request.buffer=shbuf; t->uac[branch].request.buffer_len=len; t->uac[branch].uri.s=t->uac[branch].request.buffer+ request->first_line.u.request.method.len+1; t->uac[branch].uri.len=uri->len; t->nr_of_outgoings++; /* update stats */ proxy->tx++; proxy->tx_bytes+=len; /* done! */ ret=branch; error01: if (temp_proxy) { free_proxy( proxy ); pkg_free( proxy ); } error: return ret; }
int e2e_cancel_branch( struct sip_msg *cancel_msg, struct cell *t_cancel, struct cell *t_invite, int branch ) { int ret; char *shbuf; unsigned int len; str bk_dst_uri; if (t_cancel->uac[branch].request.buffer) { LOG(L_CRIT, "ERROR: e2e_cancel_branch: buffer rewrite attempt\n"); ret=ser_error=E_BUG; goto error; } /* note -- there is a gap in proxy stats -- we don't update proxy stats with CANCEL (proxy->ok, proxy->tx, etc.) */ cancel_msg->new_uri = t_invite->uac[branch].uri; cancel_msg->parsed_uri_ok=0; bk_dst_uri = cancel_msg->dst_uri; if ( pre_print_uac_request( t_cancel, branch, cancel_msg)!= 0 ) { ret = -1; goto error01; } /* force same uri as in INVITE */ if (cancel_msg->new_uri.s!=t_invite->uac[branch].uri.s) { pkg_free(cancel_msg->new_uri.s); cancel_msg->new_uri = t_invite->uac[branch].uri; /* and just to be sure */ cancel_msg->parsed_uri_ok = 0; } /* print */ shbuf=print_uac_request( cancel_msg, &len, t_invite->uac[branch].request.dst.send_sock, t_invite->uac[branch].request.dst.proto); if (!shbuf) { LOG(L_ERR, "ERROR: e2e_cancel_branch: printing e2e cancel failed\n"); ret=ser_error=E_OUT_OF_MEM; goto error01; } /* install buffer */ t_cancel->uac[branch].request.dst=t_invite->uac[branch].request.dst; t_cancel->uac[branch].request.buffer=shbuf; t_cancel->uac[branch].request.buffer_len=len; t_cancel->uac[branch].uri.s=t_cancel->uac[branch].request.buffer+ cancel_msg->first_line.u.request.method.len+1; t_cancel->uac[branch].uri.len=t_invite->uac[branch].uri.len; t_cancel->uac[branch].br_flags = cancel_msg->flags&(~gflags_mask); /* success */ ret=1; error01: post_print_uac_request( cancel_msg, &t_invite->uac[branch].uri, &bk_dst_uri); cancel_msg->dst_uri = bk_dst_uri; error: return ret; }