Thu Oct 9 06:44:49 2008

Asterisk developer's documentation


chan_mgcp.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2006, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief Implementation of Media Gateway Control Protocol
00022  * 
00023  * \par See also
00024  * \arg \ref Config_mgcp
00025  *
00026  * \ingroup channel_drivers
00027  */
00028 
00029 /* FO: Changes
00030  * -- add distinctive ring signalling (part of RFC 3660)
00031  */
00032 
00033 /* JS: Changes
00034    -- add support for the wildcard endpoint
00035    -- seteable wildcard with wcardep on mgcp.conf
00036    -- added package indicator on RQNT, i.e "dl" --> "L/dl"
00037    -- removed MDCX just before DLCX, do we need this ?
00038 */
00039 
00040 /* JS: TODO
00041    -- reload for wildcard endpoint probably buggy
00042    -- when hf is notified we're sending CRCX after MDCX, without waiting for
00043       OK on the MDCX which fails on Cisco IAD 24XX
00044    -- honour codec order, by now the lowest codec number in "allow" is the prefered
00045 */
00046 
00047 /* SC: Changes
00048    -- packet retransmit mechanism (simplistic)
00049    -- per endpoint/subchannel mgcp command sequencing. 
00050    -- better transaction handling
00051    -- fixed some mem leaks
00052    -- run-time configuration reload 
00053    -- distinguish CA and GW default MGCP ports
00054    -- prevent clipping of DTMF tones in an established call
00055    -- fixed a few crash scenarios in 3-way
00056    -- fix for a few cases where asterisk and MGW end-up in conflicting ep states 
00057    -- enclose numeric IP in [] for outgoing requests
00058 */
00059 
00060 /* SC: TODO
00061    -- piggyback support
00062    -- responseAck support
00063    -- enhance retransmit mechanism (RTO calc. etc.)
00064    -- embedded command support
00065 */
00066 
00067 /* FS: Changes
00068    -- fixed reload_config() / do_monitor to stay responsive during reloads
00069 */
00070 
00071 #include <stdio.h>
00072 #include <string.h>
00073 #include <unistd.h>
00074 #include <sys/socket.h>
00075 #include <sys/ioctl.h>
00076 #include <net/if.h>
00077 #include <errno.h>
00078 #include <stdlib.h>
00079 #include <fcntl.h>
00080 #include <netdb.h>
00081 #include <sys/signal.h>
00082 #include <signal.h>
00083 #include <netinet/in.h>
00084 #include <netinet/in_systm.h>
00085 #include <netinet/ip.h>
00086 #include <arpa/inet.h>
00087 #include <ctype.h>
00088 
00089 #include "asterisk.h"
00090 
00091 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 53045 $")
00092 
00093 #include "asterisk/lock.h"
00094 #include "asterisk/channel.h"
00095 #include "asterisk/config.h"
00096 #include "asterisk/logger.h"
00097 #include "asterisk/module.h"
00098 #include "asterisk/pbx.h"
00099 #include "asterisk/options.h"
00100 #include "asterisk/lock.h"
00101 #include "asterisk/sched.h"
00102 #include "asterisk/io.h"
00103 #include "asterisk/rtp.h"
00104 #include "asterisk/acl.h"
00105 #include "asterisk/callerid.h"
00106 #include "asterisk/cli.h"
00107 #include "asterisk/say.h"
00108 #include "asterisk/cdr.h"
00109 #include "asterisk/astdb.h"
00110 #include "asterisk/features.h"
00111 #include "asterisk/app.h"
00112 #include "asterisk/musiconhold.h"
00113 #include "asterisk/utils.h"
00114 #include "asterisk/causes.h"
00115 #include "asterisk/dsp.h"
00116 
00117 #ifndef IPTOS_MINCOST
00118 #define IPTOS_MINCOST 0x02
00119 #endif
00120 
00121 /*
00122  * Define to work around buggy dlink MGCP phone firmware which
00123  * appears not to know that "rt" is part of the "G" package.
00124  */
00125 /* #define DLINK_BUGGY_FIRMWARE  */
00126 
00127 #define MGCPDUMPER
00128 #define DEFAULT_EXPIRY  120
00129 #define MAX_EXPIRY   3600
00130 #define CANREINVITE  1
00131 
00132 #ifndef INADDR_NONE
00133 #define INADDR_NONE (in_addr_t)(-1)
00134 #endif
00135 
00136 static const char desc[] = "Media Gateway Control Protocol (MGCP)";
00137 static const char type[] = "MGCP";
00138 static const char tdesc[] = "Media Gateway Control Protocol (MGCP)";
00139 static const char config[] = "mgcp.conf";
00140 
00141 #define MGCP_DTMF_RFC2833  (1 << 0)
00142 #define MGCP_DTMF_INBAND   (1 << 1)
00143 #define MGCP_DTMF_HYBRID   (1 << 2)
00144 
00145 #define DEFAULT_MGCP_GW_PORT  2427 /* From RFC 2705 */
00146 #define DEFAULT_MGCP_CA_PORT  2727 /* From RFC 2705 */
00147 #define MGCP_MAX_PACKET    1500 /* Also from RFC 2543, should sub headers tho */
00148 #define DEFAULT_RETRANS    1000 /* How frequently to retransmit */
00149 #define MAX_RETRANS     5    /* Try only 5 times for retransmissions */
00150 
00151 /* MGCP rtp stream modes */
00152 #define MGCP_CX_SENDONLY   0
00153 #define MGCP_CX_RECVONLY   1
00154 #define MGCP_CX_SENDRECV   2
00155 #define MGCP_CX_CONF    3
00156 #define MGCP_CX_CONFERENCE 3
00157 #define MGCP_CX_MUTE    4
00158 #define MGCP_CX_INACTIVE   4
00159 
00160 static char *mgcp_cxmodes[] = {
00161    "sendonly",
00162    "recvonly",
00163    "sendrecv",
00164    "confrnce",
00165    "inactive"
00166 };
00167 
00168 /* SC: MGCP commands */
00169 #define MGCP_CMD_EPCF 0
00170 #define MGCP_CMD_CRCX 1
00171 #define MGCP_CMD_MDCX 2
00172 #define MGCP_CMD_DLCX 3
00173 #define MGCP_CMD_RQNT 4
00174 #define MGCP_CMD_NTFY 5
00175 #define MGCP_CMD_AUEP 6
00176 #define MGCP_CMD_AUCX 7
00177 #define MGCP_CMD_RSIP 8
00178 
00179 static char context[AST_MAX_EXTENSION] = "default";
00180 
00181 static char language[MAX_LANGUAGE] = "";
00182 static char musicclass[MAX_MUSICCLASS] = "";
00183 static char cid_num[AST_MAX_EXTENSION] = "";
00184 static char cid_name[AST_MAX_EXTENSION] = "";
00185 
00186 static int dtmfmode = 0;
00187 static int nat = 0;
00188 
00189 /* Not used. Dosn't hurt for us to always send cid  */
00190 /* to the mgcp box. */
00191 /*static int use_callerid = 1;*/
00192 /*static int cur_signalling = -1;*/
00193 
00194 /*static unsigned int cur_group = 0;*/
00195 static ast_group_t cur_callergroup = 0;
00196 static ast_group_t cur_pickupgroup = 0;
00197 
00198 /* XXX Is this needed? */
00199 /*     Doesn't look like the dsp stuff for */
00200 /*     dtmfmode is actually hooked up.   */
00201 /*static int relaxdtmf = 0;*/
00202 
00203 static int tos = 0;
00204 
00205 static int immediate = 0;
00206 
00207 static int callwaiting = 0;
00208 
00209 /* Not used. Dosn't hurt for us to always send cid  */
00210 /* to the mgcp box. */
00211 /*static int callwaitingcallerid = 0;*/
00212 
00213 /*static int hidecallerid = 0;*/
00214 
00215 static int callreturn = 0;
00216 
00217 static int slowsequence = 0;
00218 
00219 static int threewaycalling = 0;
00220 
00221 /* This is for flashhook transfers */
00222 static int transfer = 0;
00223 
00224 static int cancallforward = 0;
00225 
00226 static int singlepath = 0;
00227 
00228 static int canreinvite = CANREINVITE;
00229 
00230 /*static int busycount = 3;*/
00231 
00232 /*static int callprogress = 0;*/
00233 
00234 static char accountcode[AST_MAX_ACCOUNT_CODE] = "";
00235 
00236 static char mailbox[AST_MAX_EXTENSION];
00237 
00238 static int amaflags = 0;
00239 
00240 static int adsi = 0;
00241 
00242 static int usecnt =0;
00243 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
00244 /* SC: transaction id should always be positive */
00245 static unsigned int oseq;
00246 
00247 /* Wait up to 16 seconds for first digit (FXO logic) */
00248 static int firstdigittimeout = 16000;
00249 
00250 /* How long to wait for following digits (FXO logic) */
00251 static int gendigittimeout = 8000;
00252 
00253 /* How long to wait for an extra digit, if there is an ambiguous match */
00254 static int matchdigittimeout = 3000;
00255 
00256 /* Protect the monitoring thread, so only one process can kill or start it, and not
00257    when it's doing something critical. */
00258 AST_MUTEX_DEFINE_STATIC(netlock);
00259 
00260 AST_MUTEX_DEFINE_STATIC(monlock);
00261 
00262 /* This is the thread for the monitor which checks for input on the channels
00263    which are not currently in use. */
00264 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00265 
00266 static int restart_monitor(void);
00267 
00268 static int capability = AST_FORMAT_ULAW;
00269 static int nonCodecCapability = AST_RTP_DTMF;
00270 
00271 static char ourhost[MAXHOSTNAMELEN];
00272 static struct in_addr __ourip;
00273 static int ourport;
00274 
00275 static int mgcpdebug = 0;
00276 
00277 static struct sched_context *sched;
00278 static struct io_context *io;
00279 /* The private structures of the  mgcp channels are linked for
00280    selecting outgoing channels */
00281    
00282 #define MGCP_MAX_HEADERS   64
00283 #define MGCP_MAX_LINES     64
00284 
00285 struct mgcp_request {
00286    int len;
00287    char *verb;
00288    char *identifier;
00289    char *endpoint;
00290    char *version;
00291    int headers;         /* MGCP Headers */
00292    char *header[MGCP_MAX_HEADERS];
00293    int lines;        /* SDP Content */
00294    char *line[MGCP_MAX_LINES];
00295    char data[MGCP_MAX_PACKET];
00296    int cmd;                        /* SC: int version of verb = command */
00297    unsigned int trid;              /* SC: int version of identifier = transaction id */
00298    struct mgcp_request *next;      /* SC: next in the queue */
00299 };
00300 
00301 /* SC: obsolete
00302 static struct mgcp_pkt {
00303    int retrans;
00304    struct mgcp_endpoint *owner;
00305    int packetlen;
00306    char data[MGCP_MAX_PACKET];
00307    struct mgcp_pkt *next;
00308 } *packets = NULL;   
00309 */
00310 
00311 /* MGCP message for queuing up */
00312 struct mgcp_message {
00313    struct mgcp_endpoint *owner_ep;
00314    struct mgcp_subchannel *owner_sub;
00315    int retrans;
00316    unsigned long expire;
00317    unsigned int seqno;
00318    int len;
00319    struct mgcp_message *next;
00320    char buf[0];
00321 };
00322 
00323 #define RESPONSE_TIMEOUT 30   /* in seconds */
00324 
00325 struct mgcp_response {
00326    time_t whensent;
00327    int len;
00328    int seqno;
00329    struct mgcp_response *next;
00330    char buf[0];
00331 };
00332 
00333 #define MAX_SUBS 2
00334 
00335 #define SUB_REAL 0
00336 #define SUB_ALT  1
00337 
00338 struct mgcp_subchannel {
00339    /* SC: subchannel magic string. 
00340       Needed to prove that any subchannel pointer passed by asterisk 
00341       really points to a valid subchannel memory area.
00342       Ugly.. But serves the purpose for the time being.
00343     */
00344 #define MGCP_SUBCHANNEL_MAGIC "!978!"
00345    char magic[6]; 
00346    ast_mutex_t lock;
00347    int id;
00348    struct ast_channel *owner;
00349    struct mgcp_endpoint *parent;
00350    struct ast_rtp *rtp;
00351    struct sockaddr_in tmpdest;
00352    char txident[80]; /* FIXME SC: txident is replaced by rqnt_ident in endpoint. 
00353          This should be obsoleted */
00354    char cxident[80];
00355    char callid[80];
00356 /* SC: obsolete
00357    time_t lastouttime;
00358    int lastout;
00359 */
00360    int cxmode;
00361    struct mgcp_request *cx_queue; /* SC: pending CX commands */
00362    ast_mutex_t cx_queue_lock;     /* SC: CX queue lock */
00363    int nat;
00364    int iseq; /* Not used? RTP? */
00365    int outgoing;
00366    int alreadygone;
00367 /* SC: obsolete
00368    int messagepending;
00369    struct mgcp_message *msgs;
00370 */
00371    struct mgcp_subchannel *next; /* for out circular linked list */
00372 };
00373 
00374 #define MGCP_ONHOOK  1
00375 #define MGCP_OFFHOOK 2
00376 
00377 #define TYPE_TRUNK 1
00378 #define TYPE_LINE  2
00379 
00380 struct mgcp_endpoint {
00381    ast_mutex_t lock;
00382    char name[80];
00383    struct mgcp_subchannel *sub;     /* pointer to our current connection, channel and stuff */
00384    char accountcode[AST_MAX_ACCOUNT_CODE];
00385    char exten[AST_MAX_EXTENSION];      /* Extention where to start */
00386    char context[AST_MAX_EXTENSION];
00387    char language[MAX_LANGUAGE];
00388    char cid_num[AST_MAX_EXTENSION]; /* Caller*ID */
00389    char cid_name[AST_MAX_EXTENSION];   /* Caller*ID */
00390    char lastcallerid[AST_MAX_EXTENSION];  /* Last Caller*ID */
00391    char call_forward[AST_MAX_EXTENSION];  /* Last Caller*ID */
00392    char mailbox[AST_MAX_EXTENSION];
00393    char musicclass[MAX_MUSICCLASS];
00394    char curtone[80];       /* Current tone */
00395    ast_group_t callgroup;
00396    ast_group_t pickupgroup;
00397    int callwaiting;
00398    int hascallwaiting;
00399    int transfer;
00400    int threewaycalling;
00401    int singlepath;
00402    int cancallforward;
00403    int canreinvite;
00404    int callreturn;
00405    int dnd; /* How does this affect callwait? Do we just deny a mgcp_request if we're dnd? */
00406    int hascallerid;
00407    int hidecallerid;
00408    int dtmfmode;
00409    int amaflags;
00410    int type;
00411    int slowsequence;       /* MS: Sequence the endpoint as a whole */
00412    int group;
00413    int iseq; /* Not used? */
00414    int lastout; /* tracking this on the subchannels.  Is it needed here? */
00415    int needdestroy; /* Not used? */
00416    int capability;
00417    int nonCodecCapability;
00418    int onhooktime;
00419    int msgstate; /* voicemail message state */
00420    int immediate;
00421    int hookstate;
00422    int adsi;
00423    char rqnt_ident[80];             /* SC: request identifier */
00424    struct mgcp_request *rqnt_queue; /* SC: pending RQNT commands */
00425    ast_mutex_t rqnt_queue_lock;
00426    struct mgcp_request *cmd_queue;  /* SC: pending commands other than RQNT */
00427    ast_mutex_t cmd_queue_lock;
00428    int delme;                       /* SC: needed for reload */
00429    int needaudit;                   /* SC: needed for reload */
00430    struct ast_dsp *dsp; /* XXX Should there be a dsp/subchannel? XXX */
00431    /* owner is tracked on the subchannels, and the *sub indicates whos in charge */
00432    /* struct ast_channel *owner; */
00433    /* struct ast_rtp *rtp; */
00434    /* struct sockaddr_in tmpdest; */
00435    /* message go the the endpoint and not the channel so they stay here */
00436    struct mgcp_endpoint *next;
00437    struct mgcp_gateway *parent;
00438 };
00439 
00440 static struct mgcp_gateway {
00441    /* A gateway containing one or more endpoints */
00442    char name[80];
00443    int isnamedottedip; /* SC: is the name FQDN or dotted ip */
00444    struct sockaddr_in addr;
00445    struct sockaddr_in defaddr;
00446    struct in_addr ourip;
00447    int dynamic;
00448    int expire;    /* XXX Should we ever expire dynamic registrations? XXX */
00449    struct mgcp_endpoint *endpoints;
00450    struct ast_ha *ha;
00451 /* SC: obsolete
00452    time_t lastouttime;
00453    int lastout;
00454    int messagepending;
00455 */
00456 /* JS: Wildcard endpoint name */
00457    char wcardep[30];
00458    struct mgcp_message *msgs; /* SC: gw msg queue */
00459    ast_mutex_t msgs_lock;     /* SC: queue lock */  
00460    int retransid;             /* SC: retrans timer id */
00461    int delme;                 /* SC: needed for reload */
00462    struct mgcp_response *responses;
00463    struct mgcp_gateway *next;
00464 } *gateways;
00465 
00466 AST_MUTEX_DEFINE_STATIC(mgcp_reload_lock);
00467 static int mgcp_reloading = 0;
00468 
00469 AST_MUTEX_DEFINE_STATIC(gatelock);
00470 
00471 static int mgcpsock  = -1;
00472 
00473 static struct sockaddr_in bindaddr;
00474 
00475 static struct ast_frame  *mgcp_read(struct ast_channel *ast);
00476 static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest);
00477 static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone);
00478 static int transmit_modify_request(struct mgcp_subchannel *sub);
00479 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername);
00480 static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp, int codecs);
00481 static int transmit_connection_del(struct mgcp_subchannel *sub);
00482 static int transmit_audit_endpoint(struct mgcp_endpoint *p);
00483 static void start_rtp(struct mgcp_subchannel *sub);
00484 static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,  
00485                             int result, unsigned int ident, struct mgcp_request *resp);
00486 static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub);
00487 static int mgcp_do_reload(void);
00488 static int mgcp_reload(int fd, int argc, char *argv[]);
00489 
00490 static struct ast_channel *mgcp_request(const char *type, int format, void *data, int *cause);
00491 static int mgcp_call(struct ast_channel *ast, char *dest, int timeout);
00492 static int mgcp_hangup(struct ast_channel *ast);
00493 static int mgcp_answer(struct ast_channel *ast);
00494 static struct ast_frame *mgcp_read(struct ast_channel *ast);
00495 static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame);
00496 static int mgcp_indicate(struct ast_channel *ast, int ind);
00497 static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
00498 static int mgcp_senddigit(struct ast_channel *ast, char digit);
00499 
00500 static const struct ast_channel_tech mgcp_tech = {
00501    .type = type,
00502    .description = tdesc,
00503    .capabilities = AST_FORMAT_ULAW,
00504    .properties = AST_CHAN_TP_WANTSJITTER,
00505    .requester = mgcp_request,
00506    .call = mgcp_call,
00507    .hangup = mgcp_hangup,
00508    .answer = mgcp_answer,
00509    .read = mgcp_read,
00510    .write = mgcp_write,
00511    .indicate = mgcp_indicate,
00512    .fixup = mgcp_fixup,
00513    .send_digit = mgcp_senddigit,
00514    .bridge = ast_rtp_bridge,
00515 };
00516 
00517 static int has_voicemail(struct mgcp_endpoint *p)
00518 {
00519    return ast_app_has_voicemail(p->mailbox, NULL);
00520 }
00521 
00522 static int unalloc_sub(struct mgcp_subchannel *sub)
00523 {
00524    struct mgcp_endpoint *p = sub->parent;
00525    if (p->sub == sub) {
00526       ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name, p->parent->name);
00527       return -1;
00528    }
00529    ast_log(LOG_DEBUG, "Released sub %d of channel %s@%s\n", sub->id, p->name, p->parent->name);
00530 
00531    sub->owner = NULL;
00532    if (!ast_strlen_zero(sub->cxident)) {
00533       transmit_connection_del(sub);
00534    }
00535    sub->cxident[0] = '\0';
00536    sub->callid[0] = '\0';
00537    sub->cxmode = MGCP_CX_INACTIVE;
00538    sub->outgoing = 0;
00539    sub->alreadygone = 0;
00540    memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
00541    if (sub->rtp) {
00542       ast_rtp_destroy(sub->rtp);
00543       sub->rtp = NULL;
00544    }
00545    dump_cmd_queues(NULL, sub); /* SC */
00546    return 0;
00547 }
00548 
00549 /* SC: modified for new transport mechanism */
00550 static int __mgcp_xmit(struct mgcp_gateway *gw, char *data, int len)
00551 {
00552    int res;
00553    if (gw->addr.sin_addr.s_addr)
00554       res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in));
00555    else 
00556       res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in));
00557    if (res != len) {
00558       ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno));
00559    }
00560    return res;
00561 }
00562 
00563 static int resend_response(struct mgcp_subchannel *sub, struct mgcp_response *resp)
00564 {
00565    struct mgcp_endpoint *p = sub->parent;
00566    int res;
00567    char iabuf[INET_ADDRSTRLEN];
00568    if (mgcpdebug) {
00569       ast_verbose("Retransmitting:\n%s\n to %s:%d\n", resp->buf, ast_inet_ntoa(iabuf, sizeof(iabuf), p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00570    }
00571    res = __mgcp_xmit(p->parent, resp->buf, resp->len);
00572    if (res > 0)
00573       res = 0;
00574    return res;
00575 }
00576 
00577 static int send_response(struct mgcp_subchannel *sub, struct mgcp_request *req)
00578 {
00579    struct mgcp_endpoint *p = sub->parent;
00580    int res;
00581    char iabuf[INET_ADDRSTRLEN];
00582    if (mgcpdebug) {
00583       ast_verbose("Transmitting:\n%s\n to %s:%d\n", req->data, ast_inet_ntoa(iabuf, sizeof(iabuf), p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00584    }
00585    res = __mgcp_xmit(p->parent, req->data, req->len);
00586    if (res > 0)
00587       res = 0;
00588    return res;
00589 }
00590 
00591 /* SC: modified for new transport framework */
00592 static void dump_queue(struct mgcp_gateway *gw, struct mgcp_endpoint *p)
00593 {
00594    struct mgcp_message *cur, *q = NULL, *w, *prev;
00595 
00596    ast_mutex_lock(&gw->msgs_lock);
00597    prev = NULL, cur = gw->msgs;
00598    while (cur) {
00599       if (!p || cur->owner_ep == p) {
00600          if (prev)
00601             prev->next = cur->next;
00602          else
00603             gw->msgs = cur->next;
00604 
00605          ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n", 
00606             gw->name, cur->seqno);
00607 
00608          w = cur;
00609          cur = cur->next;
00610          if (q) {
00611             w->next = q;
00612          } else {
00613             w->next = NULL;
00614          }
00615          q = w;
00616       } else {
00617          prev = cur, cur=cur->next;
00618       }
00619    }
00620    ast_mutex_unlock(&gw->msgs_lock);
00621 
00622    while (q) {
00623       cur = q;
00624       q = q->next;
00625       free(cur);
00626    }
00627 }
00628 
00629 static void mgcp_queue_frame(struct mgcp_subchannel *sub, struct ast_frame *f)
00630 {
00631    for(;;) {
00632       if (sub->owner) {
00633          if (!ast_mutex_trylock(&sub->owner->lock)) {
00634             ast_queue_frame(sub->owner, f);
00635             ast_mutex_unlock(&sub->owner->lock);
00636             break;
00637          } else {
00638             ast_mutex_unlock(&sub->lock);
00639             usleep(1);
00640             ast_mutex_lock(&sub->lock);
00641          }
00642       } else
00643          break;
00644    }
00645 }
00646 
00647 static void mgcp_queue_hangup(struct mgcp_subchannel *sub)
00648 {
00649    for(;;) {
00650       if (sub->owner) {
00651          if (!ast_mutex_trylock(&sub->owner->lock)) {
00652             ast_queue_hangup(sub->owner);
00653             ast_mutex_unlock(&sub->owner->lock);
00654             break;
00655          } else {
00656             ast_mutex_unlock(&sub->lock);
00657             usleep(1);
00658             ast_mutex_lock(&sub->lock);
00659          }
00660       } else
00661          break;
00662    }
00663 }
00664 
00665 static void mgcp_queue_control(struct mgcp_subchannel *sub, int control)
00666 {
00667    struct ast_frame f = { AST_FRAME_CONTROL, };
00668    f.subclass = control;
00669    return mgcp_queue_frame(sub, &f);
00670 }
00671 
00672 static int retrans_pkt(void *data)
00673 {
00674    struct mgcp_gateway *gw = (struct mgcp_gateway *)data;
00675    struct mgcp_message *cur, *exq = NULL, *w, *prev;
00676    int res = 0;
00677 
00678    /* find out expired msgs */
00679    ast_mutex_lock(&gw->msgs_lock);
00680 
00681    prev = NULL, cur = gw->msgs;
00682    while (cur) {
00683       if (cur->retrans < MAX_RETRANS) {
00684          cur->retrans++;
00685          if (mgcpdebug) {
00686             ast_verbose("Retransmitting #%d transaction %u on [%s]\n",
00687                cur->retrans, cur->seqno, gw->name);
00688          }
00689          __mgcp_xmit(gw, cur->buf, cur->len);
00690 
00691          prev = cur;
00692          cur = cur->next;
00693       } else {
00694          if (prev)
00695             prev->next = cur->next;
00696          else
00697             gw->msgs = cur->next;
00698 
00699          ast_log(LOG_WARNING, "Maximum retries exceeded for transaction %u on [%s]\n",
00700             cur->seqno, gw->name);
00701 
00702          w = cur;
00703          cur = cur->next;
00704 
00705          if (exq) {
00706             w->next = exq;
00707          } else {
00708             w->next = NULL;
00709          }
00710          exq = w;
00711       }
00712    }
00713 
00714    if (!gw->msgs) {
00715       gw->retransid = -1;
00716       res = 0;
00717    } else {
00718       res = 1;
00719    }
00720    ast_mutex_unlock(&gw->msgs_lock);
00721 
00722    while (exq) {
00723       cur = exq;
00724       /* time-out transaction */
00725       handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL); 
00726       exq = exq->next;
00727       free(cur);
00728    }
00729 
00730    return res;
00731 }
00732 
00733 /* SC: modified for the new transaction mechanism */
00734 static int mgcp_postrequest(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, 
00735                             char *data, int len, unsigned int seqno)
00736 {
00737    struct mgcp_message *msg = malloc(sizeof(struct mgcp_message) + len);
00738    struct mgcp_message *cur;
00739    struct mgcp_gateway *gw = ((p && p->parent) ? p->parent : NULL);
00740    struct timeval tv;
00741 
00742    if (!msg) {
00743       return -1;
00744    }
00745    if (!gw) {
00746       return -1;
00747    }
00748 /* SC
00749    time(&t);
00750    if (gw->messagepending && (gw->lastouttime + 20 < t)) {
00751       ast_log(LOG_NOTICE, "Timeout waiting for response to message:%d,  lastouttime: %ld, now: %ld.  Dumping pending queue\n",
00752          gw->msgs ? gw->msgs->seqno : -1, (long) gw->lastouttime, (long) t);
00753       dump_queue(sub->parent);
00754    }
00755 */
00756    msg->owner_sub = sub;
00757    msg->owner_ep = p;
00758    msg->seqno = seqno;
00759    msg->next = NULL;
00760    msg->len = len;
00761    msg->retrans = 0;
00762    memcpy(msg->buf, data, msg->len);
00763 
00764    ast_mutex_lock(&gw->msgs_lock);
00765    cur = gw->msgs;
00766    if (cur) {
00767       while(cur->next)
00768          cur = cur->next;
00769       cur->next = msg;
00770    } else {
00771       gw->msgs = msg;
00772    }
00773 
00774    if (gettimeofday(&tv, NULL) < 0) {
00775       /* This shouldn't ever happen, but let's be sure */
00776       ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
00777    } else {
00778       msg->expire = tv.tv_sec * 1000 + tv.tv_usec / 1000 + DEFAULT_RETRANS;
00779 
00780       if (gw->retransid == -1)
00781          gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw);
00782    }
00783    ast_mutex_unlock(&gw->msgs_lock);
00784 /* SC
00785    if (!gw->messagepending) {
00786       gw->messagepending = 1;
00787       gw->lastout = seqno;
00788       gw->lastouttime = t;
00789 */
00790    __mgcp_xmit(gw, msg->buf, msg->len);
00791       /* XXX Should schedule retransmission XXX */
00792 /* SC
00793    } else
00794       ast_log(LOG_DEBUG, "Deferring transmission of transaction %d\n", seqno);
00795 */
00796    return 0;
00797 }
00798 
00799 /* SC: modified for new transport */
00800 static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, 
00801                         struct mgcp_request *req, unsigned int seqno)
00802 {
00803    int res = 0;
00804    struct mgcp_request **queue, *q, *r, *t;
00805    char iabuf[INET_ADDRSTRLEN];
00806    ast_mutex_t *l;
00807 
00808    ast_log(LOG_DEBUG, "Slow sequence is %d\n", p->slowsequence);
00809    if (p->slowsequence) {
00810       queue = &p->cmd_queue;
00811       l = &p->cmd_queue_lock;
00812       ast_mutex_lock(l);
00813    } else {
00814       switch (req->cmd) {
00815       case MGCP_CMD_DLCX:
00816          queue = &sub->cx_queue;
00817          l = &sub->cx_queue_lock;
00818          ast_mutex_lock(l);
00819          q = sub->cx_queue;
00820          /* delete pending cx cmds */
00821          while (q) {
00822             r = q->next;
00823             free(q);
00824             q = r;
00825          }
00826          *queue = NULL;
00827