Module: kamailio
Branch: master
Commit: 2f080bd3af63678b900f9f537afbd187007eb089
URL:
https://github.com/kamailio/kamailio/commit/2f080bd3af63678b900f9f537afbd18…
Author: Alex Hermann <alex(a)speakup.nl>
Committer: Alex Hermann <alex(a)speakup.nl>
Date: 2016-07-28T12:02:15+02:00
tm: uac: Add support for onsend route to local request
---
Modified: modules/tm/uac.c
---
Diff:
https://github.com/kamailio/kamailio/commit/2f080bd3af63678b900f9f537afbd18…
Patch:
https://github.com/kamailio/kamailio/commit/2f080bd3af63678b900f9f537afbd18…
---
diff --git a/modules/tm/uac.c b/modules/tm/uac.c
index 6f165ae..bb4149a 100644
--- a/modules/tm/uac.c
+++ b/modules/tm/uac.c
@@ -57,6 +57,7 @@
#include "../../action.h"
#include "../../onsend.h"
#include "t_lookup.h"
+#include "t_fwd.h"
#endif
#define FROM_TAG_LEN (MD5_LEN + 1 /* - */ + CRC16_LEN) /* length of FROM tags */
@@ -590,23 +591,63 @@ int prepare_req_within(uac_req_t *uac_r,
return -1;
}
-static inline void send_prepared_request_impl(struct retr_buf *request, int retransmit)
+static inline int send_prepared_request_impl(struct retr_buf *request, int retransmit,
int branch)
{
+ struct cell *t;
+ struct sip_msg *p_msg;
+ struct ua_client *uac;
+ struct ip_addr ip; /* logging */
+ int ret;
+
+ t = request->my_T;
+ uac = &t->uac[branch];
+ p_msg = t->uas.request;
+
if (SEND_BUFFER(request) == -1) {
LOG(L_ERR, "t_uac: Attempt to send to precreated request failed\n");
}
- else if (unlikely(has_tran_tmcbs(request->my_T, TMCB_REQUEST_SENT)))
+ else if (unlikely(has_tran_tmcbs(t, TMCB_REQUEST_SENT)))
/* we don't know the method here */
- run_trans_callbacks_with_buf(TMCB_REQUEST_SENT, request, 0, 0,
+ run_trans_callbacks_with_buf(TMCB_REQUEST_SENT, &uac->request, 0, 0,
TMCB_LOCAL_F);
-
- if (retransmit && (start_retr(request)!=0))
- LOG(L_CRIT, "BUG: t_uac: failed to start retr. for %p\n", request);
+
+ su2ip_addr(&ip, &uac->request.dst.to);
+ DBG("send_prepared_request_impl: uac: %p branch: %d to %s:%d\n",
+ uac, branch, ip_addr2a(&ip), su_getport(&uac->request.dst.to));
+
+ if (run_onsend(p_msg, &uac->request.dst, uac->request.buffer,
+ uac->request.buffer_len)==0){
+ uac->last_received=408;
+ su2ip_addr(&ip, &uac->request.dst.to);
+ DBG("t_uac: onsend_route dropped msg. to %s:%d (%d)\n",
+ ip_addr2a(&ip), su_getport(&uac->request.dst.to),
+ uac->request.dst.proto);
+#ifdef USE_DNS_FAILOVER
+ /* if the destination resolves to more ips, add another
+ * branch/uac */
+ ret = add_uac_dns_fallback(t, p_msg, uac, retransmit);
+ if (ret > 0) {
+ su2ip_addr(&ip, &uac->request.dst.to);
+ DBG("t_uac: send on branch %d failed "
+ "(onsend_route), trying another ip %s:%d (%d)\n",
+ branch, ip_addr2a(&ip),
+ su_getport(&uac->request.dst.to),
+ uac->request.dst.proto);
+ /* success, return new branch */
+ return ret;
+ }
+#endif /* USE_DNS_FAILOVER*/
+ return -1;
+ }
+
+ if (retransmit && (start_retr(&uac->request)!=0))
+ LOG(L_CRIT, "BUG: t_uac: failed to start retr. for %p\n",
&uac->request);
+ return 0;
}
void send_prepared_request(struct retr_buf *request)
{
- send_prepared_request_impl(request, 1 /* retransmit */);
+ send_prepared_request_impl(request, 1 /* retransmit */, 0);
}
/*
@@ -628,11 +669,27 @@ int t_uac_with_ids(uac_req_t *uac_r,
struct cell *cell;
int ret;
int is_ack;
+ int branch_ret;
+ int i;
+ branch_bm_t added_branches = 1;
ret = t_uac_prepare(uac_r, &request, &cell);
if (ret < 0) return ret;
is_ack = (uac_r->method->len == 3) && (memcmp("ACK",
uac_r->method->s, 3)==0) ? 1 : 0;
- send_prepared_request_impl(request, !is_ack /* retransmit */);
+
+ /* equivalent loop to the one in t_forward_nonack */
+ for (i=0; i<cell->nr_of_outgoings; i++) {
+ if (added_branches & (1<<i)) {
+ branch_ret=send_prepared_request_impl(request, !is_ack /* retransmit */, i);
+ if (branch_ret>=0){ /* some kind of success */
+ if (branch_ret>i) {
+ /* new branch added */
+ added_branches |= 1<<branch_ret;
+ }
+ }
+ }
+ }
+
if (is_ack) {
if (cell) free_cell(cell);
if (ret_index && ret_label)