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: 406038 $")
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/netsock2.h"
00073 #include "asterisk/causes.h"
00074 #include "asterisk/dsp.h"
00075 #include "asterisk/devicestate.h"
00076 #include "asterisk/stringfields.h"
00077 #include "asterisk/abstract_jb.h"
00078 #include "asterisk/event.h"
00079 #include "asterisk/chanvars.h"
00080 #include "asterisk/pktccops.h"
00081
00082
00083
00084
00085
00086
00087
00088 #define MGCPDUMPER
00089 #define DEFAULT_EXPIRY 120
00090 #define MAX_EXPIRY 3600
00091 #define DIRECTMEDIA 1
00092
00093 #ifndef INADDR_NONE
00094 #define INADDR_NONE (in_addr_t)(-1)
00095 #endif
00096
00097
00098
00099 static struct ast_jb_conf default_jbconf =
00100 {
00101 .flags = 0,
00102 .max_size = 200,
00103 .resync_threshold = 1000,
00104 .impl = "fixed",
00105 .target_extra = 40,
00106 };
00107 static struct ast_jb_conf global_jbconf;
00108
00109 static const char tdesc[] = "Media Gateway Control Protocol (MGCP)";
00110 static const char config[] = "mgcp.conf";
00111
00112 #define MGCP_DTMF_RFC2833 (1 << 0)
00113 #define MGCP_DTMF_INBAND (1 << 1)
00114 #define MGCP_DTMF_HYBRID (1 << 2)
00115
00116 #define DEFAULT_MGCP_GW_PORT 2427
00117 #define DEFAULT_MGCP_CA_PORT 2727
00118 #define MGCP_MAX_PACKET 1500
00119 #define DEFAULT_RETRANS 1000
00120 #define MAX_RETRANS 5
00121
00122
00123 #define MGCP_CX_SENDONLY 0
00124 #define MGCP_CX_RECVONLY 1
00125 #define MGCP_CX_SENDRECV 2
00126 #define MGCP_CX_CONF 3
00127 #define MGCP_CX_CONFERENCE 3
00128 #define MGCP_CX_MUTE 4
00129 #define MGCP_CX_INACTIVE 4
00130
00131
00132 static const char * const mgcp_cxmodes[] = {
00133 "sendonly",
00134 "recvonly",
00135 "sendrecv",
00136 "confrnce",
00137 "inactive"
00138 };
00139
00140 enum {
00141 MGCP_CMD_EPCF,
00142 MGCP_CMD_CRCX,
00143 MGCP_CMD_MDCX,
00144 MGCP_CMD_DLCX,
00145 MGCP_CMD_RQNT,
00146 MGCP_CMD_NTFY,
00147 MGCP_CMD_AUEP,
00148 MGCP_CMD_AUCX,
00149 MGCP_CMD_RSIP
00150 };
00151
00152 static char context[AST_MAX_EXTENSION] = "default";
00153
00154 static char language[MAX_LANGUAGE] = "";
00155 static char musicclass[MAX_MUSICCLASS] = "";
00156 static char parkinglot[AST_MAX_CONTEXT];
00157 static char cid_num[AST_MAX_EXTENSION] = "";
00158 static char cid_name[AST_MAX_EXTENSION] = "";
00159
00160 static int dtmfmode = 0;
00161 static int nat = 0;
00162 static int ncs = 0;
00163 static int pktcgatealloc = 0;
00164 static int hangupongateremove = 0;
00165
00166 static ast_group_t cur_callergroup = 0;
00167 static ast_group_t cur_pickupgroup = 0;
00168
00169 static struct {
00170 unsigned int tos;
00171 unsigned int tos_audio;
00172 unsigned int cos;
00173 unsigned int cos_audio;
00174 } qos = { 0, 0, 0, 0 };
00175
00176 static int immediate = 0;
00177
00178 static int callwaiting = 0;
00179
00180 static int callreturn = 0;
00181
00182 static int slowsequence = 0;
00183
00184 static int threewaycalling = 0;
00185
00186
00187 static int transfer = 0;
00188
00189 static int cancallforward = 0;
00190
00191 static int singlepath = 0;
00192
00193 static int directmedia = DIRECTMEDIA;
00194
00195 static char accountcode[AST_MAX_ACCOUNT_CODE] = "";
00196
00197 static char mailbox[AST_MAX_EXTENSION];
00198
00199 static int amaflags = 0;
00200
00201 static int adsi = 0;
00202
00203 static unsigned int oseq_global = 0;
00204 AST_MUTEX_DEFINE_STATIC(oseq_lock);
00205
00206
00207 static int firstdigittimeout = 16000;
00208
00209
00210 static int gendigittimeout = 8000;
00211
00212
00213 static int matchdigittimeout = 3000;
00214
00215
00216
00217 AST_MUTEX_DEFINE_STATIC(netlock);
00218
00219 AST_MUTEX_DEFINE_STATIC(monlock);
00220
00221
00222
00223
00224 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00225
00226 static int restart_monitor(void);
00227
00228 static struct ast_format_cap *global_capability;
00229 static int nonCodecCapability = AST_RTP_DTMF;
00230
00231 static char ourhost[MAXHOSTNAMELEN];
00232 static struct in_addr __ourip;
00233 static int ourport;
00234
00235 static int mgcpdebug = 0;
00236
00237 static struct ast_sched_context *sched;
00238 static struct io_context *io;
00239
00240
00241
00242
00243 #define MGCP_MAX_HEADERS 64
00244 #define MGCP_MAX_LINES 64
00245
00246 struct mgcp_request {
00247 int len;
00248 char *verb;
00249 char *identifier;
00250 char *endpoint;
00251 char *version;
00252 int headers;
00253 char *header[MGCP_MAX_HEADERS];
00254 int lines;
00255 char *line[MGCP_MAX_LINES];
00256 char data[MGCP_MAX_PACKET];
00257 int cmd;
00258 unsigned int trid;
00259 struct mgcp_request *next;
00260 };
00261
00262
00263 struct mgcp_message {
00264 struct mgcp_endpoint *owner_ep;
00265 struct mgcp_subchannel *owner_sub;
00266 int retrans;
00267 unsigned long expire;
00268 unsigned int seqno;
00269 int len;
00270 struct mgcp_message *next;
00271 char buf[0];
00272 };
00273
00274 #define RESPONSE_TIMEOUT 30
00275
00276 struct mgcp_response {
00277 time_t whensent;
00278 int len;
00279 int seqno;
00280 struct mgcp_response *next;
00281 char buf[0];
00282 };
00283
00284 #define MAX_SUBS 2
00285
00286 #define SUB_REAL 0
00287 #define SUB_ALT 1
00288
00289 struct mgcp_subchannel {
00290
00291
00292
00293
00294
00295 #define MGCP_SUBCHANNEL_MAGIC "!978!"
00296 char magic[6];
00297 ast_mutex_t lock;
00298 int id;
00299 struct ast_channel *owner;
00300 struct mgcp_endpoint *parent;
00301 struct ast_rtp_instance *rtp;
00302 struct sockaddr_in tmpdest;
00303 char txident[80];
00304
00305 char cxident[80];
00306 char callid[80];
00307 int cxmode;
00308 struct mgcp_request *cx_queue;
00309 ast_mutex_t cx_queue_lock;
00310 int nat;
00311 int iseq;
00312 int outgoing;
00313 int alreadygone;
00314 int sdpsent;
00315 struct cops_gate *gate;
00316 struct mgcp_subchannel *next;
00317 };
00318
00319 #define MGCP_ONHOOK 1
00320 #define MGCP_OFFHOOK 2
00321
00322 #define TYPE_TRUNK 1
00323 #define TYPE_LINE 2
00324
00325 struct mgcp_endpoint {
00326 ast_mutex_t lock;
00327 char name[80];
00328 struct mgcp_subchannel *sub;
00329 char accountcode[AST_MAX_ACCOUNT_CODE];
00330 char exten[AST_MAX_EXTENSION];
00331 char context[AST_MAX_EXTENSION];
00332 char language[MAX_LANGUAGE];
00333 char cid_num[AST_MAX_EXTENSION];
00334 char cid_name[AST_MAX_EXTENSION];
00335 char lastcallerid[AST_MAX_EXTENSION];
00336 char dtmf_buf[AST_MAX_EXTENSION];
00337 char call_forward[AST_MAX_EXTENSION];
00338 char musicclass[MAX_MUSICCLASS];
00339 char curtone[80];
00340 char mailbox[AST_MAX_EXTENSION];
00341 char parkinglot[AST_MAX_CONTEXT];
00342 struct ast_event_sub *mwi_event_sub;
00343 ast_group_t callgroup;
00344 ast_group_t pickupgroup;
00345 int callwaiting;
00346 int hascallwaiting;
00347 int transfer;
00348 int threewaycalling;
00349 int singlepath;
00350 int cancallforward;
00351 int directmedia;
00352 int callreturn;
00353 int dnd;
00354 int hascallerid;
00355 int hidecallerid;
00356 int dtmfmode;
00357 int amaflags;
00358 int ncs;
00359 int pktcgatealloc;
00360 int hangupongateremove;
00361 int type;
00362 int slowsequence;
00363 int group;
00364 int iseq;
00365 int lastout;
00366 int needdestroy;
00367 struct ast_format_cap *cap;
00368 int nonCodecCapability;
00369 int onhooktime;
00370 int msgstate;
00371 int immediate;
00372 int hookstate;
00373 int adsi;
00374 char rqnt_ident[80];
00375 struct mgcp_request *rqnt_queue;
00376 ast_mutex_t rqnt_queue_lock;
00377 struct mgcp_request *cmd_queue;
00378 ast_mutex_t cmd_queue_lock;
00379 int delme;
00380 int needaudit;
00381 struct ast_dsp *dsp;
00382
00383
00384
00385
00386
00387 struct ast_variable *chanvars;
00388 struct mgcp_endpoint *next;
00389 struct mgcp_gateway *parent;
00390 };
00391
00392 static struct mgcp_gateway {
00393
00394 char name[80];
00395 int isnamedottedip;
00396 struct sockaddr_in addr;
00397 struct sockaddr_in defaddr;
00398 struct in_addr ourip;
00399 int dynamic;
00400 int expire;
00401 struct mgcp_endpoint *endpoints;
00402 struct ast_ha *ha;
00403
00404
00405
00406
00407
00408
00409 char wcardep[30];
00410 struct mgcp_message *msgs;
00411 ast_mutex_t msgs_lock;
00412 int retransid;
00413 int delme;
00414 int realtime;
00415 struct mgcp_response *responses;
00416 struct mgcp_gateway *next;
00417 } *gateways = NULL;
00418
00419 AST_MUTEX_DEFINE_STATIC(mgcp_reload_lock);
00420 static int mgcp_reloading = 0;
00421
00422
00423 AST_MUTEX_DEFINE_STATIC(gatelock);
00424
00425 static int mgcpsock = -1;
00426
00427 static struct sockaddr_in bindaddr;
00428
00429 static struct ast_frame *mgcp_read(struct ast_channel *ast);
00430 static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest);
00431 static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone);
00432 static int transmit_modify_request(struct mgcp_subchannel *sub);
00433 static int transmit_connect(struct mgcp_subchannel *sub);
00434 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername);
00435 static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp, const struct ast_format_cap *codecs);
00436 static int transmit_connection_del(struct mgcp_subchannel *sub);
00437 static int transmit_audit_endpoint(struct mgcp_endpoint *p);
00438 static void start_rtp(struct mgcp_subchannel *sub);
00439 static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
00440 int result, unsigned int ident, struct mgcp_request *resp);
00441 static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub);
00442 static char *mgcp_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
00443 static int reload_config(int reload);
00444
00445 static struct ast_channel *mgcp_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *dest, int *cause);
00446 static int mgcp_call(struct ast_channel *ast, const char *dest, int timeout);
00447 static int mgcp_hangup(struct ast_channel *ast);
00448 static int mgcp_answer(struct ast_channel *ast);
00449 static struct ast_frame *mgcp_read(struct ast_channel *ast);
00450 static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame);
00451 static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, size_t datalen);
00452 static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
00453 static int mgcp_senddigit_begin(struct ast_channel *ast, char digit);
00454 static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
00455 static int mgcp_devicestate(const char *data);
00456 static void add_header_offhook(struct mgcp_subchannel *sub, struct mgcp_request *resp, char *tone);
00457 static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp);
00458 static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v);
00459 static int mgcp_alloc_pktcgate(struct mgcp_subchannel *sub);
00460 static int acf_channel_read(struct ast_channel *chan, const char *funcname, char *preparse, char *buf, size_t buflen);
00461 static struct ast_variable *add_var(const char *buf, struct ast_variable *list);
00462 static struct ast_variable *copy_vars(struct ast_variable *src);
00463
00464 static struct ast_channel_tech mgcp_tech = {
00465 .type = "MGCP",
00466 .description = tdesc,
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, const 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_channel_name(ast));
00847 sub = ast_channel_tech_pvt(ast);
00848 p = sub->parent;
00849 headp = ast_channel_varshead(ast);
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_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) {
00881 ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
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_channel_connected(ast)->id.number.valid, ast_channel_connected(ast)->id.number.str, ""),
00905 S_COR(ast_channel_connected(ast)->id.name.valid, ast_channel_connected(ast)->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_channel_tech_pvt(ast);
00924 struct mgcp_endpoint *p = sub->parent;
00925 struct ast_channel *bridged;
00926
00927 ast_debug(1, "mgcp_hangup(%s)\n", ast_channel_name(ast));
00928 if (!ast_channel_tech_pvt(ast)) {
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_channel_name(ast), 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(ast_channel_caller(bridged)->id.number.valid, ast_channel_caller(bridged)->id.number.str, ""),
00978 S_COR(ast_channel_caller(bridged)->id.name.valid, ast_channel_caller(bridged)->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(ast_channel_caller(bridged)->id.number.valid, ast_channel_caller(bridged)->id.number.str, ""),
00989 S_COR(ast_channel_caller(bridged)->id.name.valid, ast_channel_caller(bridged)->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_channel_tech_pvt_set(ast, 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_channel_name(ast));
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_channel_name(ast), 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_channel_name(ast), 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_channel_tech_pvt(ast);
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_channel_name(ast), p->name, p->parent->name, sub->id);
01191 if (ast_channel_state(ast) != AST_STATE_UP) {
01192 ast_setstate(ast, AST_STATE_UP);
01193 ast_debug(1, "mgcp_answer(%s)\n", ast_channel_name(ast));
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 (!ast_format_cap_iscompatible(ast_channel_nativeformats(sub->owner), &f->subclass.format)) {
01214 ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(&f->subclass.format));
01215 ast_format_cap_set(ast_channel_nativeformats(sub->owner), &f->subclass.format);
01216 ast_set_read_format(sub->owner, ast_channel_readformat(sub->owner));
01217 ast_set_write_format(sub->owner, ast_channel_writeformat(sub->owner));
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_channel_tech_pvt(ast);
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_channel_tech_pvt(ast);
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 (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) {
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.format),
01259 ast_getformatname_multiple(buf, sizeof(buf), ast_channel_nativeformats(ast)),
01260 ast_getformatname(ast_channel_readformat(ast)),
01261 ast_getformatname(ast_channel_writeformat(ast)));
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 = ast_channel_tech_pvt(newchan);
01286
01287 ast_mutex_lock(&sub->lock);
01288 ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", ast_channel_name(oldchan), ast_channel_name(newchan));
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_channel_tech_pvt(ast);
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\n");
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_channel_tech_pvt(ast);
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(const char *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_channel_tech_pvt(ast);
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_channel_name(ast));
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_INCOMPLETE:
01461
01462
01463
01464 case AST_CONTROL_CONGESTION:
01465 transmit_notify_request(sub, sub->parent->ncs ? "L/cg" : "G/cg");
01466 break;
01467 case AST_CONTROL_HOLD:
01468 ast_moh_start(ast, data, NULL);
01469 break;
01470 case AST_CONTROL_UNHOLD:
01471 ast_moh_stop(ast);
01472 break;
01473 case AST_CONTROL_SRCUPDATE:
01474 ast_rtp_instance_update_source(sub->rtp);
01475 break;
01476 case AST_CONTROL_SRCCHANGE:
01477 ast_rtp_instance_change_source(sub->rtp);
01478 break;
01479 case AST_CONTROL_PROGRESS:
01480 case AST_CONTROL_PROCEEDING:
01481 transmit_modify_request(sub);
01482 case -1:
01483 transmit_notify_request(sub, "");
01484 break;
01485 default:
01486 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
01487
01488 case AST_CONTROL_PVT_CAUSE_CODE:
01489 res = -1;
01490 }
01491 ast_mutex_unlock(&sub->lock);
01492 return res;
01493 }
01494
01495 static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state, const char *linkedid)
01496 {
01497 struct ast_channel *tmp;
01498 struct ast_variable *v = NULL;
01499 struct mgcp_endpoint *i = sub->parent;
01500 struct ast_format tmpfmt;
01501
01502 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);
01503 if (tmp) {
01504 ast_channel_tech_set(tmp, &mgcp_tech);
01505 ast_format_cap_copy(ast_channel_nativeformats(tmp), i->cap);
01506 if (ast_format_cap_is_empty(ast_channel_nativeformats(tmp))) {
01507 ast_format_cap_copy(ast_channel_nativeformats(tmp), global_capability);
01508 }
01509 if (sub->rtp) {
01510 ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0));
01511 }
01512 if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) {
01513 i->dsp = ast_dsp_new();
01514 ast_dsp_set_features(i->dsp, DSP_FEATURE_DIGIT_DETECT);
01515
01516 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH);
01517 } else {
01518 i->dsp = NULL;
01519 }
01520 if (state == AST_STATE_RING)
01521 ast_channel_rings_set(tmp, 1);
01522
01523 ast_best_codec(ast_channel_nativeformats(tmp), &tmpfmt);
01524 ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt);
01525 ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
01526 ast_format_copy(ast_channel_readformat(tmp), &tmpfmt);
01527 ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);
01528 ast_channel_tech_pvt_set(tmp, sub);
01529 if (!ast_strlen_zero(i->language))
01530 ast_channel_language_set(tmp, i->language);
01531 if (!ast_strlen_zero(i->accountcode))
01532 ast_channel_accountcode_set(tmp, i->accountcode);
01533 if (i->amaflags)
01534 ast_channel_amaflags_set(tmp, i->amaflags);
01535 sub->owner = tmp;
01536 ast_module_ref(ast_module_info->self);
01537 ast_channel_callgroup_set(tmp, i->callgroup);
01538 ast_channel_pickupgroup_set(tmp, i->pickupgroup);
01539 ast_channel_call_forward_set(tmp, i->call_forward);
01540 ast_channel_context_set(tmp, i->context);
01541 ast_channel_exten_set(tmp, i->exten);
01542
01543
01544
01545 if (!ast_strlen_zero(i->cid_num)) {
01546 ast_channel_caller(tmp)->ani.number.valid = 1;
01547 ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num);
01548 }
01549
01550 if (!i->adsi) {
01551 ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE);
01552 }
01553 ast_channel_priority_set(tmp, 1);
01554
01555
01556 for (v = i->chanvars ; v ; v = v->next) {
01557 char valuebuf[1024];
01558 pbx_builtin_setvar_helper(tmp, v->name, ast_get_encoded_str(v->value, valuebuf, sizeof(valuebuf)));
01559 }
01560
01561 if (sub->rtp) {
01562 ast_jb_configure(tmp, &global_jbconf);
01563 }
01564 if (state != AST_STATE_DOWN) {
01565 if (ast_pbx_start(tmp)) {
01566 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
01567 ast_hangup(tmp);
01568 tmp = NULL;
01569 }
01570 }
01571 ast_verb(3, "MGCP mgcp_new(%s) created in state: %s\n",
01572 ast_channel_name(tmp), ast_state2str(state));
01573 } else {
01574 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
01575 }
01576 return tmp;
01577 }
01578
01579 static char *get_sdp_by_line(char* line, char *name, int nameLen)
01580 {
01581 if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
01582 char *r = line + nameLen + 1;
01583 while (*r && (*r < 33)) ++r;
01584 return r;
01585 }
01586 return "";
01587 }
01588
01589 static char *get_sdp(struct mgcp_request *req, char *name)
01590 {
01591 int x;
01592 int len = strlen(name);
01593 char *r;
01594
01595 for (x = 0; x < req->lines; x++) {
01596 r = get_sdp_by_line(req->line[x], name, len);
01597 if (r[0] != '\0') return r;
01598 }
01599 return "";
01600 }
01601
01602 static void sdpLineNum_iterator_init(int *iterator)
01603 {
01604 *iterator = 0;
01605 }
01606
01607 static char *get_sdp_iterate(int* iterator, struct mgcp_request *req, char *name)
01608 {
01609 int len = strlen(name);
01610 char *r;
01611 while (*iterator < req->lines) {
01612 r = get_sdp_by_line(req->line[(*iterator)++], name, len);
01613 if (r[0] != '\0') return r;
01614 }
01615 return "";
01616 }
01617
01618 static char *__get_header(struct mgcp_request *req, char *name, int *start, char *def)
01619 {
01620 int x;
01621 int len = strlen(name);
01622 char *r;
01623 for (x = *start; x < req->headers; x++) {
01624 if (!strncasecmp(req->header[x], name, len) &&
01625 (req->header[x][len] == ':')) {
01626 r = req->header[x] + len + 1;
01627 while (*r && (*r < 33)) {
01628 r++;
01629 }
01630 *start = x + 1;
01631 return r;
01632 }
01633 }
01634
01635 return def;
01636 }
01637
01638 static char *get_header(struct mgcp_request *req, char *name)
01639 {
01640 int start = 0;
01641 return __get_header(req, name, &start, "");
01642 }
01643
01644
01645 static char *get_csv(char *c, int *len, char **next)
01646 {
01647 char *s;
01648
01649 *next = NULL, *len = 0;
01650 if (!c) return NULL;
01651
01652 while (*c && (*c < 33 || *c == ',')) {
01653 c++;
01654 }
01655
01656 s = c;
01657 while (*c && (*c >= 33 && *c != ',')) {
01658 c++, (*len)++;
01659 }
01660 *next = c;
01661
01662 if (*len == 0) {
01663 s = NULL, *next = NULL;
01664 }
01665
01666 return s;
01667 }
01668
01669 static struct mgcp_gateway *find_realtime_gw(char *name, char *at, struct sockaddr_in *sin)
01670 {
01671 struct mgcp_gateway *g = NULL;
01672 struct ast_variable *mgcpgwconfig = NULL;
01673 struct ast_variable *gwv, *epname = NULL;
01674 struct mgcp_endpoint *e;
01675 char lines[256];
01676 int i, j;
01677
01678 ast_debug(1, "*** find Realtime MGCPGW\n");
01679
01680 if (!(i = ast_check_realtime("mgcpgw")) || !(j = ast_check_realtime("mgcpep"))) {
01681 return NULL;
01682 }
01683
01684 if (ast_strlen_zero(at)) {
01685 ast_debug(1, "null gw name\n");
01686 return NULL;
01687 }
01688
01689 if (!(mgcpgwconfig = ast_load_realtime("mgcpgw", "name", at, NULL))) {
01690 return NULL;
01691 }
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706 lines[0] = '\0';
01707 for (gwv = mgcpgwconfig; gwv; gwv = gwv->next) {
01708 if (!strcasecmp(gwv->name, "lines")) {
01709 ast_copy_string(lines, gwv->value, sizeof(lines));
01710 break;
01711 }
01712 }
01713
01714 for (gwv = gwv && gwv->next ? gwv : mgcpgwconfig; gwv->next; gwv = gwv->next);
01715
01716 if (!ast_strlen_zero(lines)) {
01717 AST_DECLARE_APP_ARGS(args,
01718 AST_APP_ARG(line)[100];
01719 );
01720 AST_STANDARD_APP_ARGS(args, lines);
01721 for (i = 0; i < args.argc; i++) {
01722 gwv->next = ast_load_realtime("mgcpep", "name", at, "line", args.line[i], NULL);
01723
01724
01725 for (epname = NULL; gwv->next; gwv = gwv->next) {
01726 if (!strcasecmp(gwv->next->name, "line")) {
01727
01728 epname = gwv->next;
01729 gwv->next = gwv->next->next;
01730 }
01731 }
01732
01733 if (epname) {
01734 gwv->next = epname;
01735 epname->next = NULL;
01736 gwv = gwv->next;
01737 }
01738 }
01739 }
01740 for (gwv = mgcpgwconfig; gwv; gwv = gwv->next) {
01741 ast_debug(1, "MGCP Realtime var: %s => %s\n", gwv->name, gwv->value);
01742 }
01743
01744 if (mgcpgwconfig) {
01745 g = build_gateway(at, mgcpgwconfig);
01746 ast_variables_destroy(mgcpgwconfig);
01747 }
01748 if (g) {
01749 g->next = gateways;
01750 g->realtime = 1;
01751 gateways = g;
01752 for (e = g->endpoints; e; e = e->next) {
01753 transmit_audit_endpoint(e);
01754 e->needaudit = 0;
01755 }
01756 }
01757 return g;
01758 }
01759
01760 static struct mgcp_subchannel *find_subchannel_and_lock(char *name, int msgid, struct sockaddr_in *sin)
01761 {
01762 struct mgcp_endpoint *p = NULL;
01763 struct mgcp_subchannel *sub = NULL;
01764 struct mgcp_gateway *g;
01765 char tmp[256] = "";
01766 char *at = NULL, *c;
01767 int found = 0;
01768 if (name) {
01769 ast_copy_string(tmp, name, sizeof(tmp));
01770 at = strchr(tmp, '@');
01771 if (!at) {
01772 ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name);
01773 return NULL;
01774 }
01775 *at++ = '\0';
01776 }
01777 ast_mutex_lock(&gatelock);
01778 if (at && (at[0] == '[')) {
01779 at++;
01780 c = strrchr(at, ']');
01781 if (c) {
01782 *c = '\0';
01783 }
01784 }
01785 for (g = gateways ? gateways : find_realtime_gw(name, at, sin); g; g = g->next ? g->next : find_realtime_gw(name, at, sin)) {
01786 if ((!name || !strcasecmp(g->name, at)) &&
01787 (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) {
01788
01789 if (sin && g->dynamic && name) {
01790 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
01791 (g->addr.sin_port != sin->sin_port)) {
01792 memcpy(&g->addr, sin, sizeof(g->addr));
01793 {
01794 struct ast_sockaddr tmp1, tmp2;
01795 struct sockaddr_in tmp3 = {0,};
01796
01797 tmp3.sin_addr = g->ourip;
01798 ast_sockaddr_from_sin(&tmp1, &g->addr);
01799 ast_sockaddr_from_sin(&tmp2, &tmp3);
01800 if (ast_ouraddrfor(&tmp1, &tmp2)) {
01801 memcpy(&g->ourip, &__ourip, sizeof(g->ourip));
01802 }
01803 ast_sockaddr_to_sin(&tmp2, &tmp3);
01804 g->ourip = tmp3.sin_addr;
01805 }
01806 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));
01807 }
01808
01809 } else if (name) {
01810 if (strcasecmp(g->name, at)) {
01811 g = g->next;
01812 continue;
01813 }
01814
01815 } else if (!name && sin) {
01816 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
01817 (g->addr.sin_port != sin->sin_port)) {
01818 if(!g->next)
01819 g = find_realtime_gw(name, at, sin);
01820 else
01821 g = g->next;
01822 continue;
01823 }
01824 } else {
01825 continue;
01826 }
01827 for (p = g->endpoints; p; p = p->next) {
01828 ast_debug(1, "Searching on %s@%s for subchannel\n", p->name, g->name);
01829 if (msgid) {
01830 sub = p->sub;
01831 found = 1;
01832 break;
01833 } else if (name && !strcasecmp(p->name, tmp)) {
01834 ast_debug(1, "Coundn't determine subchannel, assuming current master %s@%s-%d\n",
01835 p->name, g->name, p->sub->id);
01836 sub = p->sub;
01837 found = 1;
01838 break;
01839 }
01840 }
01841 if (sub && found) {
01842 ast_mutex_lock(&sub->lock);
01843 break;
01844 }
01845 }
01846 }
01847 ast_mutex_unlock(&gatelock);
01848 if (!sub) {
01849 if (name) {
01850 if (g) {
01851 ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at);
01852 } else {
01853 ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);
01854 }
01855 }
01856 }
01857 return sub;
01858 }
01859
01860 static void parse(struct mgcp_request *req)
01861 {
01862
01863 char *c;
01864 int f = 0;
01865 c = req->data;
01866
01867
01868 req->header[f] = c;
01869 for (; *c; c++) {
01870 if (*c == '\n') {
01871
01872 *c = 0;
01873 ast_debug(3, "Header: %s (%d)\n", req->header[f], (int) strlen(req->header[f]));
01874 if (ast_strlen_zero(req->header[f])) {
01875
01876 c++;
01877 break;
01878 }
01879 if (f >= MGCP_MAX_HEADERS - 1) {
01880 ast_log(LOG_WARNING, "Too many MGCP headers...\n");
01881 } else {
01882 f++;
01883 }
01884 req->header[f] = c + 1;
01885 } else if (*c == '\r') {
01886
01887 *c = 0;
01888 }
01889 }
01890
01891 if (!ast_strlen_zero(req->header[f])) {
01892 f++;
01893 }
01894 req->headers = f;
01895
01896 f = 0;
01897 req->line[f] = c;
01898 for (; *c; c++) {
01899 if (*c == '\n') {
01900
01901 *c = 0;
01902 ast_debug(3, "Line: %s (%d)\n", req->line[f], (int) strlen(req->line[f]));
01903 if (f >= MGCP_MAX_LINES - 1) {
01904 ast_log(LOG_WARNING, "Too many SDP lines...\n");
01905 } else {
01906 f++;
01907 }
01908 req->line[f] = c + 1;
01909 } else if (*c == '\r') {
01910
01911 *c = 0;
01912 }
01913 }
01914
01915 if (!ast_strlen_zero(req->line[f])) {
01916 f++;
01917 }
01918 req->lines = f;
01919
01920 c = req->header[0];
01921 while (*c && *c < 33) c++;
01922
01923 req->verb = c;
01924 while (*c && (*c > 32)) c++;
01925 if (*c) {
01926 *c = '\0';
01927 c++;
01928 while (*c && (*c < 33)) c++;
01929 req->identifier = c;
01930 while (*c && (*c > 32)) c++;
01931 if (*c) {
01932 *c = '\0';
01933 c++;
01934 while (*c && (*c < 33)) c++;
01935 req->endpoint = c;
01936 while (*c && (*c > 32)) c++;
01937 if (*c) {
01938 *c = '\0';
01939 c++;
01940 while (*c && (*c < 33)) c++;
01941 req->version = c;
01942 while (*c && (*c > 32)) c++;
01943 while (*c && (*c < 33)) c++;
01944 while (*c && (*c > 32)) c++;
01945 *c = '\0';
01946 }
01947 }
01948 }
01949
01950 ast_debug(1, "Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
01951 req->verb, req->identifier, req->endpoint, req->version);
01952 ast_debug(1, "%d headers, %d lines\n", req->headers, req->lines);
01953 if (*c) {
01954 ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c);
01955 }
01956 }
01957
01958 static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
01959 {
01960 char *m;
01961 char *c;
01962 char *a;
01963 char host[258];
01964 int len = 0;
01965 int portno;
01966 struct ast_format_cap *peercap;
01967 int peerNonCodecCapability;
01968 struct sockaddr_in sin;
01969 struct ast_sockaddr sin_tmp;
01970 char *codecs;
01971 struct ast_hostent ahp; struct hostent *hp;
01972 int codec, codec_count=0;
01973 int iterator;
01974 struct mgcp_endpoint *p = sub->parent;
01975 char tmp1[256], tmp2[256], tmp3[256];
01976
01977
01978 m = get_sdp(req, "m");
01979 c = get_sdp(req, "c");
01980 if (ast_strlen_zero(m) || ast_strlen_zero(c)) {
01981 ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c);
01982 return -1;
01983 }
01984 if (sscanf(c, "IN IP4 %256s", host) != 1) {
01985 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
01986 return -1;
01987 }
01988
01989 hp = ast_gethostbyname(host, &ahp);
01990 if (!hp) {
01991 ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c);
01992 return -1;
01993 }
01994 if (sscanf(m, "audio %30d RTP/AVP %n", &portno, &len) != 1 || !len) {
01995 ast_log(LOG_WARNING, "Malformed media stream descriptor: %s\n", m);
01996 return -1;
01997 }
01998 sin.sin_family = AF_INET;
01999 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
02000 sin.sin_port = htons(portno);
02001 ast_sockaddr_from_sin(&sin_tmp, &sin);
02002 ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
02003 ast_debug(3, "Peer RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
02004
02005 ast_rtp_codecs_payloads_clear(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp);
02006 codecs = ast_strdupa(m + len);
02007 while (!ast_strlen_zero(codecs)) {
02008 if (sscanf(codecs, "%30d%n", &codec, &len) != 1) {
02009 if (codec_count) {
02010 break;
02011 }
02012 ast_log(LOG_WARNING, "Error in codec string '%s' at '%s'\n", m, codecs);
02013 return -1;
02014 }
02015 ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, codec);
02016 codec_count++;
02017 codecs += len;
02018 }
02019
02020
02021
02022 sdpLineNum_iterator_init(&iterator);
02023 while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
02024 char* mimeSubtype = ast_strdupa(a);
02025 if (sscanf(a, "rtpmap: %30u %127[^/]/", &codec, mimeSubtype) != 2)
02026 continue;
02027
02028 ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, codec, "audio", mimeSubtype, 0);
02029 }
02030
02031
02032 if (!(peercap = ast_format_cap_alloc_nolock())) {
02033 return -1;
02034 }
02035 ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(sub->rtp), peercap, &peerNonCodecCapability);
02036 ast_format_cap_joint_copy(global_capability, peercap, p->cap);
02037 ast_debug(1, "Capabilities: us - %s, them - %s, combined - %s\n",
02038 ast_getformatname_multiple(tmp1, sizeof(tmp1), global_capability),
02039 ast_getformatname_multiple(tmp2, sizeof(tmp2), peercap),
02040 ast_getformatname_multiple(tmp3, sizeof(tmp3), p->cap));
02041 peercap = ast_format_cap_destroy(peercap);
02042
02043 ast_debug(1, "Non-codec capabilities: us - %d, them - %d, combined - %d\n",
02044 nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability);
02045 if (ast_format_cap_is_empty(p->cap)) {
02046 ast_log(LOG_WARNING, "No compatible codecs!\n");
02047 return -1;
02048 }
02049 return 0;
02050 }
02051
02052 static int add_header(struct mgcp_request *req, const char *var, const char *value)
02053 {
02054 if (req->len >= sizeof(req->data) - 4) {
02055 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
02056 return -1;
02057 }
02058 if (req->lines) {
02059 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
02060 return -1;
02061 }
02062 req->header[req->headers] = req->data + req->len;
02063 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value);
02064 req->len += strlen(req->header[req->headers]);
02065 if (req->headers < MGCP_MAX_HEADERS) {
02066 req->headers++;
02067 } else {
02068 ast_log(LOG_WARNING, "Out of header space\n");
02069 return -1;
02070 }
02071 return 0;
02072 }
02073
02074 static int add_line(struct mgcp_request *req, char *line)
02075 {
02076 if (req->len >= sizeof(req->data) - 4) {
02077 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
02078 return -1;
02079 }
02080 if (!req->lines) {
02081
02082 ast_copy_string(req->data + req->len, "\r\n", sizeof(req->data) - req->len);
02083 req->len += strlen(req->data + req->len);
02084 }
02085 req->line[req->lines] = req->data + req->len;
02086 snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
02087 req->len += strlen(req->line[req->lines]);
02088 if (req->lines < MGCP_MAX_LINES) {
02089 req->lines++;
02090 } else {
02091 ast_log(LOG_WARNING, "Out of line space\n");
02092 return -1;
02093 }
02094 return 0;
02095 }
02096
02097 static int init_resp(struct mgcp_request *req, char *resp, struct mgcp_request *orig, char *resprest)
02098 {
02099
02100 if (req->headers || req->len) {
02101 ast_log(LOG_WARNING, "Request already initialized?!?\n");
02102 return -1;
02103 }
02104 req->header[req->headers] = req->data + req->len;
02105 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest);
02106 req->len += strlen(req->header[req->headers]);
02107 if (req->headers < MGCP_MAX_HEADERS) {
02108 req->headers++;
02109 } else {
02110 ast_log(LOG_WARNING, "Out of header space\n");
02111 }
02112 return 0;
02113 }
02114
02115 static int init_req(struct mgcp_endpoint *p, struct mgcp_request *req, char *verb, unsigned int oseq)
02116 {
02117
02118 if (req->headers || req->len) {
02119 ast_log(LOG_WARNING, "Request already initialized?!?\n");
02120 return -1;
02121 }
02122 req->header[req->headers] = req->data + req->len;
02123
02124 if (p->parent->isnamedottedip) {
02125 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" : "");
02126 } else {
02127 + 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" : "");
02128 }
02129 req->len += strlen(req->header[req->headers]);
02130 if (req->headers < MGCP_MAX_HEADERS) {
02131 req->headers++;
02132 } else {
02133 ast_log(LOG_WARNING, "Out of header space\n");
02134 }
02135 return 0;
02136 }
02137
02138
02139 static int respprep(struct mgcp_request *resp, struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest)
02140 {
02141 memset(resp, 0, sizeof(*resp));
02142 init_resp(resp, msg, req, msgrest);
02143 return 0;
02144 }
02145
02146 static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
02147 {
02148 unsigned int oseq;
02149 memset(req, 0, sizeof(struct mgcp_request));
02150 ast_mutex_lock(&oseq_lock);
02151 oseq_global++;
02152 if (oseq_global > 999999999) {
02153 oseq_global = 1;
02154 }
02155 oseq = oseq_global;
02156 ast_mutex_unlock(&oseq_lock);
02157 init_req(p, req, verb, oseq);
02158 return oseq;
02159 }
02160
02161 static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest)
02162 {
02163 struct mgcp_request resp;
02164 struct mgcp_endpoint *p = sub->parent;
02165 struct mgcp_response *mgr;
02166
02167 if (!sub) {
02168 return -1;
02169 }
02170
02171 respprep(&resp, p, msg, req, msgrest);
02172 if (!(mgr = ast_calloc(1, sizeof(*mgr) + resp.len + 1))) {
02173 return send_response(sub, &resp);
02174 }
02175
02176 sscanf(req->identifier, "%30d", &mgr->seqno);
02177 time(&mgr->whensent);
02178 mgr->len = resp.len;
02179 memcpy(mgr->buf, resp.data, resp.len);
02180 mgr->buf[resp.len] = '\0';
02181 mgr->next = p->parent->responses;
02182 p->parent->responses = mgr;
02183
02184 return send_response(sub, &resp);
02185 }
02186
02187
02188 static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp)
02189 {
02190 int len;
02191 int codec;
02192 char costr[80];
02193 struct sockaddr_in sin;
02194 struct ast_sockaddr sin_tmp;
02195 char v[256];
02196 char s[256];
02197 char o[256];
02198 char c[256];
02199 char t[256];
02200 char m[256] = "";
02201 char a[1024] = "";
02202 int x;
02203 struct ast_format tmpfmt;
02204 struct sockaddr_in dest = { 0, };
02205 struct ast_sockaddr dest_tmp;
02206 struct mgcp_endpoint *p = sub->parent;
02207
02208
02209 len = 0;
02210 if (!sub->rtp) {
02211 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
02212 return -1;
02213 }
02214 ast_rtp_instance_get_local_address(sub->rtp, &sin_tmp);
02215 ast_sockaddr_to_sin(&sin_tmp, &sin);
02216 if (rtp) {
02217 ast_rtp_instance_get_remote_address(sub->rtp, &dest_tmp);
02218 ast_sockaddr_to_sin(&dest_tmp, &dest);
02219 } else {
02220 if (sub->tmpdest.sin_addr.s_addr) {
02221 dest.sin_addr = sub->tmpdest.sin_addr;
02222 dest.sin_port = sub->tmpdest.sin_port;
02223
02224 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
02225 } else {
02226 dest.sin_addr = p->parent->ourip;
02227 dest.sin_port = sin.sin_port;
02228 }
02229 }
02230 ast_debug(1, "We're at %s port %d\n", ast_inet_ntoa(p->parent->ourip), ntohs(sin.sin_port));
02231 ast_copy_string(v, "v=0\r\n", sizeof(v));
02232 snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", (int)getpid(), (int)getpid(), ast_inet_ntoa(dest.sin_addr));
02233 ast_copy_string(s, "s=session\r\n", sizeof(s));
02234 snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr));
02235 ast_copy_string(t, "t=0 0\r\n", sizeof(t));
02236 snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
02237
02238 ast_format_cap_iter_start(p->cap);
02239 while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) {
02240 if (AST_FORMAT_GET_TYPE(tmpfmt.id) != AST_FORMAT_TYPE_AUDIO) {
02241
02242 continue;
02243 }
02244 if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) {
02245 ast_debug(1, "Answering with capability %s\n", ast_getformatname(&tmpfmt));
02246 codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, &tmpfmt, 0);
02247 if (codec > -1) {
02248 snprintf(costr, sizeof(costr), " %d", codec);
02249 strncat(m, costr, sizeof(m) - strlen(m) - 1);
02250 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0));
02251 strncat(a, costr, sizeof(a) - strlen(a) - 1);
02252 }
02253 }
02254 }
02255 ast_format_cap_iter_end(p->cap);
02256
02257 for (x = 1LL; x <= AST_RTP_MAX; x <<= 1) {
02258 if (p->nonCodecCapability & x) {
02259 ast_debug(1, "Answering with non-codec capability %d\n", (int) x);
02260 codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 0, NULL, x);
02261 if (codec > -1) {
02262 snprintf(costr, sizeof(costr), " %d", codec);
02263 strncat(m, costr, sizeof(m) - strlen(m) - 1);
02264 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(0, NULL, x, 0));
02265 strncat(a, costr, sizeof(a) - strlen(a) - 1);
02266 if (x == AST_RTP_DTMF) {
02267
02268
02269 snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec);
02270 strncat(a, costr, sizeof(a) - strlen(a) - 1);
02271 }
02272 }
02273 }
02274 }
02275 strncat(m, "\r\n", sizeof(m) - strlen(m) - 1);
02276 len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a);
02277 snprintf(costr, sizeof(costr), "%d", len);
02278 add_line(resp, v);
02279 add_line(resp, o);
02280 add_line(resp, s);
02281 add_line(resp, c);
02282 add_line(resp, t);
02283 add_line(resp, m);
02284 add_line(resp, a);
02285 return 0;
02286 }
02287
02288 static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp, const struct ast_format_cap *codecs)
02289 {
02290 struct mgcp_request resp;
02291 char local[256];
02292 char tmp[80];
02293 struct mgcp_endpoint *p = sub->parent;
02294 struct ast_format tmpfmt;
02295 struct ast_sockaddr sub_tmpdest_tmp;
02296 unsigned int oseq;
02297
02298 if (ast_strlen_zero(sub->cxident) && rtp) {
02299
02300
02301 ast_rtp_instance_get_remote_address(rtp, &sub_tmpdest_tmp);
02302 ast_sockaddr_to_sin(&sub_tmpdest_tmp, &sub->tmpdest);
02303 return 0;
02304 }
02305 ast_copy_string(local, "e:on, s:off, p:20", sizeof(local));
02306 ast_format_cap_iter_start(p->cap);
02307 while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) {
02308 if (AST_FORMAT_GET_TYPE(tmpfmt.id) != AST_FORMAT_TYPE_AUDIO) {
02309
02310 continue;
02311 }
02312 if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) {
02313 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0));
02314 strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02315 }
02316 }
02317 ast_format_cap_iter_end(p->cap);
02318
02319 if (sub->gate) {
02320 if (sub->gate->state == GATE_ALLOCATED || sub->gate->state == GATE_OPEN) {
02321 snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid);
02322 strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02323 sub->sdpsent = 1;
02324 } else {
02325
02326 ast_debug(1, "Waiting for opened gate...\n");
02327 sub->sdpsent = 0;
02328 return 0;
02329 }
02330 }
02331
02332
02333 oseq = reqprep(&resp, p, "MDCX");
02334 add_header(&resp, "C", sub->callid);
02335 add_header(&resp, "L", local);
02336 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02337
02338 add_header(&resp, "X", sub->txident);
02339 add_header(&resp, "I", sub->cxident);
02340
02341 add_sdp(&resp, sub, rtp);
02342
02343 resp.cmd = MGCP_CMD_MDCX;
02344 resp.trid = oseq;
02345 return send_request(p, sub, &resp, oseq);
02346 }
02347
02348 static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp)
02349 {
02350 struct mgcp_request resp;
02351 char local[256];
02352 char tmp[80];
02353 struct ast_format tmpfmt;
02354 struct mgcp_endpoint *p = sub->parent;
02355 unsigned int oseq;
02356
02357 ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
02358 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02359
02360 ast_copy_string(local, "e:on, s:off, p:20", sizeof(local));
02361
02362 ast_format_cap_iter_start(p->cap);
02363 while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) {
02364 if (AST_FORMAT_GET_TYPE(tmpfmt.id) != AST_FORMAT_TYPE_AUDIO) {
02365
02366 continue;
02367 }
02368 if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) {
02369 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0));
02370 strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02371 }
02372 }
02373 ast_format_cap_iter_end(p->cap);
02374
02375 if (sub->gate) {
02376 if(sub->gate->state == GATE_ALLOCATED) {
02377 snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid);
02378 strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02379 }
02380 }
02381 sub->sdpsent = 1;
02382 oseq = reqprep(&resp, p, "CRCX");
02383 add_header(&resp, "C", sub->callid);
02384 add_header(&resp, "L", local);
02385 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02386
02387 add_header(&resp, "X", sub->txident);
02388
02389 add_sdp(&resp, sub, rtp);
02390
02391 resp.cmd = MGCP_CMD_CRCX;
02392 resp.trid = oseq;
02393 return send_request(p, sub, &resp, oseq);
02394 }
02395
02396 static int mgcp_pktcgate_remove(struct cops_gate *gate)
02397 {
02398 struct mgcp_subchannel *sub = gate->tech_pvt;
02399
02400 if (!sub) {
02401 return 1;
02402 }
02403
02404 ast_mutex_lock(&sub->lock);
02405 ast_debug(1, "Pktc: gate 0x%x deleted\n", gate->gateid);
02406 if (sub->gate->state != GATE_CLOSED && sub->parent->hangupongateremove) {
02407 sub->gate = NULL;
02408 if (sub->owner) {
02409 ast_softhangup(sub->owner, AST_CAUSE_REQUESTED_CHAN_UNAVAIL);
02410 ast_channel_unlock(sub->owner);
02411 }
02412 } else {
02413 sub->gate = NULL;
02414 }
02415 ast_mutex_unlock(&sub->lock);
02416 return 1;
02417 }
02418
02419 static int mgcp_pktcgate_open(struct cops_gate *gate)
02420 {
02421 struct mgcp_subchannel *sub = gate->tech_pvt;
02422 if (!sub) {
02423 return 1;
02424 }
02425 ast_mutex_lock(&sub->lock);
02426 ast_debug(1, "Pktc: gate 0x%x open\n", gate->gateid);
02427 if (!sub->sdpsent) transmit_modify_with_sdp(sub, NULL, 0);
02428 ast_mutex_unlock(&sub->lock);
02429 return 1;
02430 }
02431
02432 static int mgcp_alloc_pktcgate(struct mgcp_subchannel *sub)
02433 {
02434 struct mgcp_endpoint *p = sub->parent;
02435 sub->gate = ast_pktccops_gate_alloc(GATE_SET, NULL, ntohl(p->parent->addr.sin_addr.s_addr),
02436 8, 128000, 232, 0, 0, NULL, &mgcp_pktcgate_remove);
02437
02438 if (!sub->gate) {
02439 return 0;
02440 }
02441 sub->gate->tech_pvt = sub;
02442 sub->gate->gate_open = &mgcp_pktcgate_open;
02443 return 1;
02444 }
02445
02446 static int transmit_connect(struct mgcp_subchannel *sub)
02447 {
02448 struct mgcp_request resp;
02449 char local[256];
02450 char tmp[80];
02451 struct ast_format tmpfmt;
02452 struct mgcp_endpoint *p = sub->parent;
02453 unsigned int oseq;
02454
02455 ast_copy_string(local, "p:20, s:off, e:on", sizeof(local));
02456
02457 ast_format_cap_iter_start(p->cap);
02458 while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) {
02459 if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) {
02460 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0));
02461 strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02462 }
02463 }
02464 ast_format_cap_iter_end(p->cap);
02465
02466 ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
02467 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02468 sub->sdpsent = 0;
02469 oseq = reqprep(&resp, p, "CRCX");
02470 add_header(&resp, "C", sub->callid);
02471 add_header(&resp, "L", local);
02472 add_header(&resp, "M", "inactive");
02473
02474 add_header(&resp, "X", sub->txident);
02475
02476
02477 resp.cmd = MGCP_CMD_CRCX;
02478 resp.trid = oseq;
02479 return send_request(p, sub, &resp, oseq);
02480 }
02481
02482 static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
02483 {
02484 struct mgcp_request resp;
02485 struct mgcp_endpoint *p = sub->parent;
02486 unsigned int oseq;
02487
02488 ast_debug(3, "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
02489 tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
02490 ast_copy_string(p->curtone, tone, sizeof(p->curtone));
02491 oseq = reqprep(&resp, p, "RQNT");
02492 add_header(&resp, "X", p->rqnt_ident);
02493 switch (p->hookstate) {
02494 case MGCP_ONHOOK:
02495 add_header(&resp, "R", "L/hd(N)");
02496 break;
02497 case MGCP_OFFHOOK:
02498 add_header_offhook(sub, &resp, tone);
02499 break;
02500 }
02501 if (!ast_strlen_zero(tone)) {
02502 add_header(&resp, "S", tone);
02503 }
02504
02505 resp.cmd = MGCP_CMD_RQNT;
02506 resp.trid = oseq;
02507 return send_request(p, NULL, &resp, oseq);
02508 }
02509
02510 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername)
02511 {
02512 struct mgcp_request resp;
02513 char tone2[256];
02514 char *l, *n;
02515 struct timeval t = ast_tvnow();
02516 struct ast_tm tm;
02517 struct mgcp_endpoint *p = sub->parent;
02518 unsigned int oseq;
02519
02520 ast_localtime(&t, &tm, NULL);
02521 n = callername;
02522 l = callernum;
02523 if (!n)
02524 n = "";
02525 if (!l)
02526 l = "";
02527
02528
02529 ast_copy_string(p->lastcallerid, l, sizeof(p->lastcallerid));
02530
02531 snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone,
02532 tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n);
02533 ast_copy_string(p->curtone, tone, sizeof(p->curtone));
02534 oseq = reqprep(&resp, p, "RQNT");
02535 add_header(&resp, "X", p->rqnt_ident);
02536 switch (p->hookstate) {
02537 case MGCP_ONHOOK:
02538 add_header(&resp, "R", "L/hd(N)");
02539 break;
02540 case MGCP_OFFHOOK:
02541 add_header_offhook(sub, &resp, tone);
02542 break;
02543 }
02544 if (!ast_strlen_zero(tone2)) {
02545 add_header(&resp, "S", tone2);
02546 }
02547 ast_debug(3, "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
02548 tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
02549
02550 resp.cmd = MGCP_CMD_RQNT;
02551 resp.trid = oseq;
02552 return send_request(p, NULL, &resp, oseq);
02553 }
02554
02555 static int transmit_modify_request(struct mgcp_subchannel *sub)
02556 {
02557 struct mgcp_request resp;
02558 struct mgcp_endpoint *p = sub->parent;
02559 struct ast_format tmpfmt;
02560 int fc = 1;
02561 char local[256];
02562 char tmp[80];
02563 unsigned int oseq;
02564
02565 if (ast_strlen_zero(sub->cxident)) {
02566
02567
02568 return 0;
02569 }
02570 ast_debug(3, "Modified %s@%s-%d with new mode: %s on callid: %s\n",
02571 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02572
02573 ast_copy_string(local, "", sizeof(local));
02574 ast_format_cap_iter_start(p->cap);
02575 while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) {
02576 if (p->ncs && !fc) {
02577 ast_format_cap_set(p->cap, &tmpfmt);
02578 break;
02579 } else {
02580 fc = 0;
02581 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0));
02582 }
02583 strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02584 }
02585 ast_format_cap_iter_end(p->cap);
02586
02587 if (!sub->sdpsent) {
02588 if (sub->gate) {
02589 if (sub->gate->state == GATE_ALLOCATED || sub->gate->state == GATE_OPEN) {
02590 snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid);
02591 strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02592 } else {
02593
02594 return 0;
02595 }
02596 }
02597 }
02598
02599 oseq = reqprep(&resp, p, "MDCX");
02600 add_header(&resp, "C", sub->callid);
02601 if (!sub->sdpsent) {
02602 add_header(&resp, "L", local);
02603 }
02604 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02605
02606 add_header(&resp, "X", sub->txident);
02607 add_header(&resp, "I", sub->cxident);
02608 switch (sub->parent->hookstate) {
02609 case MGCP_ONHOOK:
02610 add_header(&resp, "R", "L/hd(N)");
02611 break;
02612 case MGCP_OFFHOOK:
02613 add_header_offhook(sub, &resp, "");
02614 break;
02615 }
02616 if (!sub->sdpsent) {
02617 add_sdp(&resp, sub, NULL);
02618 sub->sdpsent = 1;
02619 }
02620
02621 resp.cmd = MGCP_CMD_MDCX;
02622 resp.trid = oseq;
02623 return send_request(p, sub, &resp, oseq);
02624 }
02625
02626
02627 static void add_header_offhook(struct mgcp_subchannel *sub, struct mgcp_request *resp, char *tone)
02628 {
02629 struct mgcp_endpoint *p = sub->parent;
02630 char tone_indicate_end = 0;
02631
02632
02633
02634
02635 if (p && (!strcasecmp(tone, (p->ncs ? "L/ro" : "G/cg")))) {
02636 tone_indicate_end = 1;
02637 }
02638
02639 if (p && p->sub && p->sub->owner &&
02640 ast_channel_state(p->sub->owner) >= AST_STATE_RINGING &&
02641 (p->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID))) {
02642 add_header(resp, "R", "L/hu(N),L/hf(N)");
02643
02644 } else if (!tone_indicate_end){
02645 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)"));
02646 } else {
02647 ast_debug(1, "We don't want more digits if we will end the call\n");
02648 add_header(resp, "R", "L/hu(N),L/hf(N)");
02649 }
02650 }
02651
02652
02653
02654
02655 static int transmit_audit_endpoint(struct mgcp_endpoint *p)
02656 {
02657 struct mgcp_request resp;
02658 unsigned int oseq;
02659 oseq = reqprep(&resp, p, "AUEP");
02660
02661
02662 add_header(&resp, "F", "A");
02663
02664 resp.cmd = MGCP_CMD_AUEP;
02665 resp.trid = oseq;
02666 return send_request(p, NULL, &resp, oseq);
02667 }
02668
02669 static int transmit_connection_del(struct mgcp_subchannel *sub)
02670 {
02671 struct mgcp_endpoint *p = sub->parent;
02672 struct mgcp_request resp;
02673 unsigned int oseq;
02674
02675 ast_debug(3, "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n",
02676 sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02677 oseq = reqprep(&resp, p, "DLCX");
02678
02679 if (sub->callid[0])
02680 add_header(&resp, "C", sub->callid);
02681
02682 add_header(&resp, "X", sub->txident);
02683
02684 if (sub->cxident[0])
02685 add_header(&resp, "I", sub->cxident);
02686
02687 resp.cmd = MGCP_CMD_DLCX;
02688 resp.trid = oseq;
02689 return send_request(p, sub, &resp, oseq);
02690 }
02691
02692 static int transmit_connection_del_w_params(struct mgcp_endpoint *p, char *callid, char *cxident)
02693 {
02694 struct mgcp_request resp;
02695 unsigned int oseq;
02696
02697 ast_debug(3, "Delete connection %s %s@%s on callid: %s\n",
02698 cxident ? cxident : "", p->name, p->parent->name, callid ? callid : "");
02699 oseq = reqprep(&resp, p, "DLCX");
02700
02701 if (callid && *callid)
02702 add_header(&resp, "C", callid);
02703
02704 if (cxident && *cxident)
02705 add_header(&resp, "I", cxident);
02706
02707 resp.cmd = MGCP_CMD_DLCX;
02708 resp.trid = oseq;
02709 return send_request(p, p->sub, &resp, oseq);
02710 }
02711
02712
02713 static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
02714 {
02715 struct mgcp_request *t, *q;
02716
02717 if (p) {
02718 ast_mutex_lock(&p->rqnt_queue_lock);
02719 for (q = p->rqnt_queue; q; t = q->next, ast_free(q), q=t);
02720 p->rqnt_queue = NULL;
02721 ast_mutex_unlock(&p->rqnt_queue_lock);
02722
02723 ast_mutex_lock(&p->cmd_queue_lock);
02724 for (q = p->cmd_queue; q; t = q->next, ast_free(q), q=t);
02725 p->cmd_queue = NULL;
02726 ast_mutex_unlock(&p->cmd_queue_lock);
02727
02728 ast_mutex_lock(&p->sub->cx_queue_lock);
02729 for (q = p->sub->cx_queue; q; t = q->next, ast_free(q), q=t);
02730 p->sub->cx_queue = NULL;
02731 ast_mutex_unlock(&p->sub->cx_queue_lock);
02732
02733 ast_mutex_lock(&p->sub->next->cx_queue_lock);
02734 for (q = p->sub->next->cx_queue; q; t = q->next, ast_free(q), q=t);
02735 p->sub->next->cx_queue = NULL;
02736 ast_mutex_unlock(&p->sub->next->cx_queue_lock);
02737 } else if (sub) {
02738 ast_mutex_lock(&sub->cx_queue_lock);
02739 for (q = sub->cx_queue; q; t = q->next, ast_free(q), q=t);
02740 sub->cx_queue = NULL;
02741 ast_mutex_unlock(&sub->cx_queue_lock);
02742 }
02743 }
02744
02745
02746
02747 static struct mgcp_request *find_command(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
02748 struct mgcp_request **queue, ast_mutex_t *l, int ident)
02749 {
02750 struct mgcp_request *prev, *req;
02751
02752 ast_mutex_lock(l);
02753 for (prev = NULL, req = *queue; req; prev = req, req = req->next) {
02754 if (req->trid == ident) {
02755
02756 if (!prev)
02757 *queue = req->next;
02758 else
02759 prev->next = req->next;
02760
02761
02762 if (*queue) {
02763 ast_debug(1, "Posting Queued Request:\n%s to %s:%d\n", (*queue)->data,
02764 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
02765
02766 mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid);
02767 }
02768 break;
02769 }
02770 }
02771 ast_mutex_unlock(l);
02772 return req;
02773 }
02774
02775
02776 static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
02777 int result, unsigned int ident, struct mgcp_request *resp)
02778 {
02779 char *c;
02780 struct mgcp_request *req;
02781 struct mgcp_gateway *gw = p->parent;
02782
02783 if (result < 200) {
02784
02785 return;
02786 }
02787
02788 if (p->slowsequence)
02789 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
02790 else if (sub)
02791 req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident);
02792 else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident)))
02793 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
02794
02795 if (!req) {
02796 ast_verb(3, "No command found on [%s] for transaction %d. Ignoring...\n",
02797 gw->name, ident);
02798 return;
02799 }
02800
02801 if (p && (result >= 400) && (result <= 599)) {
02802 switch (result) {
02803 case 401:
02804 p->hookstate = MGCP_OFFHOOK;
02805 break;
02806 case 402:
02807 p->hookstate = MGCP_ONHOOK;
02808 break;
02809 case 406:
02810 ast_log(LOG_NOTICE, "Transaction %d timed out\n", ident);
02811 break;
02812 case 407:
02813 ast_log(LOG_NOTICE, "Transaction %d aborted\n", ident);
02814 break;
02815 }
02816 if (sub) {
02817 if (!sub->cxident[0] && (req->cmd == MGCP_CMD_CRCX)) {
02818 ast_log(LOG_NOTICE, "DLCX for all connections on %s due to error %d\n", gw->name, result);
02819 transmit_connection_del(sub);
02820 }
02821 if (sub->owner) {
02822 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
02823 result, p->name, p->parent->name, sub ? sub->id:-1);
02824 mgcp_queue_hangup(sub);
02825 }
02826 } else {
02827 if (p->sub->next->owner) {
02828 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
02829 result, p->name, p->parent->name, sub ? sub->id:-1);
02830 mgcp_queue_hangup(p->sub);
02831 }
02832
02833 if (p->sub->owner) {
02834 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
02835 result, p->name, p->parent->name, sub ? sub->id:-1);
02836 mgcp_queue_hangup(p->sub);
02837 }
02838
02839 dump_cmd_queues(p, NULL);
02840 }
02841 }
02842
02843 if (resp) {
02844
02845 if (result == 200 && (req->cmd == MGCP_CMD_CRCX || req->cmd == MGCP_CMD_MDCX)) {
02846 if (sub) {
02847 transmit_response(sub, "000", resp, "OK");
02848 if (sub->owner && ast_channel_state(sub->owner) == AST_STATE_RINGING) {
02849 ast_queue_control(sub->owner, AST_CONTROL_RINGING);
02850 }
02851 }
02852 }
02853 if (req->cmd == MGCP_CMD_CRCX) {
02854 if ((c = get_header(resp, "I"))) {
02855 if (!ast_strlen_zero(c) && sub) {
02856
02857 if (sub->owner) {
02858 if (!ast_strlen_zero(sub->cxident)) {
02859 if (strcasecmp(c, sub->cxident)) {
02860 ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c);
02861 }
02862 }
02863 ast_copy_string(sub->cxident, c, sizeof(sub->cxident));
02864 if (sub->tmpdest.sin_addr.s_addr) {
02865 transmit_modify_with_sdp(sub, NULL, 0);
02866 }
02867 } else {
02868
02869
02870
02871
02872 transmit_connection_del(sub);
02873 }
02874 }
02875 }
02876 }
02877
02878 if (req->cmd == MGCP_CMD_AUEP) {
02879
02880 if ((c = get_header(resp, "I"))) {
02881 char *v, *n;
02882 int len;
02883 while ((v = get_csv(c, &len, &n))) {
02884 if (len) {
02885 if (strncasecmp(v, p->sub->cxident, len) &&
02886 strncasecmp(v, p->sub->next->cxident, len)) {
02887
02888 char cxident[80] = "";
02889
02890 if (len > (sizeof(cxident) - 1))
02891 len = sizeof(cxident) - 1;
02892 ast_copy_string(cxident, v, len);
02893 ast_verb(3, "Non existing connection id %s on %s@%s \n",
02894 cxident, p->name, gw->name);
02895 transmit_connection_del_w_params(p, NULL, cxident);
02896 }
02897 }
02898 c = n;
02899 }
02900 }
02901
02902
02903 if ((c = get_header(resp, "ES"))) {
02904 if (!ast_strlen_zero(c)) {
02905 if (strstr(c, "hu")) {
02906 if (p->hookstate != MGCP_ONHOOK) {
02907
02908 if ((p->sub->owner || p->sub->next->owner ) &&
02909 p->hookstate == MGCP_OFFHOOK)
02910 mgcp_queue_hangup(sub);
02911 p->hookstate = MGCP_ONHOOK;
02912
02913
02914 transmit_notify_request(p->sub, "");
02915
02916 ast_verb(3, "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name);
02917 }
02918 } else if (strstr(c, "hd")) {
02919 if (p->hookstate != MGCP_OFFHOOK) {
02920 p->hookstate = MGCP_OFFHOOK;
02921
02922
02923 transmit_notify_request(p->sub, "");
02924
02925 ast_verb(3, "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name);
02926 }
02927 }
02928 }
02929 }
02930 }
02931
02932 if (resp && resp->lines) {
02933
02934 if (sub && sub->owner) {
02935 if (!sub->rtp)
02936 start_rtp(sub);
02937 if (sub->rtp)
02938 process_sdp(sub, resp);
02939 }
02940 }
02941 }
02942
02943 ast_free(req);
02944 }
02945
02946 static void start_rtp(struct mgcp_subchannel *sub)
02947 {
02948 struct ast_sockaddr bindaddr_tmp;
02949
02950 ast_mutex_lock(&sub->lock);
02951
02952 if (sub->rtp) {
02953 ast_rtp_instance_destroy(sub->rtp);
02954 sub->rtp = NULL;
02955 }
02956
02957 ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
02958 sub->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL);
02959 if (sub->rtp && sub->owner)
02960 ast_channel_set_fd(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0));
02961 if (sub->rtp) {
02962 ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "MGCP RTP");
02963 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->nat);
02964 }
02965
02966 snprintf(sub->callid, sizeof(sub->callid), "%08lx%s", ast_random(), sub->txident);
02967
02968 if(!sub->parent->pktcgatealloc) {
02969 transmit_connect_with_sdp(sub, NULL);
02970 } else {
02971 transmit_connect(sub);
02972 sub->gate = NULL;
02973 if(!mgcp_alloc_pktcgate(sub))
02974 mgcp_queue_hangup(sub);
02975 }
02976 ast_mutex_unlock(&sub->lock);
02977 }
02978
02979 static void *mgcp_ss(void *data)
02980 {
02981 struct ast_channel *chan = data;
02982 struct mgcp_subchannel *sub = ast_channel_tech_pvt(chan);
02983 struct mgcp_endpoint *p = sub->parent;
02984
02985 int len = 0;
02986 int timeout = firstdigittimeout;
02987 int res= 0;
02988 int getforward = 0;
02989 int loop_pause = 100;
02990
02991 len = strlen(p->dtmf_buf);
02992
02993 while (len < AST_MAX_EXTENSION - 1) {
02994 ast_debug(1, "Dtmf buffer '%s' for '%s@%s'\n", p->dtmf_buf, p->name, p->parent->name);
02995 res = 1;
02996 while (strlen(p->dtmf_buf) == len) {
02997 ast_safe_sleep(chan, loop_pause);
02998 timeout -= loop_pause;
02999 if (timeout <= 0){
03000 res = 0;
03001 break;
03002 }
03003 res = 1;
03004 }
03005
03006 timeout = 0;
03007 len = strlen(p->dtmf_buf);
03008
03009 if (!ast_ignore_pattern(ast_channel_context(chan), p->dtmf_buf)) {
03010
03011 ast_indicate(chan, -1);
03012 } else {
03013
03014
03015 transmit_notify_request(sub, "L/dl");
03016 }
03017 if (ast_exists_extension(chan, ast_channel_context(chan), p->dtmf_buf, 1, p->cid_num)) {
03018 if (!res || !ast_matchmore_extension(chan, ast_channel_context(chan), p->dtmf_buf, 1, p->cid_num)) {
03019 if (getforward) {
03020
03021 ast_copy_string(p->call_forward, p->dtmf_buf, sizeof(p->call_forward));
03022 ast_verb(3, "Setting call forward to '%s' on channel %s\n",
03023 p->call_forward, ast_channel_name(chan));
03024
03025 transmit_notify_request(sub, "L/sl");
03026 if (res)
03027 break;
03028 usleep(500000);
03029
03030 ast_indicate(chan, -1);
03031 sleep(1);
03032 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03033
03034 transmit_notify_request(sub, "L/dl");
03035 len = 0;
03036 getforward = 0;
03037 } else {
03038
03039 ast_indicate(chan, -1);
03040 ast_channel_exten_set(chan, p->dtmf_buf);
03041 ast_channel_dialed(chan)->number.str = ast_strdup(p->dtmf_buf);
03042 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03043 ast_set_callerid(chan,
03044 p->hidecallerid ? "" : p->cid_num,
03045 p->hidecallerid ? "" : p->cid_name,
03046 ast_channel_caller(chan)->ani.number.valid ? NULL : p->cid_num);
03047 ast_setstate(chan, AST_STATE_RING);
03048
03049 if (p->dtmfmode & MGCP_DTMF_HYBRID) {
03050 p->dtmfmode |= MGCP_DTMF_INBAND;
03051 ast_indicate(chan, -1);
03052 }
03053 res = ast_pbx_run(chan);
03054 if (res) {
03055 ast_log(LOG_WARNING, "PBX exited non-zero\n");
03056
03057
03058 transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
03059 }
03060 return NULL;
03061 }
03062 } else {
03063
03064
03065 timeout = matchdigittimeout;
03066 }
03067 } else if (res == 0) {
03068 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
03069
03070 transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
03071
03072 ast_hangup(chan);
03073 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03074 return NULL;
03075 } else if (p->hascallwaiting && p->callwaiting && !strcmp(p->dtmf_buf, "*70")) {
03076 ast_verb(3, "Disabling call waiting on %s\n", ast_channel_name(chan));
03077
03078 p->callwaiting = 0;
03079
03080 transmit_notify_request(sub, "L/sl");
03081 len = 0;
03082 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03083 timeout = firstdigittimeout;
03084 } else if (!strcmp(p->dtmf_buf,ast_pickup_ext())) {
03085
03086
03087
03088
03089 if (ast_pickup_call(chan)) {
03090 ast_log(LOG_WARNING, "No call pickup possible...\n");
03091
03092 transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
03093 }
03094 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03095 ast_hangup(chan);
03096 return NULL;
03097 } else if (!p->hidecallerid && !strcmp(p->dtmf_buf, "*67")) {
03098 ast_verb(3, "Disabling Caller*ID on %s\n", ast_channel_name(chan));
03099
03100 p->hidecallerid = 1;
03101 ast_set_callerid(chan, "", "", NULL);
03102
03103 transmit_notify_request(sub, "L/sl");
03104 len = 0;
03105 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03106 timeout = firstdigittimeout;
03107 } else if (p->callreturn && !strcmp(p->dtmf_buf, "*69")) {
03108 res = 0;
03109 if (!ast_strlen_zero(p->lastcallerid)) {
03110 res = ast_say_digit_str(chan, p->lastcallerid, "", ast_channel_language(chan));
03111 }
03112 if (!res)
03113
03114 transmit_notify_request(sub, "L/sl");
03115 break;
03116 } else if (!strcmp(p->dtmf_buf, "*78")) {
03117
03118 ast_verb(3, "Enabled DND on channel %s\n", ast_channel_name(chan));
03119
03120 transmit_notify_request(sub, "L/sl");
03121 p->dnd = 1;
03122 getforward = 0;
03123 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03124 len = 0;
03125 } else if (!strcmp(p->dtmf_buf, "*79")) {
03126
03127 ast_verb(3, "Disabled DND on channel %s\n", ast_channel_name(chan));
03128
03129 transmit_notify_request(sub, "L/sl");
03130 p->dnd = 0;
03131 getforward = 0;
03132 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03133 len = 0;
03134 } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*72")) {
03135
03136 transmit_notify_request(sub, "L/sl");
03137 getforward = 1;
03138 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03139 len = 0;
03140 } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*73")) {
03141 ast_verb(3, "Cancelling call forwarding on channel %s\n", ast_channel_name(chan));
03142
03143 transmit_notify_request(sub, "L/sl");
03144 memset(p->call_forward, 0, sizeof(p->call_forward));
03145 getforward = 0;
03146 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03147 len = 0;
03148 } else if (ast_parking_ext_valid(p->dtmf_buf, chan, ast_channel_context(chan)) &&
03149 sub->next->owner && ast_bridged_channel(sub->next->owner)) {
03150
03151
03152 ast_masq_park_call_exten(ast_bridged_channel(sub->next->owner), chan,
03153 p->dtmf_buf, ast_channel_context(chan), 0, NULL);
03154 ast_verb(3, "Parking call to '%s'\n", ast_channel_name(chan));
03155 break;
03156 } else if (!ast_strlen_zero(p->lastcallerid) && !strcmp(p->dtmf_buf, "*60")) {
03157 ast_verb(3, "Blacklisting number %s\n", p->lastcallerid);
03158 res = ast_db_put("blacklist", p->lastcallerid, "1");
03159 if (!res) {
03160
03161 transmit_notify_request(sub, "L/sl");
03162 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03163 len = 0;
03164 }
03165 } else if (p->hidecallerid && !strcmp(p->dtmf_buf, "*82")) {
03166 ast_verb(3, "Enabling Caller*ID on %s\n", ast_channel_name(chan));
03167
03168 p->hidecallerid = 0;
03169 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
03170
03171 transmit_notify_request(sub, "L/sl");
03172 len = 0;
03173 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03174 timeout = firstdigittimeout;
03175 } else if (!ast_canmatch_extension(chan, ast_channel_context(chan), p->dtmf_buf, 1,
03176 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))
03177 && ((p->dtmf_buf[0] != '*') || (strlen(p->dtmf_buf) > 2))) {
03178 ast_debug(1, "Can't match %s from '%s' in context %s\n", p->dtmf_buf,
03179 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<Unknown Caller>"),
03180 ast_channel_context(chan));
03181 break;
03182 }
03183 if (!timeout)
03184 timeout = gendigittimeout;
03185 if (len && !ast_ignore_pattern(ast_channel_context(chan), p->dtmf_buf))
03186
03187 ast_indicate(chan, -1);
03188 }
03189 #if 0
03190 for (;;) {
03191 res = ast_waitfordigit(chan, to);
03192 if (!res) {
03193 ast_debug(1, "Timeout...\n");
03194 break;
03195 }
03196 if (res < 0) {
03197 ast_debug(1, "Got hangup...\n");
03198 ast_hangup(chan);
03199 break;
03200 }
03201 exten[pos++] = res;
03202 if (!ast_ignore_pattern(chan->context, exten))
03203 ast_indicate(chan, -1);
03204 if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) {
03205 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid))
03206 to = 3000;
03207 else
03208 to = 8000;
03209 } else
03210 break;
03211 }
03212 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) {
03213 ast_copy_string(chan->exten, exten, sizeof(chan->exten)1);
03214 if (!p->rtp) {
03215 start_rtp(p);
03216 }
03217 ast_setstate(chan, AST_STATE_RING);
03218 chan->rings = 1;
03219 if (ast_pbx_run(chan)) {
03220 ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name);
03221 } else {
03222 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03223 return NULL;
03224 }
03225 }
03226 #endif
03227 ast_hangup(chan);
03228 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03229 return NULL;
03230 }
03231
03232 static int attempt_transfer(struct mgcp_endpoint *p)
03233 {
03234
03235
03236
03237
03238
03239
03240
03241
03242
03243 if (ast_bridged_channel(p->sub->owner)) {
03244
03245
03246 if (ast_bridged_channel(p->sub->next->owner))
03247 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD);
03248 if (ast_channel_state(p->sub->owner) == AST_STATE_RINGING) {
03249 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
03250 }
03251 if (ast_channel_masquerade(p->sub->next->owner, ast_bridged_channel(p->sub->owner))) {
03252 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03253 ast_channel_name(ast_bridged_channel(p->sub->owner)), ast_channel_name(p->sub->next->owner));
03254 return -1;
03255 }
03256
03257 unalloc_sub(p->sub->next);
03258 } else if (ast_bridged_channel(p->sub->next->owner)) {
03259 if (ast_channel_state(p->sub->owner) == AST_STATE_RINGING) {
03260 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
03261 }
03262 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD);
03263 if (ast_channel_masquerade(p->sub->owner, ast_bridged_channel(p->sub->next->owner))) {
03264 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03265 ast_channel_name(ast_bridged_channel(p->sub->next->owner)), ast_channel_name(p->sub->owner));
03266 return -1;
03267 }
03268
03269 ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name);
03270 p->sub = p->sub->next;
03271 unalloc_sub(p->sub->next);
03272
03273 return 1;
03274 } else {
03275 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
03276 ast_channel_name(p->sub->owner), ast_channel_name(p->sub->next->owner));
03277 ast_channel_softhangup_internal_flag_add(p->sub->next->owner, AST_SOFTHANGUP_DEV);
03278 if (p->sub->next->owner) {
03279 p->sub->next->alreadygone = 1;
03280 mgcp_queue_hangup(p->sub->next);
03281 }
03282 }
03283 return 0;
03284 }
03285
03286 static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev)
03287 {
03288 struct mgcp_endpoint *p = sub->parent;
03289 struct ast_channel *c;
03290 pthread_t t;
03291
03292
03293 if (sub->outgoing) {
03294
03295 if (sub->owner) {
03296 if (ast_bridged_channel(sub->owner))
03297 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD);
03298 sub->cxmode = MGCP_CX_SENDRECV;
03299 if (!sub->rtp) {
03300 start_rtp(sub);
03301 } else {
03302 transmit_modify_request(sub);
03303 }
03304
03305 transmit_notify_request(sub, "");
03306 mgcp_queue_control(sub, AST_CONTROL_ANSWER);
03307 }
03308 } else {
03309
03310
03311 if (!sub->owner) {
03312 if (!sub->rtp) {
03313 start_rtp(sub);
03314 } else {
03315 transmit_modify_request(sub);
03316 }
03317 if (p->immediate) {
03318
03319 #ifdef DLINK_BUGGY_FIRMWARE
03320 transmit_notify_request(sub, "rt");
03321 #else
03322 transmit_notify_request(sub, p->ncs ? "L/rt" : "G/rt");
03323 #endif
03324 c = mgcp_new(sub, AST_STATE_RING, NULL);
03325 if (!c) {
03326 ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name);
03327 transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
03328 ast_hangup(c);
03329 }
03330 } else {
03331 if (has_voicemail(p)) {
03332 transmit_notify_request(sub, "L/sl");
03333 } else {
03334 transmit_notify_request(sub, "L/dl");
03335 }
03336 c = mgcp_new(sub, AST_STATE_DOWN, NULL);
03337 if (c) {
03338 if (ast_pthread_create_detached(&t, NULL, mgcp_ss, c)) {
03339 ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
03340 ast_hangup(c);
03341 }
03342 } else {
03343 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name);
03344 }
03345 }
03346 } else {
03347 if (p->hookstate == MGCP_OFFHOOK) {
03348 ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name);
03349 } else {
03350 ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name);
03351 ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?\n");
03352 }
03353 if (ast_bridged_channel(sub->owner))
03354 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD);
03355 sub->cxmode = MGCP_CX_SENDRECV;
03356 if (!sub->rtp) {
03357 start_rtp(sub);
03358 } else {
03359 transmit_modify_request(sub);
03360 }
03361
03362 transmit_notify_request(sub, "");
03363
03364 }
03365 }
03366 }
03367
03368 static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req, struct sockaddr_in *sin)
03369 {
03370 char *ev, *s;
03371 struct ast_frame f = { 0, };
03372 struct mgcp_endpoint *p = sub->parent;
03373 struct mgcp_gateway *g = NULL;
03374 int res;
03375
03376 ast_debug(1, "Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
03377
03378 if (!strcasecmp(req->verb, "RSIP")) {
03379
03380 if (!strcasecmp( get_header(req, "RM"), "X-keepalive")) {
03381 ast_verb(3, "Received keepalive request from %s@%s\n", p->name, p->parent->name);
03382 transmit_response(sub, "200", req, "OK");
03383 } else {
03384 dump_queue(p->parent, p);
03385 dump_cmd_queues(p, NULL);
03386
03387 if ((strcmp(p->name, p->parent->wcardep) != 0)) {
03388 ast_verb(3, "Resetting interface %s@%s\n", p->name, p->parent->name);
03389 }
03390
03391 if (!strcmp(p->name, p->parent->wcardep)) {
03392
03393 struct mgcp_endpoint *tmp_ep;
03394
03395 g = p->parent;
03396 for (tmp_ep = g->endpoints; tmp_ep; tmp_ep = tmp_ep->next) {
03397
03398 if (strcmp(tmp_ep->name, g->wcardep) != 0) {
03399 struct mgcp_subchannel *tmp_sub, *first_sub;
03400 ast_verb(3, "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name);
03401
03402 first_sub = tmp_ep->sub;
03403 tmp_sub = tmp_ep->sub;
03404 while (tmp_sub) {
03405 mgcp_queue_hangup(tmp_sub);
03406 tmp_sub = tmp_sub->next;
03407 if (tmp_sub == first_sub)
03408 break;
03409 }
03410 }
03411 }
03412 } else if (sub->owner) {
03413 mgcp_queue_hangup(sub);
03414 }
03415 transmit_response(sub, "200", req, "OK");
03416
03417 if (strcmp(p->name, p->parent->wcardep) != 0) {
03418 transmit_notify_request(sub, "");
03419
03420
03421
03422 transmit_audit_endpoint(p);
03423 }
03424 }
03425 } else if (!strcasecmp(req->verb, "NTFY")) {
03426
03427 transmit_response(sub, "200", req, "OK");
03428
03429 ev = get_header(req, "O");
03430 s = strchr(ev, '/');
03431 if (s) ev = s + 1;
03432 ast_debug(1, "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev);
03433
03434 if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd") && strcasecmp(ev, "ping")) {
03435 transmit_notify_request(sub, p->curtone);
03436 }
03437 if (!strcasecmp(ev, "hd")) {
03438 p->hookstate = MGCP_OFFHOOK;
03439 sub->cxmode = MGCP_CX_SENDRECV;
03440
03441 if (p) {
03442
03443
03444 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03445 }
03446
03447 handle_hd_hf(sub, ev);
03448 } else if (!strcasecmp(ev, "hf")) {
03449
03450
03451
03452 if (p->hookstate != MGCP_OFFHOOK) {
03453
03454
03455 return -1;
03456 }
03457
03458 if (sub->owner && ast_channel_state(sub->owner) == AST_STATE_DOWN && !sub->next->owner)
03459 return -1;
03460
03461 if (p->callwaiting || p->transfer || p->threewaycalling) {
03462 ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name);
03463 p->sub = p->sub->next;
03464
03465
03466 if (!sub->next->owner) {
03467
03468 sub->cxmode = MGCP_CX_MUTE;
03469 ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
03470 transmit_modify_request(sub);
03471 if (sub->owner && ast_bridged_channel(sub->owner))
03472 ast_queue_control(sub->owner, AST_CONTROL_HOLD);
03473 sub->next->cxmode = MGCP_CX_RECVONLY;
03474 handle_hd_hf(sub->next, ev);
03475 } else if (sub->owner && sub->next->owner) {
03476
03477 if ((!sub->outgoing) && (!sub->next->outgoing)) {
03478
03479 ast_verb(3, "MGCP Conferencing %d and %d on %s@%s\n",
03480 sub->id, sub->next->id, p->name, p->parent->name);
03481 sub->cxmode = MGCP_CX_CONF;
03482 sub->next->cxmode = MGCP_CX_CONF;
03483 if (ast_bridged_channel(sub->next->owner))
03484 ast_queue_control(sub->next->owner, AST_CONTROL_UNHOLD);
03485 transmit_modify_request(sub);
03486 transmit_modify_request(sub->next);
03487 } else {
03488
03489
03490
03491 ast_verb(3, "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n",
03492 sub->id, sub->next->id, p->name, p->parent->name);
03493 sub->cxmode = MGCP_CX_MUTE;
03494 ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
03495 transmit_modify_request(sub);
03496 if (ast_bridged_channel(sub->owner))
03497 ast_queue_control(sub->owner, AST_CONTROL_HOLD);
03498
03499 if (ast_bridged_channel(sub->next->owner))
03500 ast_queue_control(sub->next->owner, AST_CONTROL_HOLD);
03501
03502 handle_hd_hf(sub->next, ev);
03503 }
03504 } else {
03505
03506 if (sub->owner) {
03507 p->sub = sub;
03508 } else if (sub->next->owner) {
03509 p->sub = sub->next;
03510 } else {
03511
03512
03513 return -1;
03514 }
03515 if (ast_bridged_channel(p->sub->owner))
03516 ast_queue_control(p->sub->owner, AST_CONTROL_UNHOLD);
03517 p->sub->cxmode = MGCP_CX_SENDRECV;
03518 transmit_modify_request(p->sub);
03519 }
03520 } else {
03521 ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n",
03522 p->name, p->parent->name);
03523 }
03524 } else if (!strcasecmp(ev, "hu")) {
03525 p->hookstate = MGCP_ONHOOK;
03526 sub->cxmode = MGCP_CX_RECVONLY;
03527 ast_debug(1, "MGCP %s@%s Went on hook\n", p->name, p->parent->name);
03528
03529
03530
03531
03532
03533 if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) {
03534
03535
03536 ast_mutex_lock(&p->sub->next->lock);
03537 res = attempt_transfer(p);
03538 if (res < 0) {
03539 if (p->sub->next->owner) {
03540 sub->next->alreadygone = 1;
03541 mgcp_queue_hangup(sub->next);
03542 }
03543 } else if (res) {
03544 ast_log(LOG_WARNING, "Transfer attempt failed\n");
03545 ast_mutex_unlock(&p->sub->next->lock);
03546 return -1;
03547 }
03548 ast_mutex_unlock(&p->sub->next->lock);
03549 } else {
03550
03551
03552 if (sub->owner) {
03553 sub->alreadygone = 1;
03554 mgcp_queue_hangup(sub);
03555 } else {
03556 ast_verb(3, "MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n",
03557 p->name, p->parent->name, sub->id);
03558
03559
03560
03561 transmit_connection_del(sub);
03562 }
03563 }
03564 if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) {
03565 p->hidecallerid = 0;
03566 if (p->hascallwaiting && !p->callwaiting) {
03567 ast_verb(3, "Enabling call waiting on MGCP/%s@%s-%d\n", p->name, p->parent->name, sub->id);
03568 p->callwaiting = -1;
03569 }
03570 if (has_voicemail(p)) {
03571 ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name);
03572 transmit_notify_request(sub, "L/vmwi(+)");
03573 } else {
03574 ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name);
03575 transmit_notify_request(sub, "L/vmwi(-)");
03576 }
03577 }
03578 } else if ((strlen(ev) == 1) &&
03579 (((ev[0] >= '0') && (ev[0] <= '9')) ||
03580 ((ev[0] >= 'A') && (ev[0] <= 'D')) ||
03581 (ev[0] == '*') || (ev[0] == '#'))) {
03582 if (sub && sub->owner && (ast_channel_state(sub->owner) >= AST_STATE_UP)) {
03583 f.frametype = AST_FRAME_DTMF;
03584 f.subclass.integer = ev[0];
03585 f.src = "mgcp";
03586
03587 mgcp_queue_frame(sub, &f);
03588 ast_mutex_lock(&sub->next->lock);
03589 if (sub->next->owner)
03590 mgcp_queue_frame(sub->next, &f);
03591 ast_mutex_unlock(&sub->next->lock);
03592 if (strstr(p->curtone, (p->ncs ? "wt1" : "wt")) && (ev[0] == 'A')) {
03593 memset(p->curtone, 0, sizeof(p->curtone));
03594 }
03595 } else {
03596 p->dtmf_buf[strlen(p->dtmf_buf)] = ev[0];
03597 p->dtmf_buf[strlen(p->dtmf_buf)] = '\0';
03598 }
03599 } else if (!strcasecmp(ev, "T")) {
03600
03601 } else if (!strcasecmp(ev, "ping")) {
03602
03603 } else {
03604 ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name);
03605 }
03606 } else {
03607 ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, ast_inet_ntoa(sin->sin_addr));
03608 transmit_response(sub, "510", req, "Unknown verb");
03609 }
03610 return 0;
03611 }
03612
03613 static int find_and_retrans(struct mgcp_subchannel *sub, struct mgcp_request *req)
03614 {
03615 int seqno=0;
03616 time_t now;
03617 struct mgcp_response *prev = NULL, *cur, *next, *answer = NULL;
03618 time(&now);
03619 if (sscanf(req->identifier, "%30d", &seqno) != 1) {
03620 seqno = 0;
03621 }
03622 for (cur = sub->parent->parent->responses, next = cur ? cur->next : NULL; cur; cur = next, next = cur ? cur->next : NULL) {
03623 if (now - cur->whensent > RESPONSE_TIMEOUT) {
03624
03625 if (prev)
03626 prev->next = next;
03627 else
03628 sub->parent->parent->responses = next;
03629 ast_free(cur);
03630 } else {
03631 if (seqno == cur->seqno)
03632 answer = cur;
03633 prev = cur;
03634 }
03635 }
03636 if (answer) {
03637 resend_response(sub, answer);
03638 return 1;
03639 }
03640 return 0;
03641 }
03642
03643 static int mgcpsock_read(int *id, int fd, short events, void *ignore)
03644 {
03645 struct mgcp_request req;
03646 struct sockaddr_in sin;
03647 struct mgcp_subchannel *sub;
03648 int res;
03649 socklen_t len;
03650 int result;
03651 int ident;
03652 len = sizeof(sin);
03653 memset(&req, 0, sizeof(req));
03654 res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
03655 if (res < 0) {
03656 if (errno != ECONNREFUSED)
03657 ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno));
03658 return 1;
03659 }
03660 req.data[res] = '\0';
03661 req.len = res;
03662 ast_debug(1, "MGCP read: \n%s\nfrom %s:%d\n", req.data, ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
03663 parse(&req);
03664 if (req.headers < 1) {
03665
03666 return 1;
03667 }
03668 if (ast_strlen_zero(req.identifier)) {
03669 ast_log(LOG_NOTICE, "Message from %s missing identifier\n", ast_inet_ntoa(sin.sin_addr));
03670 return 1;
03671 }
03672
03673 if (sscanf(req.verb, "%30d", &result) && sscanf(req.identifier, "%30d", &ident)) {
03674 if (result < 200) {
03675 ast_debug(1, "Ignoring provisional response on transaction %d\n", ident);
03676 return 1;
03677 }
03678
03679 sub = find_subchannel_and_lock(NULL, ident, &sin);
03680 if (sub) {
03681 struct mgcp_gateway *gw = sub->parent->parent;
03682 struct mgcp_message *cur, *prev;
03683
03684 ast_mutex_unlock(&sub->lock);
03685 ast_mutex_lock(&gw->msgs_lock);
03686 for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
03687 if (cur->seqno == ident) {
03688 ast_debug(1, "Got response back on transaction %d\n", ident);
03689 if (prev)
03690 prev->next = cur->next;
03691 else
03692 gw->msgs = cur->next;
03693 break;
03694 }
03695 }
03696
03697
03698 if (!gw->msgs) {
03699 AST_SCHED_DEL(sched, gw->retransid);
03700 }
03701
03702 ast_mutex_unlock(&gw->msgs_lock);
03703 if (cur) {
03704 handle_response(cur->owner_ep, cur->owner_sub, result, ident, &req);
03705 ast_free(cur);
03706 return 1;
03707 }
03708
03709 ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n",
03710 gw->name, ident);
03711 }
03712 } else {
03713 if (ast_strlen_zero(req.endpoint) ||
03714 ast_strlen_zero(req.version) ||
03715 ast_strlen_zero(req.verb)) {
03716 ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n");
03717 return 1;
03718 }
03719
03720 sub = find_subchannel_and_lock(req.endpoint, 0, &sin);
03721 if (sub) {
03722
03723 if (!find_and_retrans(sub, &req))
03724
03725 handle_request(sub, &req, &sin);
03726 ast_mutex_unlock(&sub->lock);
03727 }
03728 }
03729 return 1;
03730 }
03731
03732 static int *mgcpsock_read_id = NULL;
03733
03734 static int mgcp_prune_realtime_gateway(struct mgcp_gateway *g)
03735 {
03736 struct mgcp_endpoint *enext, *e;
03737 struct mgcp_subchannel *s, *sub;
03738 int i, prune = 1;
03739
03740 if (g->ha || !g->realtime || ast_mutex_trylock(&g->msgs_lock) || g->msgs) {
03741 ast_mutex_unlock(&g->msgs_lock);
03742 return 0;
03743 }
03744
03745 for (e = g->endpoints; e; e = e->next) {
03746 ast_mutex_lock(&e->lock);
03747 if (e->dsp || ast_mutex_trylock(&e->rqnt_queue_lock) || ast_mutex_trylock(&e->cmd_queue_lock)) {
03748 prune = 0;
03749 } else if (e->rqnt_queue || e->cmd_queue) {
03750 prune = 0;
03751 }
03752 s = e->sub;
03753 for (i = 0; (i < MAX_SUBS) && s; i++) {
03754 ast_mutex_lock(&s->lock);
03755 if (!ast_strlen_zero(s->cxident) || s->rtp || ast_mutex_trylock(&s->cx_queue_lock) || s->gate) {
03756 prune = 0;
03757 } else if (s->cx_queue) {
03758 prune = 0;
03759 }
03760 s = s->next;
03761 }
03762 }
03763
03764 for (e = g->endpoints, sub = e->sub, enext = e->next; e; e = enext, enext = e->next) {
03765 for (i = 0; (i < MAX_SUBS) && sub; i++) {
03766 s = sub;
03767 sub = sub->next;
03768 ast_mutex_unlock(&s->lock);
03769 ast_mutex_unlock(&s->cx_queue_lock);
03770 if (prune) {
03771 ast_mutex_destroy(&s->lock);
03772 ast_mutex_destroy(&s->cx_queue_lock);
03773 free(s);
03774 }
03775 }
03776 ast_mutex_unlock(&e->lock);
03777 ast_mutex_unlock(&e->rqnt_queue_lock);
03778 ast_mutex_unlock(&e->cmd_queue_lock);
03779 if (prune) {
03780 ast_mutex_destroy(&e->lock);
03781 ast_mutex_destroy(&e->rqnt_queue_lock);
03782 ast_mutex_destroy(&e->cmd_queue_lock);
03783 free(e);
03784 }
03785 }
03786 if (prune) {
03787 ast_debug(1, "***** MGCP REALTIME PRUNE GW: %s\n", g->name);
03788 }
03789 return prune;
03790 }
03791
03792 static void *do_monitor(void *data)
03793 {
03794 int res;
03795 int reloading;
03796 struct mgcp_gateway *g, *gprev;
03797
03798
03799
03800 time_t lastrun = 0;
03801
03802
03803 if (mgcpsock > -1) {
03804 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
03805 }
03806
03807
03808
03809 for (;;) {
03810
03811 ast_mutex_lock(&mgcp_reload_lock);
03812 reloading = mgcp_reloading;
03813 mgcp_reloading = 0;
03814 ast_mutex_unlock(&mgcp_reload_lock);
03815 if (reloading) {
03816 ast_verb(1, "Reloading MGCP\n");
03817 reload_config(1);
03818
03819 if (mgcpsock > -1 && !mgcpsock_read_id) {
03820 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
03821 }
03822 }
03823
03824
03825
03826
03827 ast_mutex_lock(&monlock);
03828
03829 ast_mutex_lock(&netlock);
03830
03831 #if 0
03832
03833
03834
03835 lastpass = thispass;
03836 thispass = time(NULL);
03837 g = gateways;
03838 while(g) {
03839 if (thispass != lastpass) {
03840 e = g->endpoints;
03841 while(e) {
03842 if (e->type == TYPE_LINE) {
03843 res = has_voicemail(e);
03844 if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){
03845 if (res) {
03846 transmit_notify_request(e, "L/vmwi(+)");
03847 } else {
03848 transmit_notify_request(e, "L/vmwi(-)");
03849 }
03850 e->msgstate = res;
03851 e->onhooktime = thispass;
03852 }
03853 }
03854 e = e->next;
03855 }
03856 }
03857 g = g->next;
03858 }
03859 #endif
03860
03861 if(time(NULL) > (lastrun + 60)) {
03862 ast_mutex_lock(&gatelock);
03863 g = gateways;
03864 gprev = NULL;
03865 while(g) {
03866 if(g->realtime) {
03867 if(mgcp_prune_realtime_gateway(g)) {
03868 if(gprev) {
03869 gprev->next = g->next;
03870 } else {
03871 gateways = g->next;
03872 }
03873 ast_mutex_unlock(&g->msgs_lock);
03874 ast_mutex_destroy(&g->msgs_lock);
03875 free(g);
03876 } else {
03877 ast_mutex_unlock(&g->msgs_lock);
03878 gprev = g;
03879 }
03880 } else {
03881 gprev = g;
03882 }
03883 g = g->next;
03884 }
03885 ast_mutex_unlock(&gatelock);
03886 lastrun = time(NULL);
03887 }
03888
03889 ast_mutex_unlock(&netlock);
03890
03891 ast_mutex_unlock(&monlock);
03892 pthread_testcancel();
03893
03894 res = ast_sched_wait(sched);
03895
03896 if ((res < 0) || (res > 1000)) {
03897 res = 1000;
03898 }
03899 res = ast_io_wait(io, res);
03900 ast_mutex_lock(&monlock);
03901 if (res >= 0) {
03902 ast_sched_runq(sched);
03903 }
03904 ast_mutex_unlock(&monlock);
03905 }
03906
03907 return NULL;
03908 }
03909
03910 static int restart_monitor(void)
03911 {
03912
03913 if (monitor_thread == AST_PTHREADT_STOP)
03914 return 0;
03915 if (ast_mutex_lock(&monlock)) {
03916 ast_log(LOG_WARNING, "Unable to lock monitor\n");
03917 return -1;
03918 }
03919 if (monitor_thread == pthread_self()) {
03920 ast_mutex_unlock(&monlock);
03921 ast_log(LOG_WARNING, "Cannot kill myself\n");
03922 return -1;
03923 }
03924 if (monitor_thread != AST_PTHREADT_NULL) {
03925
03926 pthread_kill(monitor_thread, SIGURG);
03927 } else {
03928
03929 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
03930 ast_mutex_unlock(&monlock);
03931 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
03932 return -1;
03933 }
03934 }
03935 ast_mutex_unlock(&monlock);
03936 return 0;
03937 }
03938
03939 static struct ast_channel *mgcp_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *dest, int *cause)
03940 {
03941 struct mgcp_subchannel *sub;
03942 struct ast_channel *tmpc = NULL;
03943 char tmp[256];
03944
03945 if (!(ast_format_cap_has_joint(cap, global_capability))) {
03946 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap));
03947
03948 }
03949 ast_copy_string(tmp, dest, sizeof(tmp));
03950 if (ast_strlen_zero(tmp)) {
03951 ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n");
03952 return NULL;
03953 }
03954 if (!(sub = find_subchannel_and_lock(tmp, 0, NULL))) {
03955 ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp);
03956 *cause = AST_CAUSE_UNREGISTERED;
03957 return NULL;
03958 }
03959
03960 ast_verb(3, "MGCP mgcp_request(%s)\n", tmp);
03961 ast_verb(3, "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n",
03962 sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0);
03963
03964 if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) ||
03965 ((!sub->parent->callwaiting) && (sub->owner)) ||
03966 (sub->parent->dnd && (ast_strlen_zero(sub->parent->call_forward)))) {
03967 if (sub->parent->hookstate == MGCP_ONHOOK) {
03968 if (has_voicemail(sub->parent)) {
03969 transmit_notify_request(sub,"L/vmwi(+)");
03970 } else {
03971 transmit_notify_request(sub,"L/vmwi(-)");
03972 }
03973 }
03974 *cause = AST_CAUSE_BUSY;
03975 ast_mutex_unlock(&sub->lock);
03976 return NULL;
03977 }
03978 tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL);
03979 ast_mutex_unlock(&sub->lock);
03980 if (!tmpc)
03981 ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
03982 restart_monitor();
03983 return tmpc;
03984 }
03985
03986
03987
03988 static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
03989 {
03990 struct mgcp_gateway *gw;
03991 struct mgcp_endpoint *e;
03992 struct mgcp_subchannel *sub;
03993 struct ast_variable *chanvars = NULL;
03994
03995
03996 int i=0, y=0;
03997 int gw_reload = 0;
03998 int ep_reload = 0;
03999 directmedia = DIRECTMEDIA;
04000
04001
04002 for (gw = gateways; gw; gw = gw->next) {
04003 if (!strcasecmp(cat, gw->name)) {
04004
04005 gw->delme = 0;
04006 gw_reload = 1;
04007 break;
04008 }
04009 }
04010
04011 if (!gw && !(gw = ast_calloc(1, sizeof(*gw)))) {
04012 return NULL;
04013 }
04014
04015 if (!gw_reload) {
04016 gw->expire = -1;
04017 gw->realtime = 0;
04018 gw->retransid = -1;
04019 ast_mutex_init(&gw->msgs_lock);
04020 ast_copy_string(gw->name, cat, sizeof(gw->name));
04021
04022 if ((strchr(gw->name, '.')) && inet_addr(gw->name) != INADDR_NONE)
04023 gw->isnamedottedip = 1;
04024 }
04025 for (; v; v = v->next) {
04026 if (!strcasecmp(v->name, "host")) {
04027 if (!strcasecmp(v->value, "dynamic")) {
04028
04029 gw->dynamic = 1;
04030 memset(&gw->addr.sin_addr, 0, 4);
04031 if (gw->addr.sin_port) {
04032
04033 gw->defaddr.sin_port = gw->addr.sin_port;
04034 gw->addr.sin_port = 0;
04035 }
04036 } else {
04037
04038 AST_SCHED_DEL(sched, gw->expire);
04039 gw->dynamic = 0;
04040 {
04041 struct ast_sockaddr tmp;
04042
04043 ast_sockaddr_from_sin(&tmp, &gw->addr);
04044 if (ast_get_ip(&tmp, v->value)) {
04045 if (!gw_reload) {
04046 ast_mutex_destroy(&gw->msgs_lock);
04047 ast_free(gw);
04048 }
04049 return NULL;
04050 }
04051 ast_sockaddr_to_sin(&tmp, &gw->addr);
04052 }
04053 }
04054 } else if (!strcasecmp(v->name, "defaultip")) {
04055 struct ast_sockaddr tmp;
04056
04057 ast_sockaddr_from_sin(&tmp, &gw->defaddr);
04058 if (ast_get_ip(&tmp, v->value)) {
04059 if (!gw_reload) {
04060 ast_mutex_destroy(&gw->msgs_lock);
04061 ast_free(gw);
04062 }
04063 return NULL;
04064 }
04065 ast_sockaddr_to_sin(&tmp, &gw->defaddr);
04066 } else if (!strcasecmp(v->name, "permit") ||
04067 !strcasecmp(v->name, "deny")) {
04068 gw->ha = ast_append_ha(v->name, v->value, gw->ha, NULL);
04069 } else if (!strcasecmp(v->name, "port")) {
04070 gw->addr.sin_port = htons(atoi(v->value));
04071 } else if (!strcasecmp(v->name, "context")) {
04072 ast_copy_string(context, v->value, sizeof(context));
04073 } else if (!strcasecmp(v->name, "dtmfmode")) {
04074 if (!strcasecmp(v->value, "inband"))
04075 dtmfmode = MGCP_DTMF_INBAND;
04076 else if (!strcasecmp(v->value, "rfc2833"))
04077 dtmfmode = MGCP_DTMF_RFC2833;
04078 else if (!strcasecmp(v->value, "hybrid"))
04079 dtmfmode = MGCP_DTMF_HYBRID;
04080 else if (!strcasecmp(v->value, "none"))
04081 dtmfmode = 0;
04082 else
04083 ast_log(LOG_WARNING, "'%s' is not a valid DTMF mode at line %d\n", v->value, v->lineno);
04084 } else if (!strcasecmp(v->name, "nat")) {
04085 nat = ast_true(v->value);
04086 } else if (!strcasecmp(v->name, "ncs")) {
04087 ncs = ast_true(v->value);
04088 } else if (!strcasecmp(v->name, "hangupongateremove")) {
04089 hangupongateremove = ast_true(v->value);
04090 } else if (!strcasecmp(v->name, "pktcgatealloc")) {
04091 pktcgatealloc = ast_true(v->value);
04092 } else if (!strcasecmp(v->name, "callerid")) {
04093 if (!strcasecmp(v->value, "asreceived")) {
04094 cid_num[0] = '\0';
04095 cid_name[0] = '\0';
04096 } else {
04097 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
04098 }
04099 } else if (!strcasecmp(v->name, "language")) {
04100 ast_copy_string(language, v->value, sizeof(language));
04101 } else if (!strcasecmp(v->name, "accountcode")) {
04102 ast_copy_string(accountcode, v->value, sizeof(accountcode));
04103 } else if (!strcasecmp(v->name, "amaflags")) {
04104 y = ast_cdr_amaflags2int(v->value);
04105 if (y < 0) {
04106 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
04107 } else {
04108 amaflags = y;
04109 }
04110 } else if (!strcasecmp(v->name, "setvar")) {
04111 chanvars = add_var(v->value, chanvars);
04112 } else if (!strcasecmp(v->name, "clearvars")) {
04113 if (chanvars) {
04114 ast_variables_destroy(chanvars);
04115 chanvars = NULL;
04116 }
04117 } else if (!strcasecmp(v->name, "musiconhold")) {
04118 ast_copy_string(musicclass, v->value, sizeof(musicclass));
04119 } else if (!strcasecmp(v->name, "parkinglot")) {
04120 ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
04121 } else if (!strcasecmp(v->name, "callgroup")) {
04122 cur_callergroup = ast_get_group(v->value);
04123 } else if (!strcasecmp(v->name, "pickupgroup")) {
04124 cur_pickupgroup = ast_get_group(v->value);
04125 } else if (!strcasecmp(v->name, "immediate")) {
04126 immediate = ast_true(v->value);
04127 } else if (!strcasecmp(v->name, "cancallforward")) {
04128 cancallforward = ast_true(v->value);
04129 } else if (!strcasecmp(v->name, "singlepath")) {
04130 singlepath = ast_true(v->value);
04131 } else if (!strcasecmp(v->name, "directmedia") || !strcasecmp(v->name, "canreinvite")) {
04132 directmedia = ast_true(v->value);
04133 } else if (!strcasecmp(v->name, "mailbox")) {
04134 ast_copy_string(mailbox, v->value, sizeof(mailbox));
04135 } else if (!strcasecmp(v->name, "hasvoicemail")) {
04136 if (ast_true(v->value) && ast_strlen_zero(mailbox)) {
04137 ast_copy_string(mailbox, gw->name, sizeof(mailbox));
04138 }
04139 } else if (!strcasecmp(v->name, "adsi")) {
04140 adsi = ast_true(v->value);
04141 } else if (!strcasecmp(v->name, "callreturn")) {
04142 callreturn = ast_true(v->value);
04143 } else if (!strcasecmp(v->name, "callwaiting")) {
04144 callwaiting = ast_true(v->value);
04145 } else if (!strcasecmp(v->name, "slowsequence")) {
04146 slowsequence = ast_true(v->value);
04147 } else if (!strcasecmp(v->name, "transfer")) {
04148 transfer = ast_true(v->value);
04149 } else if (!strcasecmp(v->name, "threewaycalling")) {
04150 threewaycalling = ast_true(v->value);
04151 } else if (!strcasecmp(v->name, "wcardep")) {
04152
04153 for (e = gw->endpoints; e; e = e->next) {
04154 if (!strcasecmp(v->value, e->name)) {
04155
04156 e->delme = 0;
04157 ep_reload = 1;
04158 break;
04159 }
04160 }
04161
04162 if (!e) {
04163
04164 e = ast_calloc(1, sizeof(*e));
04165 ep_reload = 0;
04166 }
04167
04168 if (e) {
04169 if (!ep_reload) {
04170 memset(e, 0, sizeof(struct mgcp_endpoint));
04171 ast_mutex_init(&e->lock);
04172 ast_mutex_init(&e->rqnt_queue_lock);
04173 ast_mutex_init(&e->cmd_queue_lock);
04174 e->cap = ast_format_cap_alloc_nolock();
04175 ast_copy_string(e->name, v->value, sizeof(e->name));
04176 e->needaudit = 1;
04177 }
04178 ast_copy_string(gw->wcardep, v->value, sizeof(gw->wcardep));
04179
04180 ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode));
04181 ast_copy_string(e->context, context, sizeof(e->context));
04182 ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num));
04183 ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name));
04184 ast_copy_string(e->language, language, sizeof(e->language));
04185 ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass));
04186 ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
04187 ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot));
04188 if (!ast_strlen_zero(e->mailbox)) {
04189 char *mbox, *cntx;
04190 cntx = mbox = ast_strdupa(e->mailbox);
04191 strsep(&cntx, "@");
04192 if (ast_strlen_zero(cntx)) {
04193 cntx = "default";
04194 }
04195 e->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "MGCP MWI subscription", NULL,
04196 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox,
04197 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cntx,
04198 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
04199 AST_EVENT_IE_END);
04200 }
04201 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random());
04202 e->msgstate = -1;
04203 e->amaflags = amaflags;
04204 ast_format_cap_copy(e->cap, global_capability);
04205 e->parent = gw;
04206 e->ncs = ncs;
04207 e->dtmfmode = dtmfmode;
04208 if (!ep_reload && e->sub && e->sub->rtp) {
04209 e->dtmfmode |= MGCP_DTMF_INBAND;
04210 }
04211 e->adsi = adsi;
04212 e->type = TYPE_LINE;
04213 e->immediate = immediate;
04214 e->callgroup=cur_callergroup;
04215 e->pickupgroup=cur_pickupgroup;
04216 e->callreturn = callreturn;
04217 e->cancallforward = cancallforward;
04218 e->singlepath = singlepath;
04219 e->directmedia = directmedia;
04220 e->callwaiting = callwaiting;
04221 e->hascallwaiting = callwaiting;
04222 e->slowsequence = slowsequence;
04223 e->transfer = transfer;
04224 e->threewaycalling = threewaycalling;
04225 e->onhooktime = time(NULL);
04226
04227 e->hookstate = MGCP_ONHOOK;
04228 e->chanvars = copy_vars(chanvars);
04229 if (!ep_reload) {
04230
04231 for (i = 0; i < MAX_SUBS; i++) {
04232 sub = ast_calloc(1, sizeof(*sub));
04233 if (sub) {
04234 ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
04235 ast_mutex_init(&sub->lock);
04236 ast_mutex_init(&sub->cx_queue_lock);
04237 sub->parent = e;
04238 sub->id = i;
04239 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random());
04240
04241 sub->cxmode = MGCP_CX_INACTIVE;
04242 sub->nat = nat;
04243 sub->gate = NULL;
04244 sub->sdpsent = 0;
04245 sub->next = e->sub;
04246 e->sub = sub;
04247 } else {
04248
04249 ast_log(LOG_WARNING, "Out of memory allocating subchannel\n");
04250 return NULL;
04251 }
04252 }
04253
04254
04255 for (sub = e->sub; sub && sub->next; sub = sub->next);
04256
04257 sub->next = e->sub;
04258
04259 e->next = gw->endpoints;
04260 gw->endpoints = e;
04261 }
04262 }
04263 } else if (!strcasecmp(v->name, "trunk") ||
04264 !strcasecmp(v->name, "line")) {
04265
04266
04267 for (e = gw->endpoints; e; e = e->next) {
04268 if (!strcasecmp(v->value, e->name)) {
04269
04270 e->delme = 0;
04271 ep_reload = 1;
04272 break;
04273 }
04274 }
04275
04276 if (!e) {
04277 e = ast_calloc(1, sizeof(*e));
04278 ep_reload = 0;
04279 }
04280
04281 if (e) {
04282 if (!ep_reload) {
04283 ast_mutex_init(&e->lock);
04284 ast_mutex_init(&e->rqnt_queue_lock);
04285 ast_mutex_init(&e->cmd_queue_lock);
04286 e->cap = ast_format_cap_alloc_nolock();
04287 ast_copy_string(e->name, v->value, sizeof(e->name));
04288 e->needaudit = 1;
04289 }
04290
04291 ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode));
04292 ast_copy_string(e->context, context, sizeof(e->context));
04293 ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num));
04294 ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name));
04295 ast_copy_string(e->language, language, sizeof(e->language));
04296 ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass));
04297 ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
04298 ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot));
04299 if (!ast_strlen_zero(mailbox)) {
04300 ast_verb(3, "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name);
04301 }
04302 if (!ep_reload) {
04303
04304 e->msgstate = -1;
04305 e->parent = gw;
04306 }
04307 e->amaflags = amaflags;
04308 ast_format_cap_copy(e->cap, global_capability);
04309 e->dtmfmode = dtmfmode;
04310 e->ncs = ncs;
04311 e->pktcgatealloc = pktcgatealloc;
04312 e->hangupongateremove = hangupongateremove;
04313 e->adsi = adsi;
04314 e->type = (!strcasecmp(v->name, "trunk")) ? TYPE_TRUNK : TYPE_LINE;
04315 e->immediate = immediate;
04316 e->callgroup=cur_callergroup;
04317 e->pickupgroup=cur_pickupgroup;
04318 e->callreturn = callreturn;
04319 e->cancallforward = cancallforward;
04320 e->directmedia = directmedia;
04321 e->singlepath = singlepath;
04322 e->callwaiting = callwaiting;
04323 e->hascallwaiting = callwaiting;
04324 e->slowsequence = slowsequence;
04325 e->transfer = transfer;
04326 e->threewaycalling = threewaycalling;
04327
04328
04329
04330
04331 if (e->chanvars) {
04332 ast_variables_destroy(e->chanvars);
04333 e->chanvars = NULL;
04334 }
04335 e->chanvars = copy_vars(chanvars);
04336
04337 if (!ep_reload) {
04338 e->onhooktime = time(NULL);
04339
04340 e->hookstate = MGCP_ONHOOK;
04341 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random());
04342 }
04343
04344 for (i = 0, sub = NULL; i < MAX_SUBS; i++) {
04345 if (!ep_reload) {
04346 sub = ast_calloc(1, sizeof(*sub));
04347 } else {
04348 if (!sub) {
04349 sub = e->sub;
04350 } else {
04351 sub = sub->next;
04352 }
04353 }
04354
04355 if (sub) {
04356 if (!ep_reload) {
04357 ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
04358 ast_mutex_init(&sub->lock);
04359 ast_mutex_init(&sub->cx_queue_lock);
04360 ast_copy_string(sub->magic, MGCP_SUBCHANNEL_MAGIC, sizeof(sub->magic));
04361 sub->parent = e;
04362 sub->id = i;
04363 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random());
04364 sub->cxmode = MGCP_CX_INACTIVE;
04365 sub->next = e->sub;
04366 e->sub = sub;
04367 }
04368 sub->nat = nat;
04369 } else {
04370
04371 ast_log(LOG_WARNING, "Out of memory allocating subchannel\n");
04372 return NULL;
04373 }
04374 }
04375 if (!ep_reload) {
04376
04377
04378 for (sub = e->sub; sub && sub->next; sub = sub->next);
04379
04380 sub->next = e->sub;
04381
04382 e->next = gw->endpoints;
04383 gw->endpoints = e;
04384 }
04385 }
04386 } else if (!strcasecmp(v->name, "name") || !strcasecmp(v->name, "lines")) {
04387
04388 } else {
04389 ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
04390 }
04391 }
04392 if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) {
04393 ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name);
04394 if (!gw_reload) {
04395 ast_mutex_destroy(&gw->msgs_lock);
04396 ast_free(gw);
04397 }
04398
04399
04400 gw_reload = 1;
04401 } else {
04402 gw->defaddr.sin_family = AF_INET;
04403 gw->addr.sin_family = AF_INET;
04404 if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port)) {
04405 gw->defaddr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
04406 }
04407 if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port)) {
04408 gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
04409 }
04410 {
04411 struct ast_sockaddr tmp1, tmp2;
04412 struct sockaddr_in tmp3 = {0,};
04413
04414 tmp3.sin_addr = gw->ourip;
04415 ast_sockaddr_from_sin(&tmp1, &gw->addr);
04416 ast_sockaddr_from_sin(&tmp2, &tmp3);
04417 if (gw->addr.sin_addr.s_addr && ast_ouraddrfor(&tmp1, &tmp2)) {
04418 memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip));
04419 } else {
04420 ast_sockaddr_to_sin(&tmp2, &tmp3);
04421 gw->ourip = tmp3.sin_addr;
04422 }
04423 }
04424 }
04425
04426 if (chanvars) {
04427 ast_variables_destroy(chanvars);
04428 chanvars = NULL;
04429 }
04430 return (gw_reload ? NULL : gw);
04431 }
04432
04433 static enum ast_rtp_glue_result mgcp_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
04434 {
04435 struct mgcp_subchannel *sub = NULL;
04436
04437 if (!(sub = ast_channel_tech_pvt(chan)) || !(sub->rtp))
04438 return AST_RTP_GLUE_RESULT_FORBID;
04439
04440 *instance = sub->rtp ? ao2_ref(sub->rtp, +1), sub->rtp : NULL;
04441
04442 if (sub->parent->directmedia)
04443 return AST_RTP_GLUE_RESULT_REMOTE;
04444 else
04445 return AST_RTP_GLUE_RESULT_LOCAL;
04446 }
04447
04448 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, const struct ast_format_cap *cap, int nat_active)
04449 {
04450
04451 struct mgcp_subchannel *sub;
04452 sub = ast_channel_tech_pvt(chan);
04453 if (sub && !sub->alreadygone) {
04454 transmit_modify_with_sdp(sub, rtp, cap);
04455 return 0;
04456 }
04457 return -1;
04458 }
04459
04460 static void mgcp_get_codec(struct ast_channel *chan, struct ast_format_cap *result)
04461 {
04462 struct mgcp_subchannel *sub = ast_channel_tech_pvt(chan);
04463 struct mgcp_endpoint *p = sub->parent;
04464 ast_format_cap_copy(result, p->cap);
04465 }
04466
04467 static struct ast_rtp_glue mgcp_rtp_glue = {
04468 .type = "MGCP",
04469 .get_rtp_info = mgcp_get_rtp_peer,
04470 .update_peer = mgcp_set_rtp_peer,
04471 .get_codec = mgcp_get_codec,
04472 };
04473
04474
04475 static int acf_channel_read(struct ast_channel *chan, const char *funcname, char *args, char *buf, size_t buflen)
04476 {
04477 struct mgcp_subchannel *sub = ast_channel_tech_pvt(chan);
04478 int res = 0;
04479
04480
04481 if (!chan || ast_channel_tech(chan) != &mgcp_tech) {
04482 ast_log(LOG_ERROR, "This function requires a valid MGCP channel\n");
04483 return -1;
04484 }
04485
04486 if (!strcasecmp(args, "ncs")) {
04487 snprintf(buf, buflen, "%s", sub->parent->ncs ? "yes":"no");
04488 } else {
04489 res = -1;
04490 }
04491 return res;
04492 }
04493
04494
04495 static void destroy_endpoint(struct mgcp_endpoint *e)
04496 {
04497 struct mgcp_subchannel *sub = e->sub->next, *s;
04498 int i;
04499
04500 for (i = 0; i < MAX_SUBS; i++) {
04501 ast_mutex_lock(&sub->lock);
04502 if (!ast_strlen_zero(sub->cxident)) {
04503 transmit_connection_del(sub);
04504 }
04505 if (sub->rtp) {
04506 ast_rtp_instance_destroy(sub->rtp);
04507 sub->rtp = NULL;
04508 }
04509 memset(sub->magic, 0, sizeof(sub->magic));
04510 mgcp_queue_hangup(sub);
04511 dump_cmd_queues(NULL, sub);
04512 if(sub->gate) {
04513 sub->gate->tech_pvt = NULL;
04514 sub->gate->got_dq_gi = NULL;
04515 sub->gate->gate_remove = NULL;
04516 sub->gate->gate_open = NULL;
04517 }
04518 ast_mutex_unlock(&sub->lock);
04519 sub = sub->next;
04520 }
04521
04522 if (e->dsp) {
04523 ast_dsp_free(e->dsp);
04524 }
04525
04526 dump_queue(e->parent, e);
04527 dump_cmd_queues(e, NULL);
04528
04529 sub = e->sub;
04530 for (i = 0; (i < MAX_SUBS) && sub; i++) {
04531 s = sub;
04532 sub = sub->next;
04533 ast_mutex_destroy(&s->lock);
04534 ast_mutex_destroy(&s->cx_queue_lock);
04535 ast_free(s);
04536 }
04537
04538 if (e->mwi_event_sub)
04539 ast_event_unsubscribe(e->mwi_event_sub);
04540
04541 if (e->chanvars) {
04542 ast_variables_destroy(e->chanvars);
04543 e->chanvars = NULL;
04544 }
04545
04546 ast_mutex_destroy(&e->lock);
04547 ast_mutex_destroy(&e->rqnt_queue_lock);
04548 ast_mutex_destroy(&e->cmd_queue_lock);
04549 e->cap = ast_format_cap_destroy(e->cap);
04550 ast_free(e);
04551 }
04552
04553 static void destroy_gateway(struct mgcp_gateway *g)
04554 {
04555 if (g->ha)
04556 ast_free_ha(g->ha);
04557
04558 dump_queue(g, NULL);
04559
04560 ast_free(g);
04561 }
04562
04563 static void prune_gateways(void)
04564 {
04565 struct mgcp_gateway *g, *z, *r;
04566 struct mgcp_endpoint *e, *p, *t;
04567
04568 ast_mutex_lock(&gatelock);
04569
04570
04571 for (z = NULL, g = gateways; g;) {
04572
04573 for (p = NULL, e = g->endpoints; e; ) {
04574 if (!g->realtime && (e->delme || g->delme)) {
04575 t = e;
04576 e = e->next;
04577 if (!p)
04578 g->endpoints = e;
04579 else
04580 p->next = e;
04581 destroy_endpoint(t);
04582 } else {
04583 p = e;
04584 e = e->next;
04585 }
04586 }
04587
04588 if (g->delme) {
04589 r = g;
04590 g = g->next;
04591 if (!z)
04592 gateways = g;
04593 else
04594 z->next = g;
04595
04596 destroy_gateway(r);
04597 } else {
04598 z = g;
04599 g = g->next;
04600 }
04601 }
04602
04603 ast_mutex_unlock(&gatelock);
04604 }
04605
04606 static struct ast_variable *add_var(const char *buf, struct ast_variable *list)
04607 {
04608 struct ast_variable *tmpvar = NULL;
04609 char *varname = ast_strdupa(buf), *varval = NULL;
04610
04611 if ((varval = strchr(varname, '='))) {
04612 *varval++ = '\0';
04613 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
04614 tmpvar->next = list;
04615 list = tmpvar;
04616 }
04617 }
04618 return list;
04619 }
04620
04621
04622
04623
04624 static struct ast_variable *copy_vars(struct ast_variable *src)
04625 {
04626 struct ast_variable *res = NULL, *tmp, *v = NULL;
04627
04628 for (v = src ; v ; v = v->next) {
04629 if ((tmp = ast_variable_new(v->name, v->value, v->file))) {
04630 tmp->next = res;
04631 res = tmp;
04632 }
04633 }
04634 return res;
04635 }
04636
04637
04638 static int reload_config(int reload)
04639 {
04640 struct ast_config *cfg;
04641 struct ast_variable *v;
04642 struct mgcp_gateway *g;
04643 struct mgcp_endpoint *e;
04644 char *cat;
04645 struct ast_hostent ahp;
04646 struct hostent *hp;
04647 struct ast_format format;
04648 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
04649
04650 if (gethostname(ourhost, sizeof(ourhost)-1)) {
04651 ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n");
04652 return 0;
04653 }
04654 cfg = ast_config_load(config, config_flags);
04655
04656
04657 if (!cfg) {
04658 ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config);
04659 return 0;
04660 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
04661 return 0;
04662 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
04663 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config);
04664 return 0;
04665 }
04666
04667 memset(&bindaddr, 0, sizeof(bindaddr));
04668 dtmfmode = 0;
04669
04670
04671 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
04672
04673 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
04674
04675 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
04676 continue;
04677 }
04678
04679
04680 if (!strcasecmp(v->name, "bindaddr")) {
04681 if (!(hp = ast_gethostbyname(v->value, &ahp))) {
04682 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
04683 } else {
04684 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
04685 }
04686 } else if (!strcasecmp(v->name, "allow")) {
04687 ast_getformatbyname(v->value, &format);
04688 if (!format.id) {
04689 ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
04690 } else {
04691 ast_format_cap_add(global_capability, &format);
04692 }
04693 } else if (!strcasecmp(v->name, "disallow")) {
04694 ast_getformatbyname(v->value, &format);
04695 if (!format.id) {
04696 ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
04697 } else {
04698 ast_format_cap_remove(global_capability, &format);
04699 }
04700 } else if (!strcasecmp(v->name, "tos")) {
04701 if (ast_str2tos(v->value, &qos.tos)) {
04702 ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
04703 }
04704 } else if (!strcasecmp(v->name, "tos_audio")) {
04705 if (ast_str2tos(v->value, &qos.tos_audio))
04706 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
04707 } else if (!strcasecmp(v->name, "cos")) {
04708 if (ast_str2cos(v->value, &qos.cos))
04709 ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno);
04710 } else if (!strcasecmp(v->name, "cos_audio")) {
04711 if (ast_str2cos(v->value, &qos.cos_audio))
04712 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
04713 } else if (!strcasecmp(v->name, "port")) {
04714 if (sscanf(v->value, "%5d", &ourport) == 1) {
04715 bindaddr.sin_port = htons(ourport);
04716 } else {
04717 ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config);
04718 }
04719 } else if (!strcasecmp(v->name, "firstdigittimeout")) {
04720 firstdigittimeout = atoi(v->value);
04721 } else if (!strcasecmp(v->name, "gendigittimeout")) {
04722 gendigittimeout = atoi(v->value);
04723 } else if (!strcasecmp(v->name, "matchdigittimeout")) {
04724 matchdigittimeout = atoi(v->value);
04725 }
04726 }
04727
04728
04729 ast_mutex_lock(&gatelock);
04730 for (g = gateways; g; g = g->next) {
04731 g->delme = 1;
04732 for (e = g->endpoints; e; e = e->next) {
04733 e->delme = 1;
04734 }
04735 }
04736 ast_mutex_unlock(&gatelock);
04737
04738 for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) {
04739 if (strcasecmp(cat, "general")) {
04740 ast_mutex_lock(&gatelock);
04741 if ((g = build_gateway(cat, ast_variable_browse(cfg, cat)))) {
04742 ast_verb(3, "Added gateway '%s'\n", g->name);
04743 g->next = gateways;
04744 gateways = g;
04745 }
04746 ast_mutex_unlock(&gatelock);
04747
04748
04749 if (monitor_thread == pthread_self()) {
04750 if (sched) ast_sched_runq(sched);
04751 if (io) ast_io_wait(io, 10);
04752 }
04753 }
04754 }
04755
04756
04757 prune_gateways();
04758
04759 if (ntohl(bindaddr.sin_addr.s_addr)) {
04760 memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip));
04761 } else {
04762 hp = ast_gethostbyname(ourhost, &ahp);
04763 if (!hp) {
04764 ast_log(LOG_WARNING, "Unable to get our IP address, MGCP disabled\n");
04765 ast_config_destroy(cfg);
04766 return 0;
04767 }
04768 memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
04769 }
04770 if (!ntohs(bindaddr.sin_port))
04771 bindaddr.sin_port = htons(DEFAULT_MGCP_CA_PORT);
04772 bindaddr.sin_family = AF_INET;
04773 ast_mutex_lock(&netlock);
04774 if (mgcpsock > -1)
04775 close(mgcpsock);
04776
04777 if (mgcpsock_read_id != NULL)
04778 ast_io_remove(io, mgcpsock_read_id);
04779 mgcpsock_read_id = NULL;
04780
04781 mgcpsock = socket(AF_INET, SOCK_DGRAM, 0);
04782 if (mgcpsock < 0) {
04783 ast_log(LOG_WARNING, "Unable to create MGCP socket: %s\n", strerror(errno));
04784 } else {
04785 if (bind(mgcpsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
04786 ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
04787 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
04788 strerror(errno));
04789 close(mgcpsock);
04790 mgcpsock = -1;
04791 } else {
04792 ast_verb(2, "MGCP Listening on %s:%d\n",
04793 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
04794 ast_set_qos(mgcpsock, qos.tos, qos.cos, "MGCP");
04795 }
04796 }
04797 ast_mutex_unlock(&netlock);
04798 ast_config_destroy(cfg);
04799
04800
04801 for (g = gateways; g; g = g->next) {
04802 for (e = g->endpoints; e && e->needaudit; e = e->next) {
04803 e->needaudit = 0;
04804 transmit_audit_endpoint(e);
04805 ast_verb(3, "MGCP Auditing endpoint %s@%s for hookstate\n", e->name, g->name);
04806 }
04807 }
04808
04809 return 0;
04810 }
04811
04812
04813 static int load_module(void)
04814 {
04815 struct ast_format tmpfmt;
04816
04817 if (!(global_capability = ast_format_cap_alloc())) {
04818 return AST_MODULE_LOAD_FAILURE;
04819 }
04820 if (!(mgcp_tech.capabilities = ast_format_cap_alloc())) {
04821 return AST_MODULE_LOAD_FAILURE;
04822 }
04823 ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
04824 ast_format_cap_add(mgcp_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
04825 ast_format_cap_add(mgcp_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
04826 if (!(sched = ast_sched_context_create())) {
04827 ast_log(LOG_WARNING, "Unable to create schedule context\n");
04828 return AST_MODULE_LOAD_FAILURE;
04829 }
04830
04831 if (!(io = io_context_create())) {
04832 ast_log(LOG_WARNING, "Unable to create I/O context\n");
04833 ast_sched_context_destroy(sched);
04834 return AST_MODULE_LOAD_FAILURE;
04835 }
04836
04837 if (reload_config(0))
04838 return AST_MODULE_LOAD_DECLINE;
04839
04840
04841 if (ast_channel_register(&mgcp_tech)) {
04842 ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n");
04843 io_context_destroy(io);
04844 ast_sched_context_destroy(sched);
04845 return AST_MODULE_LOAD_FAILURE;
04846 }
04847
04848 ast_rtp_glue_register(&mgcp_rtp_glue);
04849 ast_cli_register_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
04850
04851
04852 restart_monitor();
04853
04854 return AST_MODULE_LOAD_SUCCESS;
04855 }
04856
04857 static char *mgcp_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04858 {
04859 static int deprecated = 0;
04860
04861 if (e) {
04862 switch (cmd) {
04863 case CLI_INIT:
04864 e->command = "mgcp reload";
04865 e->usage =
04866 "Usage: mgcp reload\n"
04867 " 'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n";
04868 return NULL;
04869 case CLI_GENERATE:
04870 return NULL;
04871 }
04872 }
04873
04874 if (!deprecated && a && a->argc > 0) {
04875 ast_log(LOG_WARNING, "'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n");
04876 deprecated = 1;
04877 }
04878
04879 ast_mutex_lock(&mgcp_reload_lock);
04880 if (mgcp_reloading) {
04881 ast_verbose("Previous mgcp reload not yet done\n");
04882 } else {
04883 mgcp_reloading = 1;
04884 }
04885 ast_mutex_unlock(&mgcp_reload_lock);
04886 restart_monitor();
04887 return CLI_SUCCESS;
04888 }
04889
04890 static int reload(void)
04891 {
04892 mgcp_reload(NULL, 0, NULL);
04893 return 0;
04894 }
04895
04896 static int unload_module(void)
04897 {
04898 struct mgcp_endpoint *e;
04899 struct mgcp_gateway *g;
04900
04901
04902 if (ast_mutex_trylock(&mgcp_reload_lock)) {
04903 ast_log(LOG_WARNING, "MGCP is currently reloading. Unable to remove module.\n");
04904 return -1;
04905 } else {
04906 mgcp_reloading = 1;
04907 ast_mutex_unlock(&mgcp_reload_lock);
04908 }
04909
04910
04911 ast_channel_unregister(&mgcp_tech);
04912
04913
04914 if (!ast_mutex_lock(&monlock)) {
04915 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
04916 pthread_cancel(monitor_thread);
04917 pthread_kill(monitor_thread, SIGURG);
04918 pthread_join(monitor_thread, NULL);
04919 }
04920 monitor_thread = AST_PTHREADT_STOP;
04921 ast_mutex_unlock(&monlock);
04922 } else {
04923 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
04924
04925 ast_channel_register(&mgcp_tech);
04926 mgcp_reloading = 0;
04927 mgcp_reload(NULL, 0, NULL);
04928 return -1;
04929 }
04930
04931 if (!ast_mutex_lock(&gatelock)) {
04932 for (g = gateways; g; g = g->next) {
04933 g->delme = 1;
04934 for (e = g->endpoints; e; e = e->next) {
04935 e->delme = 1;
04936 }
04937 }
04938
04939 prune_gateways();
04940 ast_mutex_unlock(&gatelock);
04941 } else {
04942 ast_log(LOG_WARNING, "Unable to lock the gateways list.\n");
04943
04944 ast_channel_register(&mgcp_tech);
04945
04946 monitor_thread = AST_PTHREADT_NULL;
04947 mgcp_reloading = 0;
04948 mgcp_reload(NULL, 0, NULL);
04949 return -1;
04950 }
04951
04952 close(mgcpsock);
04953 ast_rtp_glue_unregister(&mgcp_rtp_glue);
04954 ast_cli_unregister_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
04955 ast_sched_context_destroy(sched);
04956
04957 global_capability = ast_format_cap_destroy(global_capability);
04958 mgcp_tech.capabilities = ast_format_cap_destroy(mgcp_tech.capabilities);
04959
04960 return 0;
04961 }
04962
04963 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Media Gateway Control Protocol (MGCP)",
04964 .load = load_module,
04965 .unload = unload_module,
04966 .reload = reload,
04967 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
04968 .nonoptreq = "res_pktccops",
04969 );