Skip to content

Commit

Permalink
Add generic tracing interface for mi messages
Browse files Browse the repository at this point in the history
  • Loading branch information
ionutrazvanionita committed Jan 27, 2017
1 parent 6f51a40 commit 97a6b58
Show file tree
Hide file tree
Showing 4 changed files with 338 additions and 0 deletions.
3 changes: 3 additions & 0 deletions mi/mi_core.c
Expand Up @@ -49,6 +49,7 @@
#include "../cachedb/cachedb.h"
#include "../evi/event_interface.h"
#include "mi.h"
#include "mi_trace.h"


static str up_since_ctime;
Expand Down Expand Up @@ -622,5 +623,7 @@ int init_mi_core(void)
return -1;
}

try_load_trace_api();

return 0;
}
229 changes: 229 additions & 0 deletions mi/mi_trace.c
@@ -0,0 +1,229 @@
/*
* Copyright (C) 2016 - OpenSIPS Foundation
* Copyright (C) 2001-2003 FhG Fokus
*
* This file is part of opensips, a free SIP server.
*
* opensips is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version
*
* opensips is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* History:
* -------
* 2016-09-19 first version (Ionut Ionita)
*/
#include "../ut.h"

#include "mi_trace.h"

#define TRACE_API_MODULE "proto_hep"
#define MI_ID_S "mi"
#define MI_TRACE_BUF_SIZE (1 << 10)

#define MAX_RPL_CHARS (1 << 7)
#define CORR_BUF_SIZE 64

/* CORR - magic for internally generated correltion id */
#define CORR_MAGIC "\x43\x4F\x52\x52"

trace_proto_t* mi_trace_api=NULL;
int mi_message_id;

static char* correlation_name = "correlation_id";
str correlation_value;
int correlation_id=-1, correlation_vendor=-1;


static char trace_buf[MI_TRACE_BUF_SIZE];


void try_load_trace_api(void)
{
/* already loaded */
if ( mi_trace_api )
return;

mi_trace_api = pkg_malloc(sizeof(trace_proto_t));
if (mi_trace_api == NULL)
return;

memset(mi_trace_api, 0, sizeof(trace_proto_t));
if (trace_prot_bind(TRACE_API_MODULE, mi_trace_api) < 0) {
LM_DBG("No tracing module used!\n");
return;
}

mi_message_id = mi_trace_api->get_message_id(MI_ID_S);
}

#define CHECK_OVERFLOW(_len) \
do { \
if ( _len >= MI_TRACE_BUF_SIZE ) { \
LM_ERR("not enough room in command buffer!\n"); \
return 0; \
} \
} while (0);

char* build_mi_trace_request( str* cmd, struct mi_root* mi_req, str* backend)
{
int len, new;
struct mi_node* node;

if ( !cmd || !backend )
return 0;

len = snprintf( trace_buf, MI_TRACE_BUF_SIZE,
"(%.*s) %.*s\n",
backend->len, backend->s,
cmd->len, cmd->s);

CHECK_OVERFLOW(len);

if ( mi_req ) {
node = mi_req->node.kids;

while ( node ) {
/* FIXME should we also put the name here? */
new = snprintf( trace_buf+len, MI_TRACE_BUF_SIZE - len,
"%.*s ", node->value.len, node->value.s);

len += new;
CHECK_OVERFLOW(len);

node = node->next;
}
}


return trace_buf;
}

char* build_mi_trace_reply( int code, str* reason, str* rpl_msg )
{
int len, new;

if ( !reason )
return 0;

len = snprintf( trace_buf, MI_TRACE_BUF_SIZE,
"(%d:%.*s)\n",
code, reason->len, reason->s);
CHECK_OVERFLOW(len);

if ( rpl_msg ) {
new = snprintf( trace_buf+len, MI_TRACE_BUF_SIZE,
"%.*s...\n",
rpl_msg->len > MAX_RPL_CHARS ? MAX_RPL_CHARS : rpl_msg->len,
rpl_msg->s);
len += new;

CHECK_OVERFLOW(len);
}

return trace_buf;
}

char* generate_correlation_id(int* len)
{
static char corr_buf[CORR_BUF_SIZE];

if ( !len )
return 0;

*len = snprintf(corr_buf, CORR_BUF_SIZE, "%s%d", CORR_MAGIC, rand());
if ( *len >= CORR_BUF_SIZE ) {
LM_ERR("not enough space in correlation buffer!\n");
return 0;
}

return corr_buf;
}


int trace_mi_message(union sockaddr_union* src, union sockaddr_union* dst,
str* body, str* correlation_value, trace_dest trace_dst)
{
/* FIXME is this the case for all mi impelementations?? */
const int proto = IPPROTO_TCP;
union sockaddr_union tmp, *to_su, *from_su;

trace_message message;

if (mi_trace_api->create_trace_message == NULL ||
mi_trace_api->send_message == NULL) {
LM_DBG("trace api not loaded!\n");
return 0;
}


if (src == NULL || dst == NULL) {
tmp.sin.sin_addr.s_addr = TRACE_INADDR_LOOPBACK;
tmp.sin.sin_port = 0;
tmp.sin.sin_family = AF_INET;
}

/* FIXME src and/or dst port might be in htons form */
if (src)
from_su = src;
else
from_su = &tmp;

if (dst)
to_su = dst;
else
to_su = &tmp;

message = mi_trace_api->create_trace_message(from_su, to_su,
proto, body, mi_message_id, trace_dst);
if (message == NULL) {
LM_ERR("failed to create trace message!\n");
return -1;
}

if ( correlation_value ) {
if ( correlation_id < 0 || correlation_vendor < 0 ) {
if ( load_correlation_id() < 0 ) {
LM_ERR("can't load correlation id!\n");
return -1;
}
}

if ( mi_trace_api->add_trace_data( message, correlation_value->s,
correlation_value->len, TRACE_TYPE_STR,
correlation_id, correlation_vendor) < 0 ) {
LM_ERR("can't set the correlation id!\n");
return -1;
}
}

if (mi_trace_api->send_message(message, trace_dst, 0) < 0) {
LM_ERR("failed to send trace message!\n");
return -1;
}

mi_trace_api->free_message(message);

return 0;
}

int load_correlation_id(void)
{
/* already looked for them */
if (correlation_id > 0 && correlation_vendor > 0)
return 0;

return mi_trace_api->get_data_id(correlation_name, &correlation_vendor, &correlation_id);
}


105 changes: 105 additions & 0 deletions mi/mi_trace.h
@@ -0,0 +1,105 @@
/*
* Copyright (C) 2016 - OpenSIPS Foundation
* Copyright (C) 2001-2003 FhG Fokus
*
* This file is part of opensips, a free SIP server.
*
* opensips is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version
*
* opensips is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* History:
* -------
* 2016-09-19 first version (Ionut Ionita)
*/
#ifndef _mi_trace_h
#define _mi_trace_h

#include "../trace_api.h"

extern trace_proto_t* mi_trace_api;
extern int correlation_id, correlation_vendor;
extern str correlation_value;

void try_load_trace_api(void);
int trace_mi_message(union sockaddr_union* src, union sockaddr_union* dst,
str* body, str* correlation_value, trace_dest trace_dst);
char* build_mi_trace_request( str* cmd, struct mi_root* mi_req, str* backend);
char* build_mi_trace_reply( int code, str* reason, str* rpl_msg );
char* generate_correlation_id(int* len);
int load_correlation_id(void);

static inline void mi_trace_reply( union sockaddr_union* src, union sockaddr_union* dst,
int code, str* reason, str* message, trace_dest t_dst)
{
str trace_buf;

/* trace disabled */
if ( !t_dst )
return;

/* message can be null */
if ( !reason ) {
LM_ERR("traced reply needs to have a reason!\n");
return;
}

trace_buf.s = build_mi_trace_reply( code, reason, message);
if ( !trace_buf.s ) {
LM_ERR("can't build reply buffer!\n");
return;
}

trace_buf.len = strlen(trace_buf.s);
if ( !correlation_value.s ) {
LM_ERR("can't find correlation id generated by the request!\n");
return;
}

if (trace_mi_message( src, dst, &trace_buf, &correlation_value, t_dst) < 0) {
LM_ERR("failed to trace mi command reply!\n");
}
}


static inline void mi_trace_request( union sockaddr_union* src, union sockaddr_union* dst,
char* command, int len, struct mi_root* mi_req, str* backend, trace_dest t_dst )
{
str comm_s = { command, len };
str trace_buf;

if ( !t_dst || !backend )
return;

trace_buf.s = build_mi_trace_request( &comm_s, mi_req, backend);
if ( !trace_buf.s ) {
LM_ERR("Can't build mi request for tracing!\n");
return;
}

trace_buf.len = strlen(trace_buf.s);
correlation_value.s = generate_correlation_id(&correlation_value.len);

if ( !correlation_value.s ) {
LM_ERR("failed to generate correlation id!\n");
return;
}

if (trace_mi_message( src, dst, &trace_buf, &correlation_value, t_dst) < 0) {
LM_ERR("failed to trace mi command request!\n");
}
}


#endif
1 change: 1 addition & 0 deletions modules/proto_hep/hep.c
Expand Up @@ -72,6 +72,7 @@ extern compression_api_t compression_api;
struct hep_message_id hep_ids[] = {
{ "sip" , 0x01},
{ "xlog", 0x56},
{ "mi" , 0x57},
{ NULL , 0 }
};

Expand Down

0 comments on commit 97a6b58

Please sign in to comment.