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