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