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