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