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