Changeset 687:026802543f57 in freeDiameter
- Timestamp:
- Jan 19, 2011, 5:08:21 PM (13 years ago)
- Branch:
- default
- Phase:
- public
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
include/freeDiameter/libfdproto.h
r658 r687 95 95 96 96 /* 97 * FUNCTION: fd_log_debug 98 * 99 * PARAMETERS: 97 * FUNCTION: fd_log_debug_fstr 98 * MACRO: fd_log_debug 99 * 100 * PARAMETERS: 101 * fstr : Stream where the text will be sent (default: stdout) 100 102 * format : Same format string as in the printf function 101 103 * ... : Same list as printf … … 112 114 * None. 113 115 */ 114 void fd_log_debug ( const char * format, ... ); 116 void fd_log_debug_fstr ( FILE * fstr, const char * format, ... ); 117 #define fd_log_debug(format,args...) fd_log_debug_fstr(NULL, format, ## args) 118 115 119 extern pthread_mutex_t fd_log_lock; 116 120 extern char * fd_debug_one_function; … … 1010 1014 dict_avpdata_interpret type_interpret;/* cb to convert the AVP value in more comprehensive format (or NULL) */ 1011 1015 dict_avpdata_encode type_encode; /* cb to convert formatted data into an AVP value (or NULL) */ 1012 void (*type_dump)(union avp_value * val ); /* cb called by fd_msg_dump_one for this type of data (if != NULL), to dump the AVP value in debug*/1016 void (*type_dump)(union avp_value * val, FILE * fstr); /* cb called by fd_msg_dump_one for this type of data (if != NULL), to dump the AVP value in fstr */ 1013 1017 }; 1014 1018 … … 2033 2037 void fd_msg_dump_one ( int level, msg_or_avp *obj ); 2034 2038 2039 /* 2040 * FUNCTION: fd_msg_log 2041 * 2042 * PARAMETERS: 2043 * cause : Context for calling this function. This allows the log facility to be configured precisely. 2044 * msg : The message to log. 2045 * prefix_format: Printf-style format message that is printed ahead of the message. Might be reason for drop or so. 2046 * 2047 * DESCRIPTION: 2048 * This function is called when a Diameter message reaches some particular points in the fD framework. 2049 * The actual effect is configurable: log in a separate file, dump in the debug log, etc. 2050 * 2051 * RETURN VALUE: 2052 * - 2053 */ 2054 enum fd_msg_log_cause { 2055 FD_MSG_LOG_DROPPED = 0, /* message has been dropped by the framework */ 2056 FD_MSG_LOG_RECEIVED, /* message received from the network */ 2057 FD_MSG_LOG_SENT /* message sent to another peer */ 2058 }; 2059 #define FD_MSG_LOG_MAX FD_MSG_LOG_SENT 2060 void fd_msg_log( enum fd_msg_log_cause cause, struct msg * msg, const char * prefix_format, ... ); 2061 2062 /* configure the msg_log facility */ 2063 enum fd_msg_log_method { 2064 FD_MSG_LOGTO_DEBUGONLY = 0, /* Simply log the message with other debug information, at the INFO level. This is default */ 2065 FD_MSG_LOGTO_FILE, /* Messages are dumped in a single file, defined in arg */ 2066 FD_MSG_LOGTO_DIR /* Messages are dumped in different files within one directory defined in arg. */ 2067 }; 2068 int fd_msg_log_config(enum fd_msg_log_cause cause, enum fd_msg_log_method method, const char * arg); 2035 2069 2036 2070 /*********************************************/ -
libfdcore/dict_base_proto.c
r662 r687 145 145 146 146 /* Dump the content of an Address AVP */ 147 static void Address_dump(union avp_value * avp_value )147 static void Address_dump(union avp_value * avp_value, FILE * fstr) 148 148 { 149 149 union { … … 159 159 /* The first two octets represent the address family, http://www.iana.org/assignments/address-family-numbers/ */ 160 160 if (avp_value->os.len < 2) { 161 fd_log_debug ("[invalid length: %d]", avp_value->os.len);161 fd_log_debug_fstr(fstr, "[invalid length: %d]", avp_value->os.len); 162 162 return; 163 163 } … … 170 170 s.sa.sa_family = AF_INET; 171 171 if (avp_value->os.len != 6) { 172 fd_log_debug ("[invalid IP length: %d]", avp_value->os.len);172 fd_log_debug_fstr(fstr, "[invalid IP length: %d]", avp_value->os.len); 173 173 return; 174 174 } … … 179 179 s.sa.sa_family = AF_INET6; 180 180 if (avp_value->os.len != 18) { 181 fd_log_debug ("[invalid IP6 length: %d]", avp_value->os.len);181 fd_log_debug_fstr(fstr, "[invalid IP6 length: %d]", avp_value->os.len); 182 182 return; 183 183 } … … 185 185 break; 186 186 default: 187 fd_log_debug ("[unsupported family: 0x%hx]", fam);187 fd_log_debug_fstr(fstr, "[unsupported family: 0x%hx]", fam); 188 188 return; 189 189 } 190 191 sSA_DUMP_NODE(&s.sa, NI_NUMERICHOST); 190 191 { 192 char addrbuf[INET6_ADDRSTRLEN]; 193 int rc = getnameinfo(&s.sa, sSAlen(&s.sa), addrbuf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); 194 if (rc) 195 fd_log_debug_fstr(fstr, "%s", (char *)gai_strerror(rc)); 196 else 197 fd_log_debug_fstr(fstr, "%s", addrbuf); 198 199 } 192 200 } 193 201 194 static void UTF8String_dump(union avp_value * avp_value )202 static void UTF8String_dump(union avp_value * avp_value, FILE * fstr) 195 203 { 196 204 size_t len = avp_value->os.len; 197 205 if (len > 42) 198 206 len = 42; /* avoid very long strings */ 199 fd_log_debug ("%.*s", len, avp_value->os.data);207 fd_log_debug_fstr(fstr, "%.*s", len, avp_value->os.data); 200 208 } 201 209 -
libfdproto/dictionary.c
r662 r687 1304 1304 1305 1305 /* Default dump functions */ 1306 static void dump_val_os(union avp_value * value )1306 static void dump_val_os(union avp_value * value, FILE * fstr) 1307 1307 { 1308 1308 int i; 1309 1309 for (i = 0; i < value->os.len; i++) { 1310 1310 if (i == 24) { /* Dump only up to 24 bytes of the buffer */ 1311 fd_log_debug ("[...] (len=%zd)", value->os.len);1311 fd_log_debug_fstr(fstr, "[...] (len=%zd)", value->os.len); 1312 1312 break; 1313 1313 } 1314 fd_log_debug ("%02.2X ", value->os.data[i]);1315 } 1316 } 1317 1318 static void dump_val_i32(union avp_value * value )1319 { 1320 fd_log_debug ("%i (0x%x)", value->i32, value->i32);1321 } 1322 1323 static void dump_val_i64(union avp_value * value )1324 { 1325 fd_log_debug ("%lli (0x%llx)", value->i64, value->i64);1326 } 1327 1328 static void dump_val_u32(union avp_value * value )1329 { 1330 fd_log_debug ("%u (0x%x)", value->u32, value->u32);1331 } 1332 1333 static void dump_val_u64(union avp_value * value )1334 { 1335 fd_log_debug ("%llu (0x%llx)", value->u64, value->u64);1336 } 1337 1338 static void dump_val_f32(union avp_value * value )1339 { 1340 fd_log_debug ("%f", value->f32);1341 } 1342 1343 static void dump_val_f64(union avp_value * value )1344 { 1345 fd_log_debug ("%g", value->f64);1314 fd_log_debug_fstr(fstr, "%02.2X ", value->os.data[i]); 1315 } 1316 } 1317 1318 static void dump_val_i32(union avp_value * value, FILE * fstr) 1319 { 1320 fd_log_debug_fstr(fstr, "%i (0x%x)", value->i32, value->i32); 1321 } 1322 1323 static void dump_val_i64(union avp_value * value, FILE * fstr) 1324 { 1325 fd_log_debug_fstr(fstr, "%lli (0x%llx)", value->i64, value->i64); 1326 } 1327 1328 static void dump_val_u32(union avp_value * value, FILE * fstr) 1329 { 1330 fd_log_debug_fstr(fstr, "%u (0x%x)", value->u32, value->u32); 1331 } 1332 1333 static void dump_val_u64(union avp_value * value, FILE * fstr) 1334 { 1335 fd_log_debug_fstr(fstr, "%llu (0x%llx)", value->u64, value->u64); 1336 } 1337 1338 static void dump_val_f32(union avp_value * value, FILE * fstr) 1339 { 1340 fd_log_debug_fstr(fstr, "%f", value->f32); 1341 } 1342 1343 static void dump_val_f64(union avp_value * value, FILE * fstr) 1344 { 1345 fd_log_debug_fstr(fstr, "%g", value->f64); 1346 1346 } 1347 1347 1348 1348 /* Get the dump function for basic dict_avp_basetype */ 1349 static void (*get_default_dump_val_cb(enum dict_avp_basetype datatype))(union avp_value * )1349 static void (*get_default_dump_val_cb(enum dict_avp_basetype datatype))(union avp_value *, FILE *) 1350 1350 { 1351 1351 switch (datatype) { … … 1382 1382 1383 1383 /* Formater for the AVP value dump line */ 1384 static void dump_avp_val(union avp_value *avp_value, void (*dump_val_cb)(union avp_value * avp_value), enum dict_avp_basetype datatype, char * type_name, char * const_name, int indent)1384 static void dump_avp_val(union avp_value *avp_value, void (*dump_val_cb)(union avp_value *, FILE *), enum dict_avp_basetype datatype, char * type_name, char * const_name, int indent, FILE * fstr) 1385 1385 { 1386 1386 /* Header for all AVP values dumps: */ 1387 fd_log_debug (INOBJHDR "value ", INOBJHDRVAL);1387 fd_log_debug_fstr(fstr, INOBJHDR "value ", INOBJHDRVAL); 1388 1388 1389 1389 /* If the type is provided, write it */ 1390 1390 if (type_name) 1391 fd_log_debug ("t: '%s' ", type_name);1391 fd_log_debug_fstr(fstr, "t: '%s' ", type_name); 1392 1392 1393 1393 /* Always give the base datatype anyway */ 1394 fd_log_debug ("(%s) ", type_base_name[datatype]);1394 fd_log_debug_fstr(fstr, "(%s) ", type_base_name[datatype]); 1395 1395 1396 1396 /* Now, the value */ 1397 fd_log_debug ("v: ");1397 fd_log_debug_fstr(fstr, "v: "); 1398 1398 if (const_name) 1399 fd_log_debug ("'%s' (", const_name);1400 (*dump_val_cb)(avp_value );1399 fd_log_debug_fstr(fstr, "'%s' (", const_name); 1400 (*dump_val_cb)(avp_value, fstr); 1401 1401 if (const_name) 1402 fd_log_debug (")");1402 fd_log_debug_fstr(fstr, ")"); 1403 1403 1404 1404 /* Done! */ 1405 fd_log_debug ("\n");1405 fd_log_debug_fstr(fstr, "\n"); 1406 1406 } 1407 1407 1408 1408 /* Dump the value of an AVP of known type */ 1409 void fd_dict_dump_avp_value(union avp_value *avp_value, struct dict_object * model, int indent )1410 { 1411 void (*dump_val_cb)(union avp_value *avp_value );1409 void fd_dict_dump_avp_value(union avp_value *avp_value, struct dict_object * model, int indent, FILE * fstr) 1410 { 1411 void (*dump_val_cb)(union avp_value *avp_value, FILE * fstr); 1412 1412 struct dict_object * type = NULL; 1413 1413 char * type_name = NULL; … … 1444 1444 1445 1445 /* And finally, dump the value */ 1446 dump_avp_val(avp_value, dump_val_cb, model->data.avp.avp_basetype, type_name, const_name, indent );1446 dump_avp_val(avp_value, dump_val_cb, model->data.avp.avp_basetype, type_name, const_name, indent, fstr); 1447 1447 } 1448 1448 -
libfdproto/fdproto-internal.h
r662 r687 48 48 void fd_sess_fini(void); 49 49 50 /* Where debug messages are sent */ 51 FILE * fd_g_debug_fstr; 52 50 53 /* Iterator on the rules of a parent object */ 51 54 int fd_dict_iterate_rules ( struct dict_object *parent, void * data, int (*cb)(void *, struct dict_rule_data *) ); … … 53 56 /* Dispatch / messages / dictionary API */ 54 57 int fd_dict_disp_cb(enum dict_object_type type, struct dict_object *obj, struct fd_list ** cb_list); 55 void fd_dict_dump_avp_value(union avp_value *avp_value, struct dict_object * model, int indent );58 void fd_dict_dump_avp_value(union avp_value *avp_value, struct dict_object * model, int indent, FILE * fstr); 56 59 int fd_disp_call_cb_int( struct fd_list * cb_list, struct msg ** msg, struct avp *avp, struct session *sess, enum disp_action *action, 57 60 struct dict_object * obj_app, struct dict_object * obj_cmd, struct dict_object * obj_avp, struct dict_object * obj_enu); -
libfdproto/init.c
r662 r687 51 51 } 52 52 53 /* Set the debug stream */ 54 fd_g_debug_fstr = stdout; 55 53 56 /* Initialize the modules that need it */ 54 57 fd_msg_eteid_init(); -
libfdproto/log.c
r662 r687 55 55 } 56 56 57 58 57 /* Log a debug message */ 59 void fd_log_debug (const char * format, ... )58 void fd_log_debug_fstr ( FILE * fstr, const char * format, ... ) 60 59 { 61 60 va_list ap; … … 66 65 67 66 va_start(ap, format); 68 vfprintf( stdout, format, ap);67 vfprintf( fstr ?: stdout, format, ap); 69 68 va_end(ap); 70 fflush( stdout);69 fflush(fstr ?: stdout); 71 70 72 71 pthread_cleanup_pop(0); -
libfdproto/messages.c
r686 r687 661 661 662 662 /* Dump a msg_t object */ 663 static void obj_dump_msg (struct msg * msg, int indent )663 static void obj_dump_msg (struct msg * msg, int indent, FILE * fstr ) 664 664 { 665 665 int ret = 0; 666 666 667 fd_log_debug ("%*sMSG: %p\n", INOBJHDRVAL, msg);667 fd_log_debug_fstr(fstr, "%*sMSG: %p\n", INOBJHDRVAL, msg); 668 668 669 669 if (!CHECK_MSG(msg)) { 670 fd_log_debug (INOBJHDR "INVALID!\n", INOBJHDRVAL);670 fd_log_debug_fstr(fstr, INOBJHDR "INVALID!\n", INOBJHDRVAL); 671 671 return; 672 672 } … … 674 674 if (!msg->msg_model) { 675 675 676 fd_log_debug (INOBJHDR "(no model)\n", INOBJHDRVAL);676 fd_log_debug_fstr(fstr, INOBJHDR "(no model)\n", INOBJHDRVAL); 677 677 678 678 } else { … … 682 682 ret = fd_dict_gettype(msg->msg_model, &dicttype); 683 683 if (ret || (dicttype != DICT_COMMAND)) { 684 fd_log_debug (INOBJHDR "(invalid model: %d %d)\n", INOBJHDRVAL, ret, dicttype);684 fd_log_debug_fstr(fstr, INOBJHDR "(invalid model: %d %d)\n", INOBJHDRVAL, ret, dicttype); 685 685 goto public; 686 686 } 687 687 ret = fd_dict_getval(msg->msg_model, &dictdata); 688 688 if (ret != 0) { 689 fd_log_debug (INOBJHDR "(error getting model data: %s)\n", INOBJHDRVAL, strerror(ret));689 fd_log_debug_fstr(fstr, INOBJHDR "(error getting model data: %s)\n", INOBJHDRVAL, strerror(ret)); 690 690 goto public; 691 691 } 692 fd_log_debug (INOBJHDR "model : v/m:" DUMP_CMDFL_str "/" DUMP_CMDFL_str ", %u \"%s\"\n", INOBJHDRVAL,692 fd_log_debug_fstr(fstr, INOBJHDR "model : v/m:" DUMP_CMDFL_str "/" DUMP_CMDFL_str ", %u \"%s\"\n", INOBJHDRVAL, 693 693 DUMP_CMDFL_val(dictdata.cmd_flag_val), DUMP_CMDFL_val(dictdata.cmd_flag_mask), dictdata.cmd_code, dictdata.cmd_name); 694 694 } 695 695 public: 696 fd_log_debug (INOBJHDR "public: V:%d L:%d fl:" DUMP_CMDFL_str " CC:%u A:%d hi:%x ei:%x\n", INOBJHDRVAL,696 fd_log_debug_fstr(fstr, INOBJHDR "public: V:%d L:%d fl:" DUMP_CMDFL_str " CC:%u A:%d hi:%x ei:%x\n", INOBJHDRVAL, 697 697 msg->msg_public.msg_version, 698 698 msg->msg_public.msg_length, … … 703 703 msg->msg_public.msg_eteid 704 704 ); 705 fd_log_debug (INOBJHDR "intern: rwb:%p rt:%d cb:%p(%p) qry:%p asso:%d sess:%p src:%s\n",705 fd_log_debug_fstr(fstr, INOBJHDR "intern: rwb:%p rt:%d cb:%p(%p) qry:%p asso:%d sess:%p src:%s\n", 706 706 INOBJHDRVAL, msg->msg_rawbuffer, msg->msg_routable, msg->msg_cb.fct, msg->msg_cb.data, msg->msg_query, msg->msg_associated, msg->msg_sess, msg->msg_src_id?:"(nil)"); 707 707 } 708 708 709 709 /* Dump an avp object */ 710 static void obj_dump_avp ( struct avp * avp, int indent )710 static void obj_dump_avp ( struct avp * avp, int indent, FILE * fstr ) 711 711 { 712 712 int ret = 0; … … 714 714 715 715 if (!CHECK_AVP(avp)) { 716 fd_log_debug (INOBJHDR "INVALID!\n", INOBJHDRVAL);716 fd_log_debug_fstr(fstr, INOBJHDR "INVALID!\n", INOBJHDRVAL); 717 717 return; 718 718 } … … 720 720 if (!avp->avp_model) { 721 721 722 fd_log_debug (INOBJHDR "(no model)\n", INOBJHDRVAL);722 fd_log_debug_fstr(fstr, INOBJHDR "(no model)\n", INOBJHDRVAL); 723 723 724 724 } else { … … 728 728 ret = fd_dict_gettype(avp->avp_model, &dicttype); 729 729 if (ret || (dicttype != DICT_AVP)) { 730 fd_log_debug (INOBJHDR "(invalid model: %d %d)\n", INOBJHDRVAL, ret, dicttype);730 fd_log_debug_fstr(fstr, INOBJHDR "(invalid model: %d %d)\n", INOBJHDRVAL, ret, dicttype); 731 731 goto public; 732 732 } 733 733 ret = fd_dict_getval(avp->avp_model, &dictdata); 734 734 if (ret != 0) { 735 fd_log_debug (INOBJHDR "(error getting model data: %s)\n", INOBJHDRVAL, strerror(ret));735 fd_log_debug_fstr(fstr, INOBJHDR "(error getting model data: %s)\n", INOBJHDRVAL, strerror(ret)); 736 736 goto public; 737 737 } 738 fd_log_debug (INOBJHDR "model : v/m:" DUMP_AVPFL_str "/" DUMP_AVPFL_str ", %12s, %u \"%s\"\n", INOBJHDRVAL,738 fd_log_debug_fstr(fstr, INOBJHDR "model : v/m:" DUMP_AVPFL_str "/" DUMP_AVPFL_str ", %12s, %u \"%s\"\n", INOBJHDRVAL, 739 739 DUMP_AVPFL_val(dictdata.avp_flag_val), 740 740 DUMP_AVPFL_val(dictdata.avp_flag_mask), … … 745 745 } 746 746 public: 747 fd_log_debug (INOBJHDR "public: C:%u fl:" DUMP_AVPFL_str " L:%d V:%u data:@%p\n", INOBJHDRVAL,747 fd_log_debug_fstr(fstr, INOBJHDR "public: C:%u fl:" DUMP_AVPFL_str " L:%d V:%u data:@%p\n", INOBJHDRVAL, 748 748 avp->avp_public.avp_code, 749 749 DUMP_AVPFL_val(avp->avp_public.avp_flags), … … 755 755 if (avp->avp_public.avp_value) { 756 756 if (!avp->avp_model) { 757 fd_log_debug (INOBJHDR "(data set but no model: ERROR)\n", INOBJHDRVAL);757 fd_log_debug_fstr(fstr, INOBJHDR "(data set but no model: ERROR)\n", INOBJHDRVAL); 758 758 } else { 759 fd_dict_dump_avp_value(avp->avp_public.avp_value, avp->avp_model, indent );760 } 761 } 762 763 fd_log_debug (INOBJHDR "intern: src:%p mf:%d raw:%p(%d)\n", INOBJHDRVAL, avp->avp_source, avp->avp_mustfreeos, avp->avp_rawdata, avp->avp_rawlen);759 fd_dict_dump_avp_value(avp->avp_public.avp_value, avp->avp_model, indent, fstr); 760 } 761 } 762 763 fd_log_debug_fstr(fstr, INOBJHDR "intern: src:%p mf:%d raw:%p(%d)\n", INOBJHDRVAL, avp->avp_source, avp->avp_mustfreeos, avp->avp_rawdata, avp->avp_rawlen); 764 764 } 765 765 766 766 /* Dump a single object content */ 767 static void msg_dump_intern ( int level, msg_or_avp * obj, int indent )767 static void msg_dump_intern ( int level, msg_or_avp * obj, int indent, FILE * fstr ) 768 768 { 769 769 /* Log only if we are at least at level */ … … 773 773 /* Check the object */ 774 774 if (!VALIDATE_OBJ(obj)) { 775 fd_log_debug (">>> invalid object (%p)!.\n", obj);775 fd_log_debug_fstr(fstr, ">>> invalid object (%p)!.\n", obj); 776 776 return; 777 777 } … … 780 780 switch (_C(obj)->type) { 781 781 case MSG_AVP: 782 obj_dump_avp ( _A(obj), indent );782 obj_dump_avp ( _A(obj), indent, fstr ); 783 783 break; 784 784 785 785 case MSG_MSG: 786 obj_dump_msg ( _M(obj), indent );786 obj_dump_msg ( _M(obj), indent, fstr ); 787 787 break; 788 788 … … 792 792 } 793 793 794 /* Dump a message to a specified file stream */ 795 static void fd_msg_dump_fstr ( struct msg * msg, FILE * fstr ) 796 { 797 msg_or_avp * ref = msg; 798 int indent = 2; 799 do { 800 msg_dump_intern ( NONE, ref, indent, fstr ); 801 802 /* Now find the next object */ 803 CHECK_FCT_DO( fd_msg_browse ( ref, MSG_BRW_WALK, &ref, &indent ), break ); 804 805 /* dump next object */ 806 } while (ref); 807 } 808 794 809 /* Dump a message content -- for debug mostly */ 795 810 void fd_msg_dump_walk ( int level, msg_or_avp *obj ) … … 800 815 TRACE_DEBUG(level, "------ Dumping object %p (w)-------", obj); 801 816 do { 802 msg_dump_intern ( level, ref, indent );817 msg_dump_intern ( level, ref, indent, fd_g_debug_fstr ); 803 818 804 819 /* Now find the next object */ … … 815 830 { 816 831 TRACE_DEBUG(level, "------ Dumping object %p (s)-------", obj); 817 msg_dump_intern ( level, obj, 1 );832 msg_dump_intern ( level, obj, 1, fd_g_debug_fstr ); 818 833 TRACE_DEBUG(level, "------ /end of object %p -------", obj); 819 834 } … … 1645 1660 if (mandatory && (avp->avp_public.avp_flags & AVP_FLAG_MANDATORY)) { 1646 1661 TRACE_DEBUG(INFO, "Unsupported mandatory AVP found:"); 1647 msg_dump_intern(INFO, avp, 2 );1662 msg_dump_intern(INFO, avp, 2, fd_g_debug_fstr); 1648 1663 if (error_info) { 1649 1664 error_info->pei_errcode = "DIAMETER_AVP_UNSUPPORTED"; … … 2309 2324 return ret; 2310 2325 } 2326 2327 2328 /***************************************************************************************************************/ 2329 /* messages logging facility */ 2330 #include <stdarg.h> 2331 2332 static struct { 2333 struct { 2334 enum fd_msg_log_method meth; 2335 const char * metharg; 2336 } causes[FD_MSG_LOG_MAX + 1]; 2337 pthread_mutex_t lock; 2338 int init; 2339 } ml_conf = { .lock = PTHREAD_MUTEX_INITIALIZER, .init = 0 }; 2340 2341 static void ml_conf_init(void) 2342 { 2343 memset(&ml_conf.causes, 0, sizeof(ml_conf.causes)); 2344 ml_conf.init = 1; 2345 } 2346 2347 /* Set a configuration property */ 2348 int fd_msg_log_config(enum fd_msg_log_cause cause, enum fd_msg_log_method method, const char * arg) 2349 { 2350 /* Check the parameters are valid */ 2351 TRACE_ENTRY("%d %d %p", cause, method, arg); 2352 CHECK_PARAMS( (cause >= 0) && (cause <= FD_MSG_LOG_MAX) ); 2353 CHECK_PARAMS( (method >= FD_MSG_LOGTO_DEBUGONLY) && (method <= FD_MSG_LOGTO_DIR) ); 2354 CHECK_PARAMS( (method == FD_MSG_LOGTO_DEBUGONLY) || (arg != NULL) ); 2355 2356 /* Lock the configuration */ 2357 CHECK_POSIX( pthread_mutex_lock(&ml_conf.lock) ); 2358 if (!ml_conf.init) { 2359 ml_conf_init(); 2360 } 2361 2362 /* Now set the parameter */ 2363 ml_conf.causes[cause].meth = method; 2364 ml_conf.causes[cause].metharg = arg; 2365 2366 if (method) { 2367 TRACE_DEBUG(INFO, "Logging %s messages set to %s '%s'", 2368 (cause == FD_MSG_LOG_DROPPED) ? "DROPPED" : 2369 (cause == FD_MSG_LOG_RECEIVED) ? "RECEIVED" : 2370 (cause == FD_MSG_LOG_SENT) ? "SENT" : 2371 "???", 2372 (method == FD_MSG_LOGTO_FILE) ? "file" : 2373 (method == FD_MSG_LOGTO_DIR) ? "directory" : 2374 "???", 2375 arg); 2376 } 2377 2378 CHECK_POSIX( pthread_mutex_unlock(&ml_conf.lock) ); 2379 2380 /* Done */ 2381 return 0; 2382 } 2383 2384 /* Do not log anything within this one, since log lock is held */ 2385 static void fd_cleanup_mutex_silent( void * mutex ) 2386 { 2387 (void)pthread_mutex_unlock((pthread_mutex_t *)mutex); 2388 } 2389 2390 /* Really log the message */ 2391 void fd_msg_log( enum fd_msg_log_cause cause, struct msg * msg, const char * prefix_format, ... ) 2392 { 2393 va_list ap; 2394 enum fd_msg_log_method meth; 2395 const char * metharg; 2396 FILE * fstr; 2397 2398 TRACE_ENTRY("%d %p %p", cause, msg, prefix_format); 2399 CHECK_PARAMS_DO( (cause >= 0) && (cause <= FD_MSG_LOG_MAX), 2400 { 2401 TRACE_DEBUG(INFO, "Invalid cause received (%d)! Message was:", cause); 2402 fd_msg_dump_walk(INFO, msg); 2403 } ); 2404 2405 /* First retrieve the config for this message */ 2406 CHECK_POSIX_DO( pthread_mutex_lock(&ml_conf.lock), ); 2407 if (!ml_conf.init) { 2408 ml_conf_init(); 2409 } 2410 meth = ml_conf.causes[cause].meth; 2411 metharg = ml_conf.causes[cause].metharg; 2412 CHECK_POSIX_DO( pthread_mutex_unlock(&ml_conf.lock), ); 2413 2414 /* Okay, now we will create the file descriptor */ 2415 switch (meth) { 2416 case FD_MSG_LOGTO_DEBUGONLY: 2417 fstr = fd_g_debug_fstr; 2418 break; 2419 2420 case FD_MSG_LOGTO_FILE: 2421 TODO("Log to arg file"); 2422 break; 2423 case FD_MSG_LOGTO_DIR: 2424 TODO("Log to arg directory in a new file"); 2425 break; 2426 } 2427 2428 /* Then dump the prefix message to this stream */ 2429 (void)pthread_mutex_lock(&fd_log_lock); 2430 pthread_cleanup_push(fd_cleanup_mutex_silent, &fd_log_lock); 2431 va_start(ap, prefix_format); 2432 vfprintf( fstr, prefix_format, ap); 2433 va_end(ap); 2434 fflush(fstr); 2435 pthread_cleanup_pop(0); 2436 (void)pthread_mutex_unlock(&fd_log_lock); 2437 fd_log_debug_fstr(fstr, "\n\n"); 2438 2439 /* And now the message itself */ 2440 fd_msg_dump_fstr(msg, fstr); 2441 2442 /* And finally close the stream if needed */ 2443 TODO("close?"); 2444 } 2445
Note: See TracChangeset
for help on using the changeset viewer.