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 #include "asterisk.h"
00032
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 219952 $")
00034
00035 #include <sys/socket.h>
00036 #include <sys/ioctl.h>
00037 #include <net/if.h>
00038 #include <fcntl.h>
00039 #include <netdb.h>
00040 #include <sys/signal.h>
00041 #include <signal.h>
00042 #include <netinet/in.h>
00043 #include <netinet/in_systm.h>
00044 #include <netinet/ip.h>
00045 #include <arpa/inet.h>
00046 #include <ctype.h>
00047
00048 #include "asterisk/lock.h"
00049 #include "asterisk/channel.h"
00050 #include "asterisk/config.h"
00051 #include "asterisk/module.h"
00052 #include "asterisk/pbx.h"
00053 #include "asterisk/sched.h"
00054 #include "asterisk/io.h"
00055 #include "asterisk/rtp_engine.h"
00056 #include "asterisk/acl.h"
00057 #include "asterisk/callerid.h"
00058 #include "asterisk/cli.h"
00059 #include "asterisk/say.h"
00060 #include "asterisk/cdr.h"
00061 #include "asterisk/astdb.h"
00062 #include "asterisk/features.h"
00063 #include "asterisk/app.h"
00064 #include "asterisk/musiconhold.h"
00065 #include "asterisk/utils.h"
00066 #include "asterisk/netsock.h"
00067 #include "asterisk/causes.h"
00068 #include "asterisk/dsp.h"
00069 #include "asterisk/devicestate.h"
00070 #include "asterisk/stringfields.h"
00071 #include "asterisk/abstract_jb.h"
00072 #include "asterisk/event.h"
00073 #include "asterisk/chanvars.h"
00074
00075
00076
00077
00078
00079
00080
00081 #define MGCPDUMPER
00082 #define DEFAULT_EXPIRY 120
00083 #define MAX_EXPIRY 3600
00084 #define DIRECTMEDIA 1
00085
00086 #ifndef INADDR_NONE
00087 #define INADDR_NONE (in_addr_t)(-1)
00088 #endif
00089
00090
00091 static struct ast_jb_conf default_jbconf =
00092 {
00093 .flags = 0,
00094 .max_size = -1,
00095 .resync_threshold = -1,
00096 .impl = ""
00097 };
00098 static struct ast_jb_conf global_jbconf;
00099
00100 static const char tdesc[] = "Media Gateway Control Protocol (MGCP)";
00101 static const char config[] = "mgcp.conf";
00102
00103 #define MGCP_DTMF_RFC2833 (1 << 0)
00104 #define MGCP_DTMF_INBAND (1 << 1)
00105 #define MGCP_DTMF_HYBRID (1 << 2)
00106
00107 #define DEFAULT_MGCP_GW_PORT 2427
00108 #define DEFAULT_MGCP_CA_PORT 2727
00109 #define MGCP_MAX_PACKET 1500
00110 #define DEFAULT_RETRANS 1000
00111 #define MAX_RETRANS 5
00112
00113
00114 #define MGCP_CX_SENDONLY 0
00115 #define MGCP_CX_RECVONLY 1
00116 #define MGCP_CX_SENDRECV 2
00117 #define MGCP_CX_CONF 3
00118 #define MGCP_CX_CONFERENCE 3
00119 #define MGCP_CX_MUTE 4
00120 #define MGCP_CX_INACTIVE 4
00121
00122
00123 static const char * const mgcp_cxmodes[] = {
00124 "sendonly",
00125 "recvonly",
00126 "sendrecv",
00127 "confrnce",
00128 "inactive"
00129 };
00130
00131 enum {
00132 MGCP_CMD_EPCF,
00133 MGCP_CMD_CRCX,
00134 MGCP_CMD_MDCX,
00135 MGCP_CMD_DLCX,
00136 MGCP_CMD_RQNT,
00137 MGCP_CMD_NTFY,
00138 MGCP_CMD_AUEP,
00139 MGCP_CMD_AUCX,
00140 MGCP_CMD_RSIP
00141 };
00142
00143 static char context[AST_MAX_EXTENSION] = "default";
00144
00145 static char language[MAX_LANGUAGE] = "";
00146 static char musicclass[MAX_MUSICCLASS] = "";
00147 static char parkinglot[AST_MAX_CONTEXT];
00148 static char cid_num[AST_MAX_EXTENSION] = "";
00149 static char cid_name[AST_MAX_EXTENSION] = "";
00150
00151 static int dtmfmode = 0;
00152 static int nat = 0;
00153
00154 static ast_group_t cur_callergroup = 0;
00155 static ast_group_t cur_pickupgroup = 0;
00156
00157 static struct {
00158 unsigned int tos;
00159 unsigned int tos_audio;
00160 unsigned int cos;
00161 unsigned int cos_audio;
00162 } qos = { 0, 0, 0, 0 };
00163
00164 static int immediate = 0;
00165
00166 static int callwaiting = 0;
00167
00168 static int callreturn = 0;
00169
00170 static int slowsequence = 0;
00171
00172 static int threewaycalling = 0;
00173
00174
00175 static int transfer = 0;
00176
00177 static int cancallforward = 0;
00178
00179 static int singlepath = 0;
00180
00181 static int directmedia = DIRECTMEDIA;
00182
00183 static char accountcode[AST_MAX_ACCOUNT_CODE] = "";
00184
00185 static char mailbox[AST_MAX_EXTENSION];
00186
00187 static int amaflags = 0;
00188
00189 static int adsi = 0;
00190
00191 static unsigned int oseq;
00192
00193
00194 static int firstdigittimeout = 16000;
00195
00196
00197 static int gendigittimeout = 8000;
00198
00199
00200 static int matchdigittimeout = 3000;
00201
00202
00203
00204 AST_MUTEX_DEFINE_STATIC(netlock);
00205
00206 AST_MUTEX_DEFINE_STATIC(monlock);
00207
00208
00209
00210 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00211
00212 static int restart_monitor(void);
00213
00214 static int capability = AST_FORMAT_ULAW;
00215 static int nonCodecCapability = AST_RTP_DTMF;
00216
00217 static char ourhost[MAXHOSTNAMELEN];
00218 static struct in_addr __ourip;
00219 static int ourport;
00220
00221 static int mgcpdebug = 0;
00222
00223 static struct sched_context *sched;
00224 static struct io_context *io;
00225
00226
00227
00228 #define MGCP_MAX_HEADERS 64
00229 #define MGCP_MAX_LINES 64
00230
00231 struct mgcp_request {
00232 int len;
00233 char *verb;
00234 char *identifier;
00235 char *endpoint;
00236 char *version;
00237 int headers;
00238 char *header[MGCP_MAX_HEADERS];
00239 int lines;
00240 char *line[MGCP_MAX_LINES];
00241 char data[MGCP_MAX_PACKET];
00242 int cmd;
00243 unsigned int trid;
00244 struct mgcp_request *next;
00245 };
00246
00247
00248 struct mgcp_message {
00249 struct mgcp_endpoint *owner_ep;
00250 struct mgcp_subchannel *owner_sub;
00251 int retrans;
00252 unsigned long expire;
00253 unsigned int seqno;
00254 int len;
00255 struct mgcp_message *next;
00256 char buf[0];
00257 };
00258
00259 #define RESPONSE_TIMEOUT 30
00260
00261 struct mgcp_response {
00262 time_t whensent;
00263 int len;
00264 int seqno;
00265 struct mgcp_response *next;
00266 char buf[0];
00267 };
00268
00269 #define MAX_SUBS 2
00270
00271 #define SUB_REAL 0
00272 #define SUB_ALT 1
00273
00274 struct mgcp_subchannel {
00275
00276
00277
00278
00279
00280 #define MGCP_SUBCHANNEL_MAGIC "!978!"
00281 char magic[6];
00282 ast_mutex_t lock;
00283 int id;
00284 struct ast_channel *owner;
00285 struct mgcp_endpoint *parent;
00286 struct ast_rtp_instance *rtp;
00287 struct sockaddr_in tmpdest;
00288 char txident[80];
00289
00290 char cxident[80];
00291 char callid[80];
00292 int cxmode;
00293 struct mgcp_request *cx_queue;
00294 ast_mutex_t cx_queue_lock;
00295 int nat;
00296 int iseq;
00297 int outgoing;
00298 int alreadygone;
00299 struct mgcp_subchannel *next;
00300 };
00301
00302 #define MGCP_ONHOOK 1
00303 #define MGCP_OFFHOOK 2
00304
00305 #define TYPE_TRUNK 1
00306 #define TYPE_LINE 2
00307
00308 struct mgcp_endpoint {
00309 ast_mutex_t lock;
00310 char name[80];
00311 struct mgcp_subchannel *sub;
00312 char accountcode[AST_MAX_ACCOUNT_CODE];
00313 char exten[AST_MAX_EXTENSION];
00314 char context[AST_MAX_EXTENSION];
00315 char language[MAX_LANGUAGE];
00316 char cid_num[AST_MAX_EXTENSION];
00317 char cid_name[AST_MAX_EXTENSION];
00318 char lastcallerid[AST_MAX_EXTENSION];
00319 char dtmf_buf[AST_MAX_EXTENSION];
00320 char call_forward[AST_MAX_EXTENSION];
00321 char musicclass[MAX_MUSICCLASS];
00322 char curtone[80];
00323 char mailbox[AST_MAX_EXTENSION];
00324 char parkinglot[AST_MAX_CONTEXT];
00325 struct ast_event_sub *mwi_event_sub;
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 directmedia;
00335 int callreturn;
00336 int dnd;
00337 int hascallerid;
00338 int hidecallerid;
00339 int dtmfmode;
00340 int amaflags;
00341 int type;
00342 int slowsequence;
00343 int group;
00344 int iseq;
00345 int lastout;
00346 int needdestroy;
00347 int capability;
00348 int nonCodecCapability;
00349 int onhooktime;
00350 int msgstate;
00351 int immediate;
00352 int hookstate;
00353 int adsi;
00354 char rqnt_ident[80];
00355 struct mgcp_request *rqnt_queue;
00356 ast_mutex_t rqnt_queue_lock;
00357 struct mgcp_request *cmd_queue;
00358 ast_mutex_t cmd_queue_lock;
00359 int delme;
00360 int needaudit;
00361 struct ast_dsp *dsp;
00362
00363
00364
00365
00366
00367 struct ast_variable *chanvars;
00368 struct mgcp_endpoint *next;
00369 struct mgcp_gateway *parent;
00370 };
00371
00372 static struct mgcp_gateway {
00373
00374 char name[80];
00375 int isnamedottedip;
00376 struct sockaddr_in addr;
00377 struct sockaddr_in defaddr;
00378 struct in_addr ourip;
00379 int dynamic;
00380 int expire;
00381 struct mgcp_endpoint *endpoints;
00382 struct ast_ha *ha;
00383
00384
00385
00386
00387
00388
00389 char wcardep[30];
00390 struct mgcp_message *msgs;
00391 ast_mutex_t msgs_lock;
00392 int retransid;
00393 int delme;
00394 struct mgcp_response *responses;
00395 struct mgcp_gateway *next;
00396 } *gateways;
00397
00398 AST_MUTEX_DEFINE_STATIC(mgcp_reload_lock);
00399 static int mgcp_reloading = 0;
00400
00401
00402 AST_MUTEX_DEFINE_STATIC(gatelock);
00403
00404 static int mgcpsock = -1;
00405
00406 static struct sockaddr_in bindaddr;
00407
00408 static struct ast_frame *mgcp_read(struct ast_channel *ast);
00409 static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest);
00410 static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone);
00411 static int transmit_modify_request(struct mgcp_subchannel *sub);
00412 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername);
00413 static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp, int codecs);
00414 static int transmit_connection_del(struct mgcp_subchannel *sub);
00415 static int transmit_audit_endpoint(struct mgcp_endpoint *p);
00416 static void start_rtp(struct mgcp_subchannel *sub);
00417 static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
00418 int result, unsigned int ident, struct mgcp_request *resp);
00419 static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub);
00420 static char *mgcp_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
00421 static int reload_config(int reload);
00422
00423 static struct ast_channel *mgcp_request(const char *type, int format, const struct ast_channel *requestor, void *data, int *cause);
00424 static int mgcp_call(struct ast_channel *ast, char *dest, int timeout);
00425 static int mgcp_hangup(struct ast_channel *ast);
00426 static int mgcp_answer(struct ast_channel *ast);
00427 static struct ast_frame *mgcp_read(struct ast_channel *ast);
00428 static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame);
00429 static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, size_t datalen);
00430 static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
00431 static int mgcp_senddigit_begin(struct ast_channel *ast, char digit);
00432 static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
00433 static int mgcp_devicestate(void *data);
00434 static void add_header_offhook(struct mgcp_subchannel *sub, struct mgcp_request *resp);
00435 static struct ast_variable *add_var(const char *buf, struct ast_variable *list);
00436 static struct ast_variable *copy_vars(struct ast_variable *src);
00437
00438 static const struct ast_channel_tech mgcp_tech = {
00439 .type = "MGCP",
00440 .description = tdesc,
00441 .capabilities = AST_FORMAT_ULAW,
00442 .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
00443 .requester = mgcp_request,
00444 .devicestate = mgcp_devicestate,
00445 .call = mgcp_call,
00446 .hangup = mgcp_hangup,
00447 .answer = mgcp_answer,
00448 .read = mgcp_read,
00449 .write = mgcp_write,
00450 .indicate = mgcp_indicate,
00451 .fixup = mgcp_fixup,
00452 .send_digit_begin = mgcp_senddigit_begin,
00453 .send_digit_end = mgcp_senddigit_end,
00454 .bridge = ast_rtp_instance_bridge,
00455 };
00456
00457 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00458 {
00459
00460
00461
00462
00463 }
00464
00465 static int has_voicemail(struct mgcp_endpoint *p)
00466 {
00467 int new_msgs;
00468 struct ast_event *event;
00469 char *mbox, *cntx;
00470
00471 cntx = mbox = ast_strdupa(p->mailbox);
00472 strsep(&cntx, "@");
00473 if (ast_strlen_zero(cntx))
00474 cntx = "default";
00475
00476 event = ast_event_get_cached(AST_EVENT_MWI,
00477 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox,
00478 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cntx,
00479 AST_EVENT_IE_END);
00480
00481 if (event) {
00482 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
00483 ast_event_destroy(event);
00484 } else
00485 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
00486
00487 return new_msgs;
00488 }
00489
00490 static int unalloc_sub(struct mgcp_subchannel *sub)
00491 {
00492 struct mgcp_endpoint *p = sub->parent;
00493 if (p->sub == sub) {
00494 ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name, p->parent->name);
00495 return -1;
00496 }
00497 ast_debug(1, "Released sub %d of channel %s@%s\n", sub->id, p->name, p->parent->name);
00498
00499 sub->owner = NULL;
00500 if (!ast_strlen_zero(sub->cxident)) {
00501 transmit_connection_del(sub);
00502 }
00503 sub->cxident[0] = '\0';
00504 sub->callid[0] = '\0';
00505 sub->cxmode = MGCP_CX_INACTIVE;
00506 sub->outgoing = 0;
00507 sub->alreadygone = 0;
00508 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
00509 if (sub->rtp) {
00510 ast_rtp_instance_destroy(sub->rtp);
00511 sub->rtp = NULL;
00512 }
00513 dump_cmd_queues(NULL, sub);
00514 return 0;
00515 }
00516
00517
00518 static int __mgcp_xmit(struct mgcp_gateway *gw, char *data, int len)
00519 {
00520 int res;
00521 if (gw->addr.sin_addr.s_addr)
00522 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in));
00523 else
00524 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in));
00525 if (res != len) {
00526 ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno));
00527 }
00528 return res;
00529 }
00530
00531 static int resend_response(struct mgcp_subchannel *sub, struct mgcp_response *resp)
00532 {
00533 struct mgcp_endpoint *p = sub->parent;
00534 int res;
00535 if (mgcpdebug) {
00536 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));
00537 }
00538 res = __mgcp_xmit(p->parent, resp->buf, resp->len);
00539 if (res > 0)
00540 res = 0;
00541 return res;
00542 }
00543
00544 static int send_response(struct mgcp_subchannel *sub, struct mgcp_request *req)
00545 {
00546 struct mgcp_endpoint *p = sub->parent;
00547 int res;
00548 if (mgcpdebug) {
00549 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));
00550 }
00551 res = __mgcp_xmit(p->parent, req->data, req->len);
00552 if (res > 0)
00553 res = 0;
00554 return res;
00555 }
00556
00557
00558 static void dump_queue(struct mgcp_gateway *gw, struct mgcp_endpoint *p)
00559 {
00560 struct mgcp_message *cur, *q = NULL, *w, *prev;
00561
00562 ast_mutex_lock(&gw->msgs_lock);
00563 prev = NULL, cur = gw->msgs;
00564 while (cur) {
00565 if (!p || cur->owner_ep == p) {
00566 if (prev)
00567 prev->next = cur->next;
00568 else
00569 gw->msgs = cur->next;
00570
00571 ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n",
00572 gw->name, cur->seqno);
00573
00574 w = cur;
00575 cur = cur->next;
00576 if (q) {
00577 w->next = q;
00578 } else {
00579 w->next = NULL;
00580 }
00581 q = w;
00582 } else {
00583 prev = cur, cur=cur->next;
00584 }
00585 }
00586 ast_mutex_unlock(&gw->msgs_lock);
00587
00588 while (q) {
00589 cur = q;
00590 q = q->next;
00591 ast_free(cur);
00592 }
00593 }
00594
00595 static void mgcp_queue_frame(struct mgcp_subchannel *sub, struct ast_frame *f)
00596 {
00597 for(;;) {
00598 if (sub->owner) {
00599 if (!ast_channel_trylock(sub->owner)) {
00600 ast_queue_frame(sub->owner, f);
00601 ast_channel_unlock(sub->owner);
00602 break;
00603 } else {
00604 DEADLOCK_AVOIDANCE(&sub->lock);
00605 }
00606 } else
00607 break;
00608 }
00609 }
00610
00611 static void mgcp_queue_hangup(struct mgcp_subchannel *sub)
00612 {
00613 for(;;) {
00614 if (sub->owner) {
00615 if (!ast_channel_trylock(sub->owner)) {
00616 ast_queue_hangup(sub->owner);
00617 ast_channel_unlock(sub->owner);
00618 break;
00619 } else {
00620 DEADLOCK_AVOIDANCE(&sub->lock);
00621 }
00622 } else
00623 break;
00624 }
00625 }
00626
00627 static void mgcp_queue_control(struct mgcp_subchannel *sub, int control)
00628 {
00629 struct ast_frame f = { AST_FRAME_CONTROL, };
00630 f.subclass = control;
00631 return mgcp_queue_frame(sub, &f);
00632 }
00633
00634 static int retrans_pkt(const void *data)
00635 {
00636 struct mgcp_gateway *gw = (struct mgcp_gateway *)data;
00637 struct mgcp_message *cur, *exq = NULL, *w, *prev;
00638 int res = 0;
00639
00640
00641 ast_mutex_lock(&gw->msgs_lock);
00642
00643 prev = NULL, cur = gw->msgs;
00644 while (cur) {
00645 if (cur->retrans < MAX_RETRANS) {
00646 cur->retrans++;
00647 if (mgcpdebug) {
00648 ast_verbose("Retransmitting #%d transaction %u on [%s]\n",
00649 cur->retrans, cur->seqno, gw->name);
00650 }
00651 __mgcp_xmit(gw, cur->buf, cur->len);
00652
00653 prev = cur;
00654 cur = cur->next;
00655 } else {
00656 if (prev)
00657 prev->next = cur->next;
00658 else
00659 gw->msgs = cur->next;
00660
00661 ast_log(LOG_WARNING, "Maximum retries exceeded for transaction %u on [%s]\n",
00662 cur->seqno, gw->name);
00663
00664 w = cur;
00665 cur = cur->next;
00666
00667 if (exq) {
00668 w->next = exq;
00669 } else {
00670 w->next = NULL;
00671 }
00672 exq = w;
00673 }
00674 }
00675
00676 if (!gw->msgs) {
00677 gw->retransid = -1;
00678 res = 0;
00679 } else {
00680 res = 1;
00681 }
00682 ast_mutex_unlock(&gw->msgs_lock);
00683
00684 while (exq) {
00685 cur = exq;
00686
00687 handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL);
00688 exq = exq->next;
00689 ast_free(cur);
00690 }
00691
00692 return res;
00693 }
00694
00695
00696 static int mgcp_postrequest(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
00697 char *data, int len, unsigned int seqno)
00698 {
00699 struct mgcp_message *msg;
00700 struct mgcp_message *cur;
00701 struct mgcp_gateway *gw;
00702 struct timeval now;
00703
00704 msg = ast_malloc(sizeof(*msg) + len);
00705 if (!msg) {
00706 return -1;
00707 }
00708 gw = ((p && p->parent) ? p->parent : NULL);
00709 if (!gw) {
00710 ast_free(msg);
00711 return -1;
00712 }
00713
00714
00715
00716
00717
00718
00719
00720
00721 msg->owner_sub = sub;
00722 msg->owner_ep = p;
00723 msg->seqno = seqno;
00724 msg->next = NULL;
00725 msg->len = len;
00726 msg->retrans = 0;
00727 memcpy(msg->buf, data, msg->len);
00728
00729 ast_mutex_lock(&gw->msgs_lock);
00730 cur = gw->msgs;
00731 if (cur) {
00732 while(cur->next)
00733 cur = cur->next;
00734 cur->next = msg;
00735 } else {
00736 gw->msgs = msg;
00737 }
00738
00739 now = ast_tvnow();
00740 msg->expire = now.tv_sec * 1000 + now.tv_usec / 1000 + DEFAULT_RETRANS;
00741
00742 if (gw->retransid == -1)
00743 gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw);
00744 ast_mutex_unlock(&gw->msgs_lock);
00745
00746
00747
00748
00749
00750
00751 __mgcp_xmit(gw, msg->buf, msg->len);
00752
00753
00754
00755
00756
00757 return 0;
00758 }
00759
00760
00761 static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
00762 struct mgcp_request *req, unsigned int seqno)
00763 {
00764 int res = 0;
00765 struct mgcp_request **queue, *q, *r, *t;
00766 ast_mutex_t *l;
00767
00768 ast_debug(1, "Slow sequence is %d\n", p->slowsequence);
00769 if (p->slowsequence) {
00770 queue = &p->cmd_queue;
00771 l = &p->cmd_queue_lock;
00772 ast_mutex_lock(l);
00773 } else {
00774 switch (req->cmd) {
00775 case MGCP_CMD_DLCX:
00776 queue = &sub->cx_queue;
00777 l = &sub->cx_queue_lock;
00778 ast_mutex_lock(l);
00779 q = sub->cx_queue;
00780
00781 while (q) {
00782 r = q->next;
00783 ast_free(q);
00784 q = r;
00785 }
00786 *queue = NULL;
00787 break;
00788
00789 case MGCP_CMD_CRCX:
00790 case MGCP_CMD_MDCX:
00791 queue = &sub->cx_queue;
00792 l = &sub->cx_queue_lock;
00793 ast_mutex_lock(l);
00794 break;
00795
00796 case MGCP_CMD_RQNT:
00797 queue = &p->rqnt_queue;
00798 l = &p->rqnt_queue_lock;
00799 ast_mutex_lock(l);
00800 break;
00801
00802 default:
00803 queue = &p->cmd_queue;
00804 l = &p->cmd_queue_lock;
00805 ast_mutex_lock(l);
00806 break;
00807 }
00808 }
00809
00810 r = ast_malloc(sizeof(*r));
00811 if (!r) {
00812 ast_log(LOG_WARNING, "Cannot post MGCP request: insufficient memory\n");
00813 ast_mutex_unlock(l);
00814 return -1;
00815 }
00816 memcpy(r, req, sizeof(*r));
00817
00818 if (!(*queue)) {
00819 if (mgcpdebug) {
00820 ast_verbose("Posting Request:\n%s to %s:%d\n", req->data,
00821 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00822 }
00823
00824 res = mgcp_postrequest(p, sub, req->data, req->len, seqno);
00825 } else {
00826 if (mgcpdebug) {
00827 ast_verbose("Queueing Request:\n%s to %s:%d\n", req->data,
00828 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00829 }
00830 }
00831
00832
00833 for (t = *queue; t && t->next; t = t->next);
00834
00835 r->next = NULL;
00836 if (t)
00837 t->next = r;
00838 else
00839 *queue = r;
00840
00841 ast_mutex_unlock(l);
00842
00843 return res;
00844 }
00845
00846 static int mgcp_call(struct ast_channel *ast, char *dest, int timeout)
00847 {
00848 int res;
00849 struct mgcp_endpoint *p;
00850 struct mgcp_subchannel *sub;
00851 char tone[50] = "";
00852 const char *distinctive_ring = NULL;
00853 struct varshead *headp;
00854 struct ast_var_t *current;
00855
00856 if (mgcpdebug) {
00857 ast_verb(3, "MGCP mgcp_call(%s)\n", ast->name);
00858 }
00859 sub = ast->tech_pvt;
00860 p = sub->parent;
00861 headp = &ast->varshead;
00862 AST_LIST_TRAVERSE(headp,current,entries) {
00863
00864 if (strcasecmp(ast_var_name(current),"ALERT_INFO") == 0) {
00865 distinctive_ring = ast_var_value(current);
00866 }
00867 }
00868
00869 ast_mutex_lock(&sub->lock);
00870 switch (p->hookstate) {
00871 case MGCP_OFFHOOK:
00872 if (!ast_strlen_zero(distinctive_ring)) {
00873 snprintf(tone, sizeof(tone), "L/wt%s", distinctive_ring);
00874 if (mgcpdebug) {
00875 ast_verb(3, "MGCP distinctive callwait %s\n", tone);
00876 }
00877 } else {
00878 ast_copy_string(tone, "L/wt", sizeof(tone));
00879 if (mgcpdebug) {
00880 ast_verb(3, "MGCP normal callwait %s\n", tone);
00881 }
00882 }
00883 break;
00884 case MGCP_ONHOOK:
00885 default:
00886 if (!ast_strlen_zero(distinctive_ring)) {
00887 snprintf(tone, sizeof(tone), "L/r%s", distinctive_ring);
00888 if (mgcpdebug) {
00889 ast_verb(3, "MGCP distinctive ring %s\n", tone);
00890 }
00891 } else {
00892 ast_copy_string(tone, "L/rg", sizeof(tone));
00893 if (mgcpdebug) {
00894 ast_verb(3, "MGCP default ring\n");
00895 }
00896 }
00897 break;
00898 }
00899
00900 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
00901 ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast->name);
00902 ast_mutex_unlock(&sub->lock);
00903 return -1;
00904 }
00905
00906 res = 0;
00907 sub->outgoing = 1;
00908 sub->cxmode = MGCP_CX_RECVONLY;
00909 if (p->type == TYPE_LINE) {
00910 if (!sub->rtp) {
00911 start_rtp(sub);
00912 } else {
00913 transmit_modify_request(sub);
00914 }
00915
00916 if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
00917
00918 sub->next->cxmode = MGCP_CX_RECVONLY;
00919 transmit_modify_request(sub->next);
00920 }
00921
00922 transmit_notify_request_with_callerid(sub, tone, ast->connected.id.number, ast->connected.id.name);
00923 ast_setstate(ast, AST_STATE_RINGING);
00924
00925 if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
00926
00927 sub->next->cxmode = MGCP_CX_SENDRECV;
00928 transmit_modify_request(sub->next);
00929 }
00930 } else {
00931 ast_log(LOG_NOTICE, "Don't know how to dial on trunks yet\n");
00932 res = -1;
00933 }
00934 ast_mutex_unlock(&sub->lock);
00935 ast_queue_control(ast, AST_CONTROL_RINGING);
00936 return res;
00937 }
00938
00939 static int mgcp_hangup(struct ast_channel *ast)
00940 {
00941 struct mgcp_subchannel *sub = ast->tech_pvt;
00942 struct mgcp_endpoint *p = sub->parent;
00943
00944 ast_debug(1, "mgcp_hangup(%s)\n", ast->name);
00945 if (!ast->tech_pvt) {
00946 ast_debug(1, "Asked to hangup channel not connected\n");
00947 return 0;
00948 }
00949 if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) {
00950 ast_debug(1, "Invalid magic. MGCP subchannel freed up already.\n");
00951 return 0;
00952 }
00953 ast_mutex_lock(&sub->lock);
00954 if (mgcpdebug) {
00955 ast_verb(3, "MGCP mgcp_hangup(%s) on %s@%s\n", ast->name, p->name, p->parent->name);
00956 }
00957
00958 if ((p->dtmfmode & MGCP_DTMF_INBAND) && p->dsp) {
00959
00960 if (!sub->next->owner) {
00961 if (p->dtmfmode & MGCP_DTMF_HYBRID)
00962 p->dtmfmode &= ~MGCP_DTMF_INBAND;
00963 if (mgcpdebug) {
00964 ast_verb(2, "MGCP free dsp on %s@%s\n", p->name, p->parent->name);
00965 }
00966 ast_dsp_free(p->dsp);
00967 p->dsp = NULL;
00968 }
00969 }
00970
00971 sub->owner = NULL;
00972 if (!ast_strlen_zero(sub->cxident)) {
00973 transmit_connection_del(sub);
00974 }
00975 sub->cxident[0] = '\0';
00976 if ((sub == p->sub) && sub->next->owner) {
00977 if (p->hookstate == MGCP_OFFHOOK) {
00978 if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
00979 transmit_notify_request_with_callerid(p->sub, "L/wt", ast_bridged_channel(sub->next->owner)->cid.cid_num, ast_bridged_channel(sub->next->owner)->cid.cid_name);
00980 }
00981 } else {
00982
00983 p->sub = sub->next;
00984 p->sub->cxmode = MGCP_CX_RECVONLY;
00985 transmit_modify_request(p->sub);
00986 if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
00987 transmit_notify_request_with_callerid(p->sub, "L/rg", ast_bridged_channel(sub->next->owner)->cid.cid_num, ast_bridged_channel(sub->next->owner)->cid.cid_name);
00988 }
00989 }
00990
00991 } else if ((sub == p->sub->next) && p->hookstate == MGCP_OFFHOOK) {
00992 transmit_notify_request(sub, "L/v");
00993 } else if (p->hookstate == MGCP_OFFHOOK) {
00994 transmit_notify_request(sub, "L/ro");
00995 } else {
00996 transmit_notify_request(sub, "");
00997 }
00998
00999 ast->tech_pvt = NULL;
01000 sub->alreadygone = 0;
01001 sub->outgoing = 0;
01002 sub->cxmode = MGCP_CX_INACTIVE;
01003 sub->callid[0] = '\0';
01004 if (p) {
01005 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
01006 }
01007
01008 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
01009 if (sub->rtp) {
01010 ast_rtp_instance_destroy(sub->rtp);
01011 sub->rtp = NULL;
01012 }
01013
01014 ast_module_unref(ast_module_info->self);
01015
01016 if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) {
01017 p->hidecallerid = 0;
01018 if (p->hascallwaiting && !p->callwaiting) {
01019 ast_verb(3, "Enabling call waiting on %s\n", ast->name);
01020 p->callwaiting = -1;
01021 }
01022 if (has_voicemail(p)) {
01023 if (mgcpdebug) {
01024 ast_verb(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n",
01025 ast->name, p->name, p->parent->name);
01026 }
01027 transmit_notify_request(sub, "L/vmwi(+)");
01028 } else {
01029 if (mgcpdebug) {
01030 ast_verb(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n",
01031 ast->name, p->name, p->parent->name);
01032 }
01033 transmit_notify_request(sub, "L/vmwi(-)");
01034 }
01035 }
01036 ast_mutex_unlock(&sub->lock);
01037 return 0;
01038 }
01039
01040 static char *handle_mgcp_show_endpoints(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01041 {
01042 struct mgcp_gateway *mg;
01043 struct mgcp_endpoint *me;
01044 int hasendpoints = 0;
01045 struct ast_variable * v = NULL;
01046
01047
01048 switch (cmd) {
01049 case CLI_INIT:
01050 e->command = "mgcp show endpoints";
01051 e->usage =
01052 "Usage: mgcp show endpoints\n"
01053 " Lists all endpoints known to the MGCP (Media Gateway Control Protocol) subsystem.\n";
01054 return NULL;
01055 case CLI_GENERATE:
01056 return NULL;
01057 }
01058
01059 if (a->argc != 3)
01060 return CLI_SHOWUSAGE;
01061 ast_mutex_lock(&gatelock);
01062 mg = gateways;
01063 while(mg) {
01064 me = mg->endpoints;
01065 ast_cli(a->fd, "Gateway '%s' at %s (%s)\n", mg->name, mg->addr.sin_addr.s_addr ? ast_inet_ntoa(mg->addr.sin_addr) : ast_inet_ntoa(mg->defaddr.sin_addr), mg->dynamic ? "Dynamic" : "Static");
01066 while(me) {
01067 ast_cli(a->fd, " -- '%s@%s in '%s' is %s\n", me->name, mg->name, me->context, me->sub->owner ? "active" : "idle");
01068 if (me->chanvars) {
01069 ast_cli(a->fd, " Variables:\n");
01070 for (v = me->chanvars ; v ; v = v->next) {
01071 ast_cli(a->fd, " %s = '%s'\n", v->name, v->value);
01072 }
01073 }
01074 hasendpoints = 1;
01075 me = me->next;
01076 }
01077 if (!hasendpoints) {
01078 ast_cli(a->fd, " << No Endpoints Defined >> ");
01079 }
01080 mg = mg->next;
01081 }
01082 ast_mutex_unlock(&gatelock);
01083 return CLI_SUCCESS;
01084 }
01085
01086 static char *handle_mgcp_audit_endpoint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01087 {
01088 struct mgcp_gateway *mg;
01089 struct mgcp_endpoint *me;
01090 int found = 0;
01091 char *ename,*gname, *c;
01092
01093 switch (cmd) {
01094 case CLI_INIT:
01095 e->command = "mgcp audit endpoint";
01096 e->usage =
01097 "Usage: mgcp audit endpoint <endpointid>\n"
01098 " Lists the capabilities of an endpoint in the MGCP (Media Gateway Control Protocol) subsystem.\n"
01099 " mgcp debug MUST be on to see the results of this command.\n";
01100 return NULL;
01101 case CLI_GENERATE:
01102 return NULL;
01103 }
01104
01105 if (!mgcpdebug) {
01106 return CLI_SHOWUSAGE;
01107 }
01108 if (a->argc != 4)
01109 return CLI_SHOWUSAGE;
01110
01111 ename = ast_strdupa(a->argv[3]);
01112 gname = ename;
01113 while (*gname) {
01114 if (*gname == '@') {
01115 *gname = 0;
01116 gname++;
01117 break;
01118 }
01119 gname++;
01120 }
01121 if (gname[0] == '[')
01122 gname++;
01123 if ((c = strrchr(gname, ']')))
01124 *c = '\0';
01125 ast_mutex_lock(&gatelock);
01126 mg = gateways;
01127 while(mg) {
01128 if (!strcasecmp(mg->name, gname)) {
01129 me = mg->endpoints;
01130 while(me) {
01131 if (!strcasecmp(me->name, ename)) {
01132 found = 1;
01133 transmit_audit_endpoint(me);
01134 break;
01135 }
01136 me = me->next;
01137 }
01138 if (found) {
01139 break;
01140 }
01141 }
01142 mg = mg->next;
01143 }
01144 if (!found) {
01145 ast_cli(a->fd, " << Could not find endpoint >> ");
01146 }
01147 ast_mutex_unlock(&gatelock);
01148 return CLI_SUCCESS;
01149 }
01150
01151 static char *handle_mgcp_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01152 {
01153 switch (cmd) {
01154 case CLI_INIT:
01155 e->command = "mgcp set debug {on|off}";
01156 e->usage =
01157 "Usage: mgcp set debug {on|off}\n"
01158 " Enables/Disables dumping of MGCP packets for debugging purposes\n";
01159 return NULL;
01160 case CLI_GENERATE:
01161 return NULL;
01162 }
01163
01164 if (a->argc != e->args)
01165 return CLI_SHOWUSAGE;
01166
01167 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) {
01168 mgcpdebug = 1;
01169 ast_cli(a->fd, "MGCP Debugging Enabled\n");
01170 } else if (!strncasecmp(a->argv[3], "off", 3)) {
01171 mgcpdebug = 0;
01172 ast_cli(a->fd, "MGCP Debugging Disabled\n");
01173 } else {
01174 return CLI_SHOWUSAGE;
01175 }
01176 return CLI_SUCCESS;
01177 }
01178
01179 static struct ast_cli_entry cli_mgcp[] = {
01180 AST_CLI_DEFINE(handle_mgcp_audit_endpoint, "Audit specified MGCP endpoint"),
01181 AST_CLI_DEFINE(handle_mgcp_show_endpoints, "List defined MGCP endpoints"),
01182 AST_CLI_DEFINE(handle_mgcp_set_debug, "Enable/Disable MGCP debugging"),
01183 AST_CLI_DEFINE(mgcp_reload, "Reload MGCP configuration"),
01184 };
01185
01186 static int mgcp_answer(struct ast_channel *ast)
01187 {
01188 int res = 0;
01189 struct mgcp_subchannel *sub = ast->tech_pvt;
01190 struct mgcp_endpoint *p = sub->parent;
01191
01192 ast_mutex_lock(&sub->lock);
01193 sub->cxmode = MGCP_CX_SENDRECV;
01194 if (!sub->rtp) {
01195 start_rtp(sub);
01196 } else {
01197 transmit_modify_request(sub);
01198 }
01199 ast_verb(3, "MGCP mgcp_answer(%s) on %s@%s-%d\n",
01200 ast->name, p->name, p->parent->name, sub->id);
01201 if (ast->_state != AST_STATE_UP) {
01202 ast_setstate(ast, AST_STATE_UP);
01203 ast_debug(1, "mgcp_answer(%s)\n", ast->name);
01204 transmit_notify_request(sub, "");
01205 transmit_modify_request(sub);
01206 }
01207 ast_mutex_unlock(&sub->lock);
01208 return res;
01209 }
01210
01211 static struct ast_frame *mgcp_rtp_read(struct mgcp_subchannel *sub)
01212 {
01213
01214 struct ast_frame *f;
01215
01216 f = ast_rtp_instance_read(sub->rtp, 0);
01217
01218 if (f && (f->frametype == AST_FRAME_DTMF) && !(sub->parent->dtmfmode & MGCP_DTMF_RFC2833))
01219 return &ast_null_frame;
01220 if (sub->owner) {
01221
01222 if (f->frametype == AST_FRAME_VOICE) {
01223 if (f->subclass != sub->owner->nativeformats) {
01224 ast_debug(1, "Oooh, format changed to %d\n", f->subclass);
01225 sub->owner->nativeformats = f->subclass;
01226 ast_set_read_format(sub->owner, sub->owner->readformat);
01227 ast_set_write_format(sub->owner, sub->owner->writeformat);
01228 }
01229
01230 if ((sub->parent->dtmfmode & MGCP_DTMF_INBAND) && (sub->parent->dsp)) {
01231 #if 0
01232 ast_log(LOG_NOTICE, "MGCP ast_dsp_process\n");
01233 #endif
01234 f = ast_dsp_process(sub->owner, sub->parent->dsp, f);
01235 }
01236 }
01237 }
01238 return f;
01239 }
01240
01241
01242 static struct ast_frame *mgcp_read(struct ast_channel *ast)
01243 {
01244 struct ast_frame *f;
01245 struct mgcp_subchannel *sub = ast->tech_pvt;
01246 ast_mutex_lock(&sub->lock);
01247 f = mgcp_rtp_read(sub);
01248 ast_mutex_unlock(&sub->lock);
01249 return f;
01250 }
01251
01252 static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame)
01253 {
01254 struct mgcp_subchannel *sub = ast->tech_pvt;
01255 int res = 0;
01256 if (frame->frametype != AST_FRAME_VOICE) {
01257 if (frame->frametype == AST_FRAME_IMAGE)
01258 return 0;
01259 else {
01260 ast_log(LOG_WARNING, "Can't send %d type frames with MGCP write\n", frame->frametype);
01261 return 0;
01262 }
01263 } else {
01264 if (!(frame->subclass & ast->nativeformats)) {
01265 ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
01266 frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat);
01267 return -1;
01268 }
01269 }
01270 if (sub) {
01271 ast_mutex_lock(&sub->lock);
01272 if ((sub->parent->sub == sub) || !sub->parent->singlepath) {
01273 if (sub->rtp) {
01274 res = ast_rtp_instance_write(sub->rtp, frame);
01275 }
01276 }
01277 ast_mutex_unlock(&sub->lock);
01278 }
01279 return res;
01280 }
01281
01282 static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
01283 {
01284 struct mgcp_subchannel *sub = newchan->tech_pvt;
01285
01286 ast_mutex_lock(&sub->lock);
01287 ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", oldchan->name, newchan->name);
01288 if (sub->owner != oldchan) {
01289 ast_mutex_unlock(&sub->lock);
01290 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
01291 return -1;
01292 }
01293 sub->owner = newchan;
01294 ast_mutex_unlock(&sub->lock);
01295 return 0;
01296 }
01297
01298 static int mgcp_senddigit_begin(struct ast_channel *ast, char digit)
01299 {
01300 struct mgcp_subchannel *sub = ast->tech_pvt;
01301 struct mgcp_endpoint *p = sub->parent;
01302 int res = 0;
01303
01304 ast_mutex_lock(&sub->lock);
01305 if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) {
01306 ast_log(LOG_DEBUG, "Sending DTMF using inband/hybrid\n");
01307 res = -1;
01308 } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
01309 ast_log(LOG_DEBUG, "Sending DTMF using RFC2833");
01310 ast_rtp_instance_dtmf_begin(sub->rtp, digit);
01311 } else {
01312 ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
01313 }
01314 ast_mutex_unlock(&sub->lock);
01315
01316 return res;
01317 }
01318
01319 static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)
01320 {
01321 struct mgcp_subchannel *sub = ast->tech_pvt;
01322 struct mgcp_endpoint *p = sub->parent;
01323 int res = 0;
01324 char tmp[4];
01325
01326 ast_mutex_lock(&sub->lock);
01327 if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) {
01328 ast_log(LOG_DEBUG, "Stopping DTMF using inband/hybrid\n");
01329 res = -1;
01330 } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
01331 ast_log(LOG_DEBUG, "Stopping DTMF using RFC2833\n");
01332 tmp[0] = 'D';
01333 tmp[1] = '/';
01334 tmp[2] = digit;
01335 tmp[3] = '\0';
01336 transmit_notify_request(sub, tmp);
01337 ast_rtp_instance_dtmf_end(sub->rtp, digit);
01338 } else {
01339 ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
01340 }
01341 ast_mutex_unlock(&sub->lock);
01342
01343 return res;
01344 }
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355 static int mgcp_devicestate(void *data)
01356 {
01357 struct mgcp_gateway *g;
01358 struct mgcp_endpoint *e = NULL;
01359 char *tmp, *endpt, *gw;
01360 int ret = AST_DEVICE_INVALID;
01361
01362 endpt = ast_strdupa(data);
01363 if ((tmp = strchr(endpt, '@'))) {
01364 *tmp++ = '\0';
01365 gw = tmp;
01366 } else
01367 goto error;
01368
01369 ast_mutex_lock(&gatelock);
01370 g = gateways;
01371 while (g) {
01372 if (strcasecmp(g->name, gw) == 0) {
01373 e = g->endpoints;
01374 break;
01375 }
01376 g = g->next;
01377 }
01378
01379 if (!e)
01380 goto error;
01381
01382 while (e) {
01383 if (strcasecmp(e->name, endpt) == 0)
01384 break;
01385 e = e->next;
01386 }
01387
01388 if (!e)
01389 goto error;
01390
01391
01392
01393
01394
01395
01396 ret = AST_DEVICE_UNKNOWN;
01397
01398 error:
01399 ast_mutex_unlock(&gatelock);
01400 return ret;
01401 }
01402
01403 static char *control2str(int ind) {
01404 switch (ind) {
01405 case AST_CONTROL_HANGUP:
01406 return "Other end has hungup";
01407 case AST_CONTROL_RING:
01408 return "Local ring";
01409 case AST_CONTROL_RINGING:
01410 return "Remote end is ringing";
01411 case AST_CONTROL_ANSWER:
01412 return "Remote end has answered";
01413 case AST_CONTROL_BUSY:
01414 return "Remote end is busy";
01415 case AST_CONTROL_TAKEOFFHOOK:
01416 return "Make it go off hook";
01417 case AST_CONTROL_OFFHOOK:
01418 return "Line is off hook";
01419 case AST_CONTROL_CONGESTION:
01420 return "Congestion (circuits busy)";
01421 case AST_CONTROL_FLASH:
01422 return "Flash hook";
01423 case AST_CONTROL_WINK:
01424 return "Wink";
01425 case AST_CONTROL_OPTION:
01426 return "Set a low-level option";
01427 case AST_CONTROL_RADIO_KEY:
01428 return "Key Radio";
01429 case AST_CONTROL_RADIO_UNKEY:
01430 return "Un-Key Radio";
01431 }
01432 return "UNKNOWN";
01433 }
01434
01435 static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, size_t datalen)
01436 {
01437 struct mgcp_subchannel *sub = ast->tech_pvt;
01438 int res = 0;
01439
01440 if (mgcpdebug) {
01441 ast_verb(3, "MGCP asked to indicate %d '%s' condition on channel %s\n",
01442 ind, control2str(ind), ast->name);
01443 }
01444 ast_mutex_lock(&sub->lock);
01445 switch(ind) {
01446 case AST_CONTROL_RINGING:
01447 #ifdef DLINK_BUGGY_FIRMWARE
01448 transmit_notify_request(sub, "rt");
01449 #else
01450 transmit_notify_request(sub, "G/rt");
01451 #endif
01452 break;
01453 case AST_CONTROL_BUSY:
01454 transmit_notify_request(sub, "L/bz");
01455 break;
01456 case AST_CONTROL_CONGESTION:
01457 transmit_notify_request(sub, "G/cg");
01458 break;
01459 case AST_CONTROL_HOLD:
01460 ast_moh_start(ast, data, NULL);
01461 break;
01462 case AST_CONTROL_UNHOLD:
01463 ast_moh_stop(ast);
01464 break;
01465 case AST_CONTROL_SRCUPDATE:
01466 ast_rtp_instance_new_source(sub->rtp);
01467 break;
01468 case -1:
01469 transmit_notify_request(sub, "");
01470 break;
01471 default:
01472 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
01473 res = -1;
01474 }
01475 ast_mutex_unlock(&sub->lock);
01476 return res;
01477 }
01478
01479 static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state, const char *linkedid)
01480 {
01481 struct ast_channel *tmp;
01482 struct ast_variable *v = NULL;
01483 struct mgcp_endpoint *i = sub->parent;
01484 int fmt;
01485
01486 tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, linkedid, i->accountcode, i->exten, i->context, i->amaflags, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
01487 if (tmp) {
01488 tmp->tech = &mgcp_tech;
01489 tmp->nativeformats = i->capability;
01490 if (!tmp->nativeformats)
01491 tmp->nativeformats = capability;
01492 fmt = ast_best_codec(tmp->nativeformats);
01493 if (sub->rtp)
01494 ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0));
01495 if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) {
01496 i->dsp = ast_dsp_new();
01497 ast_dsp_set_features(i->dsp, DSP_FEATURE_DIGIT_DETECT);
01498
01499 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH);
01500 } else {
01501 i->dsp = NULL;
01502 }
01503 if (state == AST_STATE_RING)
01504 tmp->rings = 1;
01505 tmp->writeformat = fmt;
01506 tmp->rawwriteformat = fmt;
01507 tmp->readformat = fmt;
01508 tmp->rawreadformat = fmt;
01509 tmp->tech_pvt = sub;
01510 if (!ast_strlen_zero(i->language))
01511 ast_string_field_set(tmp, language, i->language);
01512 if (!ast_strlen_zero(i->accountcode))
01513 ast_string_field_set(tmp, accountcode, i->accountcode);
01514 if (i->amaflags)
01515 tmp->amaflags = i->amaflags;
01516 sub->owner = tmp;
01517 ast_module_ref(ast_module_info->self);
01518 tmp->callgroup = i->callgroup;
01519 tmp->pickupgroup = i->pickupgroup;
01520 ast_string_field_set(tmp, call_forward, i->call_forward);
01521 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
01522 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
01523
01524
01525
01526 tmp->cid.cid_ani = ast_strdup(i->cid_num);
01527
01528 if (!i->adsi)
01529 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
01530 tmp->priority = 1;
01531
01532
01533 for (v = i->chanvars ; v ; v = v->next) {
01534 char valuebuf[1024];
01535 pbx_builtin_setvar_helper(tmp, v->name, ast_get_encoded_str(v->value, valuebuf, sizeof(valuebuf)));
01536 }
01537
01538 if (sub->rtp)
01539 ast_jb_configure(tmp, &global_jbconf);
01540 if (state != AST_STATE_DOWN) {
01541 if (ast_pbx_start(tmp)) {
01542 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
01543 ast_hangup(tmp);
01544 tmp = NULL;
01545 }
01546 }
01547 ast_verb(3, "MGCP mgcp_new(%s) created in state: %s\n",
01548 tmp->name, ast_state2str(state));
01549 } else {
01550 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
01551 }
01552 return tmp;
01553 }
01554
01555 static char* get_sdp_by_line(char* line, char *name, int nameLen)
01556 {
01557 if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
01558 char* r = line + nameLen + 1;
01559 while (*r && (*r < 33)) ++r;
01560 return r;
01561 }
01562 return "";
01563 }
01564
01565 static char *get_sdp(struct mgcp_request *req, char *name)
01566 {
01567 int x;
01568 int len = strlen(name);
01569 char *r;
01570
01571 for (x=0; x<req->lines; x++) {
01572 r = get_sdp_by_line(req->line[x], name, len);
01573 if (r[0] != '\0') return r;
01574 }
01575 return "";
01576 }
01577
01578 static void sdpLineNum_iterator_init(int* iterator)
01579 {
01580 *iterator = 0;
01581 }
01582
01583 static char* get_sdp_iterate(int* iterator, struct mgcp_request *req, char *name)
01584 {
01585 int len = strlen(name);
01586 char *r;
01587 while (*iterator < req->lines) {
01588 r = get_sdp_by_line(req->line[(*iterator)++], name, len);
01589 if (r[0] != '\0') return r;
01590 }
01591 return "";
01592 }
01593
01594 static char *__get_header(struct mgcp_request *req, char *name, int *start)
01595 {
01596 int x;
01597 int len = strlen(name);
01598 char *r;
01599 for (x=*start;x<req->headers;x++) {
01600 if (!strncasecmp(req->header[x], name, len) &&
01601 (req->header[x][len] == ':')) {
01602 r = req->header[x] + len + 1;
01603 while(*r && (*r < 33))
01604 r++;
01605 *start = x+1;
01606 return r;
01607 }
01608 }
01609
01610 return "";
01611 }
01612
01613 static char *get_header(struct mgcp_request *req, char *name)
01614 {
01615 int start = 0;
01616 return __get_header(req, name, &start);
01617 }
01618
01619
01620 static char *get_csv(char *c, int *len, char **next)
01621 {
01622 char *s;
01623
01624 *next = NULL, *len = 0;
01625 if (!c) return NULL;
01626
01627 while (*c && (*c < 33 || *c == ','))
01628 c++;
01629
01630 s = c;
01631 while (*c && (*c >= 33 && *c != ','))
01632 c++, (*len)++;
01633 *next = c;
01634
01635 if (*len == 0)
01636 s = NULL, *next = NULL;
01637
01638 return s;
01639 }
01640
01641 static struct mgcp_subchannel *find_subchannel_and_lock(char *name, int msgid, struct sockaddr_in *sin)
01642 {
01643 struct mgcp_endpoint *p = NULL;
01644 struct mgcp_subchannel *sub = NULL;
01645 struct mgcp_gateway *g;
01646 char tmp[256] = "";
01647 char *at = NULL, *c;
01648 int found = 0;
01649 if (name) {
01650 ast_copy_string(tmp, name, sizeof(tmp));
01651 at = strchr(tmp, '@');
01652 if (!at) {
01653 ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name);
01654 return NULL;
01655 }
01656 *at++ = '\0';
01657 }
01658 ast_mutex_lock(&gatelock);
01659 if (at && (at[0] == '[')) {
01660 at++;
01661 c = strrchr(at, ']');
01662 if (c)
01663 *c = '\0';
01664 }
01665 g = gateways;
01666 while(g) {
01667 if ((!name || !strcasecmp(g->name, at)) &&
01668 (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) {
01669
01670 if (sin && g->dynamic && name) {
01671 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
01672 (g->addr.sin_port != sin->sin_port)) {
01673 memcpy(&g->addr, sin, sizeof(g->addr));
01674 if (ast_ouraddrfor(&g->addr.sin_addr, &g->ourip))
01675 memcpy(&g->ourip, &__ourip, sizeof(g->ourip));
01676 ast_verb(3, "Registered MGCP gateway '%s' at %s port %d\n", g->name, ast_inet_ntoa(g->addr.sin_addr), ntohs(g->addr.sin_port));
01677 }
01678 }
01679
01680 else if (name) {
01681 if (strcasecmp(g->name, at)) {
01682 g = g->next;
01683 continue;
01684 }
01685 }
01686
01687 else if (!name && sin) {
01688 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
01689 (g->addr.sin_port != sin->sin_port)) {
01690 g = g->next;
01691 continue;
01692 }
01693 } else {
01694 g = g->next;
01695 continue;
01696 }
01697
01698 p = g->endpoints;
01699 while(p) {
01700 ast_debug(1, "Searching on %s@%s for subchannel\n",
01701 p->name, g->name);
01702 if (msgid) {
01703 #if 0
01704 sub = p->sub;
01705 do {
01706 ast_debug(1, "Searching on %s@%s-%d for subchannel with lastout: %d\n",
01707 p->name, g->name, sub->id, msgid);
01708 if (sub->lastout == msgid) {
01709 ast_debug(1, "Found subchannel sub%d to handle request %d sub->lastout: %d\n",
01710 sub->id, msgid, sub->lastout);
01711 found = 1;
01712 break;
01713 }
01714 sub = sub->next;
01715 } while (sub != p->sub);
01716 if (found) {
01717 break;
01718 }
01719 #endif
01720
01721 sub = p->sub;
01722 found = 1;
01723
01724 break;
01725 } else if (name && !strcasecmp(p->name, tmp)) {
01726 ast_debug(1, "Coundn't determine subchannel, assuming current master %s@%s-%d\n",
01727 p->name, g->name, p->sub->id);
01728 sub = p->sub;
01729 found = 1;
01730 break;
01731 }
01732 p = p->next;
01733 }
01734 if (sub && found) {
01735 ast_mutex_lock(&sub->lock);
01736 break;
01737 }
01738 }
01739 g = g->next;
01740 }
01741 ast_mutex_unlock(&gatelock);
01742 if (!sub) {
01743 if (name) {
01744 if (g)
01745 ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at);
01746 else
01747 ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);
01748 }
01749 }
01750 return sub;
01751 }
01752
01753 static void parse(struct mgcp_request *req)
01754 {
01755
01756 char *c;
01757 int f = 0;
01758 c = req->data;
01759
01760
01761 req->header[f] = c;
01762 while(*c) {
01763 if (*c == '\n') {
01764
01765 *c = 0;
01766 #if 0
01767 printf("Header: %s (%d)\n", req->header[f], strlen(req->header[f]));
01768 #endif
01769 if (ast_strlen_zero(req->header[f])) {
01770
01771 c++;
01772 break;
01773 }
01774 if (f >= MGCP_MAX_HEADERS - 1) {
01775 ast_log(LOG_WARNING, "Too many MGCP headers...\n");
01776 } else
01777 f++;
01778 req->header[f] = c + 1;
01779 } else if (*c == '\r') {
01780
01781 *c = 0;
01782 }
01783 c++;
01784 }
01785
01786 if (!ast_strlen_zero(req->header[f]))
01787 f++;
01788 req->headers = f;
01789
01790 f = 0;
01791 req->line[f] = c;
01792 while(*c) {
01793 if (*c == '\n') {
01794
01795 *c = 0;
01796 #if 0
01797 printf("Line: %s (%d)\n", req->line[f], strlen(req->line[f]));
01798 #endif
01799 if (f >= MGCP_MAX_LINES - 1) {
01800 ast_log(LOG_WARNING, "Too many SDP lines...\n");
01801 } else
01802 f++;
01803 req->line[f] = c + 1;
01804 } else if (*c == '\r') {
01805
01806 *c = 0;
01807 }
01808 c++;
01809 }
01810
01811 if (!ast_strlen_zero(req->line[f]))
01812 f++;
01813 req->lines = f;
01814
01815 c = req->header[0];
01816 while(*c && *c < 33) c++;
01817
01818 req->verb = c;
01819 while(*c && (*c > 32)) c++;
01820 if (*c) {
01821 *c = '\0';
01822 c++;
01823 while(*c && (*c < 33)) c++;
01824 req->identifier = c;
01825 while(*c && (*c > 32)) c++;
01826 if (*c) {
01827 *c = '\0';
01828 c++;
01829 while(*c && (*c < 33)) c++;
01830 req->endpoint = c;
01831 while(*c && (*c > 32)) c++;
01832 if (*c) {
01833 *c = '\0';
01834 c++;
01835 while(*c && (*c < 33)) c++;
01836 req->version = c;
01837 while(*c && (*c > 32)) c++;
01838 while(*c && (*c < 33)) c++;
01839 while(*c && (*c > 32)) c++;
01840 *c = '\0';
01841 }
01842 }
01843 }
01844
01845 if (mgcpdebug) {
01846 ast_verbose("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
01847 req->verb, req->identifier, req->endpoint, req->version);
01848 ast_verbose("%d headers, %d lines\n", req->headers, req->lines);
01849 }
01850 if (*c)
01851 ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c);
01852 }
01853
01854 static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
01855 {
01856 char *m;
01857 char *c;
01858 char *a;
01859 char host[258];
01860 int len;
01861 int portno;
01862 int peercapability, peerNonCodecCapability;
01863 struct sockaddr_in sin;
01864 char *codecs;
01865 struct ast_hostent ahp; struct hostent *hp;
01866 int codec, codec_count=0;
01867 int iterator;
01868 struct mgcp_endpoint *p = sub->parent;
01869
01870
01871 m = get_sdp(req, "m");
01872 c = get_sdp(req, "c");
01873 if (ast_strlen_zero(m) || ast_strlen_zero(c)) {
01874 ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c);
01875 return -1;
01876 }
01877 if (sscanf(c, "IN IP4 %256s", host) != 1) {
01878 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
01879 return -1;
01880 }
01881
01882 hp = ast_gethostbyname(host, &ahp);
01883 if (!hp) {
01884 ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c);
01885 return -1;
01886 }
01887 if (sscanf(m, "audio %30d RTP/AVP %n", &portno, &len) != 1) {
01888 ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m);
01889 return -1;
01890 }
01891 sin.sin_family = AF_INET;
01892 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
01893 sin.sin_port = htons(portno);
01894 ast_rtp_instance_set_remote_address(sub->rtp, &sin);
01895 #if 0
01896 printf("Peer RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
01897 #endif
01898
01899 ast_rtp_codecs_payloads_clear(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp);
01900 codecs = ast_strdupa(m + len);
01901 while (!ast_strlen_zero(codecs)) {
01902 if (sscanf(codecs, "%30d%n", &codec, &len) != 1) {
01903 if (codec_count)
01904 break;
01905 ast_log(LOG_WARNING, "Error in codec string '%s' at '%s'\n", m, codecs);
01906 return -1;
01907 }
01908 ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, codec);
01909 codec_count++;
01910 codecs += len;
01911 }
01912
01913
01914
01915 sdpLineNum_iterator_init(&iterator);
01916 while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
01917 char* mimeSubtype = ast_strdupa(a);
01918 if (sscanf(a, "rtpmap: %30u %127[^/]/", &codec, mimeSubtype) != 2)
01919 continue;
01920
01921 ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, codec, "audio", mimeSubtype, 0);
01922 }
01923
01924
01925 ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(sub->rtp), &peercapability, &peerNonCodecCapability);
01926 p->capability = capability & peercapability;
01927 if (mgcpdebug) {
01928 ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n",
01929 capability, peercapability, p->capability);
01930 ast_verbose("Non-codec capabilities: us - %d, them - %d, combined - %d\n",
01931 nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability);
01932 }
01933 if (!p->capability) {
01934 ast_log(LOG_WARNING, "No compatible codecs!\n");
01935 return -1;
01936 }
01937 return 0;
01938 }
01939
01940 static int add_header(struct mgcp_request *req, const char *var, const char *value)
01941 {
01942 if (req->len >= sizeof(req->data) - 4) {
01943 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
01944 return -1;
01945 }
01946 if (req->lines) {
01947 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
01948 return -1;
01949 }
01950 req->header[req->headers] = req->data + req->len;
01951 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value);
01952 req->len += strlen(req->header[req->headers]);
01953 if (req->headers < MGCP_MAX_HEADERS)
01954 req->headers++;
01955 else {
01956 ast_log(LOG_WARNING, "Out of header space\n");
01957 return -1;
01958 }
01959 return 0;
01960 }
01961
01962 static int add_line(struct mgcp_request *req, char *line)
01963 {
01964 if (req->len >= sizeof(req->data) - 4) {
01965 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
01966 return -1;
01967 }
01968 if (!req->lines) {
01969
01970 ast_copy_string(req->data + req->len, "\r\n", sizeof(req->data) - req->len);
01971 req->len += strlen(req->data + req->len);
01972 }
01973 req->line[req->lines] = req->data + req->len;
01974 snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
01975 req->len += strlen(req->line[req->lines]);
01976 if (req->lines < MGCP_MAX_LINES)
01977 req->lines++;
01978 else {
01979 ast_log(LOG_WARNING, "Out of line space\n");
01980 return -1;
01981 }
01982 return 0;
01983 }
01984
01985 static int init_resp(struct mgcp_request *req, char *resp, struct mgcp_request *orig, char *resprest)
01986 {
01987
01988 if (req->headers || req->len) {
01989 ast_log(LOG_WARNING, "Request already initialized?!?\n");
01990 return -1;
01991 }
01992 req->header[req->headers] = req->data + req->len;
01993 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest);
01994 req->len += strlen(req->header[req->headers]);
01995 if (req->headers < MGCP_MAX_HEADERS)
01996 req->headers++;
01997 else
01998 ast_log(LOG_WARNING, "Out of header space\n");
01999 return 0;
02000 }
02001
02002 static int init_req(struct mgcp_endpoint *p, struct mgcp_request *req, char *verb)
02003 {
02004
02005 if (req->headers || req->len) {
02006 ast_log(LOG_WARNING, "Request already initialized?!?\n");
02007 return -1;
02008 }
02009 req->header[req->headers] = req->data + req->len;
02010
02011 if (p->parent->isnamedottedip)
02012 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@[%s] MGCP 1.0\r\n", verb, oseq, p->name, p->parent->name);
02013 else
02014 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@%s MGCP 1.0\r\n", verb, oseq, p->name, p->parent->name);
02015 req->len += strlen(req->header[req->headers]);
02016 if (req->headers < MGCP_MAX_HEADERS)
02017 req->headers++;
02018 else
02019 ast_log(LOG_WARNING, "Out of header space\n");
02020 return 0;
02021 }
02022
02023
02024 static int respprep(struct mgcp_request *resp, struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest)
02025 {
02026 memset(resp, 0, sizeof(*resp));
02027 init_resp(resp, msg, req, msgrest);
02028 return 0;
02029 }
02030
02031 static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
02032 {
02033 memset(req, 0, sizeof(struct mgcp_request));
02034 oseq++;
02035 if (oseq > 999999999)
02036 oseq = 1;
02037 init_req(p, req, verb);
02038 return 0;
02039 }
02040
02041 static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest)
02042 {
02043 struct mgcp_request resp;
02044 struct mgcp_endpoint *p = sub->parent;
02045 struct mgcp_response *mgr;
02046
02047 respprep(&resp, p, msg, req, msgrest);
02048 mgr = ast_calloc(1, sizeof(*mgr) + resp.len + 1);
02049 if (mgr) {
02050
02051 sscanf(req->identifier, "%30d", &mgr->seqno);
02052 time(&mgr->whensent);
02053 mgr->len = resp.len;
02054 memcpy(mgr->buf, resp.data, resp.len);
02055 mgr->buf[resp.len] = '\0';
02056 mgr->next = p->parent->responses;
02057 p->parent->responses = mgr;
02058 }
02059 return send_response(sub, &resp);
02060 }
02061
02062
02063 static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp)
02064 {
02065 int len;
02066 int codec;
02067 char costr[80];
02068 struct sockaddr_in sin;
02069 char v[256];
02070 char s[256];
02071 char o[256];
02072 char c[256];
02073 char t[256];
02074 char m[256] = "";
02075 char a[1024] = "";
02076 int x;
02077 struct sockaddr_in dest = { 0, };
02078 struct mgcp_endpoint *p = sub->parent;
02079
02080
02081 len = 0;
02082 if (!sub->rtp) {
02083 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
02084 return -1;
02085 }
02086 ast_rtp_instance_get_local_address(sub->rtp, &sin);
02087 if (rtp) {
02088 ast_rtp_instance_get_remote_address(sub->rtp, &dest);
02089 } else {
02090 if (sub->tmpdest.sin_addr.s_addr) {
02091 dest.sin_addr = sub->tmpdest.sin_addr;
02092 dest.sin_port = sub->tmpdest.sin_port;
02093
02094 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
02095 } else {
02096 dest.sin_addr = p->parent->ourip;
02097 dest.sin_port = sin.sin_port;
02098 }
02099 }
02100 if (mgcpdebug) {
02101 ast_verbose("We're at %s port %d\n", ast_inet_ntoa(p->parent->ourip), ntohs(sin.sin_port));
02102 }
02103 ast_copy_string(v, "v=0\r\n", sizeof(v));
02104 snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", (int)getpid(), (int)getpid(), ast_inet_ntoa(dest.sin_addr));
02105 ast_copy_string(s, "s=session\r\n", sizeof(s));
02106 snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr));
02107 ast_copy_string(t, "t=0 0\r\n", sizeof(t));
02108 snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
02109 for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) {
02110 if (p->capability & x) {
02111 if (mgcpdebug) {
02112 ast_verbose("Answering with capability %d\n", x);
02113 }
02114 codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, x);
02115 if (codec > -1) {
02116 snprintf(costr, sizeof(costr), " %d", codec);
02117 strncat(m, costr, sizeof(m) - strlen(m) - 1);
02118 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(1, x, 0));
02119 strncat(a, costr, sizeof(a) - strlen(a) - 1);
02120 }
02121 }
02122 }
02123 for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
02124 if (p->nonCodecCapability & x) {
02125 if (mgcpdebug) {
02126 ast_verbose("Answering with non-codec capability %d\n", x);
02127 }
02128 codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 0, x);
02129 if (codec > -1) {
02130 snprintf(costr, sizeof(costr), " %d", codec);
02131 strncat(m, costr, sizeof(m) - strlen(m) - 1);
02132 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(0, x, 0));
02133 strncat(a, costr, sizeof(a) - strlen(a) - 1);
02134 if (x == AST_RTP_DTMF) {
02135
02136
02137 snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec);
02138 strncat(a, costr, sizeof(a) - strlen(a) - 1);
02139 }
02140 }
02141 }
02142 }
02143 strncat(m, "\r\n", sizeof(m) - strlen(m) - 1);
02144 len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a);
02145 snprintf(costr, sizeof(costr), "%d", len);
02146 add_line(resp, v);
02147 add_line(resp, o);
02148 add_line(resp, s);
02149 add_line(resp, c);
02150 add_line(resp, t);
02151 add_line(resp, m);
02152 add_line(resp, a);
02153 return 0;
02154 }
02155
02156 static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp, int codecs)
02157 {
02158 struct mgcp_request resp;
02159 char local[256];
02160 char tmp[80];
02161 int x;
02162 struct mgcp_endpoint *p = sub->parent;
02163
02164 if (ast_strlen_zero(sub->cxident) && rtp) {
02165
02166
02167 ast_rtp_instance_get_remote_address(rtp, &sub->tmpdest);
02168 return 0;
02169 }
02170 ast_copy_string(local, "p:20", sizeof(local));
02171 for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) {
02172 if (p->capability & x) {
02173 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0));
02174 strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02175 }
02176 }
02177 reqprep(&resp, p, "MDCX");
02178 add_header(&resp, "C", sub->callid);
02179 add_header(&resp, "L", local);
02180 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02181
02182 add_header(&resp, "X", sub->txident);
02183 add_header(&resp, "I", sub->cxident);
02184
02185 add_sdp(&resp, sub, rtp);
02186
02187 resp.cmd = MGCP_CMD_MDCX;
02188 resp.trid = oseq;
02189 return send_request(p, sub, &resp, oseq);
02190 }
02191
02192 static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp)
02193 {
02194 struct mgcp_request resp;
02195 char local[256];
02196 char tmp[80];
02197 int x;
02198 struct mgcp_endpoint *p = sub->parent;
02199
02200 ast_copy_string(local, "p:20", sizeof(local));
02201 for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) {
02202 if (p->capability & x) {
02203 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0));
02204 strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02205 }
02206 }
02207 if (mgcpdebug) {
02208 ast_verb(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
02209 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02210 }
02211 reqprep(&resp, p, "CRCX");
02212 add_header(&resp, "C", sub->callid);
02213 add_header(&resp, "L", local);
02214 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02215
02216 add_header(&resp, "X", sub->txident);
02217
02218 add_sdp(&resp, sub, rtp);
02219
02220 resp.cmd = MGCP_CMD_CRCX;
02221 resp.trid = oseq;
02222 return send_request(p, sub, &resp, oseq);
02223 }
02224
02225 static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
02226 {
02227 struct mgcp_request resp;
02228 struct mgcp_endpoint *p = sub->parent;
02229
02230 if (mgcpdebug) {
02231 ast_verb(3, "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
02232 tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
02233 }
02234 ast_copy_string(p->curtone, tone, sizeof(p->curtone));
02235 reqprep(&resp, p, "RQNT");
02236 add_header(&resp, "X", p->rqnt_ident);
02237 switch (p->hookstate) {
02238 case MGCP_ONHOOK:
02239 add_header(&resp, "R", "L/hd(N)");
02240 break;
02241 case MGCP_OFFHOOK:
02242 add_header_offhook(sub, &resp);
02243 break;
02244 }
02245 if (!ast_strlen_zero(tone)) {
02246 add_header(&resp, "S", tone);
02247 }
02248
02249 resp.cmd = MGCP_CMD_RQNT;
02250 resp.trid = oseq;
02251 return send_request(p, NULL, &resp, oseq);
02252 }
02253
02254 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername)
02255 {
02256 struct mgcp_request resp;
02257 char tone2[256];
02258 char *l, *n;
02259 struct timeval t = ast_tvnow();
02260 struct ast_tm tm;
02261 struct mgcp_endpoint *p = sub->parent;
02262
02263 ast_localtime(&t, &tm, NULL);
02264 n = callername;
02265 l = callernum;
02266 if (!n)
02267 n = "";
02268 if (!l)
02269 l = "";
02270
02271
02272 ast_copy_string(p->lastcallerid, l, sizeof(p->lastcallerid));
02273
02274 snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone,
02275 tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n);
02276 ast_copy_string(p->curtone, tone, sizeof(p->curtone));
02277 reqprep(&resp, p, "RQNT");
02278 add_header(&resp, "X", p->rqnt_ident);
02279 switch (p->hookstate) {
02280 case MGCP_ONHOOK:
02281 add_header(&resp, "R", "L/hd(N)");
02282 break;
02283 case MGCP_OFFHOOK:
02284 add_header_offhook(sub, &resp);
02285 break;
02286 }
02287 if (!ast_strlen_zero(tone2)) {
02288 add_header(&resp, "S", tone2);
02289 }
02290 if (mgcpdebug) {
02291 ast_verb(3, "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
02292 tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
02293 }
02294
02295 resp.cmd = MGCP_CMD_RQNT;
02296 resp.trid = oseq;
02297 return send_request(p, NULL, &resp, oseq);
02298 }
02299
02300 static int transmit_modify_request(struct mgcp_subchannel *sub)
02301 {
02302 struct mgcp_request resp;
02303 struct mgcp_endpoint *p = sub->parent;
02304
02305 if (ast_strlen_zero(sub->cxident)) {
02306
02307
02308 return 0;
02309 }
02310 if (mgcpdebug) {
02311 ast_verb(3, "Modified %s@%s-%d with new mode: %s on callid: %s\n",
02312 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02313 }
02314 reqprep(&resp, p, "MDCX");
02315 add_header(&resp, "C", sub->callid);
02316 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02317
02318 add_header(&resp, "X", sub->txident);
02319 add_header(&resp, "I", sub->cxident);
02320 switch (sub->parent->hookstate) {
02321 case MGCP_ONHOOK:
02322 add_header(&resp, "R", "L/hd(N)");
02323 break;
02324 case MGCP_OFFHOOK:
02325 add_header_offhook(sub, &resp);
02326 break;
02327 }
02328
02329 resp.cmd = MGCP_CMD_MDCX;
02330 resp.trid = oseq;
02331 return send_request(p, sub, &resp, oseq);
02332 }
02333
02334
02335 static void add_header_offhook(struct mgcp_subchannel *sub, struct mgcp_request *resp)
02336 {
02337 struct mgcp_endpoint *p = sub->parent;
02338
02339 if (p && p->sub && p->sub->owner && p->sub->owner->_state >= AST_STATE_RINGING && (p->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)))
02340 add_header(resp, "R", "L/hu(N),L/hf(N)");
02341 else
02342 add_header(resp, "R", "L/hu(N),L/hf(N),D/[0-9#*](N)");
02343 }
02344
02345 static int transmit_audit_endpoint(struct mgcp_endpoint *p)
02346 {
02347 struct mgcp_request resp;
02348 reqprep(&resp, p, "AUEP");
02349
02350
02351 add_header(&resp, "F", "A");
02352
02353 resp.cmd = MGCP_CMD_AUEP;
02354 resp.trid = oseq;
02355 return send_request(p, NULL, &resp, oseq);
02356 }
02357
02358 static int transmit_connection_del(struct mgcp_subchannel *sub)
02359 {
02360 struct mgcp_endpoint *p = sub->parent;
02361 struct mgcp_request resp;
02362
02363 if (mgcpdebug) {
02364 ast_verb(3, "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n",
02365 sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02366 }
02367 reqprep(&resp, p, "DLCX");
02368
02369 if (sub->callid[0])
02370 add_header(&resp, "C", sub->callid);
02371
02372 add_header(&resp, "X", sub->txident);
02373
02374 if (sub->cxident[0])
02375 add_header(&resp, "I", sub->cxident);
02376
02377 resp.cmd = MGCP_CMD_DLCX;
02378 resp.trid = oseq;
02379 return send_request(p, sub, &resp, oseq);
02380 }
02381
02382 static int transmit_connection_del_w_params(struct mgcp_endpoint *p, char *callid, char *cxident)
02383 {
02384 struct mgcp_request resp;
02385
02386 if (mgcpdebug) {
02387 ast_verb(3, "Delete connection %s %s@%s on callid: %s\n",
02388 cxident ? cxident : "", p->name, p->parent->name, callid ? callid : "");
02389 }
02390 reqprep(&resp, p, "DLCX");
02391
02392 if (callid && *callid)
02393 add_header(&resp, "C", callid);
02394
02395 if (cxident && *cxident)
02396 add_header(&resp, "I", cxident);
02397
02398 resp.cmd = MGCP_CMD_DLCX;
02399 resp.trid = oseq;
02400 return send_request(p, p->sub, &resp, oseq);
02401 }
02402
02403
02404 static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
02405 {
02406 struct mgcp_request *t, *q;
02407
02408 if (p) {
02409 ast_mutex_lock(&p->rqnt_queue_lock);
02410 for (q = p->rqnt_queue; q; t = q->next, ast_free(q), q=t);
02411 p->rqnt_queue = NULL;
02412 ast_mutex_unlock(&p->rqnt_queue_lock);
02413
02414 ast_mutex_lock(&p->cmd_queue_lock);
02415 for (q = p->cmd_queue; q; t = q->next, ast_free(q), q=t);
02416 p->cmd_queue = NULL;
02417 ast_mutex_unlock(&p->cmd_queue_lock);
02418
02419 ast_mutex_lock(&p->sub->cx_queue_lock);
02420 for (q = p->sub->cx_queue; q; t = q->next, ast_free(q), q=t);
02421 p->sub->cx_queue = NULL;
02422 ast_mutex_unlock(&p->sub->cx_queue_lock);
02423
02424 ast_mutex_lock(&p->sub->next->cx_queue_lock);
02425 for (q = p->sub->next->cx_queue; q; t = q->next, ast_free(q), q=t);
02426 p->sub->next->cx_queue = NULL;
02427 ast_mutex_unlock(&p->sub->next->cx_queue_lock);
02428 } else if (sub) {
02429 ast_mutex_lock(&sub->cx_queue_lock);
02430 for (q = sub->cx_queue; q; t = q->next, ast_free(q), q=t);
02431 sub->cx_queue = NULL;
02432 ast_mutex_unlock(&sub->cx_queue_lock);
02433 }
02434 }
02435
02436
02437
02438 static struct mgcp_request *find_command(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
02439 struct mgcp_request **queue, ast_mutex_t *l, int ident)
02440 {
02441 struct mgcp_request *prev, *req;
02442
02443 ast_mutex_lock(l);
02444 for (prev = NULL, req = *queue; req; prev = req, req = req->next) {
02445 if (req->trid == ident) {
02446
02447 if (!prev)
02448 *queue = req->next;
02449 else
02450 prev->next = req->next;
02451
02452
02453 if (*queue) {
02454 if (mgcpdebug) {
02455 ast_verbose("Posting Queued Request:\n%s to %s:%d\n", (*queue)->data,
02456 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
02457 }
02458
02459 mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid);
02460 }
02461 break;
02462 }
02463 }
02464 ast_mutex_unlock(l);
02465 return req;
02466 }
02467
02468
02469 static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
02470 int result, unsigned int ident, struct mgcp_request *resp)
02471 {
02472 char *c;
02473 struct mgcp_request *req;
02474 struct mgcp_gateway *gw = p->parent;
02475
02476 if (result < 200) {
02477
02478 return;
02479 }
02480
02481 if (p->slowsequence)
02482 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
02483 else if (sub)
02484 req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident);
02485 else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident)))
02486 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
02487
02488 if (!req) {
02489 ast_verb(3, "No command found on [%s] for transaction %d. Ignoring...\n",
02490 gw->name, ident);
02491 return;
02492 }
02493
02494 if (p && (result >= 400) && (result <= 599)) {
02495 switch (result) {
02496 case 401:
02497 p->hookstate = MGCP_OFFHOOK;
02498 break;
02499 case 402:
02500 p->hookstate = MGCP_ONHOOK;
02501 break;
02502 case 406:
02503 ast_log(LOG_NOTICE, "Transaction %d timed out\n", ident);
02504 break;
02505 case 407:
02506 ast_log(LOG_NOTICE, "Transaction %d aborted\n", ident);
02507 break;
02508 }
02509 if (sub) {
02510 if (sub->owner) {
02511 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
02512 result, p->name, p->parent->name, sub ? sub->id:-1);
02513 mgcp_queue_hangup(sub);
02514 }
02515 } else {
02516 if (p->sub->next->owner) {
02517 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
02518 result, p->name, p->parent->name, sub ? sub->id:-1);
02519 mgcp_queue_hangup(p->sub);
02520 }
02521
02522 if (p->sub->owner) {
02523 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
02524 result, p->name, p->parent->name, sub ? sub->id:-1);
02525 mgcp_queue_hangup(p->sub);
02526 }
02527
02528 dump_cmd_queues(p, NULL);
02529 }
02530 }
02531
02532 if (resp) {
02533 if (req->cmd == MGCP_CMD_CRCX) {
02534 if ((c = get_header(resp, "I"))) {
02535 if (!ast_strlen_zero(c) && sub) {
02536
02537 if (sub->owner) {
02538 if (!ast_strlen_zero(sub->cxident)) {
02539 if (strcasecmp(c, sub->cxident)) {
02540 ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c);
02541 }
02542 }
02543 ast_copy_string(sub->cxident, c, sizeof(sub->cxident));
02544 if (sub->tmpdest.sin_addr.s_addr) {
02545 transmit_modify_with_sdp(sub, NULL, 0);
02546 }
02547 } else {
02548
02549
02550
02551
02552 transmit_connection_del(sub);
02553 }
02554 }
02555 }
02556 }
02557
02558 if (req->cmd == MGCP_CMD_AUEP) {
02559
02560 if ((c = get_header(resp, "I"))) {
02561 char *v, *n;
02562 int len;
02563 while ((v = get_csv(c, &len, &n))) {
02564 if (len) {
02565 if (strncasecmp(v, p->sub->cxident, len) &&
02566 strncasecmp(v, p->sub->next->cxident, len)) {
02567
02568 char cxident[80] = "";
02569
02570 if (len > (sizeof(cxident) - 1))
02571 len = sizeof(cxident) - 1;
02572 ast_copy_string(cxident, v, len);
02573 ast_verb(3, "Non existing connection id %s on %s@%s \n",
02574 cxident, p->name, gw->name);
02575 transmit_connection_del_w_params(p, NULL, cxident);
02576 }
02577 }
02578 c = n;
02579 }
02580 }
02581
02582
02583 if ((c = get_header(resp, "ES"))) {
02584 if (!ast_strlen_zero(c)) {
02585 if (strstr(c, "hu")) {
02586 if (p->hookstate != MGCP_ONHOOK) {
02587
02588 if ((p->sub->owner || p->sub->next->owner ) &&
02589 p->hookstate == MGCP_OFFHOOK)
02590 mgcp_queue_hangup(sub);
02591 p->hookstate = MGCP_ONHOOK;
02592
02593
02594 transmit_notify_request(p->sub, "");
02595
02596 ast_verb(3, "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name);
02597 }
02598 } else if (strstr(c, "hd")) {
02599 if (p->hookstate != MGCP_OFFHOOK) {
02600 p->hookstate = MGCP_OFFHOOK;
02601
02602
02603 transmit_notify_request(p->sub, "");
02604
02605 ast_verb(3, "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name);
02606 }
02607 }
02608 }
02609 }
02610 }
02611
02612 if (resp && resp->lines) {
02613
02614 if (sub && sub->owner) {
02615 if (!sub->rtp)
02616 start_rtp(sub);
02617 if (sub->rtp)
02618 process_sdp(sub, resp);
02619 }
02620 }
02621 }
02622
02623 ast_free(req);
02624 }
02625
02626 static void start_rtp(struct mgcp_subchannel *sub)
02627 {
02628 ast_mutex_lock(&sub->lock);
02629
02630 if (sub->rtp) {
02631 ast_rtp_instance_destroy(sub->rtp);
02632 sub->rtp = NULL;
02633 }
02634
02635 sub->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr, NULL);
02636 if (sub->rtp && sub->owner)
02637 ast_channel_set_fd(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0));
02638 if (sub->rtp) {
02639 ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "MGCP RTP");
02640 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->nat);
02641 }
02642
02643 snprintf(sub->callid, sizeof(sub->callid), "%08lx%s", ast_random(), sub->txident);
02644
02645 transmit_connect_with_sdp(sub, NULL);
02646 ast_mutex_unlock(&sub->lock);
02647 }
02648
02649 static void *mgcp_ss(void *data)
02650 {
02651 struct ast_channel *chan = data;
02652 struct mgcp_subchannel *sub = chan->tech_pvt;
02653 struct mgcp_endpoint *p = sub->parent;
02654
02655 int len = 0;
02656 int timeout = firstdigittimeout;
02657 int res= 0;
02658 int getforward = 0;
02659 int loop_pause = 100;
02660
02661 len = strlen(p->dtmf_buf);
02662
02663 while(len < AST_MAX_EXTENSION-1) {
02664 res = 1;
02665 while (strlen(p->dtmf_buf) == len){
02666 ast_safe_sleep(chan, loop_pause);
02667 timeout -= loop_pause;
02668 if (timeout <= 0){
02669 res = 0;
02670 break;
02671 }
02672 res = 1;
02673 }
02674
02675 timeout = 0;
02676 len = strlen(p->dtmf_buf);
02677
02678 if (!ast_ignore_pattern(chan->context, p->dtmf_buf)) {
02679
02680 ast_indicate(chan, -1);
02681 } else {
02682
02683
02684 transmit_notify_request(sub, "L/dl");
02685 }
02686 if (ast_exists_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) {
02687 if (!res || !ast_matchmore_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) {
02688 if (getforward) {
02689
02690 ast_copy_string(p->call_forward, p->dtmf_buf, sizeof(p->call_forward));
02691 ast_verb(3, "Setting call forward to '%s' on channel %s\n",
02692 p->call_forward, chan->name);
02693
02694 transmit_notify_request(sub, "L/sl");
02695 if (res)
02696 break;
02697 usleep(500000);
02698
02699 ast_indicate(chan, -1);
02700 sleep(1);
02701 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02702
02703 transmit_notify_request(sub, "L/dl");
02704 len = 0;
02705 getforward = 0;
02706 } else {
02707
02708 ast_indicate(chan, -1);
02709 ast_copy_string(chan->exten, p->dtmf_buf, sizeof(chan->exten));
02710 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02711 ast_set_callerid(chan,
02712 p->hidecallerid ? "" : p->cid_num,
02713 p->hidecallerid ? "" : p->cid_name,
02714 chan->cid.cid_ani ? NULL : p->cid_num);
02715 ast_setstate(chan, AST_STATE_RING);
02716
02717 if (p->dtmfmode & MGCP_DTMF_HYBRID) {
02718 p->dtmfmode |= MGCP_DTMF_INBAND;
02719 ast_indicate(chan, -1);
02720 }
02721 res = ast_pbx_run(chan);
02722 if (res) {
02723 ast_log(LOG_WARNING, "PBX exited non-zero\n");
02724
02725
02726 transmit_notify_request(sub, "G/cg");
02727 }
02728 return NULL;
02729 }
02730 } else {
02731
02732
02733 timeout = matchdigittimeout;
02734 }
02735 } else if (res == 0) {
02736 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
02737
02738 transmit_notify_request(sub, "G/cg");
02739
02740 ast_hangup(chan);
02741 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02742 return NULL;
02743 } else if (p->hascallwaiting && p->callwaiting && !strcmp(p->dtmf_buf, "*70")) {
02744 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
02745
02746 p->callwaiting = 0;
02747
02748 transmit_notify_request(sub, "L/sl");
02749 len = 0;
02750 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02751 timeout = firstdigittimeout;
02752 } else if (!strcmp(p->dtmf_buf,ast_pickup_ext())) {
02753
02754
02755
02756
02757 if (ast_pickup_call(chan)) {
02758 ast_log(LOG_WARNING, "No call pickup possible...\n");
02759
02760 transmit_notify_request(sub, "G/cg");
02761 }
02762 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02763 ast_hangup(chan);
02764 return NULL;
02765 } else if (!p->hidecallerid && !strcmp(p->dtmf_buf, "*67")) {
02766 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
02767
02768 p->hidecallerid = 1;
02769 ast_set_callerid(chan, "", "", NULL);
02770
02771 transmit_notify_request(sub, "L/sl");
02772 len = 0;
02773 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02774 timeout = firstdigittimeout;
02775 } else if (p->callreturn && !strcmp(p->dtmf_buf, "*69")) {
02776 res = 0;
02777 if (!ast_strlen_zero(p->lastcallerid)) {
02778 res = ast_say_digit_str(chan, p->lastcallerid, "", chan->language);
02779 }
02780 if (!res)
02781
02782 transmit_notify_request(sub, "L/sl");
02783 break;
02784 } else if (!strcmp(p->dtmf_buf, "*78")) {
02785
02786 ast_verb(3, "Enabled DND on channel %s\n", chan->name);
02787
02788 transmit_notify_request(sub, "L/sl");
02789 p->dnd = 1;
02790 getforward = 0;
02791 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02792 len = 0;
02793 } else if (!strcmp(p->dtmf_buf, "*79")) {
02794
02795 ast_verb(3, "Disabled DND on channel %s\n", chan->name);
02796
02797 transmit_notify_request(sub, "L/sl");
02798 p->dnd = 0;
02799 getforward = 0;
02800 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02801 len = 0;
02802 } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*72")) {
02803
02804 transmit_notify_request(sub, "L/sl");
02805 getforward = 1;
02806 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02807 len = 0;
02808 } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*73")) {
02809 ast_verb(3, "Cancelling call forwarding on channel %s\n", chan->name);
02810
02811 transmit_notify_request(sub, "L/sl");
02812 memset(p->call_forward, 0, sizeof(p->call_forward));
02813 getforward = 0;
02814 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02815 len = 0;
02816 } else if (!strcmp(p->dtmf_buf, ast_parking_ext()) &&
02817 sub->next->owner && ast_bridged_channel(sub->next->owner)) {
02818
02819
02820 ast_masq_park_call(ast_bridged_channel(sub->next->owner), chan, 0, NULL);
02821 ast_verb(3, "Parking call to '%s'\n", chan->name);
02822 break;
02823 } else if (!ast_strlen_zero(p->lastcallerid) && !strcmp(p->dtmf_buf, "*60")) {
02824 ast_verb(3, "Blacklisting number %s\n", p->lastcallerid);
02825 res = ast_db_put("blacklist", p->lastcallerid, "1");
02826 if (!res) {
02827
02828 transmit_notify_request(sub, "L/sl");
02829 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02830 len = 0;
02831 }
02832 } else if (p->hidecallerid && !strcmp(p->dtmf_buf, "*82")) {
02833 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
02834
02835 p->hidecallerid = 0;
02836 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
02837
02838 transmit_notify_request(sub, "L/sl");
02839 len = 0;
02840 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02841 timeout = firstdigittimeout;
02842 } else if (!ast_canmatch_extension(chan, chan->context, p->dtmf_buf, 1, chan->cid.cid_num) &&
02843 ((p->dtmf_buf[0] != '*') || (strlen(p->dtmf_buf) > 2))) {
02844 ast_debug(1, "Can't match %s from '%s' in context %s\n", p->dtmf_buf, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
02845 break;
02846 }
02847 if (!timeout)
02848 timeout = gendigittimeout;
02849 if (len && !ast_ignore_pattern(chan->context, p->dtmf_buf))
02850
02851 ast_indicate(chan, -1);
02852 }
02853 #if 0
02854 for (;;) {
02855 res = ast_waitfordigit(chan, to);
02856 if (!res) {
02857 ast_debug(1, "Timeout...\n");
02858 break;
02859 }
02860 if (res < 0) {
02861 ast_debug(1, "Got hangup...\n");
02862 ast_hangup(chan);
02863 break;
02864 }
02865 exten[pos++] = res;
02866 if (!ast_ignore_pattern(chan->context, exten))
02867 ast_indicate(chan, -1);
02868 if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) {
02869 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid))
02870 to = 3000;
02871 else
02872 to = 8000;
02873 } else
02874 break;
02875 }
02876 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) {
02877 ast_copy_string(chan->exten, exten, sizeof(chan->exten)1);
02878 if (!p->rtp) {
02879 start_rtp(p);
02880 }
02881 ast_setstate(chan, AST_STATE_RING);
02882 chan->rings = 1;
02883 if (ast_pbx_run(chan)) {
02884 ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name);
02885 } else {
02886 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02887 return NULL;
02888 }
02889 }
02890 #endif
02891 ast_hangup(chan);
02892 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02893 return NULL;
02894 }
02895
02896 static int attempt_transfer(struct mgcp_endpoint *p)
02897 {
02898
02899
02900
02901
02902
02903
02904
02905
02906
02907 if (ast_bridged_channel(p->sub->owner)) {
02908
02909
02910 if (ast_bridged_channel(p->sub->next->owner))
02911 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD);
02912 if (p->sub->owner->_state == AST_STATE_RINGING) {
02913 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
02914 }
02915 if (ast_channel_masquerade(p->sub->next->owner, ast_bridged_channel(p->sub->owner))) {
02916 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
02917 ast_bridged_channel(p->sub->owner)->name, p->sub->next->owner->name);
02918 return -1;
02919 }
02920
02921 unalloc_sub(p->sub->next);
02922 } else if (ast_bridged_channel(p->sub->next->owner)) {
02923 if (p->sub->owner->_state == AST_STATE_RINGING) {
02924 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
02925 }
02926 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD);
02927 if (ast_channel_masquerade(p->sub->owner, ast_bridged_channel(p->sub->next->owner))) {
02928 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
02929 ast_bridged_channel(p->sub->next->owner)->name, p->sub->owner->name);
02930 return -1;
02931 }
02932
02933 ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name);
02934 p->sub = p->sub->next;
02935 unalloc_sub(p->sub->next);
02936
02937 return 1;
02938 } else {
02939 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
02940 p->sub->owner->name, p->sub->next->owner->name);
02941 p->sub->next->owner->_softhangup |= AST_SOFTHANGUP_DEV;
02942 if (p->sub->next->owner) {
02943 p->sub->next->alreadygone = 1;
02944 mgcp_queue_hangup(p->sub->next);
02945 }
02946 }
02947 return 0;
02948 }
02949
02950 static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev)
02951 {
02952 struct mgcp_endpoint *p = sub->parent;
02953 struct ast_channel *c;
02954 pthread_t t;
02955
02956
02957 if (sub->outgoing) {
02958
02959 if (sub->owner) {
02960 if (ast_bridged_channel(sub->owner))
02961 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD);
02962 sub->cxmode = MGCP_CX_SENDRECV;
02963 if (!sub->rtp) {
02964 start_rtp(sub);
02965 } else {
02966 transmit_modify_request(sub);
02967 }
02968
02969 transmit_notify_request(sub, "");
02970 mgcp_queue_control(sub, AST_CONTROL_ANSWER);
02971 }
02972 } else {
02973
02974
02975 if (!sub->owner) {
02976 if (!sub->rtp) {
02977 start_rtp(sub);
02978 } else {
02979 transmit_modify_request(sub);
02980 }
02981 if (p->immediate) {
02982
02983 #ifdef DLINK_BUGGY_FIRMWARE
02984 transmit_notify_request(sub, "rt");
02985 #else
02986 transmit_notify_request(sub, "G/rt");
02987 #endif
02988 c = mgcp_new(sub, AST_STATE_RING, NULL);
02989 if (!c) {
02990 ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name);
02991 transmit_notify_request(sub, "G/cg");
02992 ast_hangup(c);
02993 }
02994 } else {
02995 if (has_voicemail(p)) {
02996 transmit_notify_request(sub, "L/sl");
02997 } else {
02998 transmit_notify_request(sub, "L/dl");
02999 }
03000 c = mgcp_new(sub, AST_STATE_DOWN, NULL);
03001 if (c) {
03002 if (ast_pthread_create_detached(&t, NULL, mgcp_ss, c)) {
03003 ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
03004 ast_hangup(c);
03005 }
03006 } else {
03007 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name);
03008 }
03009 }
03010 } else {
03011 if (p->hookstate == MGCP_OFFHOOK) {
03012 ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name);
03013 } else {
03014 ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name);
03015 ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?\n");
03016 }
03017 if (ast_bridged_channel(sub->owner))
03018 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD);
03019 sub->cxmode = MGCP_CX_SENDRECV;
03020 if (!sub->rtp) {
03021 start_rtp(sub);
03022 } else {
03023 transmit_modify_request(sub);
03024 }
03025
03026 transmit_notify_request(sub, "");
03027
03028 }
03029 }
03030 }
03031
03032 static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req, struct sockaddr_in *sin)
03033 {
03034 char *ev, *s;
03035 struct ast_frame f = { 0, };
03036 struct mgcp_endpoint *p = sub->parent;
03037 struct mgcp_gateway *g = NULL;
03038 int res;
03039
03040 if (mgcpdebug) {
03041 ast_verbose("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
03042 }
03043
03044 if (!strcasecmp(req->verb, "RSIP")) {
03045
03046 if(!strcasecmp( get_header(req, "RM"), "X-keepalive")) {
03047 ast_verb(3, "Received keepalive request from %s@%s\n", p->name, p->parent->name);
03048 transmit_response(sub, "200", req, "OK");
03049 } else {
03050 dump_queue(p->parent, p);
03051 dump_cmd_queues(p, NULL);
03052
03053 if ((strcmp(p->name, p->parent->wcardep) != 0)) {
03054 ast_verb(3, "Resetting interface %s@%s\n", p->name, p->parent->name);
03055 }
03056
03057 if (!strcmp(p->name, p->parent->wcardep)) {
03058
03059 struct mgcp_endpoint *tmp_ep;
03060
03061 g = p->parent;
03062 tmp_ep = g->endpoints;
03063 while (tmp_ep) {
03064
03065 if (strcmp(tmp_ep->name, g->wcardep) != 0) {
03066 struct mgcp_subchannel *tmp_sub, *first_sub;
03067 ast_verb(3, "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name);
03068
03069 first_sub = tmp_ep->sub;
03070 tmp_sub = tmp_ep->sub;
03071 while (tmp_sub) {
03072 mgcp_queue_hangup(tmp_sub);
03073 tmp_sub = tmp_sub->next;
03074 if (tmp_sub == first_sub)
03075 break;
03076 }
03077 }
03078 tmp_ep = tmp_ep->next;
03079 }
03080 } else if (sub->owner) {
03081 mgcp_queue_hangup(sub);
03082 }
03083 transmit_response(sub, "200", req, "OK");
03084
03085 if (strcmp(p->name, p->parent->wcardep) != 0) {
03086 transmit_notify_request(sub, "");
03087
03088
03089
03090 transmit_audit_endpoint(p);
03091 }
03092 }
03093 } else if (!strcasecmp(req->verb, "NTFY")) {
03094
03095 transmit_response(sub, "200", req, "OK");
03096
03097 ev = get_header(req, "O");
03098 s = strchr(ev, '/');
03099 if (s) ev = s + 1;
03100 ast_debug(1, "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev);
03101
03102 if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd") && strcasecmp(ev, "ping")) {
03103 transmit_notify_request(sub, p->curtone);
03104 }
03105 if (!strcasecmp(ev, "hd")) {
03106 p->hookstate = MGCP_OFFHOOK;
03107 sub->cxmode = MGCP_CX_SENDRECV;
03108 handle_hd_hf(sub, ev);
03109 } else if (!strcasecmp(ev, "hf")) {
03110
03111
03112
03113 if (p->hookstate != MGCP_OFFHOOK) {
03114
03115
03116 return -1;
03117 }
03118
03119 if (sub->owner && sub->owner->_state == AST_STATE_DOWN && !sub->next->owner)
03120 return -1;
03121
03122 if (p->callwaiting || p->transfer || p->threewaycalling) {
03123 ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name);
03124 p->sub = p->sub->next;
03125
03126
03127 if (!sub->next->owner) {
03128
03129 sub->cxmode = MGCP_CX_MUTE;
03130 ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
03131 transmit_modify_request(sub);
03132 if (sub->owner && ast_bridged_channel(sub->owner))
03133 ast_queue_control(sub->owner, AST_CONTROL_HOLD);
03134 sub->next->cxmode = MGCP_CX_RECVONLY;
03135 handle_hd_hf(sub->next, ev);
03136 } else if (sub->owner && sub->next->owner) {
03137
03138 if ((!sub->outgoing) && (!sub->next->outgoing)) {
03139
03140 ast_verb(3, "MGCP Conferencing %d and %d on %s@%s\n",
03141 sub->id, sub->next->id, p->name, p->parent->name);
03142 sub->cxmode = MGCP_CX_CONF;
03143 sub->next->cxmode = MGCP_CX_CONF;
03144 if (ast_bridged_channel(sub->next->owner))
03145 ast_queue_control(sub->next->owner, AST_CONTROL_UNHOLD);
03146 transmit_modify_request(sub);
03147 transmit_modify_request(sub->next);
03148 } else {
03149
03150
03151
03152 ast_verb(3, "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n",
03153 sub->id, sub->next->id, p->name, p->parent->name);
03154 sub->cxmode = MGCP_CX_MUTE;
03155 ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
03156 transmit_modify_request(sub);
03157 if (ast_bridged_channel(sub->owner))
03158 ast_queue_control(sub->owner, AST_CONTROL_HOLD);
03159
03160 if (ast_bridged_channel(sub->next->owner))
03161 ast_queue_control(sub->next->owner, AST_CONTROL_HOLD);
03162
03163 handle_hd_hf(sub->next, ev);
03164 }
03165 } else {
03166
03167 if (sub->owner) {
03168 p->sub = sub;
03169 } else if (sub->next->owner) {
03170 p->sub = sub->next;
03171 } else {
03172
03173
03174 return -1;
03175 }
03176 if (ast_bridged_channel(p->sub->owner))
03177 ast_queue_control(p->sub->owner, AST_CONTROL_UNHOLD);
03178 p->sub->cxmode = MGCP_CX_SENDRECV;
03179 transmit_modify_request(p->sub);
03180 }
03181 } else {
03182 ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n",
03183 p->name, p->parent->name);
03184 }
03185 } else if (!strcasecmp(ev, "hu")) {
03186 p->hookstate = MGCP_ONHOOK;
03187 sub->cxmode = MGCP_CX_RECVONLY;
03188 ast_debug(1, "MGCP %s@%s Went on hook\n", p->name, p->parent->name);
03189
03190
03191
03192
03193
03194 if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) {
03195
03196
03197 ast_mutex_lock(&p->sub->next->lock);
03198 res = attempt_transfer(p);
03199 if (res < 0) {
03200 if (p->sub->next->owner) {
03201 sub->next->alreadygone = 1;
03202 mgcp_queue_hangup(sub->next);
03203 }
03204 } else if (res) {
03205 ast_log(LOG_WARNING, "Transfer attempt failed\n");
03206 ast_mutex_unlock(&p->sub->next->lock);
03207 return -1;
03208 }
03209 ast_mutex_unlock(&p->sub->next->lock);
03210 } else {
03211
03212
03213 if (sub->owner) {
03214 sub->alreadygone = 1;
03215 mgcp_queue_hangup(sub);
03216 } else {
03217 ast_verb(3, "MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n",
03218 p->name, p->parent->name, sub->id);
03219
03220
03221
03222 transmit_connection_del(sub);
03223 }
03224 }
03225 if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) {
03226 p->hidecallerid = 0;
03227 if (p->hascallwaiting && !p->callwaiting) {
03228 ast_verb(3, "Enabling call waiting on MGCP/%s@%s-%d\n", p->name, p->parent->name, sub->id);
03229 p->callwaiting = -1;
03230 }
03231 if (has_voicemail(p)) {
03232 ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name);
03233 transmit_notify_request(sub, "L/vmwi(+)");
03234 } else {
03235 ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name);
03236 transmit_notify_request(sub, "L/vmwi(-)");
03237 }
03238 }
03239 } else if ((strlen(ev) == 1) &&
03240 (((ev[0] >= '0') && (ev[0] <= '9')) ||
03241 ((ev[0] >= 'A') && (ev[0] <= 'D')) ||
03242 (ev[0] == '*') || (ev[0] == '#'))) {
03243 if (sub && sub->owner && (sub->owner->_state >= AST_STATE_UP)) {
03244 f.frametype = AST_FRAME_DTMF;
03245 f.subclass = ev[0];
03246 f.src = "mgcp";
03247
03248 mgcp_queue_frame(sub, &f);
03249 ast_mutex_lock(&sub->next->lock);
03250 if (sub->next->owner)
03251 mgcp_queue_frame(sub->next, &f);
03252 ast_mutex_unlock(&sub->next->lock);
03253 if (strstr(p->curtone, "wt") && (ev[0] == 'A')) {
03254 memset(p->curtone, 0, sizeof(p->curtone));
03255 }
03256 } else {
03257 p->dtmf_buf[strlen(p->dtmf_buf)] = ev[0];
03258 p->dtmf_buf[strlen(p->dtmf_buf)] = '\0';
03259 }
03260 } else if (!strcasecmp(ev, "T")) {
03261
03262 } else if (!strcasecmp(ev, "ping")) {
03263
03264 } else {
03265 ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name);
03266 }
03267 } else {
03268 ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, ast_inet_ntoa(sin->sin_addr));
03269 transmit_response(sub, "510", req, "Unknown verb");
03270 }
03271 return 0;
03272 }
03273
03274 static int find_and_retrans(struct mgcp_subchannel *sub, struct mgcp_request *req)
03275 {
03276 int seqno=0;
03277 time_t now;
03278 struct mgcp_response *prev = NULL, *cur, *next, *answer=NULL;
03279 time(&now);
03280 if (sscanf(req->identifier, "%30d", &seqno) != 1)
03281 seqno = 0;
03282 cur = sub->parent->parent->responses;
03283 while(cur) {
03284 next = cur->next;
03285 if (now - cur->whensent > RESPONSE_TIMEOUT) {
03286
03287 if (prev)
03288 prev->next = next;
03289 else
03290 sub->parent->parent->responses = next;
03291 ast_free(cur);
03292 } else {
03293 if (seqno == cur->seqno)
03294 answer = cur;
03295 prev = cur;
03296 }
03297 cur = next;
03298 }
03299 if (answer) {
03300 resend_response(sub, answer);
03301 return 1;
03302 }
03303 return 0;
03304 }
03305
03306 static int mgcpsock_read(int *id, int fd, short events, void *ignore)
03307 {
03308 struct mgcp_request req;
03309 struct sockaddr_in sin;
03310 struct mgcp_subchannel *sub;
03311 int res;
03312 socklen_t len;
03313 int result;
03314 int ident;
03315 len = sizeof(sin);
03316 memset(&req, 0, sizeof(req));
03317 res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
03318 if (res < 0) {
03319 if (errno != ECONNREFUSED)
03320 ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno));
03321 return 1;
03322 }
03323 req.data[res] = '\0';
03324 req.len = res;
03325 if (mgcpdebug) {
03326 ast_verbose("MGCP read: \n%s\nfrom %s:%d\n", req.data, ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
03327 }
03328 parse(&req);
03329 if (req.headers < 1) {
03330
03331 return 1;
03332 }
03333 if (ast_strlen_zero(req.identifier)) {
03334 ast_log(LOG_NOTICE, "Message from %s missing identifier\n", ast_inet_ntoa(sin.sin_addr));
03335 return 1;
03336 }
03337
03338 if (sscanf(req.verb, "%30d", &result) && sscanf(req.identifier, "%30d", &ident)) {
03339
03340 sub = find_subchannel_and_lock(NULL, ident, &sin);
03341 if (sub) {
03342 struct mgcp_gateway *gw = sub->parent->parent;
03343 struct mgcp_message *cur, *prev;
03344
03345 ast_mutex_unlock(&sub->lock);
03346 ast_mutex_lock(&gw->msgs_lock);
03347 for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
03348 if (cur->seqno == ident) {
03349 ast_debug(1, "Got response back on transaction %d\n", ident);
03350 if (prev)
03351 prev->next = cur->next;
03352 else
03353 gw->msgs = cur->next;
03354 break;
03355 }
03356 }
03357
03358
03359 if (!gw->msgs) {
03360 AST_SCHED_DEL(sched, gw->retransid);
03361 }
03362
03363 ast_mutex_unlock(&gw->msgs_lock);
03364 if (cur) {
03365 handle_response(cur->owner_ep, cur->owner_sub, result, ident, &req);
03366 ast_free(cur);
03367 return 1;
03368 }
03369
03370 ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n",
03371 gw->name, ident);
03372 }
03373 } else {
03374 if (ast_strlen_zero(req.endpoint) ||
03375 ast_strlen_zero(req.version) ||
03376 ast_strlen_zero(req.verb)) {
03377 ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n");
03378 return 1;
03379 }
03380
03381 sub = find_subchannel_and_lock(req.endpoint, 0, &sin);
03382 if (sub) {
03383
03384 if (!find_and_retrans(sub, &req))
03385
03386 handle_request(sub, &req, &sin);
03387 ast_mutex_unlock(&sub->lock);
03388 }
03389 }
03390 return 1;
03391 }
03392
03393 static int *mgcpsock_read_id = NULL;
03394
03395 static void *do_monitor(void *data)
03396 {
03397 int res;
03398 int reloading;
03399
03400
03401
03402
03403
03404 if (mgcpsock > -1)
03405 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
03406
03407
03408
03409
03410 for(;;) {
03411
03412 ast_mutex_lock(&mgcp_reload_lock);
03413 reloading = mgcp_reloading;
03414 mgcp_reloading = 0;
03415 ast_mutex_unlock(&mgcp_reload_lock);
03416 if (reloading) {
03417 ast_verb(1, "Reloading MGCP\n");
03418 reload_config(1);
03419
03420 if (mgcpsock > -1 && !mgcpsock_read_id) {
03421 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
03422 }
03423 }
03424
03425
03426
03427
03428 ast_mutex_lock(&monlock);
03429
03430 ast_mutex_lock(&netlock);
03431
03432 #if 0
03433
03434
03435
03436 lastpass = thispass;
03437 thispass = time(NULL);
03438 g = gateways;
03439 while(g) {
03440 if (thispass != lastpass) {
03441 e = g->endpoints;
03442 while(e) {
03443 if (e->type == TYPE_LINE) {
03444 res = has_voicemail(e);
03445 if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){
03446 if (res) {
03447 transmit_notify_request(e, "L/vmwi(+)");
03448 } else {
03449 transmit_notify_request(e, "L/vmwi(-)");
03450 }
03451 e->msgstate = res;
03452 e->onhooktime = thispass;
03453 }
03454 }
03455 e = e->next;
03456 }
03457 }
03458 g = g->next;
03459 }
03460 #endif
03461
03462 ast_mutex_unlock(&netlock);
03463
03464 ast_mutex_unlock(&monlock);
03465 pthread_testcancel();
03466
03467 res = ast_sched_wait(sched);
03468
03469 if ((res < 0) || (res > 1000))
03470 res = 1000;
03471 res = ast_io_wait(io, res);
03472 ast_mutex_lock(&monlock);
03473 if (res >= 0)
03474 ast_sched_runq(sched);
03475 ast_mutex_unlock(&monlock);
03476 }
03477
03478 return NULL;
03479 }
03480
03481 static int restart_monitor(void)
03482 {
03483
03484 if (monitor_thread == AST_PTHREADT_STOP)
03485 return 0;
03486 if (ast_mutex_lock(&monlock)) {
03487 ast_log(LOG_WARNING, "Unable to lock monitor\n");
03488 return -1;
03489 }
03490 if (monitor_thread == pthread_self()) {
03491 ast_mutex_unlock(&monlock);
03492 ast_log(LOG_WARNING, "Cannot kill myself\n");
03493 return -1;
03494 }
03495 if (monitor_thread != AST_PTHREADT_NULL) {
03496
03497 pthread_kill(monitor_thread, SIGURG);
03498 } else {
03499
03500 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
03501 ast_mutex_unlock(&monlock);
03502 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
03503 return -1;
03504 }
03505 }
03506 ast_mutex_unlock(&monlock);
03507 return 0;
03508 }
03509
03510 static struct ast_channel *mgcp_request(const char *type, int format, const struct ast_channel *requestor, void *data, int *cause)
03511 {
03512 int oldformat;
03513 struct mgcp_subchannel *sub;
03514 struct ast_channel *tmpc = NULL;
03515 char tmp[256];
03516 char *dest = data;
03517
03518 oldformat = format;
03519 format &= capability;
03520 if (!format) {
03521 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
03522 return NULL;
03523 }
03524 ast_copy_string(tmp, dest, sizeof(tmp));
03525 if (ast_strlen_zero(tmp)) {
03526 ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n");
03527 return NULL;
03528 }
03529 sub = find_subchannel_and_lock(tmp, 0, NULL);
03530 if (!sub) {
03531 ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp);
03532 *cause = AST_CAUSE_UNREGISTERED;
03533 return NULL;
03534 }
03535
03536 ast_verb(3, "MGCP mgcp_request(%s)\n", tmp);
03537 ast_verb(3, "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n",
03538 sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0);
03539
03540 if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) ||
03541 ((!sub->parent->callwaiting) && (sub->owner)) ||
03542 (sub->parent->dnd && (ast_strlen_zero(sub->parent->call_forward)))) {
03543 if (sub->parent->hookstate == MGCP_ONHOOK) {
03544 if (has_voicemail(sub->parent)) {
03545 transmit_notify_request(sub,"L/vmwi(+)");
03546 } else {
03547 transmit_notify_request(sub,"L/vmwi(-)");
03548 }
03549 }
03550 *cause = AST_CAUSE_BUSY;
03551 ast_mutex_unlock(&sub->lock);
03552 return NULL;
03553 }
03554 tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL);
03555 ast_mutex_unlock(&sub->lock);
03556 if (!tmpc)
03557 ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
03558 restart_monitor();
03559 return tmpc;
03560 }
03561
03562
03563
03564 static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
03565 {
03566 struct mgcp_gateway *gw;
03567 struct mgcp_endpoint *e;
03568 struct mgcp_subchannel *sub;
03569 struct ast_variable *chanvars = NULL;
03570
03571
03572 int i=0, y=0;
03573 int gw_reload = 0;
03574 int ep_reload = 0;
03575 directmedia = DIRECTMEDIA;
03576
03577
03578 gw = gateways;
03579 while (gw) {
03580 if (!strcasecmp(cat, gw->name)) {
03581
03582 gw->delme = 0;
03583 gw_reload = 1;
03584 break;
03585 }
03586 gw = gw->next;
03587 }
03588
03589 if (!gw)
03590 gw = ast_calloc(1, sizeof(*gw));
03591
03592 if (gw) {
03593 if (!gw_reload) {
03594 gw->expire = -1;
03595 gw->retransid = -1;
03596 ast_mutex_init(&gw->msgs_lock);
03597 ast_copy_string(gw->name, cat, sizeof(gw->name));
03598
03599 if ((strchr(gw->name, '.')) && inet_addr(gw->name) != INADDR_NONE)
03600 gw->isnamedottedip = 1;
03601 }
03602 while(v) {
03603 if (!strcasecmp(v->name, "host")) {
03604 if (!strcasecmp(v->value, "dynamic")) {
03605
03606 gw->dynamic = 1;
03607 memset(&gw->addr.sin_addr, 0, 4);
03608 if (gw->addr.sin_port) {
03609
03610 gw->defaddr.sin_port = gw->addr.sin_port;
03611 gw->addr.sin_port = 0;
03612 }
03613 } else {
03614
03615 AST_SCHED_DEL(sched, gw->expire);
03616 gw->dynamic = 0;
03617 if (ast_get_ip(&gw->addr, v->value)) {
03618 if (!gw_reload) {
03619 ast_mutex_destroy(&gw->msgs_lock);
03620 ast_free(gw);
03621 }
03622 return NULL;
03623 }
03624 }
03625 } else if (!strcasecmp(v->name, "defaultip")) {
03626 if (ast_get_ip(&gw->defaddr, v->value)) {
03627 if (!gw_reload) {
03628 ast_mutex_destroy(&gw->msgs_lock);
03629 ast_free(gw);
03630 }
03631 return NULL;
03632 }
03633 } else if (!strcasecmp(v->name, "permit") ||
03634 !strcasecmp(v->name, "deny")) {
03635 gw->ha = ast_append_ha(v->name, v->value, gw->ha, NULL);
03636 } else if (!strcasecmp(v->name, "port")) {
03637 gw->addr.sin_port = htons(atoi(v->value));
03638 } else if (!strcasecmp(v->name, "context")) {
03639 ast_copy_string(context, v->value, sizeof(context));
03640 } else if (!strcasecmp(v->name, "dtmfmode")) {
03641 if (!strcasecmp(v->value, "inband"))
03642 dtmfmode = MGCP_DTMF_INBAND;
03643 else if (!strcasecmp(v->value, "rfc2833"))
03644 dtmfmode = MGCP_DTMF_RFC2833;
03645 else if (!strcasecmp(v->value, "hybrid"))
03646 dtmfmode = MGCP_DTMF_HYBRID;
03647 else if (!strcasecmp(v->value, "none"))
03648 dtmfmode = 0;
03649 else
03650 ast_log(LOG_WARNING, "'%s' is not a valid DTMF mode at line %d\n", v->value, v->lineno);
03651 } else if (!strcasecmp(v->name, "nat")) {
03652 nat = ast_true(v->value);
03653 } else if (!strcasecmp(v->name, "callerid")) {
03654 if (!strcasecmp(v->value, "asreceived")) {
03655 cid_num[0] = '\0';
03656 cid_name[0] = '\0';
03657 } else {
03658 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
03659 }
03660 } else if (!strcasecmp(v->name, "language")) {
03661 ast_copy_string(language, v->value, sizeof(language));
03662 } else if (!strcasecmp(v->name, "accountcode")) {
03663 ast_copy_string(accountcode, v->value, sizeof(accountcode));
03664 } else if (!strcasecmp(v->name, "amaflags")) {
03665 y = ast_cdr_amaflags2int(v->value);
03666 if (y < 0) {
03667 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
03668 } else {
03669 amaflags = y;
03670 }
03671
03672 } else if (!strcasecmp(v->name, "setvar")) {
03673 chanvars = add_var(v->value, chanvars);
03674 } else if (!strcasecmp(v->name, "clearvars")) {
03675 if (chanvars) {
03676 ast_variables_destroy(chanvars);
03677 chanvars = NULL;
03678 }
03679 } else if (!strcasecmp(v->name, "musiconhold")) {
03680 ast_copy_string(musicclass, v->value, sizeof(musicclass));
03681 } else if (!strcasecmp(v->name, "parkinglot")) {
03682 ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
03683 } else if (!strcasecmp(v->name, "callgroup")) {
03684 cur_callergroup = ast_get_group(v->value);
03685 } else if (!strcasecmp(v->name, "pickupgroup")) {
03686 cur_pickupgroup = ast_get_group(v->value);
03687 } else if (!strcasecmp(v->name, "immediate")) {
03688 immediate = ast_true(v->value);
03689 } else if (!strcasecmp(v->name, "cancallforward")) {
03690 cancallforward = ast_true(v->value);
03691 } else if (!strcasecmp(v->name, "singlepath")) {
03692 singlepath = ast_true(v->value);
03693 } else if (!strcasecmp(v->name, "directmedia") || !strcasecmp(v->name, "canreinvite")) {
03694 directmedia = ast_true(v->value);
03695 } else if (!strcasecmp(v->name, "mailbox")) {
03696 ast_copy_string(mailbox, v->value, sizeof(mailbox));
03697 } else if (!strcasecmp(v->name, "hasvoicemail")) {
03698 if (ast_true(v->value) && ast_strlen_zero(mailbox)) {
03699 ast_copy_string(mailbox, gw->name, sizeof(mailbox));
03700 }
03701 } else if (!strcasecmp(v->name, "adsi")) {
03702 adsi = ast_true(v->value);
03703 } else if (!strcasecmp(v->name, "callreturn")) {
03704 callreturn = ast_true(v->value);
03705 } else if (!strcasecmp(v->name, "callwaiting")) {
03706 callwaiting = ast_true(v->value);
03707 } else if (!strcasecmp(v->name, "slowsequence")) {
03708 slowsequence = ast_true(v->value);
03709 } else if (!strcasecmp(v->name, "transfer")) {
03710 transfer = ast_true(v->value);
03711 } else if (!strcasecmp(v->name, "threewaycalling")) {
03712 threewaycalling = ast_true(v->value);
03713 } else if (!strcasecmp(v->name, "wcardep")) {
03714
03715 e = gw->endpoints;
03716 while (e) {
03717 if (!strcasecmp(v->value, e->name)) {
03718
03719 e->delme = 0;
03720 ep_reload = 1;
03721 break;
03722 }
03723 e = e->next;
03724 }
03725
03726 if (!e) {
03727
03728 e = ast_calloc(1, sizeof(*e));
03729 ep_reload = 0;
03730 }
03731
03732 if (e) {
03733 if (!ep_reload) {
03734 memset(e, 0, sizeof(struct mgcp_endpoint));
03735 ast_mutex_init(&e->lock);
03736 ast_mutex_init(&e->rqnt_queue_lock);
03737 ast_mutex_init(&e->cmd_queue_lock);
03738 ast_copy_string(e->name, v->value, sizeof(e->name));
03739 e->needaudit = 1;
03740 }
03741 ast_copy_string(gw->wcardep, v->value, sizeof(gw->wcardep));
03742
03743 ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode));
03744 ast_copy_string(e->context, context, sizeof(e->context));
03745 ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num));
03746 ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name));
03747 ast_copy_string(e->language, language, sizeof(e->language));
03748 ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass));
03749 ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
03750 ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot));
03751 if (!ast_strlen_zero(e->mailbox)) {
03752 char *mbox, *cntx;
03753 cntx = mbox = ast_strdupa(e->mailbox);
03754 strsep(&cntx, "@");
03755 if (ast_strlen_zero(cntx))
03756 cntx = "default";
03757 e->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "MGCP MWI subscription", NULL,
03758 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox,
03759 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cntx,
03760 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
03761 AST_EVENT_IE_END);
03762 }
03763 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random());
03764 e->msgstate = -1;
03765 e->amaflags = amaflags;
03766 e->capability = capability;
03767 e->parent = gw;
03768 e->dtmfmode = dtmfmode;
03769 if (!ep_reload && e->sub && e->sub->rtp)
03770 e->dtmfmode |= MGCP_DTMF_INBAND;
03771 e->adsi = adsi;
03772 e->type = TYPE_LINE;
03773 e->immediate = immediate;
03774 e->callgroup=cur_callergroup;
03775 e->pickupgroup=cur_pickupgroup;
03776 e->callreturn = callreturn;
03777 e->cancallforward = cancallforward;
03778 e->singlepath = singlepath;
03779 e->directmedia = directmedia;
03780 e->callwaiting = callwaiting;
03781 e->hascallwaiting = callwaiting;
03782 e->slowsequence = slowsequence;
03783 e->transfer = transfer;
03784 e->threewaycalling = threewaycalling;
03785 e->onhooktime = time(NULL);
03786
03787 e->hookstate = MGCP_ONHOOK;
03788 e->chanvars = copy_vars(chanvars);
03789 if (!ep_reload) {
03790
03791 for (i = 0; i < MAX_SUBS; i++) {
03792 sub = ast_calloc(1, sizeof(*sub));
03793 if (sub) {
03794 ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
03795 ast_mutex_init(&sub->lock);
03796 ast_mutex_init(&sub->cx_queue_lock);
03797 sub->parent = e;
03798 sub->id = i;
03799 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random());
03800
03801 sub->cxmode = MGCP_CX_INACTIVE;
03802 sub->nat = nat;
03803 sub->next = e->sub;
03804 e->sub = sub;
03805 } else {
03806
03807 ast_log(LOG_WARNING, "Out of memory allocating subchannel\n");
03808 return NULL;
03809 }
03810 }
03811
03812 sub = e->sub;
03813
03814 while(sub->next){
03815 sub = sub->next;
03816 }
03817
03818 sub->next = e->sub;
03819
03820 e->next = gw->endpoints;
03821 gw->endpoints = e;
03822 }
03823 }
03824 } else if (!strcasecmp(v->name, "trunk") ||
03825 !strcasecmp(v->name, "line")) {
03826
03827
03828 e = gw->endpoints;
03829 while (e) {
03830 if (!strcasecmp(v->value, e->name)) {
03831
03832 e->delme = 0;
03833 ep_reload = 1;
03834 break;
03835 }
03836 e = e->next;
03837 }
03838
03839 if (!e) {
03840 e = ast_calloc(1, sizeof(*e));
03841 ep_reload = 0;
03842 }
03843
03844 if (e) {
03845 if (!ep_reload) {
03846 ast_mutex_init(&e->lock);
03847 ast_mutex_init(&e->rqnt_queue_lock);
03848 ast_mutex_init(&e->cmd_queue_lock);
03849 ast_copy_string(e->name, v->value, sizeof(e->name));
03850 e->needaudit = 1;
03851 }
03852
03853 ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode));
03854 ast_copy_string(e->context, context, sizeof(e->context));
03855 ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num));
03856 ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name));
03857 ast_copy_string(e->language, language, sizeof(e->language));
03858 ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass));
03859 ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
03860 ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot));
03861 if (!ast_strlen_zero(mailbox)) {
03862 ast_verb(3, "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name);
03863 }
03864 if (!ep_reload) {
03865
03866 e->msgstate = -1;
03867 e->parent = gw;
03868 }
03869 e->amaflags = amaflags;
03870 e->capability = capability;
03871 e->dtmfmode = dtmfmode;
03872 e->adsi = adsi;
03873 if (!strcasecmp(v->name, "trunk"))
03874 e->type = TYPE_TRUNK;
03875 else
03876 e->type = TYPE_LINE;
03877
03878 e->immediate = immediate;
03879 e->callgroup=cur_callergroup;
03880 e->pickupgroup=cur_pickupgroup;
03881 e->callreturn = callreturn;
03882 e->cancallforward = cancallforward;
03883 e->directmedia = directmedia;
03884 e->singlepath = singlepath;
03885 e->callwaiting = callwaiting;
03886 e->hascallwaiting = callwaiting;
03887 e->slowsequence = slowsequence;
03888 e->transfer = transfer;
03889 e->threewaycalling = threewaycalling;
03890
03891
03892
03893
03894 if (e->chanvars) {
03895 ast_variables_destroy(e->chanvars);
03896 e->chanvars = NULL;
03897 }
03898 e->chanvars = copy_vars(chanvars);
03899
03900 if (!ep_reload) {
03901 e->onhooktime = time(NULL);
03902
03903 e->hookstate = MGCP_ONHOOK;
03904 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random());
03905 }
03906
03907 for (i = 0, sub = NULL; i < MAX_SUBS; i++) {
03908 if (!ep_reload) {
03909 sub = ast_calloc(1, sizeof(*sub));
03910 } else {
03911 if (!sub)
03912 sub = e->sub;
03913 else
03914 sub = sub->next;
03915 }
03916
03917 if (sub) {
03918 if (!ep_reload) {
03919 ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
03920 ast_mutex_init(&sub->lock);
03921 ast_mutex_init(&sub->cx_queue_lock);
03922 ast_copy_string(sub->magic, MGCP_SUBCHANNEL_MAGIC, sizeof(sub->magic));
03923 sub->parent = e;
03924 sub->id = i;
03925 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random());
03926 sub->cxmode = MGCP_CX_INACTIVE;
03927 sub->next = e->sub;
03928 e->sub = sub;
03929 }
03930 sub->nat = nat;
03931 } else {
03932
03933 ast_log(LOG_WARNING, "Out of memory allocating subchannel\n");
03934 return NULL;
03935 }
03936 }
03937 if (!ep_reload) {
03938
03939 sub = e->sub;
03940
03941 while (sub->next) {
03942 sub = sub->next;
03943 }
03944
03945 sub->next = e->sub;
03946
03947 e->next = gw->endpoints;
03948 gw->endpoints = e;
03949 }
03950 }
03951 } else
03952 ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
03953 v = v->next;
03954 }
03955 }
03956 if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) {
03957 ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name);
03958 if (!gw_reload) {
03959 ast_mutex_destroy(&gw->msgs_lock);
03960 ast_free(gw);
03961 }
03962
03963
03964 gw_reload = 1;
03965 } else {
03966 gw->defaddr.sin_family = AF_INET;
03967 gw->addr.sin_family = AF_INET;
03968 if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port)) {
03969 gw->defaddr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
03970 }
03971 if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port)) {
03972 gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
03973 }
03974 if (gw->addr.sin_addr.s_addr && ast_ouraddrfor(&gw->addr.sin_addr, &gw->ourip)) {
03975 memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip));
03976 }
03977 }
03978
03979 if (chanvars) {
03980 ast_variables_destroy(chanvars);
03981 chanvars = NULL;
03982 }
03983 return (gw_reload ? NULL : gw);
03984 }
03985
03986 static enum ast_rtp_glue_result mgcp_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
03987 {
03988 struct mgcp_subchannel *sub = NULL;
03989
03990 if (!(sub = chan->tech_pvt) || !(sub->rtp))
03991 return AST_RTP_GLUE_RESULT_FORBID;
03992
03993 *instance = sub->rtp ? ao2_ref(sub->rtp, +1), sub->rtp : NULL;
03994
03995 if (sub->parent->directmedia)
03996 return AST_RTP_GLUE_RESULT_REMOTE;
03997 else
03998 return AST_RTP_GLUE_RESULT_LOCAL;
03999 }
04000
04001 static int mgcp_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, int codecs, int nat_active)
04002 {
04003
04004 struct mgcp_subchannel *sub;
04005 sub = chan->tech_pvt;
04006 if (sub && !sub->alreadygone) {
04007 transmit_modify_with_sdp(sub, rtp, codecs);
04008 return 0;
04009 }
04010 return -1;
04011 }
04012
04013 static struct ast_rtp_glue mgcp_rtp_glue = {
04014 .type = "MGCP",
04015 .get_rtp_info = mgcp_get_rtp_peer,
04016 .update_peer = mgcp_set_rtp_peer,
04017 };
04018
04019 static void destroy_endpoint(struct mgcp_endpoint *e)
04020 {
04021 struct mgcp_subchannel *sub = e->sub->next, *s;
04022 int i;
04023
04024 for (i = 0; i < MAX_SUBS; i++) {
04025 ast_mutex_lock(&sub->lock);
04026 if (!ast_strlen_zero(sub->cxident)) {
04027 transmit_connection_del(sub);
04028 }
04029 if (sub->rtp) {
04030 ast_rtp_instance_destroy(sub->rtp);
04031 sub->rtp = NULL;
04032 }
04033 memset(sub->magic, 0, sizeof(sub->magic));
04034 mgcp_queue_hangup(sub);
04035 dump_cmd_queues(NULL, sub);
04036 ast_mutex_unlock(&sub->lock);
04037 sub = sub->next;
04038 }
04039
04040 if (e->dsp) {
04041 ast_dsp_free(e->dsp);
04042 }
04043
04044 dump_queue(e->parent, e);
04045 dump_cmd_queues(e, NULL);
04046
04047 sub = e->sub;
04048 for (i = 0; (i < MAX_SUBS) && sub; i++) {
04049 s = sub;
04050 sub = sub->next;
04051 ast_mutex_destroy(&s->lock);
04052 ast_mutex_destroy(&s->cx_queue_lock);
04053 ast_free(s);
04054 }
04055
04056 if (e->mwi_event_sub)
04057 ast_event_unsubscribe(e->mwi_event_sub);
04058
04059 if (e->chanvars) {
04060 ast_variables_destroy(e->chanvars);
04061 e->chanvars = NULL;
04062 }
04063
04064 ast_mutex_destroy(&e->lock);
04065 ast_mutex_destroy(&e->rqnt_queue_lock);
04066 ast_mutex_destroy(&e->cmd_queue_lock);
04067 ast_free(e);
04068 }
04069
04070 static void destroy_gateway(struct mgcp_gateway *g)
04071 {
04072 if (g->ha)
04073 ast_free_ha(g->ha);
04074
04075 dump_queue(g, NULL);
04076
04077 ast_free(g);
04078 }
04079
04080 static void prune_gateways(void)
04081 {
04082 struct mgcp_gateway *g, *z, *r;
04083 struct mgcp_endpoint *e, *p, *t;
04084
04085 ast_mutex_lock(&gatelock);
04086
04087
04088 for (z = NULL, g = gateways; g;) {
04089
04090 for (p = NULL, e = g->endpoints; e; ) {
04091 if (e->delme || g->delme) {
04092 t = e;
04093 e = e->next;
04094 if (!p)
04095 g->endpoints = e;
04096 else
04097 p->next = e;
04098 destroy_endpoint(t);
04099 } else {
04100 p = e;
04101 e = e->next;
04102 }
04103 }
04104
04105 if (g->delme) {
04106 r = g;
04107 g = g->next;
04108 if (!z)
04109 gateways = g;
04110 else
04111 z->next = g;
04112
04113 destroy_gateway(r);
04114 } else {
04115 z = g;
04116 g = g->next;
04117 }
04118 }
04119
04120 ast_mutex_unlock(&gatelock);
04121 }
04122
04123 static struct ast_variable *add_var(const char *buf, struct ast_variable *list)
04124 {
04125 struct ast_variable *tmpvar = NULL;
04126 char *varname = ast_strdupa(buf), *varval = NULL;
04127
04128 if ((varval = strchr(varname, '='))) {
04129 *varval++ = '\0';
04130 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
04131 tmpvar->next = list;
04132 list = tmpvar;
04133 }
04134 }
04135 return list;
04136 }
04137
04138
04139
04140
04141 static struct ast_variable *copy_vars(struct ast_variable *src)
04142 {
04143 struct ast_variable *res = NULL, *tmp, *v = NULL;
04144
04145 for (v = src ; v ; v = v->next) {
04146 if ((tmp = ast_variable_new(v->name, v->value, v->file))) {
04147 tmp->next = res;
04148 res = tmp;
04149 }
04150 }
04151 return res;
04152 }
04153
04154
04155 static int reload_config(int reload)
04156 {
04157 struct ast_config *cfg;
04158 struct ast_variable *v;
04159 struct mgcp_gateway *g;
04160 struct mgcp_endpoint *e;
04161 char *cat;
04162 struct ast_hostent ahp;
04163 struct hostent *hp;
04164 int format;
04165 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
04166
04167 if (gethostname(ourhost, sizeof(ourhost)-1)) {
04168 ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n");
04169 return 0;
04170 }
04171 cfg = ast_config_load(config, config_flags);
04172
04173
04174 if (!cfg) {
04175 ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config);
04176 return 0;
04177 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
04178 return 0;
04179 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
04180 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config);
04181 return 0;
04182 }
04183
04184 memset(&bindaddr, 0, sizeof(bindaddr));
04185 dtmfmode = 0;
04186
04187
04188 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
04189
04190 v = ast_variable_browse(cfg, "general");
04191 while (v) {
04192
04193 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
04194 v = v->next;
04195 continue;
04196 }
04197
04198
04199 if (!strcasecmp(v->name, "bindaddr")) {
04200 if (!(hp = ast_gethostbyname(v->value, &ahp))) {
04201 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
04202 } else {
04203 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
04204 }
04205 } else if (!strcasecmp(v->name, "allow")) {
04206 format = ast_getformatbyname(v->value);
04207 if (format < 1)
04208 ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
04209 else
04210 capability |= format;
04211 } else if (!strcasecmp(v->name, "disallow")) {
04212 format = ast_getformatbyname(v->value);
04213 if (format < 1)
04214 ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value);
04215 else
04216 capability &= ~format;
04217 } else if (!strcasecmp(v->name, "tos")) {
04218 if (ast_str2tos(v->value, &qos.tos))
04219 ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
04220 } else if (!strcasecmp(v->name, "tos_audio")) {
04221 if (ast_str2tos(v->value, &qos.tos_audio))
04222 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
04223 } else if (!strcasecmp(v->name, "cos")) {
04224 if (ast_str2cos(v->value, &qos.cos))
04225 ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno);
04226 } else if (!strcasecmp(v->name, "cos_audio")) {
04227 if (ast_str2cos(v->value, &qos.cos_audio))
04228 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
04229 } else if (!strcasecmp(v->name, "port")) {
04230 if (sscanf(v->value, "%5d", &ourport) == 1) {
04231 bindaddr.sin_port = htons(ourport);
04232 } else {
04233 ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config);
04234 }
04235 }
04236 v = v->next;
04237 }
04238
04239
04240 ast_mutex_lock(&gatelock);
04241 g = gateways;
04242 while (g) {
04243 g->delme = 1;
04244 e = g->endpoints;
04245 while (e) {
04246 e->delme = 1;
04247 e = e->next;
04248 }
04249 g = g->next;
04250 }
04251 ast_mutex_unlock(&gatelock);
04252
04253 cat = ast_category_browse(cfg, NULL);
04254 while(cat) {
04255 if (strcasecmp(cat, "general")) {
04256 ast_mutex_lock(&gatelock);
04257 g = build_gateway(cat, ast_variable_browse(cfg, cat));
04258 if (g) {
04259 ast_verb(3, "Added gateway '%s'\n", g->name);
04260 g->next = gateways;
04261 gateways = g;
04262 }
04263 ast_mutex_unlock(&gatelock);
04264
04265
04266 if (monitor_thread == pthread_self()) {
04267 if (sched) ast_sched_runq(sched);
04268 if (io) ast_io_wait(io, 10);
04269 }
04270 }
04271 cat = ast_category_browse(cfg, cat);
04272 }
04273
04274
04275 prune_gateways();
04276
04277 if (ntohl(bindaddr.sin_addr.s_addr)) {
04278 memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip));
04279 } else {
04280 hp = ast_gethostbyname(ourhost, &ahp);
04281 if (!hp) {
04282 ast_log(LOG_WARNING, "Unable to get our IP address, MGCP disabled\n");
04283 ast_config_destroy(cfg);
04284 return 0;
04285 }
04286 memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
04287 }
04288 if (!ntohs(bindaddr.sin_port))
04289 bindaddr.sin_port = ntohs(DEFAULT_MGCP_CA_PORT);
04290 bindaddr.sin_family = AF_INET;
04291 ast_mutex_lock(&netlock);
04292 if (mgcpsock > -1)
04293 close(mgcpsock);
04294
04295 if (mgcpsock_read_id != NULL)
04296 ast_io_remove(io, mgcpsock_read_id);
04297 mgcpsock_read_id = NULL;
04298
04299 mgcpsock = socket(AF_INET, SOCK_DGRAM, 0);
04300 if (mgcpsock < 0) {
04301 ast_log(LOG_WARNING, "Unable to create MGCP socket: %s\n", strerror(errno));
04302 } else {
04303 if (bind(mgcpsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
04304 ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
04305 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
04306 strerror(errno));
04307 close(mgcpsock);
04308 mgcpsock = -1;
04309 } else {
04310 ast_verb(2, "MGCP Listening on %s:%d\n",
04311 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
04312 ast_netsock_set_qos(mgcpsock, qos.tos, qos.cos, "MGCP");
04313 }
04314 }
04315 ast_mutex_unlock(&netlock);
04316 ast_config_destroy(cfg);
04317
04318
04319 g = gateways;
04320 while (g) {
04321 e = g->endpoints;
04322 while (e && e->needaudit) {
04323 e->needaudit = 0;
04324 transmit_audit_endpoint(e);
04325 ast_verb(3, "MGCP Auditing endpoint %s@%s for hookstate\n", e->name, g->name);
04326 e = e->next;
04327 }
04328 g = g->next;
04329 }
04330
04331 return 0;
04332 }
04333
04334
04335 static int load_module(void)
04336 {
04337 if (!(sched = sched_context_create())) {
04338 ast_log(LOG_WARNING, "Unable to create schedule context\n");
04339 return AST_MODULE_LOAD_FAILURE;
04340 }
04341
04342 if (!(io = io_context_create())) {
04343 ast_log(LOG_WARNING, "Unable to create I/O context\n");
04344 sched_context_destroy(sched);
04345 return AST_MODULE_LOAD_FAILURE;
04346 }
04347
04348 if (reload_config(0))
04349 return AST_MODULE_LOAD_DECLINE;
04350
04351
04352 if (ast_channel_register(&mgcp_tech)) {
04353 ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n");
04354 io_context_destroy(io);
04355 sched_context_destroy(sched);
04356 return AST_MODULE_LOAD_FAILURE;
04357 }
04358
04359 ast_rtp_glue_register(&mgcp_rtp_glue);
04360 ast_cli_register_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
04361
04362
04363 restart_monitor();
04364
04365 return AST_MODULE_LOAD_SUCCESS;
04366 }
04367
04368 static char *mgcp_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04369 {
04370 static int deprecated = 0;
04371
04372 if (e) {
04373 switch (cmd) {
04374 case CLI_INIT:
04375 e->command = "mgcp reload";
04376 e->usage =
04377 "Usage: mgcp reload\n"
04378 " 'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n";
04379 return NULL;
04380 case CLI_GENERATE:
04381 return NULL;
04382 }
04383 }
04384
04385 if (!deprecated && a && a->argc > 0) {
04386 ast_log(LOG_WARNING, "'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n");
04387 deprecated = 1;
04388 }
04389
04390 ast_mutex_lock(&mgcp_reload_lock);
04391 if (mgcp_reloading) {
04392 ast_verbose("Previous mgcp reload not yet done\n");
04393 } else
04394 mgcp_reloading = 1;
04395 ast_mutex_unlock(&mgcp_reload_lock);
04396 restart_monitor();
04397 return CLI_SUCCESS;
04398 }
04399
04400 static int reload(void)
04401 {
04402 mgcp_reload(NULL, 0, NULL);
04403 return 0;
04404 }
04405
04406 static int unload_module(void)
04407 {
04408 struct mgcp_endpoint *e;
04409 struct mgcp_gateway *g;
04410
04411
04412 if (ast_mutex_trylock(&mgcp_reload_lock)) {
04413 ast_log(LOG_WARNING, "MGCP is currently reloading. Unable to remove module.\n");
04414 return -1;
04415 } else {
04416 mgcp_reloading = 1;
04417 ast_mutex_unlock(&mgcp_reload_lock);
04418 }
04419
04420
04421 ast_channel_unregister(&mgcp_tech);
04422
04423
04424 if (!ast_mutex_lock(&monlock)) {
04425 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
04426 pthread_cancel(monitor_thread);
04427 pthread_kill(monitor_thread, SIGURG);
04428 pthread_join(monitor_thread, NULL);
04429 }
04430 monitor_thread = AST_PTHREADT_STOP;
04431 ast_mutex_unlock(&monlock);
04432 } else {
04433 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
04434
04435 ast_channel_register(&mgcp_tech);
04436 mgcp_reloading = 0;
04437 mgcp_reload(NULL, 0, NULL);
04438 return -1;
04439 }
04440
04441 if (!ast_mutex_lock(&gatelock)) {
04442 for (g = gateways; g; g = g->next) {
04443 g->delme = 1;
04444 for (e = g->endpoints; e; e = e->next)
04445 e->delme = 1;
04446 }
04447
04448 prune_gateways();
04449 ast_mutex_unlock(&gatelock);
04450 } else {
04451 ast_log(LOG_WARNING, "Unable to lock the gateways list.\n");
04452
04453 ast_channel_register(&mgcp_tech);
04454
04455 monitor_thread = AST_PTHREADT_NULL;
04456 mgcp_reloading = 0;
04457 mgcp_reload(NULL, 0, NULL);
04458 return -1;
04459 }
04460
04461 close(mgcpsock);
04462 ast_rtp_glue_unregister(&mgcp_rtp_glue);
04463 ast_cli_unregister_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
04464 sched_context_destroy(sched);
04465
04466 return 0;
04467 }
04468
04469 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Media Gateway Control Protocol (MGCP)",
04470 .load = load_module,
04471 .unload = unload_module,
04472 .reload = reload,
04473 );