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: 328446 $")
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;
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 } else if (client->buddy)
00754 resources = client->buddy->resources;
00755 while (resources) {
00756 if (resources->cap->jingle) {
00757 break;
00758 }
00759 resources = resources->next;
00760 }
00761 if (resources)
00762 snprintf(idroster, sizeof(idroster), "%s/%s", from, resources->resource);
00763 else {
00764 ast_log(LOG_ERROR, "no jingle capable clients to talk to.\n");
00765 return NULL;
00766 }
00767 }
00768 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
00769 return NULL;
00770 }
00771
00772 memcpy(&tmp->prefs, &client->prefs, sizeof(tmp->prefs));
00773
00774 if (sid) {
00775 ast_copy_string(tmp->sid, sid, sizeof(tmp->sid));
00776 ast_copy_string(tmp->them, from, sizeof(tmp->them));
00777 } else {
00778 snprintf(tmp->sid, sizeof(tmp->sid), "%08lx%08lx", ast_random(), ast_random());
00779 ast_copy_string(tmp->them, idroster, sizeof(tmp->them));
00780 tmp->initiator = 1;
00781 }
00782 ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
00783 tmp->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL);
00784 tmp->parent = client;
00785 if (!tmp->rtp) {
00786 ast_log(LOG_WARNING, "Out of RTP sessions?\n");
00787 ast_free(tmp);
00788 return NULL;
00789 }
00790 ast_copy_string(tmp->exten, "s", sizeof(tmp->exten));
00791 ast_mutex_init(&tmp->lock);
00792 ast_mutex_lock(&jinglelock);
00793 tmp->next = client->p;
00794 client->p = tmp;
00795 ast_mutex_unlock(&jinglelock);
00796 return tmp;
00797 }
00798
00799
00800 static struct ast_channel *jingle_new(struct jingle *client, struct jingle_pvt *i, int state, const char *title, const char *linkedid)
00801 {
00802 struct ast_channel *tmp;
00803 int fmt;
00804 int what;
00805 const char *str;
00806
00807 if (title)
00808 str = title;
00809 else
00810 str = i->them;
00811 tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", "", "", linkedid, 0, "Jingle/%s-%04lx", str, ast_random() & 0xffff);
00812 if (!tmp) {
00813 ast_log(LOG_WARNING, "Unable to allocate Jingle channel structure!\n");
00814 return NULL;
00815 }
00816 tmp->tech = &jingle_tech;
00817
00818
00819
00820 if (i->jointcapability)
00821 what = i->jointcapability;
00822 else if (i->capability)
00823 what = i->capability;
00824 else
00825 what = global_capability;
00826
00827
00828 if (i->rtp)
00829 ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(i->rtp), i->rtp, &i->prefs);
00830
00831 tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | (i->jointcapability & AST_FORMAT_VIDEO_MASK);
00832 fmt = ast_best_codec(tmp->nativeformats);
00833
00834 if (i->rtp) {
00835 ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(i->rtp, 0));
00836 ast_channel_set_fd(tmp, 1, ast_rtp_instance_fd(i->rtp, 1));
00837 }
00838 if (i->vrtp) {
00839 ast_channel_set_fd(tmp, 2, ast_rtp_instance_fd(i->vrtp, 0));
00840 ast_channel_set_fd(tmp, 3, ast_rtp_instance_fd(i->vrtp, 1));
00841 }
00842 if (state == AST_STATE_RING)
00843 tmp->rings = 1;
00844 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
00845 tmp->writeformat = fmt;
00846 tmp->rawwriteformat = fmt;
00847 tmp->readformat = fmt;
00848 tmp->rawreadformat = fmt;
00849 tmp->tech_pvt = i;
00850
00851 tmp->callgroup = client->callgroup;
00852 tmp->pickupgroup = client->pickupgroup;
00853 tmp->caller.id.name.presentation = client->callingpres;
00854 tmp->caller.id.number.presentation = client->callingpres;
00855 if (!ast_strlen_zero(client->accountcode))
00856 ast_string_field_set(tmp, accountcode, client->accountcode);
00857 if (client->amaflags)
00858 tmp->amaflags = client->amaflags;
00859 if (!ast_strlen_zero(client->language))
00860 ast_string_field_set(tmp, language, client->language);
00861 if (!ast_strlen_zero(client->musicclass))
00862 ast_string_field_set(tmp, musicclass, client->musicclass);
00863 i->owner = tmp;
00864 ast_copy_string(tmp->context, client->context, sizeof(tmp->context));
00865 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
00866
00867
00868 if (!ast_strlen_zero(i->cid_num)) {
00869 tmp->caller.ani.number.valid = 1;
00870 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
00871 }
00872 if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s")) {
00873 tmp->dialed.number.str = ast_strdup(i->exten);
00874 }
00875 tmp->priority = 1;
00876 if (i->rtp)
00877 ast_jb_configure(tmp, &global_jbconf);
00878 if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) {
00879 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
00880 tmp->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
00881 ast_hangup(tmp);
00882 tmp = NULL;
00883 }
00884
00885 return tmp;
00886 }
00887
00888 static int jingle_action(struct jingle *client, struct jingle_pvt *p, const char *action)
00889 {
00890 iks *iq, *jingle = NULL;
00891 int res = -1;
00892
00893 iq = iks_new("iq");
00894 jingle = iks_new("jingle");
00895
00896 if (iq) {
00897 iks_insert_attrib(iq, "type", "set");
00898 iks_insert_attrib(iq, "from", client->connection->jid->full);
00899 iks_insert_attrib(iq, "to", p->them);
00900 iks_insert_attrib(iq, "id", client->connection->mid);
00901 ast_aji_increment_mid(client->connection->mid);
00902 if (jingle) {
00903 iks_insert_attrib(jingle, "action", action);
00904 iks_insert_attrib(jingle, JINGLE_SID, p->sid);
00905 iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them);
00906 iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
00907
00908 iks_insert_node(iq, jingle);
00909
00910 ast_aji_send(client->connection, iq);
00911 res = 0;
00912 }
00913 }
00914
00915 iks_delete(jingle);
00916 iks_delete(iq);
00917
00918 return res;
00919 }
00920
00921 static void jingle_free_candidates(struct jingle_candidate *candidate)
00922 {
00923 struct jingle_candidate *last;
00924 while (candidate) {
00925 last = candidate;
00926 candidate = candidate->next;
00927 ast_free(last);
00928 }
00929 }
00930
00931 static void jingle_free_pvt(struct jingle *client, struct jingle_pvt *p)
00932 {
00933 struct jingle_pvt *cur, *prev = NULL;
00934 cur = client->p;
00935 while (cur) {
00936 if (cur == p) {
00937 if (prev)
00938 prev->next = p->next;
00939 else
00940 client->p = p->next;
00941 break;
00942 }
00943 prev = cur;
00944 cur = cur->next;
00945 }
00946 if (p->ringrule)
00947 iks_filter_remove_rule(p->parent->connection->f, p->ringrule);
00948 if (p->owner)
00949 ast_log(LOG_WARNING, "Uh oh, there's an owner, this is going to be messy.\n");
00950 if (p->rtp)
00951 ast_rtp_instance_destroy(p->rtp);
00952 if (p->vrtp)
00953 ast_rtp_instance_destroy(p->vrtp);
00954 jingle_free_candidates(p->theircandidates);
00955 ast_free(p);
00956 }
00957
00958
00959 static int jingle_newcall(struct jingle *client, ikspak *pak)
00960 {
00961 struct jingle_pvt *p, *tmp = client->p;
00962 struct ast_channel *chan;
00963 int res;
00964 iks *codec, *content, *description;
00965 char *from = NULL;
00966
00967
00968 from = iks_find_attrib(pak->x,"to");
00969 if(!from)
00970 from = client->connection->jid->full;
00971
00972 while (tmp) {
00973 if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) {
00974 ast_log(LOG_NOTICE, "Ignoring duplicate call setup on SID %s\n", tmp->sid);
00975 jingle_response(client, pak, "out-of-order", NULL);
00976 return -1;
00977 }
00978 tmp = tmp->next;
00979 }
00980
00981 if (!strcasecmp(client->name, "guest")){
00982
00983
00984 client->connection = ast_aji_get_client(from);
00985 if (!client->connection) {
00986 ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", from);
00987 return -1;
00988 }
00989 }
00990
00991 p = jingle_alloc(client, pak->from->partial, iks_find_attrib(pak->query, JINGLE_SID));
00992 if (!p) {
00993 ast_log(LOG_WARNING, "Unable to allocate jingle structure!\n");
00994 return -1;
00995 }
00996 chan = jingle_new(client, p, AST_STATE_DOWN, pak->from->user, NULL);
00997 if (!chan) {
00998 jingle_free_pvt(client, p);
00999 return -1;
01000 }
01001 ast_mutex_lock(&p->lock);
01002 ast_copy_string(p->them, pak->from->full, sizeof(p->them));
01003 if (iks_find_attrib(pak->query, JINGLE_SID)) {
01004 ast_copy_string(p->sid, iks_find_attrib(pak->query, JINGLE_SID),
01005 sizeof(p->sid));
01006 }
01007
01008
01009 content = iks_child(iks_child(pak->x));
01010 while (content) {
01011 description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_AUDIO_RTP_NS);
01012 if (description) {
01013
01014 codec = iks_child(iks_child(content));
01015 ast_copy_string(p->audio_content_name, iks_find_attrib(content, "name"), sizeof(p->audio_content_name));
01016
01017 while (codec) {
01018 ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")));
01019 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);
01020 codec = iks_next(codec);
01021 }
01022 }
01023
01024 description = NULL;
01025 codec = NULL;
01026
01027 description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_VIDEO_RTP_NS);
01028 if (description) {
01029
01030 codec = iks_child(iks_child(content));
01031 ast_copy_string(p->video_content_name, iks_find_attrib(content, "name"), sizeof(p->video_content_name));
01032
01033 while (codec) {
01034 ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")));
01035 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);
01036 codec = iks_next(codec);
01037 }
01038 }
01039
01040 content = iks_next(content);
01041 }
01042
01043 ast_mutex_unlock(&p->lock);
01044 ast_setstate(chan, AST_STATE_RING);
01045 res = ast_pbx_start(chan);
01046
01047 switch (res) {
01048 case AST_PBX_FAILED:
01049 ast_log(LOG_WARNING, "Failed to start PBX :(\n");
01050 jingle_response(client, pak, "service-unavailable", NULL);
01051 break;
01052 case AST_PBX_CALL_LIMIT:
01053 ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n");
01054 jingle_response(client, pak, "service-unavailable", NULL);
01055 break;
01056 case AST_PBX_SUCCESS:
01057 jingle_response(client, pak, NULL, NULL);
01058 jingle_create_candidates(client, p,
01059 iks_find_attrib(pak->query, JINGLE_SID),
01060 iks_find_attrib(pak->x, "from"));
01061
01062 break;
01063 }
01064
01065 return 1;
01066 }
01067
01068 static int jingle_update_stun(struct jingle *client, struct jingle_pvt *p)
01069 {
01070 struct jingle_candidate *tmp;
01071 struct hostent *hp;
01072 struct ast_hostent ahp;
01073 struct sockaddr_in sin;
01074 struct ast_sockaddr sin_tmp;
01075
01076 if (time(NULL) == p->laststun)
01077 return 0;
01078
01079 tmp = p->theircandidates;
01080 p->laststun = time(NULL);
01081 while (tmp) {
01082 char username[256];
01083 hp = ast_gethostbyname(tmp->ip, &ahp);
01084 sin.sin_family = AF_INET;
01085 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
01086 sin.sin_port = htons(tmp->port);
01087 snprintf(username, sizeof(username), "%s:%s", tmp->ufrag, p->ourcandidates->ufrag);
01088
01089 ast_sockaddr_from_sin(&sin_tmp, &sin);
01090 ast_rtp_instance_stun_request(p->rtp, &sin_tmp, username);
01091 tmp = tmp->next;
01092 }
01093 return 1;
01094 }
01095
01096 static int jingle_add_candidate(struct jingle *client, ikspak *pak)
01097 {
01098 struct jingle_pvt *p = NULL, *tmp = NULL;
01099 struct aji_client *c = client->connection;
01100 struct jingle_candidate *newcandidate = NULL;
01101 iks *traversenodes = NULL, *receipt = NULL;
01102
01103 for (tmp = client->p; tmp; tmp = tmp->next) {
01104 if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) {
01105 p = tmp;
01106 break;
01107 }
01108 }
01109
01110 if (!p)
01111 return -1;
01112
01113 traversenodes = pak->query;
01114 while(traversenodes) {
01115 if(!strcasecmp(iks_name(traversenodes), "jingle")) {
01116 traversenodes = iks_child(traversenodes);
01117 continue;
01118 }
01119 if(!strcasecmp(iks_name(traversenodes), "content")) {
01120 traversenodes = iks_child(traversenodes);
01121 continue;
01122 }
01123 if(!strcasecmp(iks_name(traversenodes), "transport")) {
01124 traversenodes = iks_child(traversenodes);
01125 continue;
01126 }
01127
01128 if(!strcasecmp(iks_name(traversenodes), "candidate")) {
01129 newcandidate = ast_calloc(1, sizeof(*newcandidate));
01130 if (!newcandidate)
01131 return 0;
01132 ast_copy_string(newcandidate->ip, iks_find_attrib(traversenodes, "ip"), sizeof(newcandidate->ip));
01133 newcandidate->port = atoi(iks_find_attrib(traversenodes, "port"));
01134 ast_copy_string(newcandidate->password, iks_find_attrib(traversenodes, "pwd"), sizeof(newcandidate->password));
01135 if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "udp"))
01136 newcandidate->protocol = AJI_PROTOCOL_UDP;
01137 else if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "ssltcp"))
01138 newcandidate->protocol = AJI_PROTOCOL_SSLTCP;
01139
01140 if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "host"))
01141 newcandidate->type = AJI_CONNECT_HOST;
01142 else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "prflx"))
01143 newcandidate->type = AJI_CONNECT_PRFLX;
01144 else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "relay"))
01145 newcandidate->type = AJI_CONNECT_RELAY;
01146 else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "srflx"))
01147 newcandidate->type = AJI_CONNECT_SRFLX;
01148
01149 newcandidate->network = atoi(iks_find_attrib(traversenodes, "network"));
01150 newcandidate->generation = atoi(iks_find_attrib(traversenodes, "generation"));
01151 newcandidate->next = NULL;
01152
01153 newcandidate->next = p->theircandidates;
01154 p->theircandidates = newcandidate;
01155 p->laststun = 0;
01156 jingle_update_stun(p->parent, p);
01157 newcandidate = NULL;
01158 }
01159 traversenodes = iks_next(traversenodes);
01160 }
01161
01162 receipt = iks_new("iq");
01163 iks_insert_attrib(receipt, "type", "result");
01164 iks_insert_attrib(receipt, "from", c->jid->full);
01165 iks_insert_attrib(receipt, "to", iks_find_attrib(pak->x, "from"));
01166 iks_insert_attrib(receipt, "id", iks_find_attrib(pak->x, "id"));
01167 ast_aji_send(c, receipt);
01168
01169 iks_delete(receipt);
01170
01171 return 1;
01172 }
01173
01174 static struct ast_frame *jingle_rtp_read(struct ast_channel *ast, struct jingle_pvt *p)
01175 {
01176 struct ast_frame *f;
01177
01178 if (!p->rtp)
01179 return &ast_null_frame;
01180 f = ast_rtp_instance_read(p->rtp, 0);
01181 jingle_update_stun(p->parent, p);
01182 if (p->owner) {
01183
01184 if (f->frametype == AST_FRAME_VOICE) {
01185 if (f->subclass.codec != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) {
01186 ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(f->subclass.codec));
01187 p->owner->nativeformats =
01188 (p->owner->nativeformats & AST_FORMAT_VIDEO_MASK) | f->subclass.codec;
01189 ast_set_read_format(p->owner, p->owner->readformat);
01190 ast_set_write_format(p->owner, p->owner->writeformat);
01191 }
01192
01193
01194
01195
01196
01197 }
01198 }
01199 return f;
01200 }
01201
01202 static struct ast_frame *jingle_read(struct ast_channel *ast)
01203 {
01204 struct ast_frame *fr;
01205 struct jingle_pvt *p = ast->tech_pvt;
01206
01207 ast_mutex_lock(&p->lock);
01208 fr = jingle_rtp_read(ast, p);
01209 ast_mutex_unlock(&p->lock);
01210 return fr;
01211 }
01212
01213
01214 static int jingle_write(struct ast_channel *ast, struct ast_frame *frame)
01215 {
01216 struct jingle_pvt *p = ast->tech_pvt;
01217 int res = 0;
01218 char buf[256];
01219
01220 switch (frame->frametype) {
01221 case AST_FRAME_VOICE:
01222 if (!(frame->subclass.codec & ast->nativeformats)) {
01223 ast_log(LOG_WARNING,
01224 "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
01225 ast_getformatname(frame->subclass.codec),
01226 ast_getformatname_multiple(buf, sizeof(buf), ast->nativeformats),
01227 ast_getformatname(ast->readformat),
01228 ast_getformatname(ast->writeformat));
01229 return 0;
01230 }
01231 if (p) {
01232 ast_mutex_lock(&p->lock);
01233 if (p->rtp) {
01234 res = ast_rtp_instance_write(p->rtp, frame);
01235 }
01236 ast_mutex_unlock(&p->lock);
01237 }
01238 break;
01239 case AST_FRAME_VIDEO:
01240 if (p) {
01241 ast_mutex_lock(&p->lock);
01242 if (p->vrtp) {
01243 res = ast_rtp_instance_write(p->vrtp, frame);
01244 }
01245 ast_mutex_unlock(&p->lock);
01246 }
01247 break;
01248 case AST_FRAME_IMAGE:
01249 return 0;
01250 break;
01251 default:
01252 ast_log(LOG_WARNING, "Can't send %d type frames with Jingle write\n",
01253 frame->frametype);
01254 return 0;
01255 }
01256
01257 return res;
01258 }
01259
01260 static int jingle_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
01261 {
01262 struct jingle_pvt *p = newchan->tech_pvt;
01263 ast_mutex_lock(&p->lock);
01264
01265 if ((p->owner != oldchan)) {
01266 ast_mutex_unlock(&p->lock);
01267 return -1;
01268 }
01269 if (p->owner == oldchan)
01270 p->owner = newchan;
01271 ast_mutex_unlock(&p->lock);
01272 return 0;
01273 }
01274
01275 static int jingle_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
01276 {
01277 int res = 0;
01278
01279 switch (condition) {
01280 case AST_CONTROL_HOLD:
01281 ast_moh_start(ast, data, NULL);
01282 break;
01283 case AST_CONTROL_UNHOLD:
01284 ast_moh_stop(ast);
01285 break;
01286 default:
01287 ast_log(LOG_NOTICE, "Don't know how to indicate condition '%d'\n", condition);
01288 res = -1;
01289 }
01290
01291 return res;
01292 }
01293
01294 static int jingle_sendtext(struct ast_channel *chan, const char *text)
01295 {
01296 int res = 0;
01297 struct aji_client *client = NULL;
01298 struct jingle_pvt *p = chan->tech_pvt;
01299
01300
01301 if (!p->parent) {
01302 ast_log(LOG_ERROR, "Parent channel not found\n");
01303 return -1;
01304 }
01305 if (!p->parent->connection) {
01306 ast_log(LOG_ERROR, "XMPP client not found\n");
01307 return -1;
01308 }
01309 client = p->parent->connection;
01310 res = ast_aji_send_chat(client, p->them, text);
01311 return res;
01312 }
01313
01314 static int jingle_digit(struct ast_channel *ast, char digit, unsigned int duration)
01315 {
01316 struct jingle_pvt *p = ast->tech_pvt;
01317 struct jingle *client = p->parent;
01318 iks *iq, *jingle, *dtmf;
01319 char buffer[2] = {digit, '\0'};
01320 iq = iks_new("iq");
01321 jingle = iks_new("jingle");
01322 dtmf = iks_new("dtmf");
01323 if(!iq || !jingle || !dtmf) {
01324 iks_delete(iq);
01325 iks_delete(jingle);
01326 iks_delete(dtmf);
01327 ast_log(LOG_ERROR, "Did not send dtmf do to memory issue\n");
01328 return -1;
01329 }
01330
01331 iks_insert_attrib(iq, "type", "set");
01332 iks_insert_attrib(iq, "to", p->them);
01333 iks_insert_attrib(iq, "from", client->connection->jid->full);
01334 iks_insert_attrib(iq, "id", client->connection->mid);
01335 ast_aji_increment_mid(client->connection->mid);
01336 iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
01337 iks_insert_attrib(jingle, "action", "session-info");
01338 iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them);
01339 iks_insert_attrib(jingle, "sid", p->sid);
01340 iks_insert_attrib(dtmf, "xmlns", JINGLE_DTMF_NS);
01341 iks_insert_attrib(dtmf, "code", buffer);
01342 iks_insert_node(iq, jingle);
01343 iks_insert_node(jingle, dtmf);
01344
01345 ast_mutex_lock(&p->lock);
01346 if (ast->dtmff.frametype == AST_FRAME_DTMF_BEGIN || duration == 0) {
01347 iks_insert_attrib(dtmf, "action", "button-down");
01348 } else if (ast->dtmff.frametype == AST_FRAME_DTMF_END || duration != 0) {
01349 iks_insert_attrib(dtmf, "action", "button-up");
01350 }
01351 ast_aji_send(client->connection, iq);
01352
01353 iks_delete(iq);
01354 iks_delete(jingle);
01355 iks_delete(dtmf);
01356 ast_mutex_unlock(&p->lock);
01357 return 0;
01358 }
01359
01360 static int jingle_digit_begin(struct ast_channel *chan, char digit)
01361 {
01362 return jingle_digit(chan, digit, 0);
01363 }
01364
01365 static int jingle_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
01366 {
01367 return jingle_digit(ast, digit, duration);
01368 }
01369
01370 static int jingle_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
01371 {
01372 ast_log(LOG_NOTICE, "XXX Implement jingle sendhtml XXX\n");
01373
01374 return -1;
01375 }
01376 static int jingle_transmit_invite(struct jingle_pvt *p)
01377 {
01378 struct jingle *aux = NULL;
01379 struct aji_client *client = NULL;
01380 iks *iq, *jingle, *content, *description, *transport;
01381 iks *payload_eg711u, *payload_pcmu;
01382
01383 aux = p->parent;
01384 client = aux->connection;
01385 iq = iks_new("iq");
01386 jingle = iks_new(JINGLE_NODE);
01387 content = iks_new("content");
01388 description = iks_new("description");
01389 transport = iks_new("transport");
01390 payload_pcmu = iks_new("payload-type");
01391 payload_eg711u = iks_new("payload-type");
01392
01393 ast_copy_string(p->audio_content_name, "asterisk-audio-content", sizeof(p->audio_content_name));
01394
01395 iks_insert_attrib(iq, "type", "set");
01396 iks_insert_attrib(iq, "to", p->them);
01397 iks_insert_attrib(iq, "from", client->jid->full);
01398 iks_insert_attrib(iq, "id", client->mid);
01399 ast_aji_increment_mid(client->mid);
01400 iks_insert_attrib(jingle, "action", JINGLE_INITIATE);
01401 iks_insert_attrib(jingle, JINGLE_SID, p->sid);
01402 iks_insert_attrib(jingle, "initiator", client->jid->full);
01403 iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
01404
01405
01406 iks_insert_attrib(content, "creator", "initiator");
01407 iks_insert_attrib(content, "name", p->audio_content_name);
01408 iks_insert_attrib(content, "profile", "RTP/AVP");
01409 iks_insert_attrib(description, "xmlns", JINGLE_AUDIO_RTP_NS);
01410 iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS);
01411 iks_insert_attrib(payload_pcmu, "id", "0");
01412 iks_insert_attrib(payload_pcmu, "name", "PCMU");
01413 iks_insert_attrib(payload_eg711u, "id", "100");
01414 iks_insert_attrib(payload_eg711u, "name", "EG711U");
01415 iks_insert_node(description, payload_pcmu);
01416 iks_insert_node(description, payload_eg711u);
01417 iks_insert_node(content, description);
01418 iks_insert_node(content, transport);
01419 iks_insert_node(jingle, content);
01420 iks_insert_node(iq, jingle);
01421
01422 ast_aji_send(client, iq);
01423
01424 iks_delete(iq);
01425 iks_delete(jingle);
01426 iks_delete(content);
01427 iks_delete(description);
01428 iks_delete(transport);
01429 iks_delete(payload_eg711u);
01430 iks_delete(payload_pcmu);
01431 return 0;
01432 }
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454 static int jingle_call(struct ast_channel *ast, char *dest, int timeout)
01455 {
01456 struct jingle_pvt *p = ast->tech_pvt;
01457
01458 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
01459 ast_log(LOG_WARNING, "jingle_call called on %s, neither down nor reserved\n", ast->name);
01460 return -1;
01461 }
01462
01463 ast_setstate(ast, AST_STATE_RING);
01464 p->jointcapability = p->capability;
01465 if (!p->ringrule) {
01466 ast_copy_string(p->ring, p->parent->connection->mid, sizeof(p->ring));
01467 p->ringrule = iks_filter_add_rule(p->parent->connection->f, jingle_ringing_ack, p,
01468 IKS_RULE_ID, p->ring, IKS_RULE_DONE);
01469 } else
01470 ast_log(LOG_WARNING, "Whoa, already have a ring rule!\n");
01471
01472 jingle_transmit_invite(p);
01473 jingle_create_candidates(p->parent, p, p->sid, p->them);
01474
01475 return 0;
01476 }
01477
01478
01479 static int jingle_hangup(struct ast_channel *ast)
01480 {
01481 struct jingle_pvt *p = ast->tech_pvt;
01482 struct jingle *client;
01483
01484 ast_mutex_lock(&p->lock);
01485 client = p->parent;
01486 p->owner = NULL;
01487 ast->tech_pvt = NULL;
01488 if (!p->alreadygone)
01489 jingle_action(client, p, JINGLE_TERMINATE);
01490 ast_mutex_unlock(&p->lock);
01491
01492 jingle_free_pvt(client, p);
01493
01494 return 0;
01495 }
01496
01497
01498 static struct ast_channel *jingle_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
01499 {
01500 struct jingle_pvt *p = NULL;
01501 struct jingle *client = NULL;
01502 char *sender = NULL, *to = NULL, *s = NULL;
01503 struct ast_channel *chan = NULL;
01504
01505 if (data) {
01506 s = ast_strdupa(data);
01507 if (s) {
01508 sender = strsep(&s, "/");
01509 if (sender && (sender[0] != '\0'))
01510 to = strsep(&s, "/");
01511 if (!to) {
01512 ast_log(LOG_ERROR, "Bad arguments in Jingle Dialstring: %s\n", (char*) data);
01513 return NULL;
01514 }
01515 }
01516 }
01517
01518 client = find_jingle(to, sender);
01519 if (!client) {
01520 ast_log(LOG_WARNING, "Could not find recipient.\n");
01521 return NULL;
01522 }
01523 if (!strcasecmp(client->name, "guest")){
01524
01525
01526 client->connection = ast_aji_get_client(sender);
01527 if (!client->connection) {
01528 ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", sender);
01529 return NULL;
01530 }
01531 }
01532
01533 ASTOBJ_WRLOCK(client);
01534 p = jingle_alloc(client, to, NULL);
01535 if (p)
01536 chan = jingle_new(client, p, AST_STATE_DOWN, to, requestor ? requestor->linkedid : NULL);
01537 ASTOBJ_UNLOCK(client);
01538
01539 return chan;
01540 }
01541
01542
01543 static char *jingle_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01544 {
01545 #define FORMAT "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n"
01546 struct jingle_pvt *p;
01547 struct ast_channel *chan;
01548 int numchans = 0;
01549 char them[AJI_MAX_JIDLEN];
01550 char *jid = NULL;
01551 char *resource = NULL;
01552
01553 switch (cmd) {
01554 case CLI_INIT:
01555 e->command = "jingle show channels";
01556 e->usage =
01557 "Usage: jingle show channels\n"
01558 " Shows current state of the Jingle channels.\n";
01559 return NULL;
01560 case CLI_GENERATE:
01561 return NULL;
01562 }
01563
01564 if (a->argc != 3)
01565 return CLI_SHOWUSAGE;
01566
01567 ast_mutex_lock(&jinglelock);
01568 ast_cli(a->fd, FORMAT, "Channel", "Jabber ID", "Resource", "Read", "Write");
01569 ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, {
01570 ASTOBJ_WRLOCK(iterator);
01571 p = iterator->p;
01572 while(p) {
01573 chan = p->owner;
01574 ast_copy_string(them, p->them, sizeof(them));
01575 jid = them;
01576 resource = strchr(them, '/');
01577 if (!resource)
01578 resource = "None";
01579 else {
01580 *resource = '\0';
01581 resource ++;
01582 }
01583 if (chan)
01584 ast_cli(a->fd, FORMAT,
01585 chan->name,
01586 jid,
01587 resource,
01588 ast_getformatname(chan->readformat),
01589 ast_getformatname(chan->writeformat)
01590 );
01591 else
01592 ast_log(LOG_WARNING, "No available channel\n");
01593 numchans ++;
01594 p = p->next;
01595 }
01596 ASTOBJ_UNLOCK(iterator);
01597 });
01598
01599 ast_mutex_unlock(&jinglelock);
01600
01601 ast_cli(a->fd, "%d active jingle channel%s\n", numchans, (numchans != 1) ? "s" : "");
01602 return CLI_SUCCESS;
01603 #undef FORMAT
01604 }
01605
01606
01607 static char *jingle_do_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01608 {
01609 switch (cmd) {
01610 case CLI_INIT:
01611 e->command = "jingle reload";
01612 e->usage =
01613 "Usage: jingle reload\n"
01614 " Reload jingle channel driver.\n";
01615 return NULL;
01616 case CLI_GENERATE:
01617 return NULL;
01618 }
01619
01620 return CLI_SUCCESS;
01621 }
01622
01623 static int jingle_parser(void *data, ikspak *pak)
01624 {
01625 struct jingle *client = ASTOBJ_REF((struct jingle *) data);
01626 ast_log(LOG_NOTICE, "Filter matched\n");
01627
01628 if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INITIATE)) {
01629
01630 jingle_newcall(client, pak);
01631 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_NEGOTIATE)) {
01632 ast_debug(3, "About to add candidate!\n");
01633 jingle_add_candidate(client, pak);
01634 ast_debug(3, "Candidate Added!\n");
01635 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_ACCEPT)) {
01636 jingle_is_answered(client, pak);
01637 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INFO)) {
01638 jingle_handle_dtmf(client, pak);
01639 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_TERMINATE)) {
01640 jingle_hangup_farend(client, pak);
01641 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", "reject")) {
01642 jingle_hangup_farend(client, pak);
01643 }
01644 ASTOBJ_UNREF(client, jingle_member_destroy);
01645 return IKS_FILTER_EAT;
01646 }
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
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 static int jingle_create_member(char *label, struct ast_variable *var, int allowguest,
01697 struct ast_codec_pref prefs, char *context,
01698 struct jingle *member)
01699 {
01700 struct aji_client *client;
01701
01702 if (!member)
01703 ast_log(LOG_WARNING, "Out of memory.\n");
01704
01705 ast_copy_string(member->name, label, sizeof(member->name));
01706 ast_copy_string(member->user, label, sizeof(member->user));
01707 ast_copy_string(member->context, context, sizeof(member->context));
01708 member->allowguest = allowguest;
01709 member->prefs = prefs;
01710 while (var) {
01711 #if 0
01712 struct jingle_candidate *candidate = NULL;
01713 #endif
01714 if (!strcasecmp(var->name, "username"))
01715 ast_copy_string(member->user, var->value, sizeof(member->user));
01716 else if (!strcasecmp(var->name, "disallow"))
01717 ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 0);
01718 else if (!strcasecmp(var->name, "allow"))
01719 ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 1);
01720 else if (!strcasecmp(var->name, "context"))
01721 ast_copy_string(member->context, var->value, sizeof(member->context));
01722 #if 0
01723 else if (!strcasecmp(var->name, "candidate")) {
01724 candidate = jingle_create_candidate(var->value);
01725 if (candidate) {
01726 candidate->next = member->ourcandidates;
01727 member->ourcandidates = candidate;
01728 }
01729 }
01730 #endif
01731 else if (!strcasecmp(var->name, "connection")) {
01732 if ((client = ast_aji_get_client(var->value))) {
01733 member->connection = client;
01734 iks_filter_add_rule(client->f, jingle_parser, member,
01735 IKS_RULE_TYPE, IKS_PAK_IQ,
01736 IKS_RULE_FROM_PARTIAL, member->user,
01737 IKS_RULE_NS, JINGLE_NS,
01738 IKS_RULE_DONE);
01739 } else {
01740 ast_log(LOG_ERROR, "connection referenced not found!\n");
01741 return 0;
01742 }
01743 }
01744 var = var->next;
01745 }
01746 if (member->connection && member->user)
01747 member->buddy = ASTOBJ_CONTAINER_FIND(&member->connection->buddies, member->user);
01748 else {
01749 ast_log(LOG_ERROR, "No Connection or Username!\n");
01750 }
01751 return 1;
01752 }
01753
01754 static int jingle_load_config(void)
01755 {
01756 char *cat = NULL;
01757 struct ast_config *cfg = NULL;
01758 char context[100];
01759 int allowguest = 1;
01760 struct ast_variable *var;
01761 struct jingle *member;
01762 struct hostent *hp;
01763 struct ast_hostent ahp;
01764 struct ast_codec_pref prefs;
01765 struct aji_client_container *clients;
01766 struct jingle_candidate *global_candidates = NULL;
01767 struct ast_flags config_flags = { 0 };
01768
01769 cfg = ast_config_load(JINGLE_CONFIG, config_flags);
01770 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
01771 return 0;
01772 }
01773
01774
01775 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
01776
01777 cat = ast_category_browse(cfg, NULL);
01778 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
01779
01780 if (!ast_jb_read_conf(&global_jbconf, var->name, var->value))
01781 continue;
01782
01783 if (!strcasecmp(var->name, "allowguest"))
01784 allowguest =
01785 (ast_true(ast_variable_retrieve(cfg, "general", "allowguest"))) ? 1 : 0;
01786 else if (!strcasecmp(var->name, "disallow"))
01787 ast_parse_allow_disallow(&prefs, &global_capability, var->value, 0);
01788 else if (!strcasecmp(var->name, "allow"))
01789 ast_parse_allow_disallow(&prefs, &global_capability, var->value, 1);
01790 else if (!strcasecmp(var->name, "context"))
01791 ast_copy_string(context, var->value, sizeof(context));
01792 else if (!strcasecmp(var->name, "externip"))
01793 ast_copy_string(externip, var->value, sizeof(externip));
01794 else if (!strcasecmp(var->name, "bindaddr")) {
01795 if (!(hp = ast_gethostbyname(var->value, &ahp))) {
01796 ast_log(LOG_WARNING, "Invalid address: %s\n", var->value);
01797 } else {
01798 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
01799 }
01800 }
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811 }
01812 while (cat) {
01813 if (strcasecmp(cat, "general")) {
01814 var = ast_variable_browse(cfg, cat);
01815 member = ast_calloc(1, sizeof(*member));
01816 ASTOBJ_INIT(member);
01817 ASTOBJ_WRLOCK(member);
01818 if (!strcasecmp(cat, "guest")) {
01819 ast_copy_string(member->name, "guest", sizeof(member->name));
01820 ast_copy_string(member->user, "guest", sizeof(member->user));
01821 ast_copy_string(member->context, context, sizeof(member->context));
01822 member->allowguest = allowguest;
01823 member->prefs = prefs;
01824 while (var) {
01825 if (!strcasecmp(var->name, "disallow"))
01826 ast_parse_allow_disallow(&member->prefs, &member->capability,
01827 var->value, 0);
01828 else if (!strcasecmp(var->name, "allow"))
01829 ast_parse_allow_disallow(&member->prefs, &member->capability,
01830 var->value, 1);
01831 else if (!strcasecmp(var->name, "context"))
01832 ast_copy_string(member->context, var->value,
01833 sizeof(member->context));
01834 else if (!strcasecmp(var->name, "parkinglot"))
01835 ast_copy_string(member->parkinglot, var->value,
01836 sizeof(member->parkinglot));
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847 var = var->next;
01848 }
01849 ASTOBJ_UNLOCK(member);
01850 clients = ast_aji_get_clients();
01851 if (clients) {
01852 ASTOBJ_CONTAINER_TRAVERSE(clients, 1, {
01853 ASTOBJ_WRLOCK(iterator);
01854 ASTOBJ_WRLOCK(member);
01855 member->connection = NULL;
01856 iks_filter_add_rule(iterator->f, jingle_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, JINGLE_NS, IKS_RULE_DONE);
01857 iks_filter_add_rule(iterator->f, jingle_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, JINGLE_DTMF_NS, IKS_RULE_DONE);
01858 ASTOBJ_UNLOCK(member);
01859 ASTOBJ_UNLOCK(iterator);
01860 });
01861 ASTOBJ_CONTAINER_LINK(&jingle_list, member);
01862 } else {
01863 ASTOBJ_UNLOCK(member);
01864 ASTOBJ_UNREF(member, jingle_member_destroy);
01865 }
01866 } else {
01867 ASTOBJ_UNLOCK(member);
01868 if (jingle_create_member(cat, var, allowguest, prefs, context, member))
01869 ASTOBJ_CONTAINER_LINK(&jingle_list, member);
01870 ASTOBJ_UNREF(member, jingle_member_destroy);
01871 }
01872 }
01873 cat = ast_category_browse(cfg, cat);
01874 }
01875 jingle_free_candidates(global_candidates);
01876 return 1;
01877 }
01878
01879
01880 static int load_module(void)
01881 {
01882 struct ast_sockaddr ourip_tmp;
01883 struct ast_sockaddr bindaddr_tmp;
01884
01885 char *jabber_loaded = ast_module_helper("", "res_jabber.so", 0, 0, 0, 0);
01886 free(jabber_loaded);
01887 if (!jabber_loaded) {
01888
01889 jabber_loaded = ast_module_helper("", "res_jabber", 0, 0, 0, 0);
01890 free(jabber_loaded);
01891 if (!jabber_loaded) {
01892 ast_log(LOG_ERROR, "chan_jingle.so depends upon res_jabber.so\n");
01893 return AST_MODULE_LOAD_DECLINE;
01894 }
01895 }
01896
01897 ASTOBJ_CONTAINER_INIT(&jingle_list);
01898 if (!jingle_load_config()) {
01899 ast_log(LOG_ERROR, "Unable to read config file %s. Not loading module.\n", JINGLE_CONFIG);
01900 return AST_MODULE_LOAD_DECLINE;
01901 }
01902
01903 sched = sched_context_create();
01904 if (!sched) {
01905 ast_log(LOG_WARNING, "Unable to create schedule context\n");
01906 }
01907
01908 io = io_context_create();
01909 if (!io) {
01910 ast_log(LOG_WARNING, "Unable to create I/O context\n");
01911 }
01912
01913 ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
01914 if (ast_find_ourip(&ourip_tmp, &bindaddr_tmp, AF_INET)) {
01915 ast_log(LOG_WARNING, "Unable to get own IP address, Jingle disabled\n");
01916 return 0;
01917 }
01918 __ourip.s_addr = htonl(ast_sockaddr_ipv4(&ourip_tmp));
01919
01920 ast_rtp_glue_register(&jingle_rtp_glue);
01921 ast_cli_register_multiple(jingle_cli, ARRAY_LEN(jingle_cli));
01922
01923 if (ast_channel_register(&jingle_tech)) {
01924 ast_log(LOG_ERROR, "Unable to register channel class %s\n", channel_type);
01925 return -1;
01926 }
01927 return 0;
01928 }
01929
01930
01931 static int reload(void)
01932 {
01933 return 0;
01934 }
01935
01936
01937 static int unload_module(void)
01938 {
01939 struct jingle_pvt *privates = NULL;
01940 ast_cli_unregister_multiple(jingle_cli, ARRAY_LEN(jingle_cli));
01941
01942 ast_channel_unregister(&jingle_tech);
01943 ast_rtp_glue_unregister(&jingle_rtp_glue);
01944
01945 if (!ast_mutex_lock(&jinglelock)) {
01946
01947 ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, {
01948 ASTOBJ_WRLOCK(iterator);
01949 privates = iterator->p;
01950 while(privates) {
01951 if (privates->owner)
01952 ast_softhangup(privates->owner, AST_SOFTHANGUP_APPUNLOAD);
01953 privates = privates->next;
01954 }
01955 iterator->p = NULL;
01956 ASTOBJ_UNLOCK(iterator);
01957 });
01958 ast_mutex_unlock(&jinglelock);
01959 } else {
01960 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
01961 return -1;
01962 }
01963 ASTOBJ_CONTAINER_DESTROYALL(&jingle_list, jingle_member_destroy);
01964 ASTOBJ_CONTAINER_DESTROY(&jingle_list);
01965 return 0;
01966 }
01967
01968 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Jingle Channel Driver",
01969 .load = load_module,
01970 .unload = unload_module,
01971 .reload = reload,
01972 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
01973 );