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