00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
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
00089
00090
00091
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
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
00120 #define DEFAULT_MGCP_CA_PORT 2727
00121 #define MGCP_MAX_PACKET 1500
00122 #define DEFAULT_RETRANS 1000
00123 #define MAX_RETRANS 5
00124
00125
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
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
00200 static int firstdigittimeout = 16000;
00201
00202
00203 static int gendigittimeout = 8000;
00204
00205
00206 static int matchdigittimeout = 3000;
00207
00208
00209
00210 AST_MUTEX_DEFINE_STATIC(netlock);
00211
00212 AST_MUTEX_DEFINE_STATIC(monlock);
00213
00214
00215
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
00232
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;
00244 char *header[MGCP_MAX_HEADERS];
00245 int lines;
00246 char *line[MGCP_MAX_LINES];
00247 char data[MGCP_MAX_PACKET];
00248 int cmd;
00249 unsigned int trid;
00250 struct mgcp_request *next;
00251 };
00252
00253
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
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
00282
00283
00284
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];
00295
00296 char cxident[80];
00297 char callid[80];
00298 int cxmode;
00299 struct mgcp_request *cx_queue;
00300 ast_mutex_t cx_queue_lock;
00301 int nat;
00302 int iseq;
00303 int outgoing;
00304 int alreadygone;
00305 struct mgcp_subchannel *next;
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;
00318 char accountcode[AST_MAX_ACCOUNT_CODE];
00319 char exten[AST_MAX_EXTENSION];
00320 char context[AST_MAX_EXTENSION];
00321 char language[MAX_LANGUAGE];
00322 char cid_num[AST_MAX_EXTENSION];
00323 char cid_name[AST_MAX_EXTENSION];
00324 char lastcallerid[AST_MAX_EXTENSION];
00325 char call_forward[AST_MAX_EXTENSION];
00326 char mailbox[AST_MAX_EXTENSION];
00327 char musicclass[MAX_MUSICCLASS];
00328 char curtone[80];
00329 char dtmf_buf[AST_MAX_EXTENSION];
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;
00341 int hascallerid;
00342 int hidecallerid;
00343 int dtmfmode;
00344 int amaflags;
00345 int type;
00346 int slowsequence;
00347 int group;
00348 int iseq;
00349 int lastout;
00350 int needdestroy;
00351 int capability;
00352 int nonCodecCapability;
00353 int onhooktime;
00354 int msgstate;
00355 int immediate;
00356 int hookstate;
00357 int adsi;
00358 char rqnt_ident[80];
00359 struct mgcp_request *rqnt_queue;
00360 ast_mutex_t rqnt_queue_lock;
00361 struct mgcp_request *cmd_queue;
00362 ast_mutex_t cmd_queue_lock;
00363 int delme;
00364 int needaudit;
00365 struct ast_dsp *dsp;
00366
00367
00368
00369
00370
00371 struct mgcp_endpoint *next;
00372 struct mgcp_gateway *parent;
00373 };
00374
00375 static struct mgcp_gateway {
00376
00377 char name[80];
00378 int isnamedottedip;
00379 struct sockaddr_in addr;
00380 struct sockaddr_in defaddr;
00381 struct in_addr ourip;
00382 int dynamic;
00383 int expire;
00384 struct mgcp_endpoint *endpoints;
00385 struct ast_ha *ha;
00386
00387
00388
00389
00390
00391
00392 char wcardep[30];
00393 struct mgcp_message *msgs;
00394 ast_mutex_t msgs_lock;
00395 int retransid;
00396 int delme;
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
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);
00487 return 0;
00488 }
00489
00490
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
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
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
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
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
00684
00685
00686
00687
00688
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
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
00720
00721
00722
00723
00724
00725 __mgcp_xmit(gw, msg->buf, msg->len);
00726
00727
00728
00729
00730
00731 return 0;
00732 }
00733
00734
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
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