diff --git a/dprint.h b/dprint.h
index a16f0ae96a2..40fc62a9540 100644
--- a/dprint.h
+++ b/dprint.h
@@ -98,6 +98,9 @@
#define L_INFO 2
#define L_DBG 3
#define L_MAX 3
+#define L_OFFSET 42 /* needs to be added and then substracted
+ because L_WARN may be confused with NULL pointer
+ (e.g. fixup_dbg_sip_msg) */
/** @brief This is the facility value used to indicate that the caller of the macro
* did not override the facility. Value 0 (the defaul) is LOG_KERN on Linux
diff --git a/modules/debugger/debugger_mod.c b/modules/debugger/debugger_mod.c
index 5603c81befd..dc5bdaa8e79 100644
--- a/modules/debugger/debugger_mod.c
+++ b/modules/debugger/debugger_mod.c
@@ -34,13 +34,14 @@
#include "../../parser/parse_param.h"
#include "../../shm_init.h"
#include "../../script_cb.h"
+#include "../../msg_translator.h"
#include "debugger_api.h"
#include "debugger_config.h"
MODULE_VERSION
-static int mod_init(void);
+static int mod_init(void);
static int child_init(int rank);
static void mod_destroy(void);
@@ -52,6 +53,12 @@ static int dbg_mod_facility_param(modparam_t type, void *val);
static int fixup_dbg_pv_dump(void** param, int param_no);
static int w_dbg_dump(struct sip_msg* msg, char* mask, char* level);
+static struct action *dbg_fixup_get_action(void **param, int param_no);
+static int fixup_dbg_sip_msg(void** param, int param_no);
+static int w_dbg_sip_msg(struct sip_msg* msg, char *level, char *facility);
+
+extern char* dump_lump_list(struct lump *list, int s_offset, char *s_buf);
+
/* parameters */
extern int _dbg_cfgtrace;
extern int _dbg_cfgpkgcheck;
@@ -64,6 +71,7 @@ extern int _dbg_step_usleep;
extern int _dbg_step_loops;
extern int _dbg_reset_msgid;
+static int _dbg_sip_msg_cline;
static char * _dbg_cfgtrace_facility_str = 0;
static int _dbg_log_assign = 0;
@@ -76,6 +84,12 @@ static cmd_export_t cmds[]={
fixup_dbg_pv_dump, 0, ANY_ROUTE},
{"dbg_pv_dump", (cmd_function)w_dbg_dump, 2,
fixup_dbg_pv_dump, 0, ANY_ROUTE},
+ {"dbg_sip_msg", (cmd_function)w_dbg_sip_msg, 0,
+ fixup_dbg_sip_msg, 0, REQUEST_ROUTE},
+ {"dbg_sip_msg", (cmd_function)w_dbg_sip_msg, 1,
+ fixup_dbg_sip_msg, 0, REQUEST_ROUTE},
+ {"dbg_sip_msg", (cmd_function)w_dbg_sip_msg, 2,
+ fixup_dbg_sip_msg, 0, REQUEST_ROUTE},
{0, 0, 0, 0, 0, 0}
};
@@ -370,6 +384,161 @@ static int dbg_mod_facility_param(modparam_t type, void *val)
return -1;
}
return 0;
+}
+static int fixup_dbg_sip_msg(void** param, int param_no)
+{
+ int facility;
+ int level;
+ struct action *dbg_sip_msg_action;
+
+ switch(param_no)
+ {
+ case 2:
+ facility = str2facility((char*)*(param));
+ if (facility == -1) {
+ LM_ERR("invalid log facility configured");
+ return E_UNSPEC;
+ }
+
+ *param = (void*)(long)facility;
+ break;
+ case 1:
+ switch(((char*)(*param))[2])
+ {
+ /* add L_OFFSET because L_WARN is consdered null pointer */
+ case 'A': level = L_ALERT + L_OFFSET; break;
+ case 'B': level = L_BUG + L_OFFSET; break;
+ case 'C': level = L_CRIT2 + L_OFFSET; break;
+ case 'E': level = L_ERR + L_OFFSET; break;
+ case 'W': level = L_WARN + L_OFFSET; break;
+ case 'N': level = L_NOTICE + L_OFFSET; break;
+ case 'I': level = L_INFO + L_OFFSET; break;
+ case 'D': level = L_DBG + L_OFFSET; break;
+ default:
+ LM_ERR("unknown log level\n");
+ return E_UNSPEC;
+ }
+
+ *param = (void*)(long)level;
+ break;
+ }
+
+ /* save the config line where this config function was called */
+ dbg_sip_msg_action = dbg_fixup_get_action(param, param_no);
+ _dbg_sip_msg_cline = dbg_sip_msg_action->cline;
+
+ return 0;
}
+/**
+ * dump current SIP message and a diff lump list
+ * part of the code taken from msg_apply_changes_f
+ */
+static int w_dbg_sip_msg(struct sip_msg* msg, char *level, char *facility)
+{
+ int ilevel = cfg_get(core, core_cfg, debug);
+ int ifacility= cfg_get(core, core_cfg, log_facility);
+ int flag = FLAG_MSG_LUMPS_ONLY; // copy lumps only, not the whole message
+ unsigned int new_buf_offs=0, orig_offs = 0;
+ char *hdr_lumps = NULL;
+ char *bdy_lumps = NULL;
+ const char *start_txt = "------------------------- START OF SIP message debug --------------------------\n";
+ const char *hdr_txt = "------------------------------ SIP header diffs -------------------------------\n";
+ const char *bdy_txt = "------------------------------- SIP body diffs --------------------------------\n";
+ const char *end_txt = "-------------------------- END OF SIP message debug ---------------------------\n\n";
+ struct dest_info send_info;
+ str obuf;
+
+ if (level != NULL) {
+ /* substract L_OFFSET previously added */
+ ilevel = (int)(long)level - L_OFFSET;
+ }
+
+ if (facility != NULL) {
+ ifacility = (int)(long)facility;
+ }
+
+ /* msg_apply_changes_f code needed to get the current msg */
+ init_dest_info(&send_info);
+ send_info.proto = PROTO_UDP;
+ if(msg->first_line.type == SIP_REPLY) {
+ obuf.s = generate_res_buf_from_sip_res(msg,
+ (unsigned int*)&obuf.len, BUILD_NO_VIA1_UPDATE);
+ } else {
+ obuf.s = build_req_buf_from_sip_req(msg,
+ (unsigned int*)&obuf.len, &send_info,
+ BUILD_NO_PATH|BUILD_NO_LOCAL_VIA|BUILD_NO_VIA1_UPDATE);
+ }
+
+ if(obuf.s == NULL)
+ {
+ LM_ERR("couldn't update msg buffer content\n");
+ return -1;
+ }
+
+ if(obuf.len >= BUF_SIZE)
+ {
+ LM_ERR("new buffer overflow (%d)\n", obuf.len);
+ pkg_free(obuf.s);
+ return -1;
+ }
+
+ /* skip original uri */
+ if (msg->new_uri.s){
+ orig_offs=msg->first_line.u.request.uri.s - msg->buf;
+ orig_offs=msg->first_line.u.request.uri.len;
+ }
+
+ /* alloc private mem and copy lumps */
+ hdr_lumps = pkg_malloc(BUF_SIZE);
+ bdy_lumps = pkg_malloc(BUF_SIZE);
+
+ new_buf_offs = 0;
+ process_lumps(msg, msg->add_rm, hdr_lumps, &new_buf_offs, &orig_offs, &send_info, flag);
+
+ new_buf_offs = 0;
+ process_lumps(msg, msg->body_lumps, bdy_lumps, &new_buf_offs, &orig_offs, &send_info, flag);
+
+ /* do the print */
+ if (hdr_lumps != NULL && bdy_lumps != NULL) {
+ LOG_FC(ifacility, ilevel, "CONFIG LINE %d\n%s%.*s%s%s%s%s%s",
+ _dbg_sip_msg_cline,
+ start_txt,
+ obuf.len, obuf.s,
+ hdr_txt, hdr_lumps,
+ bdy_txt, bdy_lumps,
+ end_txt);
+ } else if (hdr_lumps != NULL) {
+ LOG_FC(ifacility, ilevel, "CONFIG LINE %d\n%s%.*s%s%s%s",
+ _dbg_sip_msg_cline,
+ start_txt,
+ obuf.len, obuf.s,
+ hdr_txt, hdr_lumps,
+ end_txt);
+ } else if (bdy_lumps != NULL) {
+ LOG_FC(ifacility, ilevel, "CONFIG LINE %d\n%s%.*s%s%s%s",
+ _dbg_sip_msg_cline,
+ start_txt,
+ obuf.len, obuf.s,
+ bdy_txt, bdy_lumps,
+ end_txt);
+ } else {
+ LOG_FC(ifacility, ilevel, "CONFIG LINE %d\n%s%.*s%s",
+ _dbg_sip_msg_cline,
+ start_txt,
+ obuf.len, obuf.s,
+ end_txt);
+ }
+
+ /* free lumps */
+ if (hdr_lumps) {
+ pkg_free(hdr_lumps);
+ }
+
+ if (bdy_lumps) {
+ pkg_free(bdy_lumps);
+ }
+
+ return 1;
+}
diff --git a/modules/debugger/doc/debugger_admin.xml b/modules/debugger/doc/debugger_admin.xml
index c4b6eb23136..f003fb5f80f 100644
--- a/modules/debugger/doc/debugger_admin.xml
+++ b/modules/debugger/doc/debugger_admin.xml
@@ -531,8 +531,69 @@ dbg_pv_dump(30, "L_DBG");
+
+
+ dbg_sip_msg([log_level], [facility])
+
+
+ Prints how the sip message would look like if it would be sent out
+ at that point in the config(i.e. if the current lump lists would
+ have been applied at that point in the config).
+
+ It also prints a diff list for both header and body of sip msg
+ which contain the lump lists content. The lumps deleted are printed
+ with "-" sign whereas the lumps added have no sign. The config line
+ where the function has been called is also printed.
+
+
+ NOTE that dbg_sip_msg function does not modify the initially received SIP message.
+ Just displays how it WOULD look like if it were to send it at that point.
+
+
+ NOTE that the lump lists are usually applied only once, just before sending, to spare message reparse processing.
+ All the changes present in lump list are applied on the initially received SIP message.
+ One can force the lump application using msg_apply_changes() function from textopsx module.
+
+
+
+
+ dbg_sip_msg usage
+
+...
+ dbg_sip_msg();
+ dbg_sip_msg("L_ERR");
+ dbg_sip_msg("L_ERR", "LOG_LOCAL0");
+...
+
+
+ Output when dbg_sip_msg("L_ERR") is called after append_hf("P-Hint: My hint\r\n"); remove_hf("Contact");
+
+ERROR: debugger [debugger_mod.c:467]: w_dbg_sip_msg(): CONFIG LINE 338
+------------------------- START OF SIP message debug --------------------------
+OPTIONS sip:nobody@127.0.0.1 SIP/2.0
+Via: SIP/2.0/UDP 127.0.1.1:56872;branch=z9hG4bK.6d7c487a;rport;alias
+From: sip:sipsak@127.0.1.1:56872;tag=188b7433
+To: sip:nobody@127.0.0.1
+Call-ID: 411792435@127.0.1.1
+CSeq: 1 OPTIONS
+Content-Length: 0
+Max-Forwards: 70
+User-Agent: sipsak 0.9.6
+Accept: text/plain
+P-Hint: My hintt
+
+------------------------------ SIP header diffs -------------------------------
+- Contact: sip:sipsak@127.0.1.1:56872
+P-Hint: My hint
+------------------------------- SIP body diffs --------------------------------
+-------------------------- END OF SIP message debug ---------------------------
+
+
+
+
-
+
+
Exported RPC Functions
diff --git a/msg_translator.c b/msg_translator.c
index d9c6f456141..bc2c3b20453 100644
--- a/msg_translator.c
+++ b/msg_translator.c
@@ -890,12 +890,13 @@ static inline int lumps_len(struct sip_msg* msg, struct lump* lumps,
/* another helper functions, adds/Removes the lump,
code moved form build_req_from_req */
-static inline void process_lumps( struct sip_msg* msg,
- struct lump* lumps,
- char* new_buf,
- unsigned int* new_buf_offs,
- unsigned int* orig_offs,
- struct dest_info* send_info)
+void process_lumps( struct sip_msg* msg,
+ struct lump* lumps,
+ char* new_buf,
+ unsigned int* new_buf_offs,
+ unsigned int* orig_offs,
+ struct dest_info* send_info,
+ int flag)
{
struct lump *t;
struct lump *r;
@@ -1356,11 +1357,21 @@ static inline void process_lumps( struct sip_msg* msg,
break;
}
size=t->u.offset-s_offset;
- if (size){
+ if (size > 0 && flag == FLAG_MSG_ALL){
memcpy(new_buf+offset, orig+s_offset,size);
offset+=size;
s_offset+=size;
- }
+ } else if (flag == FLAG_MSG_LUMPS_ONLY) {
+ /* do not copy the whole message, jump to the lumps offs */
+ s_offset+=size;
+ }
+
+ /* the LUMP_DELs are printed with "- " before them */
+ if (t->op==LUMP_DEL && flag == FLAG_MSG_LUMPS_ONLY) {
+ new_buf[offset++] = '-';
+ new_buf[offset++] = ' ';
+ }
+
/* process before */
for(r=t->before;r;r=r->before){
switch (r->op){
@@ -1384,11 +1395,22 @@ static inline void process_lumps( struct sip_msg* msg,
}
}
skip_nop_before:
- /* process main (del only) */
- if (t->op==LUMP_DEL){
- /* skip len bytes from orig msg */
- s_offset+=t->len;
- }
+ /* process main (del only) */
+ if (t->op==LUMP_DEL && flag == FLAG_MSG_ALL){
+ /* skip len bytes from orig msg */
+ s_offset+=t->len;
+ } else if (t->op==LUMP_DEL && flag == FLAG_MSG_LUMPS_ONLY) {
+ /* copy lump value and indent as necessarely */
+ memcpy(new_buf+offset, orig + t->u.offset, t->len);
+ offset+=t->len;
+ if (new_buf[offset-1] != '\n') {
+ new_buf[offset] = '\n';
+ offset+=1;
+ }
+ /* skip len bytes from orig msg */
+ s_offset+=t->len;
+ }
+
/* process after */
for(r=t->after;r;r=r->after){
switch (r->op){
@@ -1419,6 +1441,11 @@ static inline void process_lumps( struct sip_msg* msg,
}
*new_buf_offs=offset;
*orig_offs=s_offset;
+
+ /* add '\0' to char* lump list to print it smoothly */
+ if (flag == FLAG_MSG_LUMPS_ONLY) {
+ new_buf[offset] = '\0';
+ }
#undef RCVCOMP_PARAM_ADD
#undef SENDCOMP_PARAM_ADD
}
@@ -2142,8 +2169,8 @@ char * build_req_buf_from_sip_req( struct sip_msg* msg,
}
new_buf[new_len]=0;
/* copy msg adding/removing lumps */
- process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, send_info);
- process_lumps(msg, msg->body_lumps, new_buf, &offset, &s_offset,send_info);
+ process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, send_info, FLAG_MSG_ALL);
+ process_lumps(msg, msg->body_lumps, new_buf, &offset, &s_offset,send_info, FLAG_MSG_ALL);
/* copy the rest of the message */
memcpy(new_buf+offset, buf+s_offset, len-s_offset);
new_buf[new_len]=0;
@@ -2236,8 +2263,8 @@ char * generate_res_buf_from_sip_res( struct sip_msg* msg,
new_buf[new_len]=0; /* debug: print the message */
offset=s_offset=0;
/*FIXME: no send sock*/
- process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, 0);/*FIXME:*/
- process_lumps(msg, msg->body_lumps, new_buf, &offset, &s_offset, 0);
+ process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, 0, FLAG_MSG_ALL);/*FIXME:*/
+ process_lumps(msg, msg->body_lumps, new_buf, &offset, &s_offset, 0, FLAG_MSG_ALL);
/* copy the rest of the message */
memcpy(new_buf+offset,
buf+s_offset,
@@ -2916,7 +2943,7 @@ char * build_only_headers( struct sip_msg* msg, int skip_first_line,
offset = 0;
/* copy message lumps */
- process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, send_info);
+ process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, send_info, FLAG_MSG_ALL);
/* copy the rest of the message without body */
if (len > s_offset) {
memcpy(new_buf+offset, buf+s_offset, len-s_offset);
@@ -2966,7 +2993,7 @@ char * build_body( struct sip_msg* msg,
offset = 0;
/* copy body lumps */
- process_lumps(msg, msg->body_lumps, new_buf, &offset, &s_offset, send_info);
+ process_lumps(msg, msg->body_lumps, new_buf, &offset, &s_offset, send_info, FLAG_MSG_ALL);
/* copy the rest of the message without body */
if (len > s_offset) {
memcpy(new_buf+offset, buf+s_offset, len-s_offset);
@@ -3026,9 +3053,9 @@ char * build_all( struct sip_msg* msg, int touch_clen,
offset = s_offset = 0;
/* copy message lumps */
- process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, send_info);
+ process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, send_info, FLAG_MSG_ALL);
/* copy body lumps */
- process_lumps(msg, msg->body_lumps, new_buf, &offset, &s_offset, send_info);
+ process_lumps(msg, msg->body_lumps, new_buf, &offset, &s_offset, send_info, FLAG_MSG_ALL);
/* copy the rest of the message */
memcpy(new_buf+offset, buf+s_offset, len-s_offset);
offset += (len-s_offset);
diff --git a/msg_translator.h b/msg_translator.h
index 5fa02cf2664..d95c89f5e46 100644
--- a/msg_translator.h
+++ b/msg_translator.h
@@ -31,6 +31,10 @@
#ifndef _MSG_TRANSLATOR_H
#define _MSG_TRANSLATOR_H
+/* flags used for process_lumps flag parameter */
+#define FLAG_MSG_LUMPS_ONLY 0 /* copy just the lumps */
+#define FLAG_MSG_ALL 1 /* copy all the msg */
+
#define MY_HF_SEP ": "
#define MY_HF_SEP_LEN 2
@@ -163,4 +167,17 @@ int build_sip_msg_from_buf(struct sip_msg *msg, char *buf, int len,
/* returns a copy in private memory of the boundary in a multipart body */
int get_boundary(struct sip_msg* msg, str* boundary);
+
+
+/* process the lumps of a sip msg
+ * flags = => add also the existing header to new_buf
+ * flags = => add only the lumps (unapplied info) to new_buf
+ **/
+void process_lumps( struct sip_msg* msg,
+ struct lump* lumps,
+ char* new_buf,
+ unsigned int* new_buf_offs,
+ unsigned int* orig_offs,
+ struct dest_info* send_info,
+ int flag);
#endif