ソースを参照

implemented send/bcast functions

Marius Bucur 14 年 前
コミット
f403eea587

+ 34 - 8
modules_k/dmq/dmq.c

@@ -48,6 +48,7 @@
 #include "../../lib/kmi/mi.h"
 #include "../../lib/kcore/hash_func.h"
 #include "dmq.h"
+#include "dmq_funcs.h"
 #include "peer.h"
 #include "bind_dmq.h"
 #include "worker.h"
@@ -71,6 +72,7 @@ struct sip_uri dmq_server_uri;
 
 str dmq_notification_address = {0, 0};
 struct sip_uri dmq_notification_uri;
+int ping_interval = 4;
 
 /* TM bind */
 struct tm_binds tmb;
@@ -84,7 +86,7 @@ dmq_peer_list_t* peer_list;
 /* the list of dmq servers */
 dmq_node_list_t* node_list;
 // the dmq module is a peer itself for receiving notifications regarding nodes
-dmq_peer_t dmq_notification_peer;
+dmq_peer_t* dmq_notification_peer;
 
 /** module functions */
 static int mod_init(void);
@@ -103,6 +105,7 @@ static cmd_export_t cmds[] = {
 
 static param_export_t params[] = {
 	{"num_workers", INT_PARAM, &num_workers},
+	{"ping_interval", INT_PARAM, &ping_interval},
 	{"server_address", STR_PARAM, &dmq_server_address.s},
 	{"notification_address", STR_PARAM, &dmq_notification_address.s},
 	{0, 0, 0}
@@ -177,9 +180,20 @@ static int mod_init(void) {
 		return -1;
 	}
 	
-	/* add first dmq peer - the dmq module itself to receive peer notify messages */
+	/**
+         * add the dmq notification peer.
+	 * the dmq is a peer itself so that it can receive node notifications
+	 */
+	add_notification_peer();
 	
 	startup_time = (int) time(NULL);
+	
+	/**
+	 * add the ping timer
+	 * it pings the servers once in a while so that we know which failed
+	 */
+	register_timer(ping_servers, 0, ping_interval);
+	
 	return 0;
 }
 
@@ -204,11 +218,20 @@ static int child_init(int rank) {
 				workers[i].pid = newpid;
 			}
 		}
-		/**
-		 * add the dmq notification peer.
-		 * the dmq is a peer itself so that it can receive node notifications
+		/* notification_node - the node from which the Kamailio instance
+		 * gets the server list on startup.
+		 * the address is given as a module parameter in dmq_notification_address
+		 * the module MUST have this parameter if the Kamailio instance is not
+		 * a master in this architecture
 		 */
-		add_notification_peer();
+		if(dmq_notification_address.s) {
+			notification_node = add_server_and_notify(&dmq_notification_address);
+			if(!notification_node) {
+				LM_ERR("cannot retrieve initial nodelist from %.*s\n",
+				       STR_FMT(&dmq_notification_address));
+				return -1;
+			}
+		}
 		return 0;
 	}
 	if(rank == PROC_INIT || rank == PROC_TCP_MAIN) {
@@ -234,16 +257,19 @@ static int handle_dmq_fixup(void** param, int param_no) {
 static int parse_server_address(str* uri, struct sip_uri* parsed_uri) {
 	if(!uri->s) {
 		LM_ERR("server address missing\n");
-		return -1;
+		goto empty;
 	}
 	uri->len = strlen(uri->s);
 	if(!uri->len) {
 		LM_ERR("empty server address\n");
-		return -1;
+		goto empty;
 	}
 	if(parse_uri(uri->s, uri->len, parsed_uri) < 0) {
 		LM_ERR("error parsing server address\n");
 		return -1;
 	}
 	return 0;
+empty:
+	uri->s = NULL;
+	return 0;
 }

+ 6 - 1
modules_k/dmq/dmq.h

@@ -16,7 +16,7 @@
 
 extern int num_workers;
 extern dmq_worker_t* workers;
-extern dmq_peer_t dmq_notification_peer;
+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;
@@ -28,6 +28,11 @@ extern struct sip_uri dmq_notification_uri;
 extern struct tm_binds tmb;
 extern sl_api_t slb;
 
+extern str dmq_200_rpl;
+extern str dmq_400_rpl;
+extern str dmq_500_rpl;
+extern str dmq_404_rpl;
+
 static inline int dmq_load_api(dmq_api_t* api) {
 	bind_dmq_f binddmq;
 	binddmq = (bind_dmq_f)find_export("bind_dmq", 0, 0);

+ 84 - 16
modules_k/dmq/dmq_funcs.c

@@ -1,22 +1,33 @@
 #include "dmq_funcs.h"
+#include "notification_peer.h"
 
-int register_dmq_peer(dmq_peer_t* peer) {
+dmq_peer_t* register_dmq_peer(dmq_peer_t* peer) {
+	dmq_peer_t* new_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;
+		return NULL;
 	}
-	add_peer(peer_list, peer);
+	new_peer = add_peer(peer_list, peer);
 	lock_release(&peer_list->lock);
-	return 0;
+	return new_peer;
 }
 
-void dmq_tm_callback( struct cell *t, int type, struct tmcb_params *ps) {
-	LM_ERR("callback\n");
+void dmq_tm_callback(struct cell *t, int type, struct tmcb_params *ps) {
+	dmq_cback_param_t* cb_param = (dmq_cback_param_t*)(*ps->param);
+	LM_DBG("dmq_tm_callback start\n");
+	if(cb_param->resp_cback.f) {
+		if(cb_param->resp_cback.f(ps->rpl, ps->code, cb_param->node, cb_param->resp_cback.param) < 0) {
+			LM_ERR("error in response callback\n");
+		}
+	}
+	LM_DBG("dmq_tm_callback done\n");
+	shm_free_node(cb_param->node);
+	shm_free(cb_param);
 }
 
-int build_from_str(str* username, struct sip_uri* uri, str* from) {
+int build_uri_str(str* username, struct sip_uri* uri, str* from) {
 	/* sip:user@host:port */
 	int from_len = username->len + uri->host.len + uri->port.len + 10;
 	if(!uri->host.s || !uri->host.len) {
@@ -51,19 +62,58 @@ int build_from_str(str* username, struct sip_uri* uri, str* from) {
 	return 0;
 }
 
-int send_dmq_message(dmq_peer_t* peer, str* body, dmq_node_t* node) {
+/* broadcast a dmq message
+ * peer - the peer structure on behalf of which we are sending
+ * body - the body of the message
+ * except - we do not send the message to this node
+ * resp_cback - a response callback that gets called when the transaction is complete
+ */
+int bcast_dmq_message(dmq_peer_t* peer, str* body, dmq_node_t* except, dmq_resp_cback_t* resp_cback) {
+	dmq_node_t* node;
+	
+	lock_get(&node_list->lock);
+	node = node_list->nodes;
+	while(node) {
+		if((except && cmp_dmq_node(node, except)) || node->local) {
+			node = node->next;
+			continue;
+		}
+		if(send_dmq_message(peer, body, node, resp_cback) < 0) {
+			LM_ERR("error sending dmq message\n");
+			goto error;
+		}
+		node = node->next;
+	}
+	lock_release(&node_list->lock);
+	return 0;
+error:
+	lock_release(&node_list->lock);
+	return -1;
+}
+
+/* send a dmq message
+ * peer - the peer structure on behalf of which we are sending
+ * body - the body of the message
+ * node - we send the message to this node
+ * resp_cback - a response callback that gets called when the transaction is complete
+ */
+int send_dmq_message(dmq_peer_t* peer, str* body, dmq_node_t* node, dmq_resp_cback_t* resp_cback) {
 	uac_req_t uac_r;
 	str str_hdr = {0, 0};
-	/* TODO - do not hardcode these - just for tesing purposes */
 	str from, to, req_uri;
-	void *cb_param = NULL;
-	int result;
+	dmq_cback_param_t* cb_param = NULL;
+	int result = 0;
+	
+	cb_param = shm_malloc(sizeof(*cb_param));
+	memset(cb_param, 0, sizeof(*cb_param));
+	cb_param->resp_cback = *resp_cback;
+	cb_param->node = shm_dup_node(node);
 	
-	if(build_from_str(&peer->peer_id, &dmq_server_uri, &from) < 0) {
-		LM_ERR("error building from string\n");
+	if(build_uri_str(&peer->peer_id, &dmq_server_uri, &from) < 0) {
+		LM_ERR("error building from string [username %.*s]\n", STR_FMT(&peer->peer_id));
 		return -1;
 	}
-	if(build_from_str(&peer->peer_id, &node->uri, &to) < 0) {
+	if(build_uri_str(&peer->peer_id, &node->uri, &to) < 0) {
 		LM_ERR("error building to string\n");
 		return -1;
 	}
@@ -74,10 +124,28 @@ int send_dmq_message(dmq_peer_t* peer, str* body, dmq_node_t* node) {
 	result = tmb.t_request(&uac_r, &req_uri,
 			       &to, &from,
 			       NULL);
-	if(result < 0)
-	{
+	if(result < 0) {
 		LM_ERR("error in tmb.t_request_within\n");
 		return -1;
 	}
 	return 0;
+}
+
+/* pings the servers in the nodelist
+ * if the server does not reply to the ping, it is removed from the list
+ * the ping messages are actualy notification requests
+ * this way the ping will have two uses:
+ *   - checks if the servers in the list are up and running
+ *   - updates the list of servers from the other nodes
+ */
+void ping_servers(unsigned int ticks,void *param) {
+	str* body = build_notification_body();
+	int ret;
+	LM_DBG("ping_servers\n");
+	ret = bcast_dmq_message(dmq_notification_peer, body, notification_node, &notification_callback);
+	pkg_free(body->s);
+	pkg_free(body);
+	if(ret < 0) {
+		LM_ERR("error broadcasting message\n");
+	}
 }

+ 16 - 3
modules_k/dmq/dmq_funcs.h

@@ -1,14 +1,27 @@
 #ifndef DMQ_FUNCS_H
 #define DMQ_FUNCS_H
 
+#include "../../str.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, dmq_node_t* node);
+void ping_servers(unsigned int ticks,void *param);
+
+typedef struct dmq_resp_cback {
+	int (*f)(struct sip_msg* msg, int code, dmq_node_t* node, void* param);
+	void* param;
+} dmq_resp_cback_t;
+
+typedef struct dmq_cback_param {
+	dmq_resp_cback_t resp_cback;
+	dmq_node_t* node;
+} dmq_cback_param_t;
+
+dmq_peer_t* register_dmq_peer(dmq_peer_t* peer);
+int send_dmq_message(dmq_peer_t* peer, str* body, dmq_node_t* node, dmq_resp_cback_t* resp_cback);
+int bcast_dmq_message(dmq_peer_t* peer, str* body, dmq_node_t* except, dmq_resp_cback_t* resp_cback);
 
 #endif

+ 61 - 1
modules_k/dmq/dmqnode.c

@@ -12,6 +12,65 @@ dmq_node_list_t* init_dmq_node_list() {
 	return node_list;
 }
 
+inline int cmp_dmq_node(dmq_node_t* node, dmq_node_t* cmpnode) {
+	if(!node || !cmpnode) {
+		LM_ERR("cmp_dmq_node - null node received\n");
+		return -1;
+	}
+	return STR_EQ(node->uri.host, cmpnode->uri.host) &&
+	       STR_EQ(node->uri.port, cmpnode->uri.port);
+}
+
+inline dmq_node_t* find_dmq_node(dmq_node_list_t* list, dmq_node_t* node) {
+	dmq_node_t* cur = list->nodes;
+	while(cur) {
+		if(cmp_dmq_node(cur, node)) {
+			return cur;
+		}
+		cur = cur->next;
+	}
+	return NULL;
+}
+
+inline dmq_node_t* shm_dup_node(dmq_node_t* node) {
+	dmq_node_t* newnode = shm_malloc(sizeof(dmq_node_t));
+	memcpy(newnode, node, sizeof(dmq_node_t));
+	shm_str_dup(&newnode->orig_uri, &node->orig_uri);
+	if(parse_uri(newnode->orig_uri.s, newnode->orig_uri.len, &newnode->uri) < 0) {
+		LM_ERR("error in parsing node uri\n");
+		goto error;
+	}
+	return newnode;
+error:
+	shm_free(newnode->orig_uri.s);
+	shm_free(newnode);
+	return NULL;
+}
+
+inline void shm_free_node(dmq_node_t* node) {
+	shm_free(node->orig_uri.s);
+	shm_free(node);
+}
+
+inline int del_dmq_node(dmq_node_list_t* list, dmq_node_t* node) {
+	dmq_node_t *cur, **prev;
+	lock_get(&list->lock);
+	cur = list->nodes;
+	prev = &list->nodes;
+	while(cur) {
+		if(cmp_dmq_node(cur, node)) {
+			*prev = cur->next;
+			shm_free_node(cur);
+			lock_release(&list->lock);
+			return 1;
+		}
+		prev = &cur->next;
+		cur = cur->next;
+	}
+	lock_release(&list->lock);
+	return 0;
+}
+
 inline dmq_node_t* add_dmq_node(dmq_node_list_t* list, str* uri) {
 	dmq_node_t* newnode = shm_malloc(sizeof(dmq_node_t));
 	memset(newnode, 0, sizeof(dmq_node_t));
@@ -27,6 +86,7 @@ inline dmq_node_t* add_dmq_node(dmq_node_list_t* list, str* uri) {
 	lock_release(&list->lock);
 	return newnode;
 error:
+	shm_free(newnode->orig_uri.s);
 	shm_free(newnode);
-	return 0;
+	return NULL;
 }

+ 14 - 8
modules_k/dmq/dmqnode.h

@@ -12,22 +12,28 @@
 #define NBODY_LEN 1024
 
 typedef struct dmq_node {
-	str orig_uri;
-	struct sip_uri uri;
-	int status;
-	int last_notification;
-	struct dmq_node* next;
+	int local; /* local type set means the dmq dmqnode == self */
+	str orig_uri; /* original uri string - e.g. sip:127.0.0.1:5060;passive=true */
+	struct sip_uri uri; /* parsed uri string */
+	int status; /* reserved - maybe something like active,timeout,disabled */
+	int last_notification; /* last notificatino receied from the node */
+	struct dmq_node* next; /* pointer to the next struct dmq_node */
 } dmq_node_t;
 
 typedef struct dmq_node_list {
-	gen_lock_t lock;
-	struct dmq_node* nodes;
-	int count;
+	gen_lock_t lock; /* lock for the list - must acquire before manipulating it */
+	struct dmq_node* nodes; /* the nodes in the list */
+	int count; /* the number of nodes in the list */
 } dmq_node_list_t;
 
 dmq_node_list_t* init_dmq_node_list();
 int update_node_list(dmq_node_list_t* remote_list);
 dmq_node_t* add_dmq_node(dmq_node_list_t* list, str* uri);
+dmq_node_t* find_dmq_node(dmq_node_list_t* list, dmq_node_t* node);
+int del_dmq_node(dmq_node_list_t* list, dmq_node_t* node);
+int cmp_dmq_node(dmq_node_t* node, dmq_node_t* cmpnode);
+dmq_node_t* shm_dup_node(dmq_node_t* node);
+void shm_free_node(dmq_node_t* node);
 
 extern dmq_node_t* self_node;
 extern dmq_node_t* notification_node;	

+ 17 - 9
modules_k/dmq/message.c

@@ -1,5 +1,6 @@
 #include "../../parser/parse_to.h"
-#include "../../parser/parse_uri.h" 
+#include "../../parser/parse_uri.h"
+#include "../../sip_msg_clone.h"
 #include "../../parser/parse_content.h"
 #include "../../parser/parse_from.h"
 #include "../../ut.h"
@@ -8,16 +9,18 @@
 #include "peer.h"
 #include "message.h"
 
-static str dmq_200_rpl  = str_init("OK");
-static str dmq_400_rpl  = str_init("Bad request");
-static str dmq_500_rpl  = str_init("Server Internal Error");
-static str dmq_404_rpl  = str_init("User Not Found");
+str dmq_200_rpl  = str_init("OK");
+str dmq_400_rpl  = str_init("Bad request");
+str dmq_500_rpl  = str_init("Server Internal Error");
+str dmq_404_rpl  = str_init("User Not Found");
 
 int handle_dmq_message(struct sip_msg* msg, char* str1, char* str2) {
 	dmq_peer_t* peer;
+	struct sip_msg* cloned_msg = NULL;
+	int cloned_msg_len;
 	if ((parse_sip_msg_uri(msg) < 0) || (!msg->parsed_uri.user.s)) {
-			LM_ERR("cannot parse msg URI\n");
-			return -1;
+			LM_ERR("error parsing msg uri\n");
+			goto error;
 	}
 	LM_DBG("handle_dmq_message [%.*s %.*s] [%s %s]\n",
 	       msg->first_line.u.request.method.len, msg->first_line.u.request.method.s,
@@ -25,7 +28,7 @@ int handle_dmq_message(struct sip_msg* msg, char* str1, char* str2) {
 	       ZSW(str1), ZSW(str2));
 	/* the peer id is given as the userinfo part of the request URI */
 	peer = find_peer(msg->parsed_uri.user);
-	if(peer) {
+	if(!peer) {
 		LM_DBG("no peer found for %.*s\n", msg->parsed_uri.user.len, msg->parsed_uri.user.s);
 		if(slb.freply(msg, 404, &dmq_404_rpl) < 0)
 		{
@@ -35,7 +38,12 @@ int handle_dmq_message(struct sip_msg* msg, char* str1, char* str2) {
 		return 0;
 	}
 	LM_DBG("handle_dmq_message peer found: %.*s\n", msg->parsed_uri.user.len, msg->parsed_uri.user.s);
-	add_dmq_job(msg, peer);
+	cloned_msg = sip_msg_shm_clone(msg, &cloned_msg_len, 1);
+	if(!cloned_msg) {
+		LM_ERR("error cloning sip message\n");
+		goto error;
+	}
+	add_dmq_job(cloned_msg, peer);
 	return 0;
 error:
 	return -1;

+ 91 - 36
modules_k/dmq/notification_peer.c

@@ -1,13 +1,17 @@
 #include "notification_peer.h"
-#include "dmq_funcs.h"
+
+static str notification_content_type = str_init("text/plain");
+dmq_resp_cback_t notification_callback = {&notification_callback_f, 0};
 
 int add_notification_peer() {
-	dmq_notification_peer.callback = dmq_notification_callback;
-	dmq_notification_peer.description.s = "notification_peer";
-	dmq_notification_peer.description.len = 17;
-	dmq_notification_peer.peer_id.s = "notification_peer";
-	dmq_notification_peer.peer_id.len = 17;
-	if(register_dmq_peer(&dmq_notification_peer) < 0) {
+	dmq_peer_t not_peer;
+	not_peer.callback = dmq_notification_callback;
+	not_peer.description.s = "notification_peer";
+	not_peer.description.len = 17;
+	not_peer.peer_id.s = "notification_peer";
+	not_peer.peer_id.len = 17;
+	dmq_notification_peer = register_dmq_peer(&not_peer);
+	if(!dmq_notification_peer) {
 		LM_ERR("error in register_dmq_peer\n");
 		goto error;
 	}
@@ -17,20 +21,28 @@ int add_notification_peer() {
 		LM_ERR("error adding self node\n");
 		goto error;
 	}
-	/* add the notification server to the node list */
-	notification_node = add_dmq_node(node_list, &dmq_notification_address);
-	if(!notification_node) {
+	/* local node - only for self */
+	self_node->local = 1;
+	return 0;
+error:
+	return -1;
+}
+
+dmq_node_t* add_server_and_notify(str* server_address) {
+	/* add the notification server to the node list - if any */
+	dmq_node_t* node = add_dmq_node(node_list, server_address);
+	if(!node) {
 		LM_ERR("error adding notification node\n");
 		goto error;
 	}
-	/* initial notification request to receive the complete node list */
-	if(request_initial_nodelist() < 0) {
-		LM_ERR("error in request_initial_notification\n");
+	/* request initial list from the notification server */
+	if(request_nodelist(node) < 0) {
+		LM_ERR("error requesting initial nodelist\n");
 		goto error;
 	}
-	return 0;
+	return node;
 error:
-	return -1;
+	return NULL;
 }
 
 /**
@@ -50,7 +62,7 @@ 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;
+	dmq_node_t *cur = NULL;
 	char *tmp, *end, *match;
 	if(!msg->content_length) {
 		LM_ERR("no content length header found\n");
@@ -66,47 +78,78 @@ int extract_node_list(dmq_node_list_t* update_list, struct sip_msg* msg) {
 	tmp = body.s;
 	end = body.s + body.len;
 	
+	/* acquire big list lock */
+	lock_get(&update_list->lock);
 	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){
+		if(match) {
 			match++;
-		}else {
+		} 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;
+		tmp_uri.len = match - tmp - 1;
+		tmp = match;
 		shm_str_dup(&cur->orig_uri, &tmp_uri);
+		/* trim the \r, \n and \0's */
 		trim_r(cur->orig_uri);
-		
-		tmp = match;
-		
-		prev = cur;
+		if(parse_uri(cur->orig_uri.s, cur->orig_uri.len, &cur->uri) < 0) {
+			LM_ERR("cannot parse uri\n");
+			goto error;
+		}
+		if(!find_dmq_node(update_list, cur)) {
+			LM_DBG("found new node %.*s\n", STR_FMT(&cur->orig_uri));
+			cur->next = update_list->nodes;
+			update_list->nodes = cur;
+			update_list->count++;
+			total_nodes++;
+		} else {
+			shm_free(cur->orig_uri.s);
+			shm_free(cur);
+		}
 	}
-	lock_get(&update_list->lock);
-	first->next = update_list->nodes;
-	update_list->nodes = cur;
+	/* release big list lock */
 	lock_release(&update_list->lock);
 	return total_nodes;
+error:
+	lock_release(&update_list->lock);
+	shm_free(cur->orig_uri.s);
+	shm_free(cur);
+	return -1;
 }
 
 int dmq_notification_callback(struct sip_msg* msg, peer_reponse_t* resp) {
 	int nodes_recv;
+	str* response_body = NULL;
 	/* received dmqnode list */
-	LM_ERR("dmq triggered from dmq_notification_callback\n");
+	LM_DBG("dmq triggered from dmq_notification_callback\n");
+	/* parse the message headers */
+	if(parse_headers(msg, HDR_EOH_F, 0) < 0) {
+		LM_ERR("error parsing message headers\n");
+		goto error;
+	}
 	nodes_recv = extract_node_list(node_list, msg);
-	LM_DBG("received %d nodes\n", nodes_recv);
+	LM_DBG("received %d new nodes\n", nodes_recv);
+	response_body = build_notification_body();
+	resp->content_type = notification_content_type;
+	resp->reason = dmq_200_rpl;
+	resp->body = *response_body;
+	resp->resp_code = 200;
+	
+	/* if we received any new nodes tell about them to the others */
+	if(nodes_recv > 0) {
+		bcast_dmq_message(dmq_notification_peer, response_body, 0, &notification_callback);
+	}
+	LM_DBG("broadcasted message\n");
+	pkg_free(response_body);
 	return 0;
+error:
+	return -1;
 }
 
 int build_node_str(dmq_node_t* node, char* buf, int buflen) {
@@ -162,11 +205,23 @@ error:
 	return NULL;
 }
 
-int request_initial_nodelist() {
+int request_nodelist(dmq_node_t* node) {
 	str* body = build_notification_body();
 	int ret;
-	ret = send_dmq_message(&dmq_notification_peer, body, notification_node);
+	ret = send_dmq_message(dmq_notification_peer, body, node, &notification_callback);
 	pkg_free(body->s);
 	pkg_free(body);
 	return ret;
+}
+
+int notification_callback_f(struct sip_msg* msg, int code, dmq_node_t* node, void* param) {
+	int ret;
+	LM_DBG("notification_callback_f triggered [%p %d %p]\n", msg, code, param);
+	if(code == 408) {
+		/* deleting node - the server did not respond */
+		LM_ERR("deleting server %.*s because of failed request\n", STR_FMT(&node->orig_uri));
+		ret = del_dmq_node(node_list, node);
+		LM_DBG("del_dmq_node returned %d\n", ret);
+	}
+	return 0;
 }

+ 10 - 4
modules_k/dmq/notification_peer.h

@@ -1,13 +1,19 @@
-#include "dmq.h"
-#include "dmqnode.h"
-#include "peer.h"
 #include "../../parser/msg_parser.h"
 #include "../../parser/parse_content.h"
 #include "../../ut.h"
+#include "dmq.h"
+#include "dmqnode.h"
+#include "peer.h"
+#include "dmq_funcs.h"
 
 int add_notification_peer();
 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();
+int request_nodelist(dmq_node_t* node);
+dmq_node_t* add_server_and_notify(str* server_address);
+
+/* helper functions */
+extern int notification_callback_f(struct sip_msg* msg, int code, dmq_node_t* node, void* param);
+extern dmq_resp_cback_t notification_callback;

+ 2 - 1
modules_k/dmq/peer.c

@@ -22,7 +22,7 @@ dmq_peer_t* search_peer_list(dmq_peer_list_t* peer_list, dmq_peer_t* peer) {
 	return 0;
 }
 
-void add_peer(dmq_peer_list_t* peer_list, dmq_peer_t* peer) {
+dmq_peer_t* add_peer(dmq_peer_list_t* peer_list, dmq_peer_t* peer) {
 	dmq_peer_t* new_peer = shm_malloc(sizeof(dmq_peer_t));
 	*new_peer = *peer;
 	
@@ -34,6 +34,7 @@ void add_peer(dmq_peer_list_t* peer_list, dmq_peer_t* peer) {
 	
 	new_peer->next = peer_list->peers;
 	peer_list->peers = new_peer;
+	return new_peer;
 }
 
 dmq_peer_t* find_peer(str peer_id) {

+ 4 - 2
modules_k/dmq/peer.h

@@ -11,6 +11,8 @@
 
 typedef struct peer_response {
 	int resp_code;
+	str content_type;
+	str reason;
 	str body;
 } peer_reponse_t;
 
@@ -33,9 +35,9 @@ extern dmq_peer_list_t* peer_list;
 
 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*);
+typedef dmq_peer_t* (*register_dmq_peer_t)(dmq_peer_t*);
 
-void add_peer(dmq_peer_list_t* peer_list, dmq_peer_t* peer);
+dmq_peer_t* add_peer(dmq_peer_list_t* peer_list, dmq_peer_t* peer);
 dmq_peer_t* find_peer(str peer_id);
 
 

+ 62 - 1
modules_k/dmq/worker.c

@@ -1,6 +1,45 @@
 #include "dmq.h"
 #include "peer.h"
 #include "worker.h"
+#include "../../data_lump_rpl.h"
+#include "../../mod_fix.h"
+
+/* set the body of a response */
+static int set_reply_body(struct sip_msg* msg, str* body, str* content_type)
+{
+	char* buf;
+	int len;
+	int value_len;
+	str nb = *body;
+	str nc = *content_type;
+
+	/* add content-type */
+	value_len = nc.len;
+	len=sizeof("Content-Type: ") - 1 + value_len + CRLF_LEN;
+	buf=pkg_malloc(sizeof(char)*(len));
+
+	if (buf==0) {
+		LM_ERR("out of pkg memory\n");
+		return -1;
+	}
+	memcpy(buf, "Content-Type: ", sizeof("Content-Type: ") - 1);
+	memcpy(buf+sizeof("Content-Type: ") - 1, nc.s, value_len);
+	memcpy(buf+sizeof("Content-Type: ") - 1 + value_len, CRLF, CRLF_LEN);
+	if (add_lump_rpl(msg, buf, len, LUMP_RPL_HDR) == 0) {
+		LM_ERR("failed to insert content-type lump\n");
+		pkg_free(buf);
+		return -1;
+	}
+	pkg_free(buf);
+
+	/* add body */
+	if (add_lump_rpl(msg, nb.s, nb.len, LUMP_RPL_BODY) == 0) {
+		LM_ERR("cannot add body lump\n");
+		return -1;
+	}
+		
+	return 1;
+}
 
 void worker_loop(int id) {
 	dmq_worker_t* worker = &workers[id];
@@ -13,6 +52,8 @@ void worker_loop(int id) {
 		LM_DBG("dmq_worker [%d %d] lock acquired\n", id, my_pid());
 		/* multiple lock_release calls might be performed, so remove from queue until empty */
 		do {
+			/* fill the response with 0's */
+			memset(&peer_response, 0, sizeof(peer_response));
 			current_job = job_queue_pop(worker->queue);
 			/* job_queue_pop might return NULL if queue is empty */
 			if(current_job) {
@@ -20,6 +61,26 @@ void worker_loop(int id) {
 				if(ret_value < 0) {
 					LM_ERR("running job failed\n");
 				}
+				/* add the body to the reply */
+				if(peer_response.body.s) {
+					if(set_reply_body(current_job->msg, &peer_response.body, &peer_response.content_type) < 0) {
+						LM_ERR("error adding lumps\n");
+						continue;
+					}
+				}
+				/* send the reply */
+				if(slb.freply(current_job->msg, peer_response.resp_code, &peer_response.reason) < 0)
+				{
+					LM_ERR("error sending reply\n");
+				}
+				
+				/* if body given, free the lumps and free the body */
+				if(peer_response.body.s) {
+					del_nonshm_lump_rpl(&current_job->msg->reply_lump);
+					pkg_free(peer_response.body.s);
+				}
+				LM_DBG("sent reply\n");
+				shm_free(current_job->msg);
 				shm_free(current_job);
 				worker->jobs_processed++;
 			}
@@ -35,7 +96,7 @@ int add_dmq_job(struct sip_msg* msg, dmq_peer_t* peer) {
 	new_job.msg = msg;
 	new_job.orig_peer = peer;
 	if(!num_workers) {
-		LM_ERR("error in add_dmq_job no workers spawned\n");
+		LM_ERR("error in add_dmq_job: no workers spawned\n");
 		return -1;
 	}
 	/* initialize the worker with the first one */