瀏覽代碼

added send_dmq_message functionality and also used it to send initial notification message

Marius Bucur 14 年之前
父節點
當前提交
a3918ba707

+ 2 - 0
modules_k/dmq/bind_dmq.c

@@ -1,5 +1,7 @@
+#include "dmq.h"
 #include "bind_dmq.h"
 #include "peer.h"
+#include "dmq_funcs.h"
 
 int bind_dmq(dmq_api_t* api) {
 	api->register_dmq_peer = register_dmq_peer;

+ 32 - 9
modules_k/dmq/dmq.c

@@ -60,14 +60,12 @@ static void destroy(void);
 
 MODULE_VERSION
 
-/* database connection */
-int library_mode = 0;
-str server_address = {0, 0};
 int startup_time = 0;
 int pid = 0;
 
 /* module parameters */
 int num_workers = DEFAULT_NUM_WORKERS;
+str dmq_server_address = {0, 0};
 
 /* TM bind */
 struct tm_binds tmb;
@@ -75,6 +73,7 @@ struct tm_binds tmb;
 sl_api_t slb;
 
 /** module variables */
+str dmq_request_method = {"KDMQ", 4};
 dmq_worker_t* workers;
 dmq_peer_list_t* peer_list;
 /* the list of dmq servers */
@@ -87,6 +86,7 @@ static int mod_init(void);
 static int child_init(int);
 static void destroy(void);
 static int handle_dmq_fixup(void** param, int param_no);
+static int check_dmq_server_address();
 
 static cmd_export_t cmds[] = {
 	{"handle_dmq_message",  (cmd_function)handle_dmq_message, 0, handle_dmq_fixup, 0, 
@@ -98,6 +98,7 @@ static cmd_export_t cmds[] = {
 
 static param_export_t params[] = {
 	{"num_workers", INT_PARAM, &num_workers},
+	{"server_address", STR_PARAM, &dmq_server_address.s},
 	{0, 0, 0}
 };
 
@@ -131,23 +132,19 @@ static int mod_init(void) {
 		return -1;
 	}
 
-	if(library_mode== 1) {
-		LM_DBG("dmq module used for API library purpose only\n");
-	}
-
 	/* bind the SL API */
 	if (sl_load_api(&slb)!=0) {
 		LM_ERR("cannot bind to SL API\n");
 		return -1;
 	}
-
+	
 	/* load all TM stuff */
 	if(load_tm_api(&tmb)==-1) {
 		LM_ERR("can't load tm functions. TM module probably not loaded\n");
 		return -1;
 	}
-	
 	/* load peer list - the list containing the module callbacks for dmq */
+	
 	peer_list = init_peer_list();
 	
 	/* load the dmq node list - the list containing the dmq servers */
@@ -155,6 +152,12 @@ static int mod_init(void) {
 	
 	/* register worker processes - add one because of the ping process */
 	register_procs(num_workers);
+	/* check server_address not empty and correct */
+	
+	if(check_dmq_server_address() < 0) {
+		LM_ERR("server address invalid\n");
+		return -1;
+	}
 	
 	/* allocate workers array */
 	workers = shm_malloc(num_workers * sizeof(*workers));
@@ -214,4 +217,24 @@ static void destroy(void) {
 
 static int handle_dmq_fixup(void** param, int param_no) {
  	return 0;
+}
+
+static int check_dmq_server_address() {
+	if(!dmq_server_address.s) {
+		return -1;
+	}
+	dmq_server_address.len = strlen(dmq_server_address.s);
+	if(!dmq_server_address.len) {
+		LM_ERR("empty server address\n");
+		return -1;
+	}
+	if(strncmp(dmq_server_address.s, "sip:", 4)) {
+		LM_ERR("server address must start with sip:\n");
+		return -1;
+	}
+	if(!strchr(dmq_server_address.s + 4, ':')) {
+		LM_ERR("server address must be of form sip:host:port\n");
+		return -1;
+	}
+	return 0;
 }

+ 8 - 0
modules_k/dmq/dmq.h

@@ -4,6 +4,8 @@
 #include "../../dprint.h"
 #include "../../error.h"
 #include "../../sr_module.h"
+#include "../../modules/tm/tm_load.h"
+#include "../../modules/sl/sl.h"
 #include "bind_dmq.h"
 #include "peer.h"
 #include "worker.h"
@@ -14,8 +16,14 @@
 extern int num_workers;
 extern dmq_worker_t* workers;
 extern dmq_peer_t dmq_notification_peer;
+extern str dmq_server_address;
 extern dmq_peer_list_t* peer_list;
 extern dmq_node_list_t* node_list;
+extern str dmq_request_method;
+
+/* sl and tm */
+extern struct tm_binds tmb;
+extern sl_api_t slb;
 
 static inline int dmq_load_api(dmq_api_t* api) {
 	bind_dmq_f binddmq;

+ 38 - 0
modules_k/dmq/dmq_funcs.c

@@ -0,0 +1,38 @@
+#include "dmq_funcs.h"
+
+int register_dmq_peer(dmq_peer_t* peer) {
+	lock_get(&peer_list->lock);
+	if(search_peer_list(peer_list, peer)) {
+		LM_ERR("peer already exists: %.*s %.*s\n", peer->peer_id.len, peer->peer_id.s,
+		       peer->description.len, peer->description.s);
+		return -1;
+	}
+	add_peer(peer_list, peer);
+	lock_release(&peer_list->lock);
+	return 0;
+}
+
+void dmq_tm_callback( struct cell *t, int type, struct tmcb_params *ps) {
+	LM_ERR("callback\n");
+}
+
+int send_dmq_message(dmq_peer_t* peer, str* body) {
+	uac_req_t uac_r;
+	str str_hdr = {0, 0};
+	/* TODO - do not hardcode these - just for tesing purposes */
+	str from = {"sip:[email protected]:5060", 25};
+	str req_uri = from;
+	void *cb_param = NULL;
+	int result;
+	set_uac_req(&uac_r, &dmq_request_method, &str_hdr, body, NULL, TMCB_LOCAL_COMPLETED,
+			dmq_tm_callback, (void*)cb_param);
+	result = tmb.t_request(&uac_r, &req_uri,
+			       &from, &from,
+			       NULL);
+	if(result < 0)
+	{
+		LM_ERR("error in tmb.t_request_within\n");
+		return -1;
+	}
+	return 0;
+}

+ 14 - 0
modules_k/dmq/dmq_funcs.h

@@ -0,0 +1,14 @@
+#ifndef DMQ_FUNCS_H
+#define DMQ_FUNCS_H
+
+#include "../../modules/tm/dlg.h"
+#include "../../modules/tm/tm_load.h"
+#include "dmq.h"
+#include "peer.h"
+#include "worker.h"
+#include "../../str.h"
+
+int register_dmq_peer(dmq_peer_t* peer);
+int send_dmq_message(dmq_peer_t* peer, str* body);
+
+#endif

+ 13 - 0
modules_k/dmq/dmqnode.c

@@ -1,3 +1,4 @@
+#include "../../ut.h"
 #include "dmqnode.h"
 #include "dmq.h"
 
@@ -6,4 +7,16 @@ dmq_node_list_t* init_dmq_node_list() {
 	memset(node_list, 0, sizeof(dmq_node_list_t));
 	lock_init(&node_list->lock);
 	return node_list;
+}
+
+inline int add_dmq_node(dmq_node_list_t* list, dmq_node_t* newnode) {
+	dmq_node_t* copy = shm_malloc(sizeof(dmq_node_t));
+	memcpy(copy, newnode, sizeof(dmq_node_t));
+	shm_str_dup(&copy->orig_uri, &newnode->orig_uri);
+	lock_get(&list->lock);
+	copy->next = list->nodes;
+	list->nodes = copy;
+	list->count++;
+	lock_release(&list->lock);
+	return 0;
 }

+ 5 - 1
modules_k/dmq/dmqnode.h

@@ -9,11 +9,14 @@
 #include "../../mem/shm_mem.h"
 #include "../../parser/parse_uri.h"
 
+#define NBODY_LEN 1024
+
 typedef struct dmq_node {
+	str orig_uri;
 	struct sip_uri* uri;
 	int status;
 	int last_notification;
-	struct dmqnode* next;
+	struct dmq_node* next;
 } dmq_node_t;
 
 typedef struct dmq_node_list {
@@ -24,5 +27,6 @@ typedef struct dmq_node_list {
 
 dmq_node_list_t* init_dmq_node_list();
 int update_node_list(dmq_node_list_t* remote_list);
+int add_dmq_node(dmq_node_list_t* list, dmq_node_t* newnode);
 
 #endif

+ 137 - 12
modules_k/dmq/notification_peer.c

@@ -1,28 +1,153 @@
 #include "notification_peer.h"
+#include "dmq_funcs.h"
 
 int add_notification_peer() {
-	int ret;
+	dmq_node_t self_node;
+	self_node.orig_uri = dmq_server_address;
+	
 	dmq_notification_peer.callback = dmq_notification_callback;
 	dmq_notification_peer.description.s = "dmqpeer";
 	dmq_notification_peer.description.len = 7;
 	dmq_notification_peer.peer_id.s = "dmqpeer";
 	dmq_notification_peer.peer_id.len = 7;
-	ret = register_dmq_peer(&dmq_notification_peer);
-	return ret;
+	if(register_dmq_peer(&dmq_notification_peer) < 0) {
+		LM_ERR("error in register_dmq_peer\n");
+		goto error;
+	}
+	/* add itself to the node list */
+	if(add_dmq_node(node_list, &self_node) < 0) {
+		LM_ERR("error adding self node\n");
+		goto error;
+	}
+	if(request_initial_nodelist() < 0) {
+		LM_ERR("error in request_initial_notification\n");
+		goto error;
+	}
+	return 0;
+error:
+	return -1;
+}
+
+int extract_node_list(dmq_node_list_t* update_list, struct sip_msg* msg) {
+	int content_length, total_nodes = 0;
+	str body;
+	str tmp_uri;
+	dmq_node_t *cur = NULL, *prev = NULL, *first = NULL;
+	char *tmp, *end, *match;
+	if(!msg->content_length) {
+		LM_ERR("no content length header found\n");
+		return -1;
+	}
+	content_length = get_content_length(msg);
+	if(!content_length) {
+		LM_DBG("content length is 0\n");
+		return total_nodes;
+	}
+	body.s = get_body(msg);
+	body.len = content_length;
+	tmp = body.s;
+	end = body.s + body.len;
+	
+	while(tmp < end) {
+		total_nodes++;
+		cur = shm_malloc(sizeof(dmq_node_t));
+		memset(cur, 0, sizeof(*cur));
+		/* keep the list tail in first */
+		if(!first) {
+			first = cur;
+		}
+		cur->next = prev;
+		
+		match = q_memchr(tmp, '\n', end - tmp);
+		if (match){
+			match++;
+		}else {
+			/* for the last line - take all of it */
+			match = end;
+		}
+		/* create the orig_uri from the parsed uri line and trim it */
+		tmp_uri.s = tmp;
+		tmp_uri.len = match - tmp;
+		shm_str_dup(&cur->orig_uri, &tmp_uri);
+		trim_r(cur->orig_uri);
+		
+		tmp = match;
+		
+		prev = cur;
+	}
+	lock_get(&update_list->lock);
+	first->next = update_list->nodes;
+	update_list->nodes = cur;
+	lock_release(&update_list->lock);
+	return total_nodes;
 }
 
-int dmq_notification_callback(struct sip_msg* msg) {
+int dmq_notification_callback(struct sip_msg* msg, peer_reponse_t* resp) {
+	int nodes_recv;
 	/* received dmqnode list */
-	dmq_node_list_t* rlist;
 	LM_ERR("dmq triggered from dmq_notification_callback\n");
-	rlist = extract_node_list(msg);
-	if(!rlist) {
-		LM_ERR("extract_node_list failed\n");
+	nodes_recv = extract_node_list(node_list, msg);
+	LM_DBG("received %d nodes\n", nodes_recv);
+	return 0;
+}
+
+int build_node_str(dmq_node_t* node, char* buf, int buflen) {
+	if(buflen < node->orig_uri.len) {
+		LM_ERR("no more space left for node string\n");
 		return -1;
 	}
-	if(update_node_list(rlist) < 0) {
-		LM_ERR("cannot update node_list\n");
-		return -1;
+	memcpy(buf, node->orig_uri.s, node->orig_uri.len);
+	return node->orig_uri.len;
+}
+
+/* builds the body of a notification message from the list of servers 
+ * the result will look something like:
+ * sip:host1:port1;param1=value1\r\n
+ * sip:host2:port2;param2=value2\r\n
+ * sip:host3:port3;param3=value3
+ */
+str* build_notification_body() {
+	/* the length of the current line describing the server */
+	int slen;
+	/* the current length of the body */
+	int clen = 0;
+	dmq_node_t* cur_node = NULL;
+	str* body;
+	body = pkg_malloc(sizeof(str));
+	memset(body, 0, sizeof(str));
+	/* we allocate a chunk of data for the body */
+	body->len = NBODY_LEN;
+	body->s = pkg_malloc(body->len);
+	/* we add each server to the body - each on a different line */
+	lock_get(&node_list->lock);
+	cur_node = node_list->nodes;
+	while(cur_node) {
+		LM_DBG("body_len = %d - clen = %d\n", body->len, clen);
+		/* body->len - clen - 2 bytes left to write - including the \r\n */
+		slen = build_node_str(cur_node, body->s + clen, body->len - clen - 2);
+		if(slen < 0) {
+			LM_ERR("cannot build_node_string\n");
+			goto error;
+		}
+		clen += slen;
+		body->s[clen++] = '\r';
+		body->s[clen++] = '\n';
+		cur_node = cur_node->next;
 	}
-	return 0;
+	lock_release(&node_list->lock);
+	body->len = clen;
+	return body;
+error:
+	pkg_free(body->s);
+	pkg_free(body);
+	return NULL;
+}
+
+int request_initial_nodelist() {
+	str* body = build_notification_body();
+	int ret;
+	ret = send_dmq_message(&dmq_notification_peer, body);
+	pkg_free(body->s);
+	pkg_free(body);
+	return ret;
 }

+ 9 - 2
modules_k/dmq/notification_peer.h

@@ -1,6 +1,13 @@
 #include "dmq.h"
 #include "dmqnode.h"
+#include "peer.h"
+#include "../../parser/msg_parser.h"
+#include "../../parser/parse_content.h"
+#include "../../ut.h"
 
 int add_notification_peer();
-int dmq_notification_callback(struct sip_msg* msg);
-dmq_node_list_t* extract_node_list(struct sip_msg* msg);
+int dmq_notification_callback(struct sip_msg* msg, peer_reponse_t* resp);
+int extract_node_list(dmq_node_list_t* update_list, struct sip_msg* msg);
+str* build_notification_body();
+int build_node_str(dmq_node_t* node, char* buf, int buflen);
+int request_initial_nodelist();

+ 0 - 12
modules_k/dmq/peer.c

@@ -36,18 +36,6 @@ void add_peer(dmq_peer_list_t* peer_list, dmq_peer_t* peer) {
 	peer_list->peers = new_peer;
 }
 
-int register_dmq_peer(dmq_peer_t* peer) {
-	lock_get(&peer_list->lock);
-	if(search_peer_list(peer_list, peer)) {
-		LM_ERR("peer already exists: %.*s %.*s\n", peer->peer_id.len, peer->peer_id.s,
-		       peer->description.len, peer->description.s);
-		return -1;
-	}
-	add_peer(peer_list, peer);
-	lock_release(&peer_list->lock);
-	return 0;
-}
-
 dmq_peer_t* find_peer(str peer_id) {
 	dmq_peer_t foo_peer;
 	foo_peer.peer_id = peer_id;

+ 7 - 2
modules_k/dmq/peer.h

@@ -9,7 +9,12 @@
 #include "../../mem/shm_mem.h"
 #include "../../parser/msg_parser.h"
 
-typedef int(*peer_callback_t)(struct sip_msg*);
+typedef struct peer_response {
+	int resp_code;
+	str body;
+} peer_reponse_t;
+
+typedef int(*peer_callback_t)(struct sip_msg*, peer_reponse_t* resp);
 
 typedef struct dmq_peer {
 	str peer_id;
@@ -30,7 +35,7 @@ dmq_peer_list_t* init_peer_list();
 dmq_peer_t* search_peer_list(dmq_peer_list_t* peer_list, dmq_peer_t* peer);
 typedef int (*register_dmq_peer_t)(dmq_peer_t*);
 
-int register_dmq_peer(dmq_peer_t* peer);
+void add_peer(dmq_peer_list_t* peer_list, dmq_peer_t* peer);
 dmq_peer_t* find_peer(str peer_id);
 
 

+ 3 - 1
modules_k/dmq/worker.c

@@ -1,9 +1,11 @@
 #include "dmq.h"
+#include "peer.h"
 #include "worker.h"
 
 void worker_loop(int id) {
 	dmq_worker_t* worker = &workers[id];
 	dmq_job_t* current_job;
+	peer_reponse_t peer_response;
 	int ret_value;
 	for(;;) {
 		LM_DBG("dmq_worker [%d %d] getting lock\n", id, my_pid());
@@ -14,7 +16,7 @@ void worker_loop(int id) {
 			current_job = job_queue_pop(worker->queue);
 			/* job_queue_pop might return NULL if queue is empty */
 			if(current_job) {
-				ret_value = current_job->f(current_job->msg);
+				ret_value = current_job->f(current_job->msg, &peer_response);
 				if(ret_value < 0) {
 					LM_ERR("running job failed\n");
 				}