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