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