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