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