Skip to content

Commit

Permalink
websocket: implemented ws.dump rpc command
Browse files Browse the repository at this point in the history
  • Loading branch information
miconda committed Dec 22, 2016
1 parent 2f2bf30 commit bca64f7
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/modules/websocket/websocket.c
Expand Up @@ -362,6 +362,11 @@ static int pv_get_ws_conid_f(struct sip_msg *msg, pv_param_t *param,
return pv_get_sintval(msg, param, res, msg->rcv.proto_reserved1);
}

static const char* ws_rpc_dump_doc[2] = {
"List websocket connections",
0
};

static const char* ws_rpc_close_doc[2] = {
"Close a websocket connection by id",
0
Expand All @@ -378,6 +383,7 @@ static const char* ws_rpc_pong_doc[2] = {
};

rpc_export_t ws_rpc_cmds[] = {
{"ws.dump", ws_rpc_dump, ws_rpc_dump_doc, 0},
{"ws.close", ws_rpc_close, ws_rpc_close_doc, 0},
{"ws.ping", ws_rpc_ping, ws_rpc_ping_doc, 0},
{"ws.pong", ws_rpc_pong, ws_rpc_pong_doc, 0},
Expand Down
183 changes: 183 additions & 0 deletions src/modules/websocket/ws_conn.c
Expand Up @@ -709,3 +709,186 @@ struct mi_root *ws_mi_dump(struct mi_root *cmd, void *param)

return rpl_tree;
}


static int ws_rpc_add_node(rpc_t* rpc, void* ctx, void* ih, ws_connection_t *wsc)
{
int interval;
char *src_proto, *dst_proto, *pong, *sub_protocol;
char src_ip[IP6_MAX_STR_SIZE + 1], dst_ip[IP6_MAX_STR_SIZE + 1];
struct tcp_connection *con = tcpconn_get(wsc->id, 0, 0, 0, 0);
char rplbuf[512];

if (con)
{
src_proto = (con->rcv.proto== PROTO_WS) ? "ws" : "wss";
memset(src_ip, 0, IP6_MAX_STR_SIZE + 1);
ip_addr2sbuf(&con->rcv.src_ip, src_ip, IP6_MAX_STR_SIZE);

dst_proto = (con->rcv.proto == PROTO_WS) ? "ws" : "wss";
memset(dst_ip, 0, IP6_MAX_STR_SIZE + 1);
ip_addr2sbuf(&con->rcv.dst_ip, dst_ip, IP6_MAX_STR_SIZE);

pong = wsc->awaiting_pong ? "awaiting Pong, " : "";

interval = (int)time(NULL) - wsc->last_used;
if (wsc->sub_protocol == SUB_PROTOCOL_SIP)
sub_protocol = "sip";
else if (wsc->sub_protocol == SUB_PROTOCOL_MSRP)
sub_protocol = "msrp";
else
sub_protocol = "**UNKNOWN**";

if (snprintf(rplbuf, 512,
"%d: %s:%s:%hu -> %s:%s:%hu (state: %s"
", %s last used %ds ago"
", sub-protocol: %s)",
wsc->id,
src_proto,
strlen(src_ip) ? src_ip : "*",
con->rcv.src_port,
dst_proto,
strlen(dst_ip) ? dst_ip : "*",
con->rcv.dst_port,
wsconn_state_str[wsc->state],
pong,
interval,
sub_protocol) < 0) {
tcpconn_put(con);
rpc->fault(ctx, 500, "Failed to print connection details");
return -1;
}
if (rpc->array_add(ih, "s", rplbuf)<0)
{
tcpconn_put(con);
rpc->fault(ctx, 500, "Failed to add to response");
return -1;
}

tcpconn_put(con);
return 1;
}
else
return 0;
}

void ws_rpc_dump(rpc_t* rpc, void* ctx)
{
int h, connections = 0, truncated = 0, order = 0, found = 0;
ws_connection_t *wsc;
str sorder = {0};
void* th;
void* ih;
void* dh;

if(rpc->scan(ctx, "*S", &sorder)==1)
{
if (sorder.len == 7 && strncasecmp(sorder.s, "id_hash", 7) == 0) {
order = 0;
} else if (sorder.len == 9 && strncasecmp(sorder.s, "used_desc", 9) == 0) {
order = 1;
} else if (sorder.len == 8 && strncasecmp(sorder.s, "used_asc", 8) == 0) {
order = 2;
} else {
LM_WARN("bad display order parameter\n");
rpc->fault(ctx, 400, str_status_bad_param.s);
return;
}
}

/* add root node */
if (rpc->add(ctx, "{", &th) < 0)
{
rpc->fault(ctx, 500, "Internal error root reply");
return;
}
if(rpc->struct_add(th, "[{",
"connections", "info", &ih, &dh)<0)
{
rpc->fault(ctx, 500, "Internal error connections structure");
return;
}

WSCONN_LOCK;
if (order == 0)
{
for (h = 0; h < TCP_ID_HASH_SIZE; h++)
{
wsc = wsconn_id_hash[h];
while(wsc)
{
if ((found = ws_rpc_add_node(rpc, ctx, ih, wsc)) < 0)
{
WSCONN_UNLOCK;
return;
}


connections += found;
if (connections >= MAX_WS_CONNS_DUMP)
{
truncated = 1;
break;
}

wsc = wsc->id_next;
}

if (truncated == 1)
break;
}
}
else if (order == 1)
{
wsc = wsconn_used_list->head;
while (wsc)
{
if ((found = ws_rpc_add_node(rpc, ctx, ih, wsc)) < 0)
{
WSCONN_UNLOCK;
return;
}

connections += found;
if (connections >= MAX_WS_CONNS_DUMP)
{
truncated = 1;
break;
}

wsc = wsc->used_next;
}
}
else
{
wsc = wsconn_used_list->tail;
while (wsc)
{
if ((found = ws_rpc_add_node(rpc, ctx, ih, wsc)) < 0)
{
WSCONN_UNLOCK;
return;
}

connections += found;
if (connections >= MAX_WS_CONNS_DUMP)
{
truncated = 1;
break;
}

wsc = wsc->used_prev;
}
}
WSCONN_UNLOCK;

if(rpc->struct_add(dh, "ds",
"wscounter", "truncated",
connections, (truncated==1)?"yes":"no")<0)
{
rpc->fault(ctx, 500, "Internal error adding info structure");
return;
}

return;
}
1 change: 1 addition & 0 deletions src/modules/websocket/ws_conn.h
Expand Up @@ -99,4 +99,5 @@ int wsconn_put(ws_connection_t *wsc);
ws_connection_t **wsconn_get_list(void);
int wsconn_put_list(ws_connection_t **list);
struct mi_root *ws_mi_dump(struct mi_root *cmd, void *param);
void ws_rpc_dump(rpc_t* rpc, void* ctx);
#endif /* _WS_CONN_H */

0 comments on commit bca64f7

Please sign in to comment.