Bladeren bron

tm: invoke tm:local-request on generated ACK messages (#4250)

tsearle 3 maanden geleden
bovenliggende
commit
c020f76b23
1 gewijzigde bestanden met toevoegingen van 107 en 20 verwijderingen
  1. 107 20
      src/modules/tm/uac.c

+ 107 - 20
src/modules/tm/uac.c

@@ -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;
 }