First pass at handling responses properly for retransmissions

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@3036 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Mark Spencer 2004-05-21 06:05:20 +00:00
parent 93da37619a
commit ad67680ed3
1 changed files with 74 additions and 3 deletions

View File

@ -280,6 +280,16 @@ struct mgcp_message {
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 @@ static struct mgcp_gateway {
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 @@ static int __mgcp_xmit(struct mgcp_gateway *gw, char *data, int len)
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 @@ static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp
{
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 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req,
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 @@ static int mgcpsock_read(int *id, int fd, short events, void *ignore)
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 @@ static int mgcpsock_read(int *id, int fd, short events, void *ignore)
/* 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;