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: 346086 $")
00040
00041 #include <sys/socket.h>
00042 #include <fcntl.h>
00043 #include <netdb.h>
00044 #include <netinet/in.h>
00045 #include <arpa/inet.h>
00046 #include <sys/signal.h>
00047 #include <iksemel.h>
00048 #include <pthread.h>
00049
00050 #include "asterisk/lock.h"
00051 #include "asterisk/channel.h"
00052 #include "asterisk/config.h"
00053 #include "asterisk/module.h"
00054 #include "asterisk/pbx.h"
00055 #include "asterisk/sched.h"
00056 #include "asterisk/io.h"
00057 #include "asterisk/rtp_engine.h"
00058 #include "asterisk/acl.h"
00059 #include "asterisk/callerid.h"
00060 #include "asterisk/file.h"
00061 #include "asterisk/cli.h"
00062 #include "asterisk/app.h"
00063 #include "asterisk/musiconhold.h"
00064 #include "asterisk/manager.h"
00065 #include "asterisk/stringfields.h"
00066 #include "asterisk/utils.h"
00067 #include "asterisk/causes.h"
00068 #include "asterisk/astobj.h"
00069 #include "asterisk/abstract_jb.h"
00070 #include "asterisk/jabber.h"
00071 #include "asterisk/jingle.h"
00072
00073 #define JINGLE_CONFIG "jingle.conf"
00074
00075
00076 static struct ast_jb_conf default_jbconf =
00077 {
00078 .flags = 0,
00079 .max_size = -1,
00080 .resync_threshold = -1,
00081 .impl = "",
00082 .target_extra = -1,
00083 };
00084 static struct ast_jb_conf global_jbconf;
00085
00086 enum jingle_protocol {
00087 AJI_PROTOCOL_UDP,
00088 AJI_PROTOCOL_SSLTCP,
00089 };
00090
00091 enum jingle_connect_type {
00092 AJI_CONNECT_HOST,
00093 AJI_CONNECT_PRFLX,
00094 AJI_CONNECT_RELAY,
00095 AJI_CONNECT_SRFLX,
00096 };
00097
00098 struct jingle_pvt {
00099 ast_mutex_t lock;
00100 time_t laststun;
00101 struct jingle *parent;
00102 char sid[100];
00103 char them[AJI_MAX_JIDLEN];
00104 char ring[10];
00105 iksrule *ringrule;
00106 int initiator;
00107 int alreadygone;
00108 format_t capability;
00109 struct ast_codec_pref prefs;
00110 struct jingle_candidate *theircandidates;
00111 struct jingle_candidate *ourcandidates;
00112 char cid_num[80];
00113 char cid_name[80];
00114 char exten[80];
00115 struct ast_channel *owner;
00116 char audio_content_name[100];
00117 struct ast_rtp_instance *rtp;
00118 char video_content_name[100];
00119 struct ast_rtp_instance *vrtp;
00120 format_t jointcapability;
00121 format_t peercapability;
00122 struct jingle_pvt *next;
00123 };
00124
00125 struct jingle_candidate {
00126 unsigned int component;
00127 unsigned int foundation;
00128 unsigned int generation;
00129 char ip[16];
00130 unsigned int network;
00131 unsigned int port;
00132 unsigned int priority;
00133 enum jingle_protocol protocol;
00134 char password[100];
00135 enum jingle_connect_type type;
00136 char ufrag[100];
00137 unsigned int preference;
00138 struct jingle_candidate *next;
00139 };
00140
00141 struct jingle {
00142 ASTOBJ_COMPONENTS(struct jingle);
00143 struct aji_client *connection;
00144 struct aji_buddy *buddy;
00145 struct jingle_pvt *p;
00146 struct ast_codec_pref prefs;
00147 int amaflags;
00148 char user[100];
00149 char context[100];
00150 char accountcode[AST_MAX_ACCOUNT_CODE];
00151 format_t capability;
00152 ast_group_t callgroup;
00153 ast_group_t pickupgroup;
00154 int callingpres;
00155 int allowguest;
00156 char language[MAX_LANGUAGE];
00157 char musicclass[MAX_MUSICCLASS];
00158 char parkinglot[AST_MAX_CONTEXT];
00159 };
00160
00161 struct jingle_container {
00162 ASTOBJ_CONTAINER_COMPONENTS(struct jingle);
00163 };
00164
00165 static const char desc[] = "Jingle Channel";
00166 static const char channel_type[] = "Jingle";
00167
00168 static format_t global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263;
00169
00170 AST_MUTEX_DEFINE_STATIC(jinglelock);
00171
00172
00173 static struct ast_channel *jingle_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
00174 static int jingle_sendtext(struct ast_channel *ast, const char *text);
00175 static int jingle_digit_begin(struct ast_channel *ast, char digit);
00176 static int jingle_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
00177 static int jingle_call(struct ast_channel *ast, char *dest, int timeout);
00178 static int jingle_hangup(struct ast_channel *ast);
00179 static int jingle_answer(struct ast_channel *ast);
00180 static int jingle_newcall(struct jingle *client, ikspak *pak);
00181 static struct ast_frame *jingle_read(struct ast_channel *ast);
00182 static int jingle_write(struct ast_channel *ast, struct ast_frame *f);
00183 static int jingle_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
00184 static int jingle_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
00185 static int jingle_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
00186 static struct jingle_pvt *jingle_alloc(struct jingle *client, const char *from, const char *sid);
00187 static char *jingle_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
00188 static char *jingle_do_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
00189
00190
00191 static const struct ast_channel_tech jingle_tech = {
00192 .type = "Jingle",
00193 .description = "Jingle Channel Driver",
00194 .capabilities = AST_FORMAT_AUDIO_MASK,
00195 .requester = jingle_request,
00196 .send_text = jingle_sendtext,
00197 .send_digit_begin = jingle_digit_begin,
00198 .send_digit_end = jingle_digit_end,
00199 .bridge = ast_rtp_instance_bridge,
00200 .call = jingle_call,
00201 .hangup = jingle_hangup,
00202 .answer = jingle_answer,
00203 .read = jingle_read,
00204 .write = jingle_write,
00205 .exception = jingle_read,
00206 .indicate = jingle_indicate,
00207 .fixup = jingle_fixup,
00208 .send_html = jingle_sendhtml,
00209 .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER
00210 };
00211
00212 static struct sockaddr_in bindaddr = { 0, };
00213
00214 static struct sched_context *sched;
00215 static struct io_context *io;
00216 static struct in_addr __ourip;
00217
00218 static struct ast_cli_entry jingle_cli[] = {
00219 AST_CLI_DEFINE(jingle_do_reload, "Reload Jingle configuration"),
00220 AST_CLI_DEFINE(jingle_show_channels, "Show Jingle channels"),
00221 };
00222
00223
00224 static char externip[16];
00225
00226 static struct jingle_container jingle_list;
00227
00228 static void jingle_member_destroy(struct jingle *obj)
00229 {
00230 ast_free(obj);
00231 }
00232
00233 static struct jingle *find_jingle(char *name, char *connection)
00234 {
00235 struct jingle *jingle = NULL;
00236
00237 jingle = ASTOBJ_CONTAINER_FIND(&jingle_list, name);
00238 if (!jingle && strchr(name, '@'))
00239 jingle = ASTOBJ_CONTAINER_FIND_FULL(&jingle_list, name, user,,, strcasecmp);
00240
00241 if (!jingle) {
00242
00243 ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, {
00244 ASTOBJ_RDLOCK(iterator);
00245 if (!strcasecmp(iterator->name, "guest")) {
00246 jingle = iterator;
00247 }
00248 ASTOBJ_UNLOCK(iterator);
00249
00250 if (jingle)
00251 break;
00252 });
00253
00254 }
00255 return jingle;
00256 }
00257
00258
00259 static void add_codec_to_answer(const struct jingle_pvt *p, int codec, iks *dcodecs)
00260 {
00261 char *format = ast_getformatname(codec);
00262
00263 if (!strcasecmp("ulaw", format)) {
00264 iks *payload_eg711u, *payload_pcmu;
00265 payload_pcmu = iks_new("payload-type");
00266 iks_insert_attrib(payload_pcmu, "id", "0");
00267 iks_insert_attrib(payload_pcmu, "name", "PCMU");
00268 payload_eg711u = iks_new("payload-type");
00269 iks_insert_attrib(payload_eg711u, "id", "100");
00270 iks_insert_attrib(payload_eg711u, "name", "EG711U");
00271 iks_insert_node(dcodecs, payload_pcmu);
00272 iks_insert_node(dcodecs, payload_eg711u);
00273 }
00274 if (!strcasecmp("alaw", format)) {
00275 iks *payload_eg711a;
00276 iks *payload_pcma = iks_new("payload-type");
00277 iks_insert_attrib(payload_pcma, "id", "8");
00278 iks_insert_attrib(payload_pcma, "name", "PCMA");
00279 payload_eg711a = iks_new("payload-type");
00280 iks_insert_attrib(payload_eg711a, "id", "101");
00281 iks_insert_attrib(payload_eg711a, "name", "EG711A");
00282 iks_insert_node(dcodecs, payload_pcma);
00283 iks_insert_node(dcodecs, payload_eg711a);
00284 }
00285 if (!strcasecmp("ilbc", format)) {
00286 iks *payload_ilbc = iks_new("payload-type");
00287 iks_insert_attrib(payload_ilbc, "id", "97");
00288 iks_insert_attrib(payload_ilbc, "name", "iLBC");
00289 iks_insert_node(dcodecs, payload_ilbc);
00290 }
00291 if (!strcasecmp("g723", format)) {
00292 iks *payload_g723 = iks_new("payload-type");
00293 iks_insert_attrib(payload_g723, "id", "4");
00294 iks_insert_attrib(payload_g723, "name", "G723");
00295 iks_insert_node(dcodecs, payload_g723);
00296 }
00297 }
00298
00299 static int jingle_accept_call(struct jingle *client, struct jingle_pvt *p)
00300 {
00301 struct jingle_pvt *tmp = client->p;
00302 struct aji_client *c = client->connection;
00303 iks *iq, *jingle, *dcodecs, *payload_red, *payload_audio, *payload_cn;
00304 int x;
00305 format_t pref_codec = 0;
00306 int alreadysent = 0;
00307
00308 if (p->initiator)
00309 return 1;
00310
00311 iq = iks_new("iq");
00312 jingle = iks_new(JINGLE_NODE);
00313 dcodecs = iks_new("description");
00314 if (iq && jingle && dcodecs) {
00315 iks_insert_attrib(dcodecs, "xmlns", JINGLE_AUDIO_RTP_NS);
00316
00317 for (x = 0; x < 64; x++) {
00318 if (!(pref_codec = ast_codec_pref_index(&client->prefs, x)))
00319 break;
00320 if (!(client->capability & pref_codec))
00321 continue;
00322 if (alreadysent & pref_codec)
00323 continue;
00324 add_codec_to_answer(p, pref_codec, dcodecs);
00325 alreadysent |= pref_codec;
00326 }
00327 payload_red = iks_new("payload-type");
00328 iks_insert_attrib(payload_red, "id", "117");
00329 iks_insert_attrib(payload_red, "name", "red");
00330 payload_audio = iks_new("payload-type");
00331 iks_insert_attrib(payload_audio, "id", "106");
00332 iks_insert_attrib(payload_audio, "name", "audio/telephone-event");
00333 payload_cn = iks_new("payload-type");
00334 iks_insert_attrib(payload_cn, "id", "13");
00335 iks_insert_attrib(payload_cn, "name", "CN");
00336
00337
00338 iks_insert_attrib(iq, "type", "set");
00339 iks_insert_attrib(iq, "to", (p->them) ? p->them : client->user);
00340 iks_insert_attrib(iq, "id", client->connection->mid);
00341 ast_aji_increment_mid(client->connection->mid);
00342
00343 iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
00344 iks_insert_attrib(jingle, "action", JINGLE_ACCEPT);
00345 iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them);
00346 iks_insert_attrib(jingle, JINGLE_SID, tmp->sid);
00347 iks_insert_node(iq, jingle);
00348 iks_insert_node(jingle, dcodecs);
00349 iks_insert_node(dcodecs, payload_red);
00350 iks_insert_node(dcodecs, payload_audio);
00351 iks_insert_node(dcodecs, payload_cn);
00352
00353 ast_aji_send(c, iq);
00354
00355 iks_delete(payload_red);
00356 iks_delete(payload_audio);
00357 iks_delete(payload_cn);
00358 iks_delete(dcodecs);
00359 iks_delete(jingle);
00360 iks_delete(iq);
00361 }
00362 return 1;
00363 }
00364
00365 static int jingle_ringing_ack(void *data, ikspak *pak)
00366 {
00367 struct jingle_pvt *p = data;
00368
00369 if (p->ringrule)
00370 iks_filter_remove_rule(p->parent->connection->f, p->ringrule);
00371 p->ringrule = NULL;
00372 if (p->owner)
00373 ast_queue_control(p->owner, AST_CONTROL_RINGING);
00374 return IKS_FILTER_EAT;
00375 }
00376
00377 static int jingle_answer(struct ast_channel *ast)
00378 {
00379 struct jingle_pvt *p = ast->tech_pvt;
00380 struct jingle *client = p->parent;
00381 int res = 0;
00382
00383 ast_debug(1, "Answer!\n");
00384 ast_mutex_lock(&p->lock);
00385 jingle_accept_call(client, p);
00386 ast_mutex_unlock(&p->lock);
00387 return res;
00388 }
00389
00390 static enum ast_rtp_glue_result jingle_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
00391 {
00392 struct jingle_pvt *p = chan->tech_pvt;
00393 enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_FORBID;
00394
00395 if (!p)
00396 return res;
00397
00398 ast_mutex_lock(&p->lock);
00399 if (p->rtp) {
00400 ao2_ref(p->rtp, +1);
00401 *instance = p->rtp;
00402 res = AST_RTP_GLUE_RESULT_LOCAL;
00403 }
00404 ast_mutex_unlock(&p->lock);
00405
00406 return res;
00407 }
00408
00409 static format_t jingle_get_codec(struct ast_channel *chan)
00410 {
00411 struct jingle_pvt *p = chan->tech_pvt;
00412 return p->peercapability;
00413 }
00414
00415 static int jingle_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *tpeer, format_t codecs, int nat_active)
00416 {
00417 struct jingle_pvt *p;
00418
00419 p = chan->tech_pvt;
00420 if (!p)
00421 return -1;
00422 ast_mutex_lock(&p->lock);
00423
00424
00425
00426
00427
00428
00429
00430
00431 ast_mutex_unlock(&p->lock);
00432 return 0;
00433 }
00434
00435 static struct ast_rtp_glue jingle_rtp_glue = {
00436 .type = "Jingle",
00437 .get_rtp_info = jingle_get_rtp_peer,
00438 .get_codec = jingle_get_codec,
00439 .update_peer = jingle_set_rtp_peer,
00440 };
00441
00442 static int jingle_response(struct jingle *client, ikspak *pak, const char *reasonstr, const char *reasonstr2)
00443 {
00444 iks *response = NULL, *error = NULL, *reason = NULL;
00445 int res = -1;
00446
00447 response = iks_new("iq");
00448 if (response) {
00449 iks_insert_attrib(response, "type", "result");
00450 iks_insert_attrib(response, "from", client->connection->jid->full);
00451 iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from"));
00452 iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id"));
00453 if (reasonstr) {
00454 error = iks_new("error");
00455 if (error) {
00456 iks_insert_attrib(error, "type", "cancel");
00457 reason = iks_new(reasonstr);
00458 if (reason)
00459 iks_insert_node(error, reason);
00460 iks_insert_node(response, error);
00461 }
00462 }
00463 ast_aji_send(client->connection, response);
00464 res = 0;
00465 }
00466
00467 iks_delete(reason);
00468 iks_delete(error);
00469 iks_delete(response);
00470
00471 return res;
00472 }
00473
00474 static int jingle_is_answered(struct jingle *client, ikspak *pak)
00475 {
00476 struct jingle_pvt *tmp;
00477
00478 ast_debug(1, "The client is %s\n", client->name);
00479
00480 for (tmp = client->p; tmp; tmp = tmp->next) {
00481 if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid))
00482 break;
00483 }
00484
00485 if (tmp) {
00486 if (tmp->owner)
00487 ast_queue_control(tmp->owner, AST_CONTROL_ANSWER);
00488 } else
00489 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
00490 jingle_response(client, pak, NULL, NULL);
00491 return 1;
00492 }
00493
00494 static int jingle_handle_dtmf(struct jingle *client, ikspak *pak)
00495 {
00496 struct jingle_pvt *tmp;
00497 iks *dtmfnode = NULL, *dtmfchild = NULL;
00498 char *dtmf;
00499
00500 for (tmp = client->p; tmp; tmp = tmp->next) {
00501 if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid))
00502 break;
00503 }
00504
00505 if (tmp) {
00506 if(iks_find_with_attrib(pak->x, "dtmf-method", "method", "rtp")) {
00507 jingle_response(client,pak,
00508 "feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
00509 "unsupported-dtmf-method xmlns='http://www.xmpp.org/extensions/xep-0181.html#ns-errors'");
00510 return -1;
00511 }
00512 if ((dtmfnode = iks_find(pak->x, "dtmf"))) {
00513 if((dtmf = iks_find_attrib(dtmfnode, "code"))) {
00514 if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-up")) {
00515 struct ast_frame f = {AST_FRAME_DTMF_BEGIN, };
00516 f.subclass.integer = dtmf[0];
00517 ast_queue_frame(tmp->owner, &f);
00518 ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer);
00519 } else if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-down")) {
00520 struct ast_frame f = {AST_FRAME_DTMF_END, };
00521 f.subclass.integer = dtmf[0];
00522 ast_queue_frame(tmp->owner, &f);
00523 ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer);
00524 } else if(iks_find_attrib(pak->x, "dtmf")) {
00525 struct ast_frame f = {AST_FRAME_DTMF, };
00526 f.subclass.integer = dtmf[0];
00527 ast_queue_frame(tmp->owner, &f);
00528 ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer);
00529 }
00530 }
00531 } else if ((dtmfnode = iks_find_with_attrib(pak->x, JINGLE_NODE, "action", "session-info"))) {
00532 if((dtmfchild = iks_find(dtmfnode, "dtmf"))) {
00533 if((dtmf = iks_find_attrib(dtmfchild, "code"))) {
00534 if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-up")) {
00535 struct ast_frame f = {AST_FRAME_DTMF_END, };
00536 f.subclass.integer = dtmf[0];
00537 ast_queue_frame(tmp->owner, &f);
00538 ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer);
00539 } else if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-down")) {
00540 struct ast_frame f = {AST_FRAME_DTMF_BEGIN, };
00541 f.subclass.integer = dtmf[0];
00542 ast_queue_frame(tmp->owner, &f);
00543 ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer);
00544 }
00545 }
00546 }
00547 }
00548 jingle_response(client, pak, NULL, NULL);
00549 return 1;
00550 } else
00551 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
00552
00553 jingle_response(client, pak, NULL, NULL);
00554 return 1;
00555 }
00556
00557
00558 static int jingle_hangup_farend(struct jingle *client, ikspak *pak)
00559 {
00560 struct jingle_pvt *tmp;
00561
00562 ast_debug(1, "The client is %s\n", client->name);
00563
00564 for (tmp = client->p; tmp; tmp = tmp->next) {
00565 if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid))
00566 break;
00567 }
00568
00569 if (tmp) {
00570 tmp->alreadygone = 1;
00571 if (tmp->owner)
00572 ast_queue_hangup(tmp->owner);
00573 } else
00574 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
00575 jingle_response(client, pak, NULL, NULL);
00576 return 1;
00577 }
00578
00579 static int jingle_create_candidates(struct jingle *client, struct jingle_pvt *p, char *sid, char *from)
00580 {
00581 struct jingle_candidate *tmp;
00582 struct aji_client *c = client->connection;
00583 struct jingle_candidate *ours1 = NULL, *ours2 = NULL;
00584 struct sockaddr_in sin = { 0, };
00585 struct ast_sockaddr sin_tmp;
00586 struct ast_sockaddr us_tmp;
00587 struct ast_sockaddr bindaddr_tmp;
00588 struct in_addr us;
00589 struct in_addr externaddr;
00590 iks *iq, *jingle, *content, *transport, *candidate;
00591 char component[16], foundation[16], generation[16], network[16], pass[16], port[7], priority[16], user[16];
00592
00593
00594 iq = iks_new("iq");
00595 jingle = iks_new(JINGLE_NODE);
00596 content = iks_new("content");
00597 transport = iks_new("transport");
00598 candidate = iks_new("candidate");
00599 if (!iq || !jingle || !content || !transport || !candidate) {
00600 ast_log(LOG_ERROR, "Memory allocation error\n");
00601 goto safeout;
00602 }
00603 ours1 = ast_calloc(1, sizeof(*ours1));
00604 ours2 = ast_calloc(1, sizeof(*ours2));
00605 if (!ours1 || !ours2)
00606 goto safeout;
00607
00608 iks_insert_node(iq, jingle);
00609 iks_insert_node(jingle, content);
00610 iks_insert_node(content, transport);
00611 iks_insert_node(transport, candidate);
00612
00613 for (; p; p = p->next) {
00614 if (!strcasecmp(p->sid, sid))
00615 break;
00616 }
00617
00618 if (!p) {
00619 ast_log(LOG_NOTICE, "No matching jingle session - SID %s!\n", sid);
00620 goto safeout;
00621 }
00622
00623 ast_rtp_instance_get_local_address(p->rtp, &sin_tmp);
00624 ast_sockaddr_to_sin(&sin_tmp, &sin);
00625 ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
00626 ast_find_ourip(&us_tmp, &bindaddr_tmp, AF_INET);
00627 us.s_addr = htonl(ast_sockaddr_ipv4(&us_tmp));
00628
00629
00630 ours1->component = 1;
00631 ours1->foundation = (unsigned int)bindaddr.sin_addr.s_addr | AJI_CONNECT_HOST | AJI_PROTOCOL_UDP;
00632 ours1->generation = 0;
00633 ast_copy_string(ours1->ip, ast_inet_ntoa(us), sizeof(ours1->ip));
00634 ours1->network = 0;
00635 ours1->port = ntohs(sin.sin_port);
00636 ours1->priority = 1678246398;
00637 ours1->protocol = AJI_PROTOCOL_UDP;
00638 snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random());
00639 ast_copy_string(ours1->password, pass, sizeof(ours1->password));
00640 ours1->type = AJI_CONNECT_HOST;
00641 snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random());
00642 ast_copy_string(ours1->ufrag, user, sizeof(ours1->ufrag));
00643 p->ourcandidates = ours1;
00644
00645 if (!ast_strlen_zero(externip)) {
00646
00647 if (inet_aton(externip, &externaddr))
00648 ast_log(LOG_WARNING, "Invalid extern IP : %s\n", externip);
00649
00650 ours2->component = 1;
00651 ours2->foundation = (unsigned int)externaddr.s_addr | AJI_CONNECT_PRFLX | AJI_PROTOCOL_UDP;
00652 ours2->generation = 0;
00653 ast_copy_string(ours2->ip, externip, sizeof(ours2->ip));
00654 ours2->network = 0;
00655 ours2->port = ntohs(sin.sin_port);
00656 ours2->priority = 1678246397;
00657 ours2->protocol = AJI_PROTOCOL_UDP;
00658 snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random());
00659 ast_copy_string(ours2->password, pass, sizeof(ours2->password));
00660 ours2->type = AJI_CONNECT_PRFLX;
00661
00662 snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random());
00663 ast_copy_string(ours2->ufrag, user, sizeof(ours2->ufrag));
00664 ours1->next = ours2;
00665 ours2 = NULL;
00666 }
00667 ours1 = NULL;
00668
00669 for (tmp = p->ourcandidates; tmp; tmp = tmp->next) {
00670 snprintf(component, sizeof(component), "%u", tmp->component);
00671 snprintf(foundation, sizeof(foundation), "%u", tmp->foundation);
00672 snprintf(generation, sizeof(generation), "%u", tmp->generation);
00673 snprintf(network, sizeof(network), "%u", tmp->network);
00674 snprintf(port, sizeof(port), "%u", tmp->port);
00675 snprintf(priority, sizeof(priority), "%u", tmp->priority);
00676
00677 iks_insert_attrib(iq, "from", c->jid->full);
00678 iks_insert_attrib(iq, "to", from);
00679 iks_insert_attrib(iq, "type", "set");
00680 iks_insert_attrib(iq, "id", c->mid);
00681 ast_aji_increment_mid(c->mid);
00682 iks_insert_attrib(jingle, "action", JINGLE_NEGOTIATE);
00683 iks_insert_attrib(jingle, JINGLE_SID, sid);
00684 iks_insert_attrib(jingle, "initiator", (p->initiator) ? c->jid->full : from);
00685 iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
00686 iks_insert_attrib(content, "creator", p->initiator ? "initiator" : "responder");
00687 iks_insert_attrib(content, "name", "asterisk-audio-content");
00688 iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS);
00689 iks_insert_attrib(candidate, "component", component);
00690 iks_insert_attrib(candidate, "foundation", foundation);
00691 iks_insert_attrib(candidate, "generation", generation);
00692 iks_insert_attrib(candidate, "ip", tmp->ip);
00693 iks_insert_attrib(candidate, "network", network);
00694 iks_insert_attrib(candidate, "port", port);
00695 iks_insert_attrib(candidate, "priority", priority);
00696 switch (tmp->protocol) {
00697 case AJI_PROTOCOL_UDP:
00698 iks_insert_attrib(candidate, "protocol", "udp");
00699 break;
00700 case AJI_PROTOCOL_SSLTCP:
00701 iks_insert_attrib(candidate, "protocol", "ssltcp");
00702 break;
00703 }
00704 iks_insert_attrib(candidate, "pwd", tmp->password);
00705 switch (tmp->type) {
00706 case AJI_CONNECT_HOST:
00707 iks_insert_attrib(candidate, "type", "host");
00708 break;
00709 case AJI_CONNECT_PRFLX:
00710 iks_insert_attrib(candidate, "type", "prflx");
00711 break;
00712 case AJI_CONNECT_RELAY:
00713 iks_insert_attrib(candidate, "type", "relay");
00714 break;
00715 case AJI_CONNECT_SRFLX:
00716 iks_insert_attrib(candidate, "type", "srflx");
00717 break;
00718 }
00719 iks_insert_attrib(candidate, "ufrag", tmp->ufrag);
00720
00721 ast_aji_send(c, iq);
00722 }
00723 p->laststun = 0;
00724
00725 safeout:
00726 if (ours1)
00727 ast_free(ours1);
00728 if (ours2)
00729 ast_free(ours2);
00730 iks_delete(iq);
00731 iks_delete(jingle);
00732 iks_delete(content);
00733 iks_delete(transport);
00734 iks_delete(candidate);
00735
00736 return 1;
00737 }
00738
00739 static struct jingle_pvt *jingle_alloc(struct jingle *client, const char *from, const char *sid)
00740 {
00741 struct jingle_pvt *tmp = NULL;
00742 struct aji_resource *resources = NULL;
00743 struct aji_buddy *buddy = NULL;
00744 char idroster[200];
00745 struct ast_sockaddr bindaddr_tmp;
00746
00747 ast_debug(1, "The client is %s for alloc\n", client->name);
00748 if (!sid && !strchr(from, '/')) {
00749 if (!strcasecmp(client->name, "guest")) {
00750 buddy = ASTOBJ_CONTAINER_FIND(&client->connection->buddies, from);
00751 if (buddy) {
00752 resources = buddy->resources;
00753 }
00754 } else if (client->buddy)
00755 resources = client->buddy->resources;
00756 while (resources) {
00757 if (resources->cap->jingle) {
00758 break;
00759 }
00760 resources = resources->next;
00761 }
00762 if (resources)
00763 snprintf(idroster, sizeof(idroster), "%s/%s", from, resources->resource);
00764 else {
00765 ast_log(LOG_ERROR, "no jingle capable clients to talk to.\n");
00766 if (buddy) {
00767 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy);
00768 }
00769 return NULL;
00770 }
00771 if (buddy) {
00772 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy);
00773 }
00774 }
00775 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
00776 return NULL;
00777 }
00778
00779 memcpy(&tmp->prefs, &client->prefs, sizeof(tmp->prefs));
00780
00781 if (sid) {
00782 ast_copy_string(tmp->sid, sid, sizeof(tmp->sid));
00783 ast_copy_string(tmp->them, from, sizeof(tmp->them));
00784 } else {
00785 snprintf(tmp->sid, sizeof(tmp->sid), "%08lx%08lx", ast_random(), ast_random());
00786 ast_copy_string(tmp->them, idroster, sizeof(tmp->them));
00787 tmp->initiator = 1;
00788 }
00789 ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
00790 tmp->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL);
00791 tmp->parent = client;
00792 if (!tmp->rtp) {
00793 ast_log(LOG_WARNING, "Out of RTP sessions?\n");
00794 ast_free(tmp);
00795 return NULL;
00796 }
00797 ast_copy_string(tmp->exten, "s", sizeof(tmp->exten));
00798 ast_mutex_init(&tmp->lock);
00799 ast_mutex_lock(&jinglelock);
00800 tmp->next = client->p;
00801 client->p = tmp;
00802 ast_mutex_unlock(&jinglelock);
00803 return tmp;
00804 }
00805
00806
00807 static struct ast_channel *jingle_new(struct jingle *client, struct jingle_pvt *i, int state, const char *title, const char *linkedid)
00808 {
00809 struct ast_channel *tmp;
00810 int fmt;
00811 int what;
00812 const char *str;
00813
00814 if (title)
00815 str = title;
00816 else
00817 str = i->them;
00818 tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", "", "", linkedid, 0, "Jingle/%s-%04lx", str, ast_random() & 0xffff);
00819 if (!tmp) {
00820 ast_log(LOG_WARNING, "Unable to allocate Jingle channel structure!\n");
00821 return NULL;
00822 }
00823 tmp->tech = &jingle_tech;
00824
00825
00826
00827 if (i->jointcapability)
00828 what = i->jointcapability;
00829 else if (i->capability)
00830 what = i->capability;
00831 else
00832 what = global_capability;
00833
00834
00835 if (i->rtp)
00836 ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(i->rtp), i->rtp, &i->prefs);
00837
00838 tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | (i->jointcapability & AST_FORMAT_VIDEO_MASK);
00839 fmt = ast_best_codec(tmp->nativeformats);
00840
00841 if (i->rtp) {
00842 ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(i->rtp, 0));
00843 ast_channel_set_fd(tmp, 1, ast_rtp_instance_fd(i->rtp, 1));
00844 }
00845 if (i->vrtp) {
00846 ast_channel_set_fd(tmp, 2, ast_rtp_instance_fd(i->vrtp, 0));
00847 ast_channel_set_fd(tmp, 3, ast_rtp_instance_fd(i->vrtp, 1));
00848 }
00849 if (state == AST_STATE_RING)
00850 tmp->rings = 1;
00851 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
00852 tmp->writeformat = fmt;
00853 tmp->rawwriteformat = fmt;
00854 tmp->readformat = fmt;
00855 tmp->rawreadformat = fmt;
00856 tmp->tech_pvt = i;
00857
00858 tmp->callgroup = client->callgroup;
00859 tmp->pickupgroup = client->pickupgroup;
00860 tmp->caller.id.name.presentation = client->callingpres;
00861 tmp->caller.id.number.presentation = client->callingpres;
00862 if (!ast_strlen_zero(client->accountcode))
00863 ast_string_field_set(tmp, accountcode, client->accountcode);
00864 if (client->amaflags)
00865 tmp->amaflags = client->amaflags;
00866 if (!ast_strlen_zero(client->language))
00867 ast_string_field_set(tmp, language, client->language);
00868 if (!ast_strlen_zero(client->musicclass))
00869 ast_string_field_set(tmp, musicclass, client->musicclass);
00870 i->owner = tmp;
00871 ast_copy_string(tmp->context, client->context, sizeof(tmp->context));
00872 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
00873
00874
00875 if (!ast_strlen_zero(i->cid_num)) {
00876 tmp->caller.ani.number.valid = 1;
00877 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
00878 }
00879 if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s")) {
00880 tmp->dialed.number.str = ast_strdup(i->exten);
00881 }
00882 tmp->priority = 1;
00883 if (i->rtp)
00884 ast_jb_configure(tmp, &global_jbconf);
00885 if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) {
00886 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
00887 tmp->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
00888 ast_hangup(tmp);
00889 tmp = NULL;
00890 }
00891
00892 return tmp;
00893 }
00894
00895 static int jingle_action(struct jingle *client, struct jingle_pvt *p, const char *action)
00896 {
00897 iks *iq, *jingle = NULL;
00898 int res = -1;
00899
00900 iq = iks_new("iq");
00901 jingle = iks_new("jingle");
00902
00903 if (iq) {
00904 iks_insert_attrib(iq, "type", "set");
00905 iks_insert_attrib(iq, "from", client->connection->jid->full);
00906 iks_insert_attrib(iq, "to", p->them);
00907 iks_insert_attrib(iq, "id", client->connection->mid);
00908 ast_aji_increment_mid(client->connection->mid);
00909 if (jingle) {
00910 iks_insert_attrib(jingle, "action", action);
00911 iks_insert_attrib(jingle, JINGLE_SID, p->sid);
00912 iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them);
00913 iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
00914
00915 iks_insert_node(iq, jingle);
00916
00917 ast_aji_send(client->connection, iq);
00918 res = 0;
00919 }
00920 }
00921
00922 iks_delete(jingle);
00923 iks_delete(iq);
00924
00925 return res;
00926 }
00927
00928 static void jingle_free_candidates(struct jingle_candidate *candidate)
00929 {
00930 struct jingle_candidate *last;
00931 while (candidate) {
00932 last = candidate;
00933 candidate = candidate->next;
00934 ast_free(last);
00935 }
00936 }
00937
00938 static void jingle_free_pvt(struct jingle *client, struct jingle_pvt *p)
00939 {
00940 struct jingle_pvt *cur, *prev = NULL;
00941 cur = client->p;
00942 while (cur) {
00943 if (cur == p) {
00944 if (prev)
00945 prev->next = p->next;
00946 else
00947 client->p = p->next;
00948 break;
00949 }
00950 prev = cur;
00951 cur = cur->next;
00952 }
00953 if (p->ringrule)
00954 iks_filter_remove_rule(p->parent->connection->f, p->ringrule);
00955 if (p->owner)
00956 ast_log(LOG_WARNING, "Uh oh, there's an owner, this is going to be messy.\n");
00957 if (p->rtp)
00958 ast_rtp_instance_destroy(p->rtp);
00959 if (p->vrtp)
00960 ast_rtp_instance_destroy(p->vrtp);
00961 jingle_free_candidates(p->theircandidates);
00962 ast_free(p);
00963 }
00964
00965
00966 static int jingle_newcall(struct jingle *client, ikspak *pak)
00967 {
00968 struct jingle_pvt *p, *tmp = client->p;
00969 struct ast_channel *chan;
00970 int res;
00971 iks *codec, *content, *description;
00972 char *from = NULL;
00973
00974
00975 from = iks_find_attrib(pak->x,"to");
00976 if(!from)
00977 from = client->connection->jid->full;
00978
00979 while (tmp) {
00980 if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) {
00981 ast_log(LOG_NOTICE, "Ignoring duplicate call setup on SID %s\n", tmp->sid);
00982 jingle_response(client, pak, "out-of-order", NULL);
00983 return -1;
00984 }
00985 tmp = tmp->next;
00986 }
00987
00988 if (!strcasecmp(client->name, "guest")){
00989
00990
00991 if (client->connection) {
00992 ASTOBJ_UNREF(client->connection, ast_aji_client_destroy);
00993 }
00994 client->connection = ast_aji_get_client(from);
00995 if (!client->connection) {
00996 ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", from);
00997 return -1;
00998 }
00999 }
01000
01001 p = jingle_alloc(client, pak->from->partial, iks_find_attrib(pak->query, JINGLE_SID));
01002 if (!p) {
01003 ast_log(LOG_WARNING, "Unable to allocate jingle structure!\n");
01004 return -1;
01005 }
01006 chan = jingle_new(client, p, AST_STATE_DOWN, pak->from->user, NULL);
01007 if (!chan) {
01008 jingle_free_pvt(client, p);
01009 return -1;
01010 }
01011 ast_mutex_lock(&p->lock);
01012 ast_copy_string(p->them, pak->from->full, sizeof(p->them));
01013 if (iks_find_attrib(pak->query, JINGLE_SID)) {
01014 ast_copy_string(p->sid, iks_find_attrib(pak->query, JINGLE_SID),
01015 sizeof(p->sid));
01016 }
01017
01018
01019 content = iks_child(iks_child(pak->x));
01020 while (content) {
01021 description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_AUDIO_RTP_NS);
01022 if (description) {
01023
01024 codec = iks_child(iks_child(content));
01025 ast_copy_string(p->audio_content_name, iks_find_attrib(content, "name"), sizeof(p->audio_content_name));
01026
01027 while (codec) {
01028 ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")));
01029 ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
01030 codec = iks_next(codec);
01031 }
01032 }
01033
01034 description = NULL;
01035 codec = NULL;
01036
01037 description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_VIDEO_RTP_NS);
01038 if (description) {
01039
01040 codec = iks_child(iks_child(content));
01041 ast_copy_string(p->video_content_name, iks_find_attrib(content, "name"), sizeof(p->video_content_name));
01042
01043 while (codec) {
01044 ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")));
01045 ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
01046 codec = iks_next(codec);
01047 }
01048 }
01049
01050 content = iks_next(content);
01051 }
01052
01053 ast_mutex_unlock(&p->lock);
01054 ast_setstate(chan, AST_STATE_RING);
01055 res = ast_pbx_start(chan);
01056
01057 switch (res) {
01058 case AST_PBX_FAILED:
01059 ast_log(LOG_WARNING, "Failed to start PBX :(\n");
01060 jingle_response(client, pak, "service-unavailable", NULL);
01061 break;
01062 case AST_PBX_CALL_LIMIT:
01063 ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n");
01064 jingle_response(client, pak, "service-unavailable", NULL);
01065 break;
01066 case AST_PBX_SUCCESS:
01067 jingle_response(client, pak, NULL, NULL);
01068 jingle_create_candidates(client, p,
01069 iks_find_attrib(pak->query, JINGLE_SID),
01070 iks_find_attrib(pak->x, "from"));
01071
01072 break;
01073 }
01074
01075 return 1;
01076 }
01077
01078 static int jingle_update_stun(struct jingle *client, struct jingle_pvt *p)
01079 {
01080 struct jingle_candidate *tmp;
01081 struct hostent *hp;
01082 struct ast_hostent ahp;
01083 struct sockaddr_in sin;
01084 struct ast_sockaddr sin_tmp;
01085
01086 if (time(NULL) == p->laststun)
01087 return 0;
01088
01089 tmp = p->theircandidates;
01090 p->laststun = time(NULL);
01091 while (tmp) {
01092 char username[256];
01093 hp = ast_gethostbyname(tmp->ip, &ahp);
01094 sin.sin_family = AF_INET;
01095 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
01096 sin.sin_port = htons(tmp->port);
01097 snprintf(username, sizeof(username), "%s:%s", tmp->ufrag, p->ourcandidates->ufrag);
01098
01099 ast_sockaddr_from_sin(&sin_tmp, &sin);
01100 ast_rtp_instance_stun_request(p->rtp, &sin_tmp, username);
01101 tmp = tmp->next;
01102 }
01103 return 1;
01104 }
01105
01106 static int jingle_add_candidate(struct jingle *client, ikspak *pak)
01107 {
01108 struct jingle_pvt *p = NULL, *tmp = NULL;
01109 struct aji_client *c = client->connection;
01110 struct jingle_candidate *newcandidate = NULL;
01111 iks *traversenodes = NULL, *receipt = NULL;
01112
01113 for (tmp = client->p; tmp; tmp = tmp->next) {
01114 if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) {
01115 p = tmp;
01116 break;
01117 }
01118 }
01119
01120 if (!p)
01121 return -1;
01122
01123 traversenodes = pak->query;
01124 while(traversenodes) {
01125 if(!strcasecmp(iks_name(traversenodes), "jingle")) {
01126 traversenodes = iks_child(traversenodes);
01127 continue;
01128 }
01129 if(!strcasecmp(iks_name(traversenodes), "content")) {
01130 traversenodes = iks_child(traversenodes);
01131 continue;
01132 }
01133 if(!strcasecmp(iks_name(traversenodes), "transport")) {
01134 traversenodes = iks_child(traversenodes);
01135 continue;
01136 }
01137
01138 if(!strcasecmp(iks_name(traversenodes), "candidate")) {
01139 newcandidate = ast_calloc(1, sizeof(*newcandidate));
01140 if (!newcandidate)
01141 return 0;
01142 ast_copy_string(newcandidate->ip, iks_find_attrib(traversenodes, "ip"), sizeof(newcandidate->ip));
01143 newcandidate->port = atoi(iks_find_attrib(traversenodes, "port"));
01144 ast_copy_string(newcandidate->password, iks_find_attrib(traversenodes, "pwd"), sizeof(newcandidate->password));
01145 if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "udp"))
01146 newcandidate->protocol = AJI_PROTOCOL_UDP;
01147 else if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "ssltcp"))
01148 newcandidate->protocol = AJI_PROTOCOL_SSLTCP;
01149
01150 if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "host"))
01151 newcandidate->type = AJI_CONNECT_HOST;
01152 else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "prflx"))
01153 newcandidate->type = AJI_CONNECT_PRFLX;
01154 else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "relay"))
01155 newcandidate->type = AJI_CONNECT_RELAY;
01156 else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "srflx"))
01157 newcandidate->type = AJI_CONNECT_SRFLX;
01158
01159 newcandidate->network = atoi(iks_find_attrib(traversenodes, "network"));
01160 newcandidate->generation = atoi(iks_find_attrib(traversenodes, "generation"));
01161 newcandidate->next = NULL;
01162
01163 newcandidate->next = p->theircandidates;
01164 p->theircandidates = newcandidate;
01165 p->laststun = 0;
01166 jingle_update_stun(p->parent, p);
01167 newcandidate = NULL;
01168 }
01169 traversenodes = iks_next(traversenodes);
01170 }
01171
01172 receipt = iks_new("iq");
01173 iks_insert_attrib(receipt, "type", "result");
01174 iks_insert_attrib(receipt, "from", c->jid->full);
01175 iks_insert_attrib(receipt, "to", iks_find_attrib(pak->x, "from"));
01176 iks_insert_attrib(receipt, "id", iks_find_attrib(pak->x, "id"));
01177 ast_aji_send(c, receipt);
01178
01179 iks_delete(receipt);
01180
01181 return 1;
01182 }
01183
01184 static struct ast_frame *jingle_rtp_read(struct ast_channel *ast, struct jingle_pvt *p)
01185 {
01186 struct ast_frame *f;
01187
01188 if (!p->rtp)
01189 return &ast_null_frame;
01190 f = ast_rtp_instance_read(p->rtp, 0);
01191 jingle_update_stun(p->parent, p);
01192 if (p->owner) {
01193
01194 if (f->frametype == AST_FRAME_VOICE) {
01195 if (f->subclass.codec != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) {
01196 ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(f->subclass.codec));
01197 p->owner->nativeformats =
01198 (p->owner->nativeformats & AST_FORMAT_VIDEO_MASK) | f->subclass.codec;
01199 ast_set_read_format(p->owner, p->owner->readformat);
01200 ast_set_write_format(p->owner, p->owner->writeformat);
01201 }
01202
01203
01204
01205
01206
01207 }
01208 }
01209 return f;
01210 }
01211
01212 static struct ast_frame *jingle_read(struct ast_channel *ast)
01213 {
01214 struct ast_frame *fr;
01215 struct jingle_pvt *p = ast->tech_pvt;
01216
01217 ast_mutex_lock(&p->lock);
01218 fr = jingle_rtp_read(ast, p);
01219 ast_mutex_unlock(&p->lock);
01220 return fr;
01221 }
01222
01223
01224 static int jingle_write(struct ast_channel *ast, struct ast_frame *frame)
01225 {
01226 struct jingle_pvt *p = ast->tech_pvt;
01227 int res = 0;
01228 char buf[256];
01229
01230 switch (frame->frametype) {
01231 case AST_FRAME_VOICE:
01232 if (!(frame->subclass.codec & ast->nativeformats)) {
01233 ast_log(LOG_WARNING,
01234 "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
01235 ast_getformatname(frame->subclass.codec),
01236 ast_getformatname_multiple(buf, sizeof(buf), ast->nativeformats),
01237 ast_getformatname(ast->readformat),
01238 ast_getformatname(ast->writeformat));
01239 return 0;
01240 }
01241 if (p) {
01242 ast_mutex_lock(&p->lock);
01243 if (p->rtp) {
01244 res = ast_rtp_instance_write(p->rtp, frame);
01245 }
01246 ast_mutex_unlock(&p->lock);
01247 }
01248 break;
01249 case AST_FRAME_VIDEO:
01250 if (p) {
01251 ast_mutex_lock(&p->lock);
01252 if (p->vrtp) {
01253 res = ast_rtp_instance_write(p->vrtp, frame);
01254 }
01255 ast_mutex_unlock(&p->lock);
01256 }
01257 break;
01258 case AST_FRAME_IMAGE:
01259 return 0;
01260 break;
01261 default:
01262 ast_log(LOG_WARNING, "Can't send %d type frames with Jingle write\n",
01263 frame->frametype);
01264 return 0;
01265 }
01266
01267 return res;
01268 }
01269
01270 static int jingle_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
01271 {
01272 struct jingle_pvt *p = newchan->tech_pvt;
01273 ast_mutex_lock(&p->lock);
01274
01275 if ((p->owner != oldchan)) {
01276 ast_mutex_unlock(&p->lock);
01277 return -1;
01278 }
01279 if (p->owner == oldchan)
01280 p->owner = newchan;
01281 ast_mutex_unlock(&p->lock);
01282 return 0;
01283 }
01284
01285 static int jingle_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
01286 {
01287 int res = 0;
01288
01289 switch (condition) {
01290 case AST_CONTROL_HOLD:
01291 ast_moh_start(ast, data, NULL);
01292 break;
01293 case AST_CONTROL_UNHOLD:
01294 ast_moh_stop(ast);
01295 break;
01296 default:
01297 ast_log(LOG_NOTICE, "Don't know how to indicate condition '%d'\n", condition);
01298 res = -1;
01299 }
01300
01301 return res;
01302 }
01303
01304 static int jingle_sendtext(struct ast_channel *chan, const char *text)
01305 {
01306 int res = 0;
01307 struct aji_client *client = NULL;
01308 struct jingle_pvt *p = chan->tech_pvt;
01309
01310
01311 if (!p->parent) {
01312 ast_log(LOG_ERROR, "Parent channel not found\n");
01313 return -1;
01314 }
01315 if (!p->parent->connection) {
01316 ast_log(LOG_ERROR, "XMPP client not found\n");
01317 return -1;
01318 }
01319 client = p->parent->connection;
01320 res = ast_aji_send_chat(client, p->them, text);
01321 return res;
01322 }
01323
01324 static int jingle_digit(struct ast_channel *ast, char digit, unsigned int duration)
01325 {
01326 struct jingle_pvt *p = ast->tech_pvt;
01327 struct jingle *client = p->parent;
01328 iks *iq, *jingle, *dtmf;
01329 char buffer[2] = {digit, '\0'};
01330 iq = iks_new("iq");
01331 jingle = iks_new("jingle");
01332 dtmf = iks_new("dtmf");
01333 if(!iq || !jingle || !dtmf) {
01334 iks_delete(iq);
01335 iks_delete(jingle);
01336 iks_delete(dtmf);
01337 ast_log(LOG_ERROR, "Did not send dtmf do to memory issue\n");
01338 return -1;
01339 }
01340
01341 iks_insert_attrib(iq, "type", "set");
01342 iks_insert_attrib(iq, "to", p->them);
01343 iks_insert_attrib(iq, "from", client->connection->jid->full);
01344 iks_insert_attrib(iq, "id", client->connection->mid);
01345 ast_aji_increment_mid(client->connection->mid);
01346 iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
01347 iks_insert_attrib(jingle, "action", "session-info");
01348 iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them);
01349 iks_insert_attrib(jingle, "sid", p->sid);
01350 iks_insert_attrib(dtmf, "xmlns", JINGLE_DTMF_NS);
01351 iks_insert_attrib(dtmf, "code", buffer);
01352 iks_insert_node(iq, jingle);
01353 iks_insert_node(jingle, dtmf);
01354
01355 ast_mutex_lock(&p->lock);
01356 if (ast->dtmff.frametype == AST_FRAME_DTMF_BEGIN || duration == 0) {
01357 iks_insert_attrib(dtmf, "action", "button-down");
01358 } else if (ast->dtmff.frametype == AST_FRAME_DTMF_END || duration != 0) {
01359 iks_insert_attrib(dtmf, "action", "button-up");
01360 }
01361 ast_aji_send(client->connection, iq);
01362
01363 iks_delete(iq);
01364 iks_delete(jingle);
01365 iks_delete(dtmf);
01366 ast_mutex_unlock(&p->lock);
01367 return 0;
01368 }
01369
01370 static int jingle_digit_begin(struct ast_channel *chan, char digit)
01371 {
01372 return jingle_digit(chan, digit, 0);
01373 }
01374
01375 static int jingle_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
01376 {
01377 return jingle_digit(ast, digit, duration);
01378 }
01379
01380 static int jingle_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
01381 {
01382 ast_log(LOG_NOTICE, "XXX Implement jingle sendhtml XXX\n");
01383
01384 return -1;
01385 }
01386 static int jingle_transmit_invite(struct jingle_pvt *p)
01387 {
01388 struct jingle *aux = NULL;
01389 struct aji_client *client = NULL;
01390 iks *iq, *jingle, *content, *description, *transport;
01391 iks *payload_eg711u, *payload_pcmu;
01392
01393 aux = p->parent;
01394 client = aux->connection;
01395 iq = iks_new("iq");
01396 jingle = iks_new(JINGLE_NODE);
01397 content = iks_new("content");
01398 description = iks_new("description");
01399 transport = iks_new("transport");
01400 payload_pcmu = iks_new("payload-type");
01401 payload_eg711u = iks_new("payload-type");
01402
01403 ast_copy_string(p->audio_content_name, "asterisk-audio-content", sizeof(p->audio_content_name));
01404
01405 iks_insert_attrib(iq, "type", "set");
01406 iks_insert_attrib(iq, "to", p->them);
01407 iks_insert_attrib(iq, "from", client->jid->full);
01408 iks_insert_attrib(iq, "id", client->mid);
01409 ast_aji_increment_mid(client->mid);
01410 iks_insert_attrib(jingle, "action", JINGLE_INITIATE);
01411 iks_insert_attrib(jingle, JINGLE_SID, p->sid);
01412 iks_insert_attrib(jingle, "initiator", client->jid->full);
01413 iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
01414
01415
01416 iks_insert_attrib(content, "creator", "initiator");
01417 iks_insert_attrib(content, "name", p->audio_content_name);
01418 iks_insert_attrib(content, "profile", "RTP/AVP");
01419 iks_insert_attrib(description, "xmlns", JINGLE_AUDIO_RTP_NS);
01420 iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS);
01421 iks_insert_attrib(payload_pcmu, "id", "0");
01422 iks_insert_attrib(payload_pcmu, "name", "PCMU");
01423 iks_insert_attrib(payload_eg711u, "id", "100");
01424 iks_insert_attrib(payload_eg711u, "name", "EG711U");
01425 iks_insert_node(description, payload_pcmu);
01426 iks_insert_node(description, payload_eg711u);
01427 iks_insert_node(content, description);
01428 iks_insert_node(content, transport);
01429 iks_insert_node(jingle, content);
01430 iks_insert_node(iq, jingle);
01431
01432 ast_aji_send(client, iq);
01433
01434 iks_delete(iq);
01435 iks_delete(jingle);
01436 iks_delete(content);
01437 iks_delete(description);
01438 iks_delete(transport);
01439 iks_delete(payload_eg711u);
01440 iks_delete(payload_pcmu);
01441 return 0;
01442 }
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464 static int jingle_call(struct ast_channel *ast, char *dest, int timeout)
01465 {
01466 struct jingle_pvt *p = ast->tech_pvt;
01467
01468 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
01469 ast_log(LOG_WARNING, "jingle_call called on %s, neither down nor reserved\n", ast->name);
01470 return -1;
01471 }
01472
01473 ast_setstate(ast, AST_STATE_RING);
01474 p->jointcapability = p->capability;
01475 if (!p->ringrule) {
01476 ast_copy_string(p->ring, p->parent->connection->mid, sizeof(p->ring));
01477 p->ringrule = iks_filter_add_rule(p->parent->connection->f, jingle_ringing_ack, p,
01478 IKS_RULE_ID, p->ring, IKS_RULE_DONE);
01479 } else
01480 ast_log(LOG_WARNING, "Whoa, already have a ring rule!\n");
01481
01482 jingle_transmit_invite(p);
01483 jingle_create_candidates(p->parent, p, p->sid, p->them);
01484
01485 return 0;
01486 }
01487
01488
01489 static int jingle_hangup(struct ast_channel *ast)
01490 {
01491 struct jingle_pvt *p = ast->tech_pvt;
01492 struct jingle *client;
01493
01494 ast_mutex_lock(&p->lock);
01495 client = p->parent;
01496 p->owner = NULL;
01497 ast->tech_pvt = NULL;
01498 if (!p->alreadygone)
01499 jingle_action(client, p, JINGLE_TERMINATE);
01500 ast_mutex_unlock(&p->lock);
01501
01502 jingle_free_pvt(client, p);
01503
01504 return 0;
01505 }
01506
01507
01508 static struct ast_channel *jingle_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
01509 {
01510 struct jingle_pvt *p = NULL;
01511 struct jingle *client = NULL;
01512 char *sender = NULL, *to = NULL, *s = NULL;
01513 struct ast_channel *chan = NULL;
01514
01515 if (data) {
01516 s = ast_strdupa(data);
01517 if (s) {
01518 sender = strsep(&s, "/");
01519 if (sender && (sender[0] != '\0'))
01520 to = strsep(&s, "/");
01521 if (!to) {
01522 ast_log(LOG_ERROR, "Bad arguments in Jingle Dialstring: %s\n", (char*) data);
01523 return NULL;
01524 }
01525 }
01526 }
01527
01528 client = find_jingle(to, sender);
01529 if (!client) {
01530 ast_log(LOG_WARNING, "Could not find recipient.\n");
01531 return NULL;
01532 }
01533 if (!strcasecmp(client->name, "guest")){
01534
01535
01536 if (client->connection) {
01537 ASTOBJ_UNREF(client->connection, ast_aji_client_destroy);
01538 }
01539 client->connection = ast_aji_get_client(sender);
01540 if (!client->connection) {
01541 ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", sender);
01542 return NULL;
01543 }
01544 }
01545
01546 ASTOBJ_WRLOCK(client);
01547 p = jingle_alloc(client, to, NULL);
01548 if (p)
01549 chan = jingle_new(client, p, AST_STATE_DOWN, to, requestor ? requestor->linkedid : NULL);
01550 ASTOBJ_UNLOCK(client);
01551
01552 return chan;
01553 }
01554
01555
01556 static char *jingle_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01557 {
01558 #define FORMAT "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n"
01559 struct jingle_pvt *p;
01560 struct ast_channel *chan;
01561 int numchans = 0;
01562 char them[AJI_MAX_JIDLEN];
01563 char *jid = NULL;
01564 char *resource = NULL;
01565
01566 switch (cmd) {
01567 case CLI_INIT:
01568 e->command = "jingle show channels";
01569 e->usage =
01570 "Usage: jingle show channels\n"
01571 " Shows current state of the Jingle channels.\n";
01572 return NULL;
01573 case CLI_GENERATE:
01574 return NULL;
01575 }
01576
01577 if (a->argc != 3)
01578 return CLI_SHOWUSAGE;
01579
01580 ast_mutex_lock(&jinglelock);
01581 ast_cli(a->fd, FORMAT, "Channel", "Jabber ID", "Resource", "Read", "Write");
01582 ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, {
01583 ASTOBJ_WRLOCK(iterator);
01584 p = iterator->p;
01585 while(p) {
01586 chan = p->owner;
01587 ast_copy_string(them, p->them, sizeof(them));
01588 jid = them;
01589 resource = strchr(them, '/');
01590 if (!resource)
01591 resource = "None";
01592 else {
01593 *resource = '\0';
01594 resource ++;
01595 }
01596 if (chan)
01597 ast_cli(a->fd, FORMAT,
01598 chan->name,
01599 jid,
01600 resource,
01601 ast_getformatname(chan->readformat),
01602 ast_getformatname(chan->writeformat)
01603 );
01604 else
01605 ast_log(LOG_WARNING, "No available channel\n");
01606 numchans ++;
01607 p = p->next;
01608 }
01609 ASTOBJ_UNLOCK(iterator);
01610 });
01611
01612 ast_mutex_unlock(&jinglelock);
01613
01614 ast_cli(a->fd, "%d active jingle channel%s\n", numchans, (numchans != 1) ? "s" : "");
01615 return CLI_SUCCESS;
01616 #undef FORMAT
01617 }
01618
01619
01620 static char *jingle_do_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01621 {
01622 switch (cmd) {
01623 case CLI_INIT:
01624 e->command = "jingle reload";
01625 e->usage =
01626 "Usage: jingle reload\n"
01627 " Reload jingle channel driver.\n";
01628 return NULL;
01629 case CLI_GENERATE:
01630 return NULL;
01631 }
01632
01633 return CLI_SUCCESS;
01634 }
01635
01636 static int jingle_parser(void *data, ikspak *pak)
01637 {
01638 struct jingle *client = ASTOBJ_REF((struct jingle *) data);
01639 ast_log(LOG_NOTICE, "Filter matched\n");
01640
01641 if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INITIATE)) {
01642
01643 jingle_newcall(client, pak);
01644 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_NEGOTIATE)) {
01645 ast_debug(3, "About to add candidate!\n");
01646 jingle_add_candidate(client, pak);
01647 ast_debug(3, "Candidate Added!\n");
01648 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_ACCEPT)) {
01649 jingle_is_answered(client, pak);
01650 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INFO)) {
01651 jingle_handle_dtmf(client, pak);
01652 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_TERMINATE)) {
01653 jingle_hangup_farend(client, pak);
01654 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", "reject")) {
01655 jingle_hangup_farend(client, pak);
01656 }
01657 ASTOBJ_UNREF(client, jingle_member_destroy);
01658 return IKS_FILTER_EAT;
01659 }
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709 static int jingle_create_member(char *label, struct ast_variable *var, int allowguest,
01710 struct ast_codec_pref prefs, char *context,
01711 struct jingle *member)
01712 {
01713 struct aji_client *client;
01714
01715 if (!member)
01716 ast_log(LOG_WARNING, "Out of memory.\n");
01717
01718 ast_copy_string(member->name, label, sizeof(member->name));
01719 ast_copy_string(member->user, label, sizeof(member->user));
01720 ast_copy_string(member->context, context, sizeof(member->context));
01721 member->allowguest = allowguest;
01722 member->prefs = prefs;
01723 while (var) {
01724 #if 0
01725 struct jingle_candidate *candidate = NULL;
01726 #endif
01727 if (!strcasecmp(var->name, "username"))
01728 ast_copy_string(member->user, var->value, sizeof(member->user));
01729 else if (!strcasecmp(var->name, "disallow"))
01730 ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 0);
01731 else if (!strcasecmp(var->name, "allow"))
01732 ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 1);
01733 else if (!strcasecmp(var->name, "context"))
01734 ast_copy_string(member->context, var->value, sizeof(member->context));
01735 #if 0
01736 else if (!strcasecmp(var->name, "candidate")) {
01737 candidate = jingle_create_candidate(var->value);
01738 if (candidate) {
01739 candidate->next = member->ourcandidates;
01740 member->ourcandidates = candidate;
01741 }
01742 }
01743 #endif
01744 else if (!strcasecmp(var->name, "connection")) {
01745 if ((client = ast_aji_get_client(var->value))) {
01746 member->connection = client;
01747 iks_filter_add_rule(client->f, jingle_parser, member,
01748 IKS_RULE_TYPE, IKS_PAK_IQ,
01749 IKS_RULE_FROM_PARTIAL, member->user,
01750 IKS_RULE_NS, JINGLE_NS,
01751 IKS_RULE_DONE);
01752 } else {
01753 ast_log(LOG_ERROR, "connection referenced not found!\n");
01754 return 0;
01755 }
01756 }
01757 var = var->next;
01758 }
01759 if (member->connection && member->user)
01760 member->buddy = ASTOBJ_CONTAINER_FIND(&member->connection->buddies, member->user);
01761 else {
01762 ast_log(LOG_ERROR, "No Connection or Username!\n");
01763 }
01764 return 1;
01765 }
01766
01767 static int jingle_load_config(void)
01768 {
01769 char *cat = NULL;
01770 struct ast_config *cfg = NULL;
01771 char context[100];
01772 int allowguest = 1;
01773 struct ast_variable *var;
01774 struct jingle *member;
01775 struct hostent *hp;
01776 struct ast_hostent ahp;
01777 struct ast_codec_pref prefs;
01778 struct aji_client_container *clients;
01779 struct jingle_candidate *global_candidates = NULL;
01780 struct ast_flags config_flags = { 0 };
01781
01782 cfg = ast_config_load(JINGLE_CONFIG, config_flags);
01783 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
01784 return 0;
01785 }
01786
01787
01788 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
01789
01790 cat = ast_category_browse(cfg, NULL);
01791 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
01792
01793 if (!ast_jb_read_conf(&global_jbconf, var->name, var->value))
01794 continue;
01795
01796 if (!strcasecmp(var->name, "allowguest"))
01797 allowguest =
01798 (ast_true(ast_variable_retrieve(cfg, "general", "allowguest"))) ? 1 : 0;
01799 else if (!strcasecmp(var->name, "disallow"))
01800 ast_parse_allow_disallow(&prefs, &global_capability, var->value, 0);
01801 else if (!strcasecmp(var->name, "allow"))
01802 ast_parse_allow_disallow(&prefs, &global_capability, var->value, 1);
01803 else if (!strcasecmp(var->name, "context"))
01804 ast_copy_string(context, var->value, sizeof(context));
01805 else if (!strcasecmp(var->name, "externip"))
01806 ast_copy_string(externip, var->value, sizeof(externip));
01807 else if (!strcasecmp(var->name, "bindaddr")) {
01808 if (!(hp = ast_gethostbyname(var->value, &ahp))) {
01809 ast_log(LOG_WARNING, "Invalid address: %s\n", var->value);
01810 } else {
01811 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
01812 }
01813 }
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824 }
01825 while (cat) {
01826 if (strcasecmp(cat, "general")) {
01827 var = ast_variable_browse(cfg, cat);
01828 member = ast_calloc(1, sizeof(*member));
01829 ASTOBJ_INIT(member);
01830 ASTOBJ_WRLOCK(member);
01831 if (!strcasecmp(cat, "guest")) {
01832 ast_copy_string(member->name, "guest", sizeof(member->name));
01833 ast_copy_string(member->user, "guest", sizeof(member->user));
01834 ast_copy_string(member->context, context, sizeof(member->context));
01835 member->allowguest = allowguest;
01836 member->prefs = prefs;
01837 while (var) {
01838 if (!strcasecmp(var->name, "disallow"))
01839 ast_parse_allow_disallow(&member->prefs, &member->capability,
01840 var->value, 0);
01841 else if (!strcasecmp(var->name, "allow"))
01842 ast_parse_allow_disallow(&member->prefs, &member->capability,
01843 var->value, 1);
01844 else if (!strcasecmp(var->name, "context"))
01845 ast_copy_string(member->context, var->value,
01846 sizeof(member->context));
01847 else if (!strcasecmp(var->name, "parkinglot"))
01848 ast_copy_string(member->parkinglot, var->value,
01849 sizeof(member->parkinglot));
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860 var = var->next;
01861 }
01862 ASTOBJ_UNLOCK(member);
01863 clients = ast_aji_get_clients();
01864 if (clients) {
01865 ASTOBJ_CONTAINER_TRAVERSE(clients, 1, {
01866 ASTOBJ_WRLOCK(iterator);
01867 ASTOBJ_WRLOCK(member);
01868 if (member->connection) {
01869 ASTOBJ_UNREF(member->connection, ast_aji_client_destroy);
01870 }
01871 member->connection = NULL;
01872 iks_filter_add_rule(iterator->f, jingle_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, JINGLE_NS, IKS_RULE_DONE);
01873 iks_filter_add_rule(iterator->f, jingle_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, JINGLE_DTMF_NS, IKS_RULE_DONE);
01874 ASTOBJ_UNLOCK(member);
01875 ASTOBJ_UNLOCK(iterator);
01876 });
01877 ASTOBJ_CONTAINER_LINK(&jingle_list, member);
01878 } else {
01879 ASTOBJ_UNLOCK(member);
01880 ASTOBJ_UNREF(member, jingle_member_destroy);
01881 }
01882 } else {
01883 ASTOBJ_UNLOCK(member);
01884 if (jingle_create_member(cat, var, allowguest, prefs, context, member))
01885 ASTOBJ_CONTAINER_LINK(&jingle_list, member);
01886 ASTOBJ_UNREF(member, jingle_member_destroy);
01887 }
01888 }
01889 cat = ast_category_browse(cfg, cat);
01890 }
01891 jingle_free_candidates(global_candidates);
01892 return 1;
01893 }
01894
01895
01896 static int load_module(void)
01897 {
01898 struct ast_sockaddr ourip_tmp;
01899 struct ast_sockaddr bindaddr_tmp;
01900
01901 char *jabber_loaded = ast_module_helper("", "res_jabber.so", 0, 0, 0, 0);
01902 free(jabber_loaded);
01903 if (!jabber_loaded) {
01904
01905 jabber_loaded = ast_module_helper("", "res_jabber", 0, 0, 0, 0);
01906 free(jabber_loaded);
01907 if (!jabber_loaded) {
01908 ast_log(LOG_ERROR, "chan_jingle.so depends upon res_jabber.so\n");
01909 return AST_MODULE_LOAD_DECLINE;
01910 }
01911 }
01912
01913 ASTOBJ_CONTAINER_INIT(&jingle_list);
01914 if (!jingle_load_config()) {
01915 ast_log(LOG_ERROR, "Unable to read config file %s. Not loading module.\n", JINGLE_CONFIG);
01916 return AST_MODULE_LOAD_DECLINE;
01917 }
01918
01919 sched = sched_context_create();
01920 if (!sched) {
01921 ast_log(LOG_WARNING, "Unable to create schedule context\n");
01922 }
01923
01924 io = io_context_create();
01925 if (!io) {
01926 ast_log(LOG_WARNING, "Unable to create I/O context\n");
01927 }
01928
01929 ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
01930 if (ast_find_ourip(&ourip_tmp, &bindaddr_tmp, AF_INET)) {
01931 ast_log(LOG_WARNING, "Unable to get own IP address, Jingle disabled\n");
01932 return 0;
01933 }
01934 __ourip.s_addr = htonl(ast_sockaddr_ipv4(&ourip_tmp));
01935
01936 ast_rtp_glue_register(&jingle_rtp_glue);
01937 ast_cli_register_multiple(jingle_cli, ARRAY_LEN(jingle_cli));
01938
01939 if (ast_channel_register(&jingle_tech)) {
01940 ast_log(LOG_ERROR, "Unable to register channel class %s\n", channel_type);
01941 return -1;
01942 }
01943 return 0;
01944 }
01945
01946
01947 static int reload(void)
01948 {
01949 return 0;
01950 }
01951
01952
01953 static int unload_module(void)
01954 {
01955 struct jingle_pvt *privates = NULL;
01956 ast_cli_unregister_multiple(jingle_cli, ARRAY_LEN(jingle_cli));
01957
01958 ast_channel_unregister(&jingle_tech);
01959 ast_rtp_glue_unregister(&jingle_rtp_glue);
01960
01961 if (!ast_mutex_lock(&jinglelock)) {
01962
01963 ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, {
01964 ASTOBJ_WRLOCK(iterator);
01965 privates = iterator->p;
01966 while(privates) {
01967 if (privates->owner)
01968 ast_softhangup(privates->owner, AST_SOFTHANGUP_APPUNLOAD);
01969 privates = privates->next;
01970 }
01971 iterator->p = NULL;
01972 ASTOBJ_UNLOCK(iterator);
01973 });
01974 ast_mutex_unlock(&jinglelock);
01975 } else {
01976 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01977 return -1;
01978 }
01979 ASTOBJ_CONTAINER_DESTROYALL(&jingle_list, jingle_member_destroy);
01980 ASTOBJ_CONTAINER_DESTROY(&jingle_list);
01981 return 0;
01982 }
01983
01984 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Jingle Channel Driver",
01985 .load = load_module,
01986 .unload = unload_module,
01987 .reload = reload,
01988 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
01989 );