Navigation


Changeset 687:026802543f57 in freeDiameter


Ignore:
Timestamp:
Jan 19, 2011, 5:08:21 PM (11 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Prepare for new message log facility

Files:
7 edited

Legend:

Unmodified
Added
Removed
  • include/freeDiameter/libfdproto.h

    r658 r687  
    9595
    9696/*
    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)
    100102 *  format      : Same format string as in the printf function
    101103 *  ...         : Same list as printf
     
    112114 *  None.
    113115 */
    114 void fd_log_debug ( const char * format, ... );
     116void fd_log_debug_fstr ( FILE * fstr, const char * format, ... );
     117#define fd_log_debug(format,args...) fd_log_debug_fstr(NULL, format, ## args)
     118
    115119extern pthread_mutex_t  fd_log_lock;
    116120extern char * fd_debug_one_function;
     
    10101014        dict_avpdata_interpret   type_interpret;/* cb to convert the AVP value in more comprehensive format (or NULL) */
    10111015        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 */
    10131017};
    10141018
     
    20332037void fd_msg_dump_one  ( int level, msg_or_avp *obj );
    20342038
     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 */
     2054enum 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
     2060void fd_msg_log( enum fd_msg_log_cause cause, struct msg * msg, const char * prefix_format, ... );
     2061
     2062/* configure the msg_log facility */
     2063enum 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};
     2068int fd_msg_log_config(enum fd_msg_log_cause cause, enum fd_msg_log_method method, const char * arg);
    20352069
    20362070/*********************************************/
  • libfdcore/dict_base_proto.c

    r662 r687  
    145145
    146146/* Dump the content of an Address AVP */
    147 static void Address_dump(union avp_value * avp_value)
     147static void Address_dump(union avp_value * avp_value, FILE * fstr)
    148148{
    149149        union {
     
    159159        /* The first two octets represent the address family, http://www.iana.org/assignments/address-family-numbers/ */
    160160        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);
    162162                return;
    163163        }
     
    170170                        s.sa.sa_family = AF_INET;
    171171                        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);
    173173                                return;
    174174                        }
     
    179179                        s.sa.sa_family = AF_INET6;
    180180                        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);
    182182                                return;
    183183                        }
     
    185185                        break;
    186186                default:
    187                         fd_log_debug("[unsupported family: 0x%hx]", fam);
     187                        fd_log_debug_fstr(fstr, "[unsupported family: 0x%hx]", fam);
    188188                        return;
    189189        }
    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        }
    192200}
    193201
    194 static void UTF8String_dump(union avp_value * avp_value)
     202static void UTF8String_dump(union avp_value * avp_value, FILE * fstr)
    195203{
    196204        size_t len = avp_value->os.len;
    197205        if (len > 42)
    198206                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);
    200208}
    201209
  • libfdproto/dictionary.c

    r662 r687  
    13041304
    13051305/* Default dump functions */
    1306 static void dump_val_os(union avp_value * value)
     1306static void dump_val_os(union avp_value * value, FILE * fstr)
    13071307{
    13081308        int i;
    13091309        for (i = 0; i < value->os.len; i++) {
    13101310                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);
    13121312                        break;
    13131313                }
    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
     1318static 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
     1323static 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
     1328static 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
     1333static 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
     1338static void dump_val_f32(union avp_value * value, FILE * fstr)
     1339{
     1340        fd_log_debug_fstr(fstr, "%f", value->f32);
     1341}
     1342
     1343static void dump_val_f64(union avp_value * value, FILE * fstr)
     1344{
     1345        fd_log_debug_fstr(fstr, "%g", value->f64);
    13461346}
    13471347
    13481348/* 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 *)
     1349static void (*get_default_dump_val_cb(enum dict_avp_basetype datatype))(union avp_value *, FILE *)
    13501350{
    13511351        switch (datatype) {
     
    13821382
    13831383/* 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)
     1384static 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)
    13851385{
    13861386        /* Header for all AVP values dumps: */
    1387         fd_log_debug(INOBJHDR "value ", INOBJHDRVAL);
     1387        fd_log_debug_fstr(fstr, INOBJHDR "value ", INOBJHDRVAL);
    13881388       
    13891389        /* If the type is provided, write it */
    13901390        if (type_name)
    1391                 fd_log_debug("t: '%s' ", type_name);
     1391                fd_log_debug_fstr(fstr, "t: '%s' ", type_name);
    13921392       
    13931393        /* 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]);
    13951395       
    13961396        /* Now, the value */
    1397         fd_log_debug("v: ");
     1397        fd_log_debug_fstr(fstr, "v: ");
    13981398        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);
    14011401        if (const_name)
    1402                 fd_log_debug(")");
     1402                fd_log_debug_fstr(fstr, ")");
    14031403       
    14041404        /* Done! */
    1405         fd_log_debug("\n");
     1405        fd_log_debug_fstr(fstr, "\n");
    14061406}
    14071407
    14081408/* 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);
     1409void 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);
    14121412        struct dict_object * type = NULL;
    14131413        char * type_name = NULL;
     
    14441444       
    14451445        /* 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);
    14471447}
    14481448
  • libfdproto/fdproto-internal.h

    r662 r687  
    4848void fd_sess_fini(void);
    4949
     50/* Where debug messages are sent */
     51FILE * fd_g_debug_fstr;
     52
    5053/* Iterator on the rules of a parent object */
    5154int fd_dict_iterate_rules ( struct dict_object *parent, void * data, int (*cb)(void *, struct dict_rule_data *) );
     
    5356/* Dispatch / messages / dictionary API */
    5457int 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);
     58void fd_dict_dump_avp_value(union avp_value *avp_value, struct dict_object * model, int indent, FILE * fstr);
    5659int fd_disp_call_cb_int( struct fd_list * cb_list, struct msg ** msg, struct avp *avp, struct session *sess, enum disp_action *action,
    5760                        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  
    5151        }
    5252       
     53        /* Set the debug stream */
     54        fd_g_debug_fstr = stdout;
     55       
    5356        /* Initialize the modules that need it */
    5457        fd_msg_eteid_init();
  • libfdproto/log.c

    r662 r687  
    5555}
    5656
    57 
    5857/* Log a debug message */
    59 void fd_log_debug ( const char * format, ... )
     58void fd_log_debug_fstr ( FILE * fstr, const char * format, ... )
    6059{
    6160        va_list ap;
     
    6665       
    6766        va_start(ap, format);
    68         vfprintf( stdout, format, ap);
     67        vfprintf( fstr ?: stdout, format, ap);
    6968        va_end(ap);
    70         fflush(stdout);
     69        fflush(fstr ?: stdout);
    7170
    7271        pthread_cleanup_pop(0);
  • libfdproto/messages.c

    r686 r687  
    661661
    662662/* Dump a msg_t object */
    663 static void obj_dump_msg (struct msg * msg, int indent )
     663static void obj_dump_msg (struct msg * msg, int indent, FILE * fstr )
    664664{
    665665        int ret = 0;
    666666       
    667         fd_log_debug("%*sMSG: %p\n", INOBJHDRVAL, msg);
     667        fd_log_debug_fstr(fstr, "%*sMSG: %p\n", INOBJHDRVAL, msg);
    668668       
    669669        if (!CHECK_MSG(msg)) {
    670                 fd_log_debug(INOBJHDR "INVALID!\n", INOBJHDRVAL);
     670                fd_log_debug_fstr(fstr, INOBJHDR "INVALID!\n", INOBJHDRVAL);
    671671                return;
    672672        }
     
    674674        if (!msg->msg_model) {
    675675               
    676                 fd_log_debug(INOBJHDR "(no model)\n", INOBJHDRVAL);
     676                fd_log_debug_fstr(fstr, INOBJHDR "(no model)\n", INOBJHDRVAL);
    677677               
    678678        } else {
     
    682682                ret = fd_dict_gettype(msg->msg_model, &dicttype);
    683683                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);
    685685                        goto public;
    686686                }
    687687                ret = fd_dict_getval(msg->msg_model, &dictdata);
    688688                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));
    690690                        goto public;
    691691                }
    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,
    693693                        DUMP_CMDFL_val(dictdata.cmd_flag_val), DUMP_CMDFL_val(dictdata.cmd_flag_mask), dictdata.cmd_code, dictdata.cmd_name);
    694694        }
    695695public:
    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,
    697697                msg->msg_public.msg_version,
    698698                msg->msg_public.msg_length,
     
    703703                msg->msg_public.msg_eteid
    704704                );
    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",
    706706                        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)");
    707707}
    708708
    709709/* Dump an avp object */
    710 static void obj_dump_avp ( struct avp * avp, int indent )
     710static void obj_dump_avp ( struct avp * avp, int indent, FILE * fstr )
    711711{
    712712        int ret = 0;
     
    714714       
    715715        if (!CHECK_AVP(avp)) {
    716                 fd_log_debug(INOBJHDR "INVALID!\n", INOBJHDRVAL);
     716                fd_log_debug_fstr(fstr, INOBJHDR "INVALID!\n", INOBJHDRVAL);
    717717                return;
    718718        }
     
    720720        if (!avp->avp_model) {
    721721               
    722                 fd_log_debug(INOBJHDR "(no model)\n", INOBJHDRVAL);
     722                fd_log_debug_fstr(fstr, INOBJHDR "(no model)\n", INOBJHDRVAL);
    723723               
    724724        } else {
     
    728728                ret = fd_dict_gettype(avp->avp_model, &dicttype);
    729729                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);
    731731                        goto public;
    732732                }
    733733                ret = fd_dict_getval(avp->avp_model, &dictdata);
    734734                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));
    736736                        goto public;
    737737                }
    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,
    739739                        DUMP_AVPFL_val(dictdata.avp_flag_val),
    740740                        DUMP_AVPFL_val(dictdata.avp_flag_mask),
     
    745745        }
    746746public:
    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,
    748748                avp->avp_public.avp_code,
    749749                DUMP_AVPFL_val(avp->avp_public.avp_flags),
     
    755755        if (avp->avp_public.avp_value) {
    756756                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);
    758758                } 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);
    764764}
    765765
    766766/* Dump a single object content */
    767 static void msg_dump_intern ( int level, msg_or_avp * obj, int indent )
     767static void msg_dump_intern ( int level, msg_or_avp * obj, int indent, FILE * fstr )
    768768{
    769769        /* Log only if we are at least at level */
     
    773773        /* Check the object */
    774774        if (!VALIDATE_OBJ(obj)) {
    775                 fd_log_debug( ">>> invalid object (%p)!.\n", obj);
     775                fd_log_debug_fstr(fstr, ">>> invalid object (%p)!.\n", obj);
    776776                return;
    777777        }
     
    780780        switch (_C(obj)->type) {
    781781                case MSG_AVP:
    782                         obj_dump_avp ( _A(obj), indent );
     782                        obj_dump_avp ( _A(obj), indent, fstr );
    783783                        break;
    784784               
    785785                case MSG_MSG:
    786                         obj_dump_msg ( _M(obj), indent );
     786                        obj_dump_msg ( _M(obj), indent, fstr );
    787787                        break;
    788788               
     
    792792}
    793793
     794/* Dump a message to a specified file stream */
     795static 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
    794809/* Dump a message content -- for debug mostly */
    795810void fd_msg_dump_walk ( int level, msg_or_avp *obj )
     
    800815        TRACE_DEBUG(level, "------ Dumping object %p (w)-------", obj);
    801816        do {
    802                 msg_dump_intern ( level, ref, indent );
     817                msg_dump_intern ( level, ref, indent, fd_g_debug_fstr );
    803818               
    804819                /* Now find the next object */
     
    815830{
    816831        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 );
    818833        TRACE_DEBUG(level, "------ /end of object %p -------", obj);
    819834}
     
    16451660                if (mandatory && (avp->avp_public.avp_flags & AVP_FLAG_MANDATORY)) {
    16461661                        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);
    16481663                        if (error_info) {
    16491664                                error_info->pei_errcode = "DIAMETER_AVP_UNSUPPORTED";
     
    23092324        return ret;
    23102325}
     2326
     2327
     2328/***************************************************************************************************************/
     2329/* messages logging facility */
     2330#include <stdarg.h>
     2331
     2332static 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
     2341static 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 */
     2348int 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 */
     2385static void fd_cleanup_mutex_silent( void * mutex )
     2386{
     2387        (void)pthread_mutex_unlock((pthread_mutex_t *)mutex);
     2388}
     2389
     2390/* Really log the message */
     2391void 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.