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