[Asterisk-cvs] asterisk/channels chan_mgcp.c,1.50,1.51

markster at lists.digium.com markster at lists.digium.com
Fri May 21 01:52:25 CDT 2004


Update of /usr/cvsroot/asterisk/channels
In directory mongoose.digium.com:/tmp/cvs-serv10186/channels

Modified Files:
	chan_mgcp.c 
Log Message:
First pass at handling responses properly for retransmissions


Index: chan_mgcp.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_mgcp.c,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -d -r1.50 -r1.51
--- chan_mgcp.c	20 May 2004 16:30:10 -0000	1.50
+++ chan_mgcp.c	21 May 2004 06:05:20 -0000	1.51
@@ -280,6 +280,16 @@
 	unsigned char buf[0];
 };
 
+#define RESPONSE_TIMEOUT 30	/* in seconds */
+
+struct mgcp_response {
+	time_t whensent;
+	int len;
+	int seqno;
+	struct mgcp_response *next;
+	unsigned char buf[0];
+};
+
 #define MAX_SUBS 2
 
 #define SUB_REAL 0
@@ -405,6 +415,7 @@
 	ast_mutex_t msgs_lock;     /* SC: queue lock */  
     int retransid;             /* SC: retrans timer id */
     int delme;                 /* SC: needed for reload */
+	struct mgcp_response *responses;
 	struct mgcp_gateway *next;
 } *gateways;
 
@@ -478,6 +489,19 @@
 	return res;
 }
 
+static int resend_response(struct mgcp_subchannel *sub, struct mgcp_response *resp)
+{
+    struct mgcp_endpoint *p = sub->parent;
+	int res;
+	if (mgcpdebug) {
+		ast_verbose("Retransmitting:\n%s\n to %s:%d\n", resp->buf, inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
+    }
+	res = __mgcp_xmit(p->parent, resp->buf, resp->len);
+	if (res > 0)
+		res = 0;
+	return res;
+}
+
 static int send_response(struct mgcp_subchannel *sub, struct mgcp_request *req)
 {
     struct mgcp_endpoint *p = sub->parent;
@@ -1774,7 +1798,20 @@
 {
 	struct mgcp_request resp;
     struct mgcp_endpoint *p = sub->parent;
+	struct mgcp_response *mgr;
 	respprep(&resp, p, msg, req, msgrest);
+	mgr = malloc(sizeof(struct mgcp_response) + resp.len + 1);
+	if (mgr) {
+		/* Store MGCP response in case we have to retransmit */
+		memset(mgr, 0, sizeof(struct mgcp_response));
+		sscanf(req->identifier, "%d", &mgr->seqno);
+		time(&mgr->whensent);
+		mgr->len = resp.len;
+		memcpy(mgr->buf, resp.data, resp.len);
+		mgr->buf[resp.len] = '\0';
+		mgr->next = p->parent->responses;
+		p->parent->responses = mgr->next;
+	}
 	return send_response(sub, &resp);
 }
 
@@ -3036,6 +3073,38 @@
 	return 0;
 }
 
+static int find_and_retrans(struct mgcp_subchannel *sub, struct mgcp_request *req)
+{
+	int seqno=0;
+	time_t now;
+	struct mgcp_response *prev = NULL, *cur, *next, *answer=NULL;
+	time(&now);
+	if (sscanf(req->identifier, "%d", &seqno) != 1) 
+		seqno = 0;
+	cur = sub->parent->parent->responses;
+	while(cur) {
+		next = cur->next;
+		if (now - cur->whensent > RESPONSE_TIMEOUT) {
+			/* Delete this entry */
+			if (prev)
+				prev->next = next;
+			else
+				sub->parent->parent->responses = next;
+			free(cur);
+		} else {
+			if (seqno == cur->seqno)
+				answer = cur;
+			prev = cur;
+		}
+		cur = next;
+	}
+	if (answer) {
+		resend_response(sub, answer);
+		return 1;
+	}
+	return 0;
+}
+
 static int mgcpsock_read(int *id, int fd, short events, void *ignore)
 {
 	struct mgcp_request req;
@@ -3079,7 +3148,7 @@
             ast_mutex_lock(&gw->msgs_lock);
             for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
                 if (cur->seqno == ident) {
-                    ast_log(LOG_DEBUG, "Got response back on tansaction %d\n", ident);
+                    ast_log(LOG_DEBUG, "Got response back on transaction %d\n", ident);
                     if (prev)
                         prev->next = cur->next;
                     else 
@@ -3115,8 +3184,10 @@
 		/* Process request, with iflock held */
 		sub = find_subchannel(req.endpoint, 0, &sin);
 		if (sub) {
-            /* pass the request off to the currently mastering subchannel */
-			handle_request(sub, &req, &sin);
+			/* look first to find a matching response in the queue */
+			if (!find_and_retrans(sub, &req))
+	            /* pass the request off to the currently mastering subchannel */
+				handle_request(sub, &req, &sin);
 		}
 	}
 	return 1;




More information about the svn-commits mailing list