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