Skip to content

Commit

Permalink
cgrates: handle commands from cgrates
Browse files Browse the repository at this point in the history
  • Loading branch information
razvancrainea committed Jan 25, 2017
1 parent 3891b52 commit cebc7f7
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 19 deletions.
92 changes: 89 additions & 3 deletions modules/cgrates/cgrates_acc.c
Expand Up @@ -154,7 +154,7 @@ static inline void cgr_free_acc_ctx(struct cgr_acc_ctx *ctx)
ctxstr.len = sizeof(ctx);
ctxstr.s = (char *)&ctx;
dlg = cgr_dlgb.get_dlg();
if (dlg && !cgr_dlgb.store_dlg_value(dlg, &cgr_ctx_str, &ctxstr))
if (dlg && cgr_dlgb.store_dlg_value(dlg, &cgr_ctx_str, &ctxstr) < 0)
LM_ERR("cannot reset context in dialog %p!\n", dlg);
}

Expand Down Expand Up @@ -263,7 +263,7 @@ static inline int cgr_help_set_str(str **dst, str src)


static json_object *cgr_get_start_acc_msg(struct sip_msg *msg,
struct cgr_acc_ctx *ctx)
struct dlg_cell *dlg, struct cgr_acc_ctx *ctx)
{
struct cgr_msg *cmsg;
str stime;
Expand All @@ -290,6 +290,18 @@ static json_object *cgr_get_start_acc_msg(struct sip_msg *msg,
goto error;
}

if (ctx && !cgr_get_const_kv(ctx->kv_store, "DialogID") &&
cgr_msg_push_int(cmsg, "DialogID", dlg->h_id) < 0) {
LM_ERR("cannot push DialogID!\n");
goto error;
}

if (ctx && !cgr_get_const_kv(ctx->kv_store, "DialogEntry") &&
cgr_msg_push_int(cmsg, "DialogEntry", dlg->h_entry) < 0) {
LM_ERR("cannot push DialogEntry!\n");
goto error;
}

/* Account */
if (cgr_msg_push_str(cmsg, "Account", &ctx->acc) < 0) {
LM_ERR("cannot push Account info!\n");
Expand Down Expand Up @@ -634,7 +646,7 @@ static void cgr_tmcb_func(struct cell* t, int type, struct tmcb_params *ps)
LM_ERR("cannot find dialog!\n");
goto unref;
}
jmsg = cgr_get_start_acc_msg(ps->req, ctx);
jmsg = cgr_get_start_acc_msg(ps->req, dlg, ctx);
if (!jmsg) {
LM_ERR("cannot build the json to send to cgrates\n");
goto error;
Expand Down Expand Up @@ -824,3 +836,77 @@ static void cgr_dlg_callback(struct dlg_cell *dlg, int type,
unref_ctx:
cgr_ref_acc_ctx(ctx, -1, "dialog");
}

int cgr_acc_terminate(json_object *param, json_object **ret)
{
str terminate_str;
const char *err;
str reason = {0, 0};
json_object *event = NULL;
unsigned int h_entry, h_id;
unsigned int h_id_found = 0;
unsigned int h_entry_found = 0;
static str terminate_str_pre = str_init("CGRateS Disconnect: ");

json_object_object_foreach(param, pkey, pval) {
switch (json_object_get_type(pval)) {
case json_type_string:
if (strcmp(pkey, "Reason") != 0)
continue;
reason.s = (char *)json_object_get_string(pval);
break;
case json_type_object:
if (strcmp(pkey, "EventStart") != 0)
continue;
event = json_object_get(pval);
default:
break;
}
}
if (!event) {
err = "EventStart parameter not found";
goto error;
}

json_object_object_foreach(event, key, val) {
if (strcmp(key, "DialogID") == 0) {
h_id = json_object_get_int(val);
h_id_found = 1;
} else if (strcmp(key, "DialogEntry") == 0) {
h_entry = json_object_get_int(val);
h_entry_found = 1;
}
}
if (!h_entry_found || !h_id_found) {
err = "dialog identifiers not found";
goto error;
}
if (reason.s) {
reason.len = strlen(reason.s);
terminate_str.s = pkg_malloc(terminate_str_pre.len + reason.len);
if (!terminate_str.s) {
err = "internal error";
goto error;
}
memcpy(terminate_str.s, terminate_str_pre.s, terminate_str_pre.len);
memcpy(terminate_str.s + terminate_str_pre.len, reason.s, reason.len);
terminate_str.len = terminate_str_pre.len + reason.len;
} else {
terminate_str.s = terminate_str_pre.s;
terminate_str.len = terminate_str_pre.len - 2 /* skip the ': ' */;
}
if (cgr_dlgb.terminate_dlg(h_entry, h_id, &terminate_str) < 0) {
if (terminate_str.s != terminate_str_pre.s)
pkg_free(terminate_str.s);
err = "cannot terminate dialog";
goto error;
}
if (terminate_str.s != terminate_str_pre.s)
pkg_free(terminate_str.s);
*ret = json_object_new_int(0);
return 0;
error:
LM_ERR("cannot handle terminate: %s\n", err);
*ret = json_object_new_string(err);
return -1;
}
2 changes: 2 additions & 0 deletions modules/cgrates/cgrates_acc.h
Expand Up @@ -22,6 +22,7 @@
#ifndef _CGRATES_ACC_H_
#define _CGRATES_ACC_H_

#include <json.h>
#include "../dialog/dlg_load.h"

/*
Expand Down Expand Up @@ -59,6 +60,7 @@ struct cgr_acc_ctx *cgr_tryget_acc_ctx(void);
void cgr_ref_acc_ctx(struct cgr_acc_ctx *ctx, int how, const char *who);
void cgr_loaded_callback(struct dlg_cell *dlg, int type,
struct dlg_cb_params *_params);
int cgr_acc_terminate(json_object *param, json_object **ret);

#define CGRF_DO_CDR (1<<0)
#define CGRF_DO_MISSED (1<<1)
Expand Down
72 changes: 59 additions & 13 deletions modules/cgrates/cgrates_common.c
Expand Up @@ -215,6 +215,17 @@ int cgr_msg_push_str(struct cgr_msg *cmsg, const char *key, str *value)
return -1;
}

int cgr_msg_push_int(struct cgr_msg *cmsg, const char *key, unsigned int value)
{
json_object *jmsg;
jmsg = json_object_new_int(value);
JSON_CHECK(jmsg, key);
json_object_object_add(cmsg->params, key, jmsg);
return 0;
error:
return -1;
}

#undef JSON_CHECK

/* context manipulation */
Expand Down Expand Up @@ -305,16 +316,14 @@ int cgr_handle_cmd(struct sip_msg *msg, json_object *jmsg,
struct cgr_conn *c = NULL;
int ret = 1;
str smsg;
char *r;

/* reset the error */
CGR_RESET_REPLY_CTX();

smsg.s = (char *)json_object_to_json_string(jmsg);
smsg.len = strlen(smsg.s);

r = (char *)json_object_to_json_string(jmsg);
LM_DBG("sending json string: %s\n", r);
LM_DBG("sending json string: %s\n", smsg.s);

/* connect to all servers */
/* go through each server and initialize the state */
Expand Down Expand Up @@ -389,7 +398,6 @@ int cgr_handle_async_cmd(struct sip_msg *msg, json_object *jmsg,
struct cgr_param *cp = NULL;
int ret = 1;
str smsg;
char *r;

smsg.s = (char *)json_object_to_json_string(jmsg);
smsg.len = strlen(smsg.s);
Expand All @@ -403,8 +411,7 @@ int cgr_handle_async_cmd(struct sip_msg *msg, json_object *jmsg,
cp->reply_f = f;
cp->reply_p = p;

r = (char *)json_object_to_json_string(jmsg);
LM_DBG("sending json string: %s\n", r);
LM_DBG("sending json string: %s\n", smsg.s);

list_for_each(l, &cgrates_engines) {
e = list_entry(l, struct cgr_engine, list);
Expand Down Expand Up @@ -532,19 +539,59 @@ int cgrc_async_read(struct cgr_conn *c,
/* function ran when an event is sent over a fd */
int cgrates_async_resume_req(int fd, void *param)
{
if (cgrc_async_read((struct cgr_conn *)param, NULL, NULL) < 0)
return -1;
cgrc_async_read((struct cgr_conn *)param, NULL, NULL);
/* if successfull, just continue listening */
if (async_status == ASYNC_DONE)
async_status = ASYNC_CONTINUE;

/* XXX: return is only used if fd changes - we are not currently
* support this */
return 1;
}

static inline int cgrates_process_req(struct cgr_engine *e, json_object *id,
static inline int cgrates_process_req(struct cgr_conn *c, json_object *id,
char *method, json_object *param)
{
int ret;
json_object *jobj = NULL;
json_object *jret = NULL;
str smsg;

LM_INFO("Received new request method=%s param=%p\n",
method, param);
if (strcmp(method, "SMGClientV1.DisconnectSession") == 0) {
ret = cgr_acc_terminate(param, &jret);
} else {
LM_ERR("cannot handle method %s\n", method);
ret = -1;
jret = json_object_new_string("Unknown Method");
}

jobj = json_object_new_object();
if (!jobj) {
LM_ERR("cannot create a new json object!\n");
if (jret)
json_object_put(jret);
return -1;
}
if (ret < 0) {
json_object_object_add(jobj, "error", jret);
json_object_object_add(jobj, "result", NULL);
} else {
json_object_object_add(jobj, "error", NULL);
json_object_object_add(jobj, "result", jret);
}
if (id)
json_object_object_add(jobj, "id", id);

smsg.s = (char *)json_object_to_json_string(jobj);
smsg.len = strlen(smsg.s);

LM_DBG("sending json response: %s\n", smsg.s);
cgrc_send(c, &smsg);

json_object_put(jobj);

return -1;
}

Expand Down Expand Up @@ -572,7 +619,6 @@ int cgrates_process(json_object *jobj,
int l = 0;
enum cgrm_type msg_type = CGRM_UNSPEC;
enum json_type type;
struct cgr_engine *e = c->engine;

LM_DBG("Processing JSON: %s\n",
(char *)json_object_to_json_string(jobj));
Expand Down Expand Up @@ -603,7 +649,7 @@ int cgrates_process(json_object *jobj,
err = 0;
break;
case json_type_string:
error = (char *)json_object_to_json_string(val);
error = (char *)json_object_get_string(val);
break;
default:
LM_DBG("Unknown type %d for the \"error\" key\n", type);
Expand All @@ -619,7 +665,7 @@ int cgrates_process(json_object *jobj,
LM_DBG("Unknown type %d for the \"method\" key\n", type);
return -3;
}
method = (char *)json_object_to_json_string(val);
method = (char *)json_object_get_string(val);
} else if (strcmp(key, "params") == 0) {
if (msg_type != CGRM_UNSPEC && msg_type != CGRM_REQ) {
LM_ERR("Invalid JSON \"params\" property in a JSON-RPC reply!\n");
Expand Down Expand Up @@ -677,7 +723,7 @@ int cgrates_process(json_object *jobj,
LM_ERR("no method or parameters specified!\n");
return -3;
}
cgrates_process_req(e, id, method, jresult);
cgrates_process_req(c, id, method, jresult);
return 0;
}
/* never gets here */
Expand Down
1 change: 1 addition & 0 deletions modules/cgrates/cgrates_common.h
Expand Up @@ -88,6 +88,7 @@ struct cgr_msg {
int cgrates_set_reply(int type, int_str *value);
struct cgr_msg *cgr_get_generic_msg(str *method, struct list_head *list);
int cgr_msg_push_str(struct cgr_msg *cmsg, const char *key, str *value);
int cgr_msg_push_int(struct cgr_msg *cmsg, const char *key, unsigned int value);

/* key-value manipulation */
struct cgr_kv *cgr_new_kv(str key);
Expand Down
7 changes: 4 additions & 3 deletions modules/cgrates/cgrates_engine.c
Expand Up @@ -86,13 +86,10 @@ struct cgr_conn *cgr_get_default_conn(struct cgr_engine *e)
e->disable_time + cgre_retry_tout);
return NULL;
}
LM_INFO("deault_con = %p\n", e->default_con);

/* use the default connection */
if (!e->default_con)
return NULL;
LM_DBG("conn=%p state=%x now=%lu until=%lu\n", e->default_con,
e->default_con->state, now, e->default_con->disable_time + cgre_retry_tout);
if (e->default_con->state == CGRC_FREE) {
LM_DBG("using default connection - running in sync mode!\n");
return e->default_con;
Expand All @@ -106,8 +103,12 @@ struct cgr_conn *cgr_get_default_conn(struct cgr_engine *e)
e->host.s, e->port);
e->default_con->state = CGRC_FREE;
e->disable_time = 0;
cgrc_start_listen(e->default_con);
return e->default_con;
}
} else {
LM_DBG("conn=%p state=%x now=%lu until=%lu\n", e->default_con,
e->default_con->state, now, e->default_con->disable_time + cgre_retry_tout);
}
return NULL;
}
Expand Down

0 comments on commit cebc7f7

Please sign in to comment.