|
@@ -237,8 +237,8 @@ static inline int t_build_msg_from_buf(struct sip_msg *msg, char *buf,
|
|
|
}
|
|
|
|
|
|
#ifdef WITH_EVENT_LOCAL_REQUEST
|
|
|
-static inline int t_run_local_req(char **buf, int *buf_len, uac_req_t *uac_r,
|
|
|
- struct cell *new_cell, struct retr_buf *request)
|
|
|
+static inline int t_run_local_req(char **buf, int *buf_len, int buf_offset,
|
|
|
+ uac_req_t *uac_r, struct cell *new_cell, struct retr_buf *request)
|
|
|
{
|
|
|
struct sip_msg lreq = {0};
|
|
|
struct onsend_info onsnd_info;
|
|
@@ -246,6 +246,7 @@ static inline int t_run_local_req(char **buf, int *buf_len, uac_req_t *uac_r,
|
|
|
int sflag_bk;
|
|
|
char *buf1;
|
|
|
int buf_len1;
|
|
|
+ char *buf2;
|
|
|
int backup_route_type;
|
|
|
struct cell *backup_t;
|
|
|
int backup_branch;
|
|
@@ -357,24 +358,10 @@ static inline int t_run_local_req(char **buf, int *buf_len, uac_req_t *uac_r,
|
|
|
request->dst.proto = lreq.force_send_socket->proto;
|
|
|
}
|
|
|
|
|
|
- LM_DBG("apply new updates with Via to sip msg\n");
|
|
|
- buf1 = build_req_buf_from_sip_req(&lreq, (unsigned int *)&buf_len1,
|
|
|
- &request->dst, BUILD_NEW_LOCAL_VIA | BUILD_IN_SHM);
|
|
|
- if(likely(buf1)) {
|
|
|
- shm_free(*buf);
|
|
|
- *buf = buf1;
|
|
|
- *buf_len = buf_len1;
|
|
|
- /* a possible change of the method is not handled! */
|
|
|
- refresh_shortcuts = 1;
|
|
|
- }
|
|
|
-
|
|
|
- } else {
|
|
|
- normal_update:
|
|
|
- if(unlikely(lreq.add_rm || lreq.body_lumps || lreq.new_uri.s)) {
|
|
|
- LM_DBG("apply new updates without Via to sip msg\n");
|
|
|
+ if(buf_offset == 0) {
|
|
|
+ LM_DBG("apply new updates with Via to sip msg\n");
|
|
|
buf1 = build_req_buf_from_sip_req(&lreq, (unsigned int *)&buf_len1,
|
|
|
- &request->dst,
|
|
|
- BUILD_NO_LOCAL_VIA | BUILD_NO_VIA1_UPDATE | BUILD_IN_SHM);
|
|
|
+ &request->dst, BUILD_NEW_LOCAL_VIA | BUILD_IN_SHM);
|
|
|
if(likely(buf1)) {
|
|
|
shm_free(*buf);
|
|
|
*buf = buf1;
|
|
@@ -382,6 +369,65 @@ static inline int t_run_local_req(char **buf, int *buf_len, uac_req_t *uac_r,
|
|
|
/* a possible change of the method is not handled! */
|
|
|
refresh_shortcuts = 1;
|
|
|
}
|
|
|
+ } else {
|
|
|
+ LM_DBG("apply new updates with Via to sip msg, preserving "
|
|
|
+ "prefix\n");
|
|
|
+ buf1 = build_req_buf_from_sip_req(&lreq, (unsigned int *)&buf_len1,
|
|
|
+ &request->dst, BUILD_NEW_LOCAL_VIA);
|
|
|
+ if(likely(buf1)) {
|
|
|
+ buf2 = shm_malloc(buf_offset + buf_len1);
|
|
|
+ if(unlikely(!buf2)) {
|
|
|
+ SHM_MEM_ERROR_FMT("required (%u)\n", buf_offset + buf_len1);
|
|
|
+ pkg_free(buf1);
|
|
|
+ goto clean;
|
|
|
+ }
|
|
|
+ memcpy(buf2, *buf - buf_offset, buf_offset);
|
|
|
+ memcpy(buf2 + buf_offset, buf1, buf_len1);
|
|
|
+ shm_free(*buf - buf_offset);
|
|
|
+ pkg_free(buf1);
|
|
|
+ *buf = buf2 + buf_offset;
|
|
|
+ *buf_len = buf_len1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ } else {
|
|
|
+ normal_update:
|
|
|
+ if(unlikely(lreq.add_rm || lreq.body_lumps || lreq.new_uri.s)) {
|
|
|
+ if(buf_offset == 0) {
|
|
|
+ LM_DBG("apply new updates without Via to sip msg\n");
|
|
|
+ buf1 = build_req_buf_from_sip_req(&lreq,
|
|
|
+ (unsigned int *)&buf_len1, &request->dst,
|
|
|
+ BUILD_NO_LOCAL_VIA | BUILD_NO_VIA1_UPDATE
|
|
|
+ | BUILD_IN_SHM);
|
|
|
+ if(likely(buf1)) {
|
|
|
+ shm_free(*buf);
|
|
|
+ *buf = buf1;
|
|
|
+ *buf_len = buf_len1;
|
|
|
+ /* a possible change of the method is not handled! */
|
|
|
+ refresh_shortcuts = 1;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ LM_DBG("apply new updates without Via to sip msg, preserving "
|
|
|
+ "prefix\n");
|
|
|
+ buf1 = build_req_buf_from_sip_req(&lreq,
|
|
|
+ (unsigned int *)&buf_len1, &request->dst,
|
|
|
+ BUILD_NO_LOCAL_VIA | BUILD_NO_VIA1_UPDATE);
|
|
|
+ if(likely(buf1)) {
|
|
|
+ buf2 = shm_malloc(buf_offset + buf_len1);
|
|
|
+ if(unlikely(!buf2)) {
|
|
|
+ SHM_MEM_ERROR_FMT(
|
|
|
+ "required (%u)\n", buf_offset + buf_len1);
|
|
|
+ pkg_free(buf1);
|
|
|
+ goto clean;
|
|
|
+ }
|
|
|
+ memcpy(buf2, *buf - buf_offset, buf_offset);
|
|
|
+ memcpy(buf2 + buf_offset, buf1, buf_len1);
|
|
|
+ shm_free(*buf - buf_offset);
|
|
|
+ *buf = buf2 + buf_offset;
|
|
|
+ *buf_len = buf_len1;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -559,7 +605,7 @@ static inline int t_uac_prepare(
|
|
|
#ifdef WITH_EVENT_LOCAL_REQUEST
|
|
|
if(unlikely(goto_on_local_req >= 0 || tm_event_callback.len > 0)) {
|
|
|
refresh_shortcuts =
|
|
|
- t_run_local_req(&buf, &buf_len, uac_r, new_cell, request);
|
|
|
+ t_run_local_req(&buf, &buf_len, 0, uac_r, new_cell, request);
|
|
|
if(unlikely(refresh_shortcuts == E_DROP)) {
|
|
|
shm_free(buf);
|
|
|
ret = E_DROP;
|
|
@@ -823,6 +869,9 @@ struct retr_buf *local_ack_rb(sip_msg_t *rpl_2xx, struct cell *trans,
|
|
|
unsigned int buf_len;
|
|
|
char *buffer;
|
|
|
struct dest_info dst;
|
|
|
+ dlg_t *dlg;
|
|
|
+ uac_req_t uac_req;
|
|
|
+ str method;
|
|
|
|
|
|
buf_len = (unsigned)sizeof(struct retr_buf);
|
|
|
buffer = build_dlg_ack(rpl_2xx, trans, branch, hdrs, body, &buf_len, &dst);
|
|
@@ -832,10 +881,12 @@ struct retr_buf *local_ack_rb(sip_msg_t *rpl_2xx, struct cell *trans,
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
+
|
|
|
/* 'buffer' now points into a contiguous chunk of memory with enough
|
|
|
* room to hold both the retr. buffer and the string raw buffer: it
|
|
|
* points to the beginning of the string buffer; we iterate back to get
|
|
|
* the beginning of the space for the retr. buffer. */
|
|
|
+
|
|
|
lack = &((struct retr_buf *)buffer)[-1];
|
|
|
lack->buffer = buffer;
|
|
|
lack->buffer_len = buf_len;
|
|
@@ -846,6 +897,42 @@ struct retr_buf *local_ack_rb(sip_msg_t *rpl_2xx, struct cell *trans,
|
|
|
lack->rbtype = TYPE_LOCAL_ACK;
|
|
|
lack->my_T = trans;
|
|
|
|
|
|
+#ifdef WITH_EVENT_LOCAL_REQUEST
|
|
|
+ dlg = (dlg_t *)shm_malloc(sizeof(dlg_t));
|
|
|
+ if(dlg == 0) {
|
|
|
+ SHM_MEM_ERROR_FMT("required (%u)\n", sizeof(dlg_t));
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ memset(dlg, 0, sizeof(dlg_t));
|
|
|
+ dlg->state = DLG_NEW;
|
|
|
+ if(dlg_response_uac(dlg, rpl_2xx, IS_NOT_TARGET_REFRESH) < 0) {
|
|
|
+ LM_ERR("failed to create new dialog\n");
|
|
|
+ shm_free(buffer);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ dlg->send_sock = dst.send_sock;
|
|
|
+
|
|
|
+ /* Clear everything */
|
|
|
+ memset(&uac_req, 0, sizeof(uac_req));
|
|
|
+ method.s = ACK;
|
|
|
+ method.len = ACK_LEN;
|
|
|
+ uac_req.method = &method;
|
|
|
+ uac_req.body = body;
|
|
|
+ uac_req.dialog = dlg;
|
|
|
+
|
|
|
+ t_run_local_req(&buffer, (int *)&buf_len, (unsigned)sizeof(struct retr_buf),
|
|
|
+ &uac_req, trans, lack);
|
|
|
+
|
|
|
+ /* t_local_run_req could have changed the buffer, if so we need to update
|
|
|
+ * lack just in case
|
|
|
+ */
|
|
|
+ lack = &((struct retr_buf *)buffer)[-1];
|
|
|
+ lack->buffer = buffer;
|
|
|
+ lack->buffer_len = buf_len;
|
|
|
+
|
|
|
+ free_dlg(dlg);
|
|
|
+#endif
|
|
|
+
|
|
|
return lack;
|
|
|
}
|
|
|
|