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"); +
+ + <function moreinfo="none">dbg_sip_msg([log_level], [facility])</function> + + + 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. + + + + + <function>dbg_sip_msg</function> 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