update chan_jingle to reflect the recent change to the indicate prototype
[asterisk/asterisk.git] / channels / chan_jingle.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Matt O'Gorman <mogorman@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \author Matt O'Gorman <mogorman@digium.com>
22  *
23  * \brief Jingle Channel Driver
24  * 
25  * \ingroup channel_drivers
26  */
27
28 /*** MODULEINFO
29         <depend>iksemel</depend>
30  ***/
31
32
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <sys/socket.h>
38 #include <errno.h>
39 #include <stdlib.h>
40 #include <fcntl.h>
41 #include <netdb.h>
42 #include <netinet/in.h>
43 #include <arpa/inet.h>
44 #include <sys/signal.h>
45 #include <iksemel.h>
46
47 #include "asterisk.h"
48
49 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
50 #include "asterisk/lock.h"
51 #include "asterisk/channel.h"
52 #include "asterisk/config.h"
53 #include "asterisk/logger.h"
54 #include "asterisk/module.h"
55 #include "asterisk/pbx.h"
56 #include "asterisk/options.h"
57 #include "asterisk/lock.h"
58 #include "asterisk/sched.h"
59 #include "asterisk/io.h"
60 #include "asterisk/rtp.h"
61 #include "asterisk/acl.h"
62 #include "asterisk/callerid.h"
63 #include "asterisk/file.h"
64 #include "asterisk/cli.h"
65 #include "asterisk/app.h"
66 #include "asterisk/musiconhold.h"
67 #include "asterisk/manager.h"
68 #include "asterisk/stringfields.h"
69 #include "asterisk/utils.h"
70 #include "asterisk/causes.h"
71 #include "asterisk/astobj.h"
72 #include "asterisk/jabber.h"
73 #include "asterisk/jingle.h"
74
75 #define JINGLE_CONFIG "jingle.conf"
76
77 enum jingle_protocol {
78         AJI_PROTOCOL_UDP = 1,
79         AJI_PROTOCOL_SSLTCP = 2,
80 };
81
82 enum jingle_connect_type {
83         AJI_CONNECT_STUN = 1,
84         AJI_CONNECT_LOCAL = 2,
85         AJI_CONNECT_RELAY = 3,
86 };
87
88 struct jingle_pvt {
89         ast_mutex_t lock;               /* Channel private lock */
90         time_t laststun;
91         struct jingle *parent;  /* Parent client */
92         char sid[100];
93         char from[100];
94         char ring[10];                  /* Message ID of ring */
95         iksrule *ringrule;              /* Rule for matching RING request */
96         int initiator;                  /* If we're the initiator */
97         int alreadygone;
98         int capability;
99         struct ast_codec_pref prefs;
100         struct jingle_candidate *theircandidates;
101         struct jingle_candidate *ourcandidates;
102         char cid_num[80];               /*!< Caller ID num */
103         char cid_name[80];              /*!< Caller ID name */
104         char exten[80];         /* Called extension */
105         struct ast_channel *owner;      /* Master Channel */
106         struct ast_rtp *rtp;    /*!< RTP Session */
107         struct ast_rtp *vrtp;
108         int jointcapability;    /*!< Supported capability at both ends (codecs ) */
109         int peercapability;
110         struct jingle_pvt *next;        /* Next entity */
111 };
112
113 struct jingle_candidate {
114         char name[100];
115         enum jingle_protocol protocol;
116         double preference;
117         char username[100];
118         char password[100];
119         enum jingle_connect_type type;
120         char network[6];
121         int generation;
122         char ip[16];
123         int port;
124         int receipt;
125         struct jingle_candidate *next;
126 };
127
128 struct jingle {
129         ASTOBJ_COMPONENTS(struct jingle);
130         struct aji_client *connection;
131         struct aji_buddy *buddy;
132         struct jingle_pvt *p;
133         struct ast_codec_pref prefs;
134         int amaflags;                   /*!< AMA Flags */
135         char user[100];
136         char context[100];
137         char accountcode[AST_MAX_ACCOUNT_CODE]; /* Account code */
138         int capability;
139         ast_group_t callgroup;  /*!< Call group */
140         ast_group_t pickupgroup;        /*!< Pickup group */
141         int callingpres;                /*!< Calling presentation */
142         int allowguest;
143         char language[MAX_LANGUAGE];    /*!<  Default language for prompts */
144         char musicclass[MAX_MUSICCLASS];        /*!<  Music on Hold class */
145 };
146
147 struct jingle_container {
148         ASTOBJ_CONTAINER_COMPONENTS(struct jingle);
149 };
150
151 static const char desc[] = "Jingle Channel";
152 static const char type[] = "Jingle";
153 static const char tdesc[] = "Jingle Channel Driver";
154
155 static int usecnt = 0;
156 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
157
158
159 static int global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263;
160
161 /* Protect the interface list (of sip_pvt's) */
162 AST_MUTEX_DEFINE_STATIC(jinglelock);
163
164 AST_MUTEX_DEFINE_STATIC(rand_lock);     /*!< Lock for thread-safe random generator */
165
166
167 static struct ast_channel *jingle_request(const char *type, int format, void *data, int *cause);
168 static int jingle_digit(struct ast_channel *ast, char digit);
169 static int jingle_call(struct ast_channel *ast, char *dest, int timeout);
170 static int jingle_hangup(struct ast_channel *ast);
171 static int jingle_answer(struct ast_channel *ast);
172 static int jingle_newcall(struct jingle *client, ikspak *pak);
173 static struct ast_frame *jingle_read(struct ast_channel *ast);
174 static int jingle_write(struct ast_channel *ast, struct ast_frame *f);
175 static int jingle_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
176 static int jingle_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
177 static int jingle_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
178 static struct jingle_pvt *jingle_alloc(struct jingle *client, const char *from, const char *sid);
179
180 /* PBX interface structure for channel registration */
181 static const struct ast_channel_tech jingle_tech = {
182         .type = type,
183         .description = tdesc,
184         .capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1),
185         .requester = jingle_request,
186         .send_digit = jingle_digit,
187 //  .devicestate = jingle_devicestate,
188 //  .transfer = jingle_transfer,
189         .bridge = ast_rtp_bridge,
190         .call = jingle_call,
191         .hangup = jingle_hangup,
192         .answer = jingle_answer,
193         .read = jingle_read,
194         .write = jingle_write,
195         .exception = jingle_read,
196         .indicate = jingle_indicate,
197         .fixup = jingle_fixup,
198         .send_html = jingle_sendhtml,
199 };
200
201 static struct sockaddr_in bindaddr = { 0, };    /*!< The address we bind to */
202
203 static struct sched_context *sched;     /*!< The scheduling context */
204 static struct io_context *io;   /*!< The IO context */
205 static struct in_addr __ourip;
206 /*----- RTP interface functions */
207 static int jingle_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp,
208                                                            struct ast_rtp *vrtp, int codecs, int nat_active);
209 static struct ast_rtp *jingle_get_rtp_peer(struct ast_channel *chan);
210 static int jingle_get_codec(struct ast_channel *chan);
211
212 static struct ast_rtp_protocol jingle_rtp = {
213         type: "jingle",
214         get_rtp_info: jingle_get_rtp_peer,
215         set_rtp_peer: jingle_set_rtp_peer,
216         get_codec: jingle_get_codec,
217 };
218
219 char externip[16];
220
221 struct jingle_container jingles;
222
223 static void jingle_member_destroy(struct jingle *obj)
224 {
225         free(obj);
226 }
227
228 static struct jingle *find_jingle(char *name, char *connection)
229 {
230         struct jingle *jingle = NULL;
231
232         jingle = ASTOBJ_CONTAINER_FIND(&jingles, name);
233         if (!jingle && strchr(name, '@'))
234                 jingle = ASTOBJ_CONTAINER_FIND_FULL(&jingles, name, user,,, strcasecmp);
235
236         if (!jingle) {                          /* guest call */
237                 ASTOBJ_CONTAINER_TRAVERSE(&jingles, 1, {
238                         ASTOBJ_WRLOCK(iterator);
239                         if (!strcasecmp(iterator->name, "guest")) {
240                                 if (!strcasecmp(iterator->connection->jid->partial, connection)) {
241                                         jingle = iterator;
242                                         break;
243                                 } else if (!strcasecmp(iterator->connection->name, connection)) {
244                                         jingle = iterator;
245                                         break;
246                                 }
247                         }
248                         ASTOBJ_UNLOCK(iterator);
249                 });
250
251         }
252         return jingle;
253 }
254
255
256 static void add_codec_to_answer(const struct jingle_pvt *p, int codec, iks *dcodecs)
257 {
258         ast_verbose("Adding codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec));
259         if (!strcasecmp("ulaw", ast_getformatname(codec))) {
260                 iks *payload_eg711u, *payload_pcmu;
261                 payload_pcmu = iks_new("payload-type");
262                 iks_insert_attrib(payload_pcmu, "id", "0");
263                 iks_insert_attrib(payload_pcmu, "name", "PCMU");
264                 iks_insert_attrib(payload_pcmu, "xmlns", "http://www.google.com/session/phone");
265                 payload_eg711u = iks_new("payload-type");
266                 iks_insert_attrib(payload_eg711u, "id", "100");
267                 iks_insert_attrib(payload_eg711u, "name", "EG711U");
268                 iks_insert_attrib(payload_eg711u, "xmlns", "http://www.google.com/session/phone");
269                 iks_insert_node(dcodecs, payload_pcmu);
270         //      iks_insert_node(dcodecs, payload_eg711u);
271         }
272         if (!strcasecmp("alaw", ast_getformatname(codec))) {
273                 iks *payload_eg711a, *payload_pcma;
274                 payload_pcma = iks_new("payload-type");
275                 iks_insert_attrib(payload_pcma, "id", "8");
276                 iks_insert_attrib(payload_pcma, "name", "PCMA");
277                 iks_insert_attrib(payload_pcma, "xmlns", "http://www.google.com/session/phone");
278                 payload_eg711a = iks_new("payload-type");
279                 iks_insert_attrib(payload_eg711a, "id", "101");
280                 iks_insert_attrib(payload_eg711a, "name", "EG711A");
281                 iks_insert_attrib(payload_eg711a, "xmlns", "http://www.google.com/session/phone");
282                 iks_insert_node(dcodecs, payload_pcma);
283                 iks_insert_node(dcodecs, payload_eg711a);
284         }
285         if (!strcasecmp("ilbc", ast_getformatname(codec))) {
286                 iks *payload_ilbc;
287                 payload_ilbc = iks_new("payload-type");
288                 iks_insert_attrib(payload_ilbc, "id", "102");
289                 iks_insert_attrib(payload_ilbc, "name", "iLBC");
290                 iks_insert_attrib(payload_ilbc, "xmlns", "http://www.google.com/session/phone");
291                 iks_insert_node(dcodecs, payload_ilbc);
292         }
293         if (!strcasecmp("g723", ast_getformatname(codec))) {
294                 iks *payload_g723;
295                 payload_g723 = iks_new("payload-type");
296                 iks_insert_attrib(payload_g723, "id", "4");
297                 iks_insert_attrib(payload_g723, "name", "G723");
298                 iks_insert_attrib(payload_g723, "xmlns", "http://www.google.com/session/phone");
299                 iks_insert_node(dcodecs, payload_g723);
300         }
301         ast_rtp_lookup_code(p->rtp, 1, codec);
302 }
303
304 static int jingle_accept_call(struct jingle *client, struct jingle_pvt *p)
305 {
306         struct jingle_pvt *tmp = client->p;
307         struct aji_client *c = client->connection;
308         iks *iq, *jingle, *dcodecs, *payload_red, *payload_audio, *payload_cn;
309         int x;
310         int pref_codec = 0;
311         int alreadysent = 0;
312
313         if (p->initiator)
314                 return 1;
315
316         iq = iks_new("iq");
317         jingle = iks_new(GOOGLE_NODE);
318         dcodecs = iks_new("description");
319         if (iq && jingle && dcodecs) {
320                 iks_insert_attrib(dcodecs, "xmlns", "http://www.google.com/session/phone");
321
322                 for (x = 0; x < 32; x++) {
323                         if (!(pref_codec = ast_codec_pref_index(&client->prefs, x)))
324                                 break;
325                         if (!(client->capability & pref_codec))
326                                 continue;
327                         if (alreadysent & pref_codec)
328                                 continue;
329                         if (pref_codec <= AST_FORMAT_MAX_AUDIO)
330                                 add_codec_to_answer(p, pref_codec, dcodecs);
331                         else
332                                 add_codec_to_answer(p, pref_codec, dcodecs);
333                         alreadysent |= pref_codec;
334                 }
335                 payload_red = iks_new("payload-type");
336                 iks_insert_attrib(payload_red, "id", "117");
337                 iks_insert_attrib(payload_red, "name", "red");
338                 iks_insert_attrib(payload_red, "xmlns", "http://www.google.com/session/phone");
339                 payload_audio = iks_new("payload-type");
340                 iks_insert_attrib(payload_audio, "id", "106");
341                 iks_insert_attrib(payload_audio, "name", "audio/telephone-event");
342                 iks_insert_attrib(payload_audio, "xmlns", "http://www.google.com/session/phone");
343                 payload_cn = iks_new("payload-type");
344                 iks_insert_attrib(payload_cn, "id", "13");
345                 iks_insert_attrib(payload_cn, "name", "CN");
346                 iks_insert_attrib(payload_cn, "xmlns", "http://www.google.com/session/phone");
347
348
349                 iks_insert_attrib(iq, "type", "set");
350                 //      iks_insert_attrib(iq,"from",client->connection->jid->full);
351                 iks_insert_attrib(iq, "to", (p->from) ? p->from : client->user);
352                 iks_insert_attrib(iq, "id", client->connection->mid);
353                 ast_aji_increment_mid(client->connection->mid);
354
355                 iks_insert_attrib(jingle, "xmlns", "http://www.google.com/session");
356                 iks_insert_attrib(jingle, "type", JINGLE_ACCEPT);
357                 ast_verbose("WOOH %d\n", p->initiator);
358                 iks_insert_attrib(jingle, "initiator",
359                                                   p->initiator ? client->connection->jid->full : p->from);
360                 iks_insert_attrib(jingle, GOOGLE_SID, tmp->sid);
361                 iks_insert_node(iq, jingle);
362                 iks_insert_node(jingle, dcodecs);
363                 iks_insert_node(dcodecs, payload_red);
364                 iks_insert_node(dcodecs, payload_audio);
365                 iks_insert_node(dcodecs, payload_cn);
366
367                 iks_send(c->p, iq);
368                 iks_delete(payload_red);
369                 iks_delete(payload_audio);
370                 iks_delete(payload_cn);
371                 iks_delete(dcodecs);
372                 iks_delete(jingle);
373                 iks_delete(iq);
374         }
375         return 1;
376 }
377
378 static int jingle_ringing_ack(void *data, ikspak *pak)
379 {
380         struct jingle_pvt *p = data;
381         if (p->ringrule)
382                 iks_filter_remove_rule(p->parent->connection->f, p->ringrule);
383         p->ringrule = NULL;
384         if (p->owner)
385                 ast_queue_control(p->owner, AST_CONTROL_RINGING);
386         return IKS_FILTER_EAT;
387 }
388
389 static int jingle_answer(struct ast_channel *ast)
390 {
391         struct jingle_pvt *p = ast->tech_pvt;
392         struct jingle *client = p->parent;
393         int res = 0;
394         ast_log(LOG_DEBUG, "Answer!\n");
395         ast_mutex_lock(&p->lock);
396         jingle_accept_call(client, p);
397         ast_mutex_unlock(&p->lock);
398         return res;
399 }
400
401 static force_inline int thread_safe_rand(void)
402 {
403         int val;
404
405         ast_mutex_lock(&rand_lock);
406         val = rand();
407         ast_mutex_unlock(&rand_lock);
408
409         return val;
410 }
411
412 static struct ast_rtp *jingle_get_rtp_peer(struct ast_channel *chan)
413 {
414         struct jingle_pvt *p;
415         struct ast_rtp *rtp = NULL;
416         p = chan->tech_pvt;
417         if (!p)
418                 return NULL;
419         ast_mutex_lock(&p->lock);
420         if (p->rtp)
421                 rtp = p->rtp;
422         ast_mutex_unlock(&p->lock);
423         return rtp;
424 }
425
426 static int jingle_get_codec(struct ast_channel *chan)
427 {
428         struct jingle_pvt *p = chan->tech_pvt;
429         return p->peercapability;
430 }
431
432 static int jingle_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active)
433 {
434         struct jingle_pvt *p;
435
436         p = chan->tech_pvt;
437         if (!p)
438                 return -1;
439         ast_mutex_lock(&p->lock);
440
441 /*      if (rtp)
442                 ast_rtp_get_peer(rtp, &p->redirip);
443         else
444                 memset(&p->redirip, 0, sizeof(p->redirip));
445         p->redircodecs = codecs; */
446
447         /* Reset lastrtprx timer */
448         ast_mutex_unlock(&p->lock);
449         return 0;
450 }
451
452 static int jingle_response(struct jingle *client, ikspak *pak, const char *reasonstr)
453 {
454         iks *response, *error = NULL, *reason = NULL;
455         int res = -1;
456
457         response = iks_new("iq");
458         if (response) {
459                 iks_insert_attrib(response, "type", "result");
460                 iks_insert_attrib(response, "from", client->connection->jid->full);
461                 iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from"));
462                 iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id"));
463                 if (reasonstr) {
464                         error = iks_new("error");
465                         if (error) {
466                                 iks_insert_attrib(error, "type", "cancel");
467                                 reason = iks_new(reasonstr);
468                                 if (reason)
469                                         iks_insert_node(error, reason);
470                                 iks_insert_node(response, error);
471                         }
472                 }
473                 iks_send(client->connection->p, response);
474                 if (reason)
475                         iks_delete(reason);
476                 if (error)
477                         iks_delete(error);
478                 iks_delete(response);
479                 res = 0;
480         }
481         return res;
482 }
483
484 static int jingle_is_answered(struct jingle *client, ikspak *pak)
485 {
486         struct jingle_pvt *tmp;
487
488         ast_log(LOG_DEBUG, "The client is %s\n", client->name);
489         tmp = client->p;
490         /* Make sure our new call doesn't exist yet */
491         while (tmp) {
492                 ast_verbose("FFFFF %s\n", tmp->sid);
493                 if (iks_find_with_attrib(pak->x, GOOGLE_NODE, GOOGLE_SID, tmp->sid)) {
494                         break;
495                 }
496                 tmp = tmp->next;
497         }
498
499         if (tmp) {
500                 if (tmp->owner)
501                         ast_queue_control(tmp->owner, AST_CONTROL_ANSWER);
502         } else
503                 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
504         jingle_response(client, pak, NULL);
505         return 1;
506 }
507
508 static int jingle_hangup_farend(struct jingle *client, ikspak *pak)
509 {
510         struct jingle_pvt *tmp;
511
512         ast_log(LOG_DEBUG, "The client is %s\n", client->name);
513         tmp = client->p;
514         /* Make sure our new call doesn't exist yet */
515         while (tmp) {
516                 if (iks_find_with_attrib(pak->x, GOOGLE_NODE, GOOGLE_SID, tmp->sid)) {
517                         break;
518                 }
519                 tmp = tmp->next;
520         }
521
522         if (tmp) {
523                 tmp->alreadygone = 1;
524                 ast_queue_hangup(tmp->owner);
525         } else
526                 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
527         jingle_response(client, pak, NULL);
528         ast_verbose("END CALL\n");
529         return 1;
530 }
531
532 static int jingle_create_candidates(struct jingle *client, struct jingle_pvt *p, char *sid, char *from)
533 {
534         struct jingle_candidate *tmp;
535         struct aji_client *c = client->connection;
536         struct jingle_candidate *ours1 = NULL, *ours2 = NULL;
537         struct sockaddr_in sin;
538         struct sockaddr_in dest;
539         struct in_addr us;
540         char iabuf[INET_ADDRSTRLEN];
541
542         iks *iq, *jingle, *candidate;
543         char user[17], pass[17], preference[5], port[7];
544
545
546         iq = iks_new("iq");
547         jingle = iks_new(GOOGLE_NODE);
548         candidate = iks_new("candidate");
549         ours1 = (struct jingle_candidate *) ast_calloc(1, sizeof(struct jingle_candidate));
550         ours2 = (struct jingle_candidate *) ast_calloc(1, sizeof(struct jingle_candidate));
551         if (!iq || !jingle || !candidate || !ours1 || !ours2) {
552                 ast_log(LOG_WARNING, "out of memory!\n");
553                 goto safeout;
554         }
555
556         iks_insert_node(iq, jingle);
557         iks_insert_node(jingle, candidate);
558
559         while (p) {
560                 if (!strcasecmp(p->sid, sid)) {
561                         break;
562                 }
563                 p = p->next;
564         }
565
566         if (!p) {
567                 ast_log(LOG_NOTICE, "No matching jingle session!\n");
568                 goto safeout;
569         }
570
571         ast_rtp_get_us(p->rtp, &sin);
572         ast_find_ourip(&us, bindaddr);
573
574         /* Setup our jingle candidates */
575         ast_copy_string(ours1->name, "rtp", sizeof(ours1->name));
576         ours1->port = ntohs(sin.sin_port);
577         ours1->preference = 1;
578         snprintf(user, sizeof(user), "%08x%08x", thread_safe_rand(), thread_safe_rand());
579         snprintf(pass, sizeof(pass), "%08x%08x", thread_safe_rand(), thread_safe_rand());
580         ast_copy_string(ours1->username, user, sizeof(ours1->username));
581         ast_copy_string(ours1->password, pass, sizeof(ours1->password));
582         ast_inet_ntoa(ours1->ip, sizeof(ours1->ip), us);
583         ours1->protocol = AJI_PROTOCOL_UDP;
584         ours1->type = AJI_CONNECT_LOCAL;
585         ours1->generation = 0;
586         p->ourcandidates = ours1;
587
588         if (!ast_strlen_zero(externip)) {
589                 /* XXX We should really stun for this one not just go with externip XXX */
590                 snprintf(user, sizeof(user), "%08x%08x", thread_safe_rand(), thread_safe_rand());
591                 snprintf(pass, sizeof(pass), "%08x%08x", thread_safe_rand(), thread_safe_rand());
592                 ast_copy_string(ours2->username, user, sizeof(ours2->username));
593                 ast_copy_string(ours2->password, pass, sizeof(ours2->password));
594                 ast_copy_string(ours2->ip, externip, sizeof(ours2->ip));
595                 ast_copy_string(ours2->name, "rtp", sizeof(ours1->name));
596                 ours2->port = ntohs(sin.sin_port);
597                 ours2->preference = 0.9;
598                 ours2->protocol = AJI_PROTOCOL_UDP;
599                 ours2->type = AJI_CONNECT_STUN;
600                 ours2->generation = 0;
601                 ours1->next = ours2;
602                 ours2 = NULL;
603         }
604         ours1 = NULL;
605         dest.sin_addr = __ourip;        /// THIS IS BAD NEED TO FIX
606         dest.sin_port = sin.sin_port;
607
608         ast_verbose("We're at %s port %d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), us), ntohs(sin.sin_port));     /// THIS IS BAD NEED TO FIX
609
610         tmp = p->ourcandidates;
611         while (tmp) {                           /*send standard candidates */
612                 snprintf(port, sizeof(port), "%d", tmp->port);
613                 snprintf(preference, sizeof(preference), "%.2f", tmp->preference);
614                 iks_insert_attrib(iq, "from", c->jid->full);
615                 iks_insert_attrib(iq, "to", from);
616                 iks_insert_attrib(iq, "type", "set");
617                 iks_insert_attrib(iq, "id", c->mid);
618                 ast_aji_increment_mid(c->mid);
619                 iks_insert_attrib(jingle, "type", "candidates");
620                 iks_insert_attrib(jingle, "id", sid);
621                 iks_insert_attrib(jingle, "initiator", (p->initiator) ? c->jid->full : from);
622                 iks_insert_attrib(jingle, "xmlns", GOOGLE_NS);
623                 iks_insert_attrib(candidate, "name", tmp->name);
624                 iks_insert_attrib(candidate, "address", tmp->ip);
625                 iks_insert_attrib(candidate, "port", port);
626                 iks_insert_attrib(candidate, "username", tmp->username);
627                 iks_insert_attrib(candidate, "password", tmp->password);
628                 iks_insert_attrib(candidate, "preference", preference);
629                 if (tmp->protocol == AJI_PROTOCOL_UDP)
630                         iks_insert_attrib(candidate, "protocol", "udp");
631                 if (tmp->protocol == AJI_PROTOCOL_SSLTCP)
632                         iks_insert_attrib(candidate, "protocol", "ssltcp");
633                 if (tmp->type == AJI_CONNECT_STUN)
634                         iks_insert_attrib(candidate, "type", "stun");
635                 if (tmp->type == AJI_CONNECT_LOCAL)
636                         iks_insert_attrib(candidate, "type", "local");
637                 if (tmp->type == AJI_CONNECT_RELAY)
638                         iks_insert_attrib(candidate, "type", "relay");
639                 iks_insert_attrib(candidate, "network", "0");
640                 iks_insert_attrib(candidate, "generation", "0");
641                 iks_send(c->p, iq);
642                 tmp = tmp->next;
643         }
644         p->laststun = 0;
645
646 safeout:
647         if (ours1)
648                 free(ours1);
649         if (ours2)
650                 free(ours2);
651         if (iq)
652                 iks_delete(iq);
653         if (jingle)
654                 iks_delete(jingle);
655         if (candidate)
656                 iks_delete(candidate);
657         return 1;
658 }
659
660 static struct jingle_pvt *jingle_alloc(struct jingle *client, const char *from, const char *sid)
661 {
662         struct jingle_pvt *tmp = NULL;
663         struct aji_resource *resources = NULL;
664         struct aji_buddy *buddy;
665         char idroster[200];
666
667         ast_log(LOG_DEBUG, "The client is %s for alloc\n", client->name);
668         if (!sid && !strchr(from, '/')) {       /*I started call! */
669                 ast_verbose("shouldnt be called on inbound!\n");
670                 if (!strcasecmp(client->name, "guest")) {
671                         buddy = ASTOBJ_CONTAINER_FIND(&client->connection->buddies, from);
672                         if (buddy)
673                                 resources = buddy->resources;
674                         ast_verbose("shouldnt be called on inbound! %s ----- %s ---- %s\n",
675                                                 client->name, from, buddy->name);
676                 } else {
677                         resources = client->buddy->resources;
678                 }
679                 while (resources) {
680                         if (resources->cap->jingle) {
681                                 ast_verbose("WOW FOUND\n");
682                                 break;
683                         }
684                         resources = resources->next;
685                 }
686                 if (resources)
687                         snprintf(idroster, sizeof(idroster), "%s/%s", from, resources->resource);
688                 else {
689                         ast_log(LOG_ERROR, "no jingle capable clients to talk to.\n");
690                         return NULL;
691                 }
692         }
693         if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
694                 return NULL;
695         }
696         if (sid) {
697                 ast_copy_string(tmp->sid, sid, sizeof(tmp->sid));
698                 ast_copy_string(tmp->from, from, sizeof(tmp->from));
699         } else {
700                 snprintf(tmp->sid, sizeof(tmp->sid), "%08lx%08lx", ast_random(), ast_random());
701                 ast_copy_string(tmp->from, idroster, sizeof(tmp->from));
702                 tmp->initiator = 1;
703         }
704         tmp->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
705         tmp->parent = client;
706         if (!tmp->rtp) {
707                 ast_log(LOG_WARNING, "Out of RTP sessions?\n");
708                 free(tmp);
709                 return NULL;
710         }
711         ast_copy_string(tmp->exten, "s", sizeof(tmp->exten));
712         ast_mutex_init(&tmp->lock);
713         ast_mutex_lock(&jinglelock);
714         tmp->next = client->p;
715         client->p = tmp;
716         ast_mutex_unlock(&jinglelock);
717         return tmp;
718 }
719
720 /*! \brief Start new jingle channel */
721 static struct ast_channel *jingle_new(struct jingle *client, struct jingle_pvt *i, int state, const char *title)
722 {
723         struct ast_channel *tmp;
724         int fmt;
725         int what;
726
727         tmp = ast_channel_alloc(1);
728         if (!tmp) {
729                 ast_log(LOG_WARNING, "Unable to allocate Jingle channel structure!\n");
730                 return NULL;
731         }
732         tmp->tech = &jingle_tech;
733
734         /* Select our native format based on codec preference until we receive
735            something from another device to the contrary. */
736         if (i->jointcapability)
737                 what = i->jointcapability;
738         else if (i->capability)
739                 what = i->capability;
740         else
741                 what = global_capability;
742         tmp->nativeformats =
743                 ast_codec_choose(&i->prefs, what,
744                                                  1) | (i->jointcapability & AST_FORMAT_VIDEO_MASK);
745         fmt = ast_best_codec(tmp->nativeformats);
746
747         if (title)
748                 ast_string_field_build(tmp, name, "Jingle/%s-%04lx", title,
749                                                            ast_random() & 0xffff);
750         else
751                 ast_string_field_build(tmp, name, "Jingle/%s-%04lx", i->from,
752                                                            ast_random() & 0xffff);
753
754         if (i->rtp) {
755                 tmp->fds[0] = ast_rtp_fd(i->rtp);
756                 tmp->fds[1] = ast_rtcp_fd(i->rtp);
757         }
758         if (i->vrtp) {
759                 tmp->fds[2] = ast_rtp_fd(i->vrtp);
760                 tmp->fds[3] = ast_rtcp_fd(i->vrtp);
761         }
762         if (state == AST_STATE_RING)
763                 tmp->rings = 1;
764         tmp->adsicpe = AST_ADSI_UNAVAILABLE;
765         tmp->writeformat = fmt;
766         tmp->rawwriteformat = fmt;
767         tmp->readformat = fmt;
768         tmp->rawreadformat = fmt;
769         tmp->tech_pvt = i;
770
771         tmp->callgroup = client->callgroup;
772         tmp->pickupgroup = client->pickupgroup;
773         tmp->cid.cid_pres = client->callingpres;
774         if (!ast_strlen_zero(client->accountcode))
775                 ast_string_field_set(tmp, accountcode, client->accountcode);
776         if (client->amaflags)
777                 tmp->amaflags = client->amaflags;
778         if (!ast_strlen_zero(client->language))
779                 ast_string_field_set(tmp, language, client->language);
780         if (!ast_strlen_zero(client->musicclass))
781                 ast_string_field_set(tmp, musicclass, client->musicclass);
782         i->owner = tmp;
783         ast_mutex_lock(&usecnt_lock);
784         usecnt++;
785         ast_mutex_unlock(&usecnt_lock);
786         ast_copy_string(tmp->context, client->context, sizeof(tmp->context));
787         ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
788         if (!ast_strlen_zero(i->cid_num))
789                 tmp->cid.cid_num = ast_strdup(i->cid_num);
790         if (!ast_strlen_zero(i->cid_name))
791                 tmp->cid.cid_name = ast_strdup(i->cid_name);
792         if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s"))
793                 tmp->cid.cid_dnid = ast_strdup(i->exten);
794         tmp->priority = 1;
795         ast_setstate(tmp, state);
796         if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) {
797                 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
798                 tmp->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
799                 ast_hangup(tmp);
800                 tmp = NULL;
801         }
802         return tmp;
803 }
804
805 static int jingle_action(struct jingle *client, struct jingle_pvt *p, const char *action)
806 {
807         iks *request, *session = NULL;
808         int res = -1;
809
810         request = iks_new("iq");
811         if (request) {
812                 iks_insert_attrib(request, "type", "set");
813                 iks_insert_attrib(request, "from", client->connection->jid->full);
814                 iks_insert_attrib(request, "to", p->from);
815                 iks_insert_attrib(request, "id", client->connection->mid);
816                 ast_aji_increment_mid(client->connection->mid);
817                 session = iks_new("session");
818                 if (session) {
819                         iks_insert_attrib(session, "type", action);
820                         iks_insert_attrib(session, "id", p->sid);
821                         iks_insert_attrib(session, "initiator",
822                                                           p->initiator ? client->connection->jid->full : p->from);
823                         iks_insert_attrib(session, "xmlns", "http://www.google.com/session");
824                         iks_insert_node(request, session);
825                         iks_send(client->connection->p, request);
826                         iks_delete(session);
827                         res = 0;
828                 }
829                 iks_delete(request);
830         }
831         return res;
832 }
833
834 static void jingle_free_candidates(struct jingle_candidate *candidate)
835 {
836         struct jingle_candidate *last;
837         while (candidate) {
838                 last = candidate;
839                 candidate = candidate->next;
840                 free(last);
841         }
842 }
843
844 static struct jingle_candidate *jingle_dup_candidates(struct jingle_candidate *candidate)
845 {
846         struct jingle_candidate *newcan = NULL, *prev = NULL, *tmp;
847         while (candidate) {
848                 tmp = malloc(sizeof(struct jingle_candidate));
849                 if (tmp) {
850                         memcpy(tmp, candidate, sizeof(struct jingle_candidate));
851                         tmp->next = NULL;
852                         if (prev)
853                                 prev->next = tmp;
854                         else
855                                 newcan = tmp;
856                         prev = tmp;
857                 }
858                 candidate = candidate->next;
859         }
860         return newcan;
861 }
862
863 static void jingle_free_pvt(struct jingle *client, struct jingle_pvt *p)
864 {
865         struct jingle_pvt *cur, *prev = NULL;
866         cur = client->p;
867         while (cur) {
868                 if (cur == p) {
869                         if (prev)
870                                 prev->next = p->next;
871                         else
872                                 client->p = p->next;
873                         break;
874                 }
875                 prev = cur;
876                 cur = cur->next;
877         }
878         if (p->ringrule)
879                 iks_filter_remove_rule(p->parent->connection->f, p->ringrule);
880         if (p->owner)
881                 ast_log(LOG_WARNING, "Uh oh, there's an owner, this is going to be messy.\n");
882         if (p->rtp)
883                 ast_rtp_destroy(p->rtp);
884         if (p->vrtp)
885                 ast_rtp_destroy(p->vrtp);
886         jingle_free_candidates(p->theircandidates);
887         free(p);
888 }
889
890
891 static int jingle_newcall(struct jingle *client, ikspak *pak)
892 {
893         struct jingle_pvt *p, *tmp = client->p;
894         struct ast_channel *chan;
895         int res;
896         iks *codec;
897
898         /* Make sure our new call doesn't exist yet */
899         while (tmp) {
900                 if (iks_find_with_attrib(pak->x, GOOGLE_NODE, GOOGLE_SID, tmp->sid)) {
901                         ast_log(LOG_NOTICE, "Ignoring duplicate call setup on SID %s\n", tmp->sid);
902                         jingle_response(client, pak, "out-of-order");
903                         return -1;
904                 }
905                 tmp = tmp->next;
906         }
907
908         p = jingle_alloc(client, pak->from->partial, iks_find_attrib(pak->query, GOOGLE_SID));
909         if (!p) {
910                 ast_log(LOG_WARNING, "Unable to allocate jingle structure!\n");
911                 return -1;
912         }
913         chan = jingle_new(client, p, AST_STATE_DOWN, pak->from->user);
914         if (chan) {
915                 ast_mutex_lock(&p->lock);
916                 ast_copy_string(p->from, pak->from->full, sizeof(p->from));
917                 if (iks_find_attrib(pak->query, GOOGLE_SID)) {
918                         ast_copy_string(p->sid, iks_find_attrib(pak->query, GOOGLE_SID),
919                                                         sizeof(p->sid));
920                 }
921
922                 codec = iks_child(iks_child(iks_child(pak->x)));
923                 while (codec) {
924                         ast_rtp_set_m_type(p->rtp, atoi(iks_find_attrib(codec, "id")));
925                         ast_rtp_set_rtpmap_type(p->rtp, atoi(iks_find_attrib(codec, "id")), "audio",
926                                                                         iks_find_attrib(codec, "name"));
927                         ast_verbose("yatta!!\n");
928                         codec = iks_next(codec);
929                 }
930                 
931                 ast_mutex_unlock(&p->lock);
932                 ast_setstate(chan, AST_STATE_RING);
933                 res = ast_pbx_start(chan);
934
935                 switch (res) {
936                 case AST_PBX_FAILED:
937                         ast_log(LOG_WARNING, "Failed to start PBX :(\n");
938                         jingle_response(client, pak, "service-unavailable");
939                         break;
940                 case AST_PBX_CALL_LIMIT:
941                         ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n");
942                         jingle_response(client, pak, "service-unavailable");
943                         break;
944                 case AST_PBX_SUCCESS:
945                         jingle_response(client, pak, NULL);
946                         jingle_create_candidates(client, p,
947                                         iks_find_attrib(pak->query, GOOGLE_SID),
948                                         iks_find_attrib(pak->x, "from"));
949                         /* nothing to do */
950                         break;
951                 }
952         } else {
953                 jingle_free_pvt(client, p);
954         }
955         return 1;
956 }
957
958 static int jingle_update_stun(struct jingle *client, struct jingle_pvt *p)
959 {
960         struct jingle_candidate *tmp;
961         struct hostent *hp;
962         struct ast_hostent ahp;
963         struct sockaddr_in sin;
964
965         if (time(NULL) == p->laststun)
966                 return 0;
967
968         tmp = p->theircandidates;
969         p->laststun = time(NULL);
970         while (tmp) {
971                 char username[256];
972                 hp = ast_gethostbyname(tmp->ip, &ahp);
973                 sin.sin_family = AF_INET;
974                 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
975                 sin.sin_port = htons(tmp->port);
976                 snprintf(username, sizeof(username), "%s%s", tmp->username,
977                                  p->ourcandidates->username);
978
979                 ast_rtp_stun_request(p->rtp, &sin, username);
980                 tmp = tmp->next;
981         }
982         return 1;
983 }
984
985 static int jingle_add_candidate(struct jingle *client, ikspak *pak)
986 {
987         struct jingle_pvt *p = NULL, *tmp = NULL;
988         struct aji_client *c = client->connection;
989         struct jingle_candidate *newcandidate = NULL;
990         iks  *traversenodes = NULL, *receipt = NULL;
991         newcandidate =
992                 (struct jingle_candidate *) ast_calloc(1, sizeof(struct jingle_candidate));
993         if (!newcandidate)
994                 return 0;
995         memset(newcandidate, 0, sizeof(struct jingle_candidate));
996         tmp = client->p;
997         while (tmp) {
998                 if (iks_find_with_attrib(pak->x, GOOGLE_NODE, GOOGLE_SID, tmp->sid)) {
999                         p = tmp;
1000                         break;
1001                 }
1002                 tmp = tmp->next;
1003         }
1004
1005         if (!p) {
1006                 ast_verbose("NO MATCH\n");
1007                 return -1;
1008         }
1009
1010         traversenodes = pak->query;
1011         while(traversenodes) {
1012                 ast_verbose("OOH %s\n", iks_name(traversenodes));
1013                 if(!strcasecmp(iks_name(traversenodes), "session")) {
1014                         ast_verbose("XXXX OOH A SESSION\n");
1015                         traversenodes = iks_child(traversenodes);
1016                         continue;
1017                 }
1018                 if(!strcasecmp(iks_name(traversenodes), "candidate")) {
1019                         ast_verbose("XXXX OOH A CANDIDATE\n");
1020                         newcandidate =
1021                                 (struct jingle_candidate *) ast_calloc(1, sizeof(struct jingle_candidate));
1022                         if (!newcandidate)
1023                                 return 0;
1024                         memset(newcandidate, 0, sizeof(struct jingle_candidate));
1025                         ast_copy_string(newcandidate->name, iks_find_attrib(traversenodes, "name"),
1026                                                         sizeof(newcandidate->name));
1027                         ast_copy_string(newcandidate->ip, iks_find_attrib(traversenodes, "address"),
1028                                                         sizeof(newcandidate->ip));
1029                         newcandidate->port = atoi(iks_find_attrib(traversenodes, "port"));
1030                         ast_copy_string(newcandidate->username, iks_find_attrib(traversenodes, "username"),
1031                                                         sizeof(newcandidate->username));
1032                         ast_copy_string(newcandidate->password, iks_find_attrib(traversenodes, "password"),
1033                                                         sizeof(newcandidate->password));
1034                         newcandidate->preference = atof(iks_find_attrib(traversenodes, "preference"));
1035                         if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "udp"))
1036                                 newcandidate->protocol = AJI_PROTOCOL_UDP;
1037                         if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "ssltcp"))
1038                                 newcandidate->protocol = AJI_PROTOCOL_SSLTCP;
1039                 
1040                         if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "stun"))
1041                                 newcandidate->type = AJI_CONNECT_STUN;
1042                         if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "local"))
1043                                 newcandidate->type = AJI_CONNECT_LOCAL;
1044                         if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "relay"))
1045                                 newcandidate->type = AJI_CONNECT_RELAY;
1046                         ast_copy_string(newcandidate->network, iks_find_attrib(traversenodes, "network"),
1047                                                         sizeof(newcandidate->network));
1048                         newcandidate->generation = atoi(iks_find_attrib(traversenodes, "generation"));
1049                         newcandidate->next = NULL;
1050                 
1051                         newcandidate->next = p->theircandidates;
1052                         p->theircandidates = newcandidate;
1053                         p->laststun = 0;
1054                         jingle_update_stun(p->parent, p);
1055                         newcandidate = NULL;
1056                 }
1057                 traversenodes = iks_next(traversenodes);
1058         }
1059         
1060         receipt = iks_new("iq");
1061         iks_insert_attrib(receipt, "type", "result");
1062         iks_insert_attrib(receipt, "from", c->jid->full);
1063         iks_insert_attrib(receipt, "to", iks_find_attrib(pak->x, "from"));
1064         iks_insert_attrib(receipt, "id", iks_find_attrib(pak->x, "id"));
1065         iks_send(c->p, receipt);
1066         iks_delete(receipt);
1067
1068         return 1;
1069 }
1070
1071 static struct ast_frame *jingle_rtp_read(struct ast_channel *ast, struct jingle_pvt *p)
1072 {
1073         struct ast_frame *f;
1074         if (!p->rtp) {
1075                 return &ast_null_frame;
1076         }
1077         f = ast_rtp_read(p->rtp);
1078         jingle_update_stun(p->parent, p);
1079         if (p->owner) {
1080                 /* We already hold the channel lock */
1081                 if (f->frametype == AST_FRAME_VOICE) {
1082                         if (f->subclass != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) {
1083                                 if (option_debug)
1084                                         ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
1085                                 p->owner->nativeformats =
1086                                         (p->owner->nativeformats & AST_FORMAT_VIDEO_MASK) | f->subclass;
1087                                 ast_set_read_format(p->owner, p->owner->readformat);
1088                                 ast_set_write_format(p->owner, p->owner->writeformat);
1089                         }
1090 /*                      if ((ast_test_flag(p, SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) {
1091                                 f = ast_dsp_process(p->owner, p->vad, f);
1092                                 if (option_debug && f && (f->frametype == AST_FRAME_DTMF))
1093                                         ast_log(LOG_DEBUG, "* Detected inband DTMF '%c'\n", f->subclass);
1094                         } */
1095                 }
1096         }
1097         return f;
1098 }
1099
1100 static struct ast_frame *jingle_read(struct ast_channel *ast)
1101 {
1102         struct ast_frame *fr;
1103         struct jingle_pvt *p = ast->tech_pvt;
1104
1105         ast_mutex_lock(&p->lock);
1106         fr = jingle_rtp_read(ast, p);
1107         ast_mutex_unlock(&p->lock);
1108         return fr;
1109 }
1110
1111 /*! \brief Send frame to media channel (rtp) */
1112 static int jingle_write(struct ast_channel *ast, struct ast_frame *frame)
1113 {
1114         struct jingle_pvt *p = ast->tech_pvt;
1115         int res = 0;
1116
1117         switch (frame->frametype) {
1118         case AST_FRAME_VOICE:
1119                 if (!(frame->subclass & ast->nativeformats)) {
1120                         ast_log(LOG_WARNING,
1121                                         "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
1122                                         frame->subclass, ast->nativeformats, ast->readformat,
1123                                         ast->writeformat);
1124                         return 0;
1125                 }
1126                 if (p) {
1127                         ast_mutex_lock(&p->lock);
1128                         if (p->rtp) {
1129                                 res = ast_rtp_write(p->rtp, frame);
1130                         }
1131                         ast_mutex_unlock(&p->lock);
1132                 }
1133                 break;
1134         case AST_FRAME_VIDEO:
1135                 if (p) {
1136                         ast_mutex_lock(&p->lock);
1137                         if (p->vrtp) {
1138                                 res = ast_rtp_write(p->vrtp, frame);
1139                         }
1140                         ast_mutex_unlock(&p->lock);
1141                 }
1142                 break;
1143         case AST_FRAME_IMAGE:
1144                 return 0;
1145                 break;
1146         default:
1147                 ast_log(LOG_WARNING, "Can't send %d type frames with Jingle write\n",
1148                                 frame->frametype);
1149                 return 0;
1150         }
1151
1152         return res;
1153 }
1154
1155 static int jingle_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
1156 {
1157         struct jingle_pvt *p = newchan->tech_pvt;
1158         ast_mutex_lock(&p->lock);
1159
1160         if ((p->owner != oldchan)) {
1161                 ast_mutex_unlock(&p->lock);
1162                 return -1;
1163         }
1164         if (p->owner == oldchan)
1165                 p->owner = newchan;
1166         ast_mutex_unlock(&p->lock);
1167         return 0;
1168 }
1169
1170 static int jingle_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
1171 {
1172         ast_log(LOG_NOTICE, "XXX Implement jingle indicate XXX\n");
1173
1174         return -1;
1175 }
1176
1177 static int jingle_digit(struct ast_channel *ast, char digit)
1178 {
1179         ast_log(LOG_NOTICE, "XXX Implement jingle digit XXX\n");
1180
1181         return -1;
1182 }
1183
1184 static int jingle_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
1185 {
1186         ast_log(LOG_NOTICE, "XXX Implement jingle sendhtml XXX\n");
1187
1188         return -1;
1189 }
1190 static int jingle_transmit_invite(struct jingle_pvt *p)
1191 {
1192         struct jingle *jingle = NULL;
1193         struct aji_client *client = NULL;
1194         iks *iq, *desc, *session;
1195         iks *payload_eg711u, *payload_pcmu;
1196
1197         jingle = p->parent;
1198         client = jingle->connection;
1199         iq = iks_new("iq");
1200         desc = iks_new("description");
1201         session = iks_new("session");
1202         iks_insert_attrib(iq, "type", "set");
1203         iks_insert_attrib(iq, "to", p->from);
1204         iks_insert_attrib(iq, "from", client->jid->full);
1205         iks_insert_attrib(iq, "id", client->mid);
1206         ast_aji_increment_mid(client->mid);
1207         iks_insert_attrib(session, "type", "initiate");
1208         iks_insert_attrib(session, "id", p->sid);
1209         iks_insert_attrib(session, "initiator", client->jid->full);
1210         iks_insert_attrib(session, "xmlns", "http://www.google.com/session");
1211         iks_insert_attrib(desc, "xmlns", "http://www.google.com/session/phone");
1212         payload_pcmu = iks_new("payload-type");
1213         iks_insert_attrib(payload_pcmu, "id", "0");
1214         iks_insert_attrib(payload_pcmu, "name", "PCMU");
1215         payload_eg711u = iks_new("payload-type");
1216         iks_insert_attrib(payload_eg711u, "id", "100");
1217         iks_insert_attrib(payload_eg711u, "name", "EG711U");
1218         iks_insert_node(desc, payload_pcmu);
1219         iks_insert_node(desc, payload_eg711u);
1220         iks_insert_node(iq, session);
1221         iks_insert_node(session, desc);
1222         iks_send(client->p, iq);
1223         iks_delete(iq);
1224         iks_delete(desc);
1225         iks_delete(session);
1226         iks_delete(payload_eg711u);
1227         iks_delete(payload_pcmu);
1228         return 0;
1229 }
1230
1231 static int jingle_auto_congest(void *nothing)
1232 {
1233         struct jingle_pvt *p = nothing;
1234
1235         ast_mutex_lock(&p->lock);
1236         if (p->owner) {
1237                 /* XXX fails on possible deadlock */
1238                 if (!ast_channel_trylock(p->owner)) {
1239                         ast_log(LOG_NOTICE, "Auto-congesting %s\n", p->owner->name);
1240                         ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
1241                         ast_channel_unlock(p->owner);
1242                 }
1243         }
1244         ast_mutex_unlock(&p->lock);
1245         return 0;
1246 }
1247
1248 /*! \brief Initiate new call, part of PBX interface 
1249  *      dest is the dial string */
1250 static int jingle_call(struct ast_channel *ast, char *dest, int timeout)
1251 {
1252         struct jingle_pvt *p = ast->tech_pvt;
1253
1254         if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
1255                 ast_log(LOG_WARNING, "jingle_call called on %s, neither down nor reserved\n", ast->name);
1256                 return -1;
1257         }
1258
1259         ast_setstate(ast, AST_STATE_RING);
1260         p->jointcapability = p->capability;
1261         if (!p->ringrule) {
1262                 ast_copy_string(p->ring, p->parent->connection->mid, sizeof(p->ring));
1263                 p->ringrule = iks_filter_add_rule(p->parent->connection->f, jingle_ringing_ack, p,
1264                                                         IKS_RULE_ID, p->ring, IKS_RULE_DONE);
1265         } else {
1266                 ast_log(LOG_WARNING, "Whoa, already have a ring rule!\n");
1267         }
1268         jingle_transmit_invite(p);
1269         jingle_create_candidates(p->parent, p, p->sid, p->from);
1270
1271         return 0;
1272 }
1273
1274 /*! \brief Hangup a call through the jingle proxy channel */
1275 static int jingle_hangup(struct ast_channel *ast)
1276 {
1277         struct jingle_pvt *p = ast->tech_pvt;
1278         struct jingle *client;
1279
1280         ast_mutex_lock(&p->lock);
1281         client = p->parent;
1282         p->owner = NULL;
1283         ast->tech_pvt = NULL;
1284         if (!p->alreadygone)
1285                 jingle_action(client, p, "terminate");
1286         ast_mutex_unlock(&p->lock);
1287
1288         jingle_free_pvt(client, p);
1289         ast_mutex_lock(&usecnt_lock);
1290         usecnt--;
1291         ast_mutex_unlock(&usecnt_lock);
1292
1293         return 0;
1294 }
1295
1296 /*! \brief Part of PBX interface */
1297 static struct ast_channel *jingle_request(const char *type, int format, void *data, int *cause)
1298 {
1299         struct jingle_pvt *p = NULL;
1300         struct jingle *client = NULL;
1301         char *sender = NULL, *to = NULL, *s = NULL;
1302         struct ast_channel *chan = NULL;
1303
1304         if (data) {
1305                 s = ast_strdupa((char *) data);
1306                 if (s) {
1307                         sender = strsep(&s, "/");
1308                         if (sender && (sender[0] != '\0'))
1309                                 to = strsep(&s, "/");
1310                         if (!to) {
1311                                 ast_log(LOG_ERROR, "Bad arguments\n");
1312                                 if (s)
1313                                         free(s);
1314                                 return NULL;
1315                         }
1316                 }
1317         }
1318         ast_verbose("to : %s\n from :%s\n", to, sender);
1319         client = find_jingle(to, sender);
1320         if (!client) {
1321                 ast_log(LOG_WARNING, "Could not find Recipiant.\n");
1322                 if (s)
1323                         free(s);
1324                 return NULL;
1325         }
1326         p = jingle_alloc(client, to, NULL);
1327         if (p) {
1328                 chan = jingle_new(client, p, AST_STATE_DOWN, to);
1329         }
1330         return chan;
1331 }
1332
1333 #if 0
1334 /*! \brief CLI command "jingle show channels" */
1335 static int jingle_show(int fd, int argc, char **argv)
1336 {
1337         struct jingle_pvt *p = NULL;
1338         struct jingle *peer = NULL;
1339         struct jingle_candidate *tmp;
1340         struct jingle *client = NULL;
1341         client = ast_aji_get_client("asterisk");
1342         if (argc != 3)
1343                 return RESULT_SHOWUSAGE;
1344         ast_mutex_lock(&jinglelock);
1345         if (client)
1346                 p = jingles->p;
1347         while (p) {
1348                 ast_mutex_lock(&p->lock);
1349                 ast_cli(fd, "SID = %s\n", p->sid);
1350                 tmp = p->candidates;
1351                 while (tmp) {
1352                         ast_verbose("port %d\n", tmp->port);
1353                         tmp = tmp->next;
1354                 }
1355                 ast_mutex_unlock(&p->lock);
1356                 p = p->next;
1357         }
1358         if (!jingles->p)
1359                 ast_cli(fd, "No jingle channels in use\n");
1360         ast_mutex_unlock(&jinglelock);
1361         return RESULT_SUCCESS;
1362 }
1363 #endif
1364 static char show_jingle_usage[] =
1365         "Usage: jingle show channels\n"
1366         "       Provides summary information on active jingle channels.\n";
1367
1368 //static struct ast_cli_entry cli_show_jingle = {
1369 //  { "jingle", "show", "channels", NULL }, jingle_show, 
1370 //  "Show status of jingle channels", show_jingle_usage, NULL };
1371
1372
1373 static int jingle_parser(void *data, ikspak *pak)
1374 {
1375         struct jingle *client = ASTOBJ_REF((struct jingle *) data);
1376
1377         ast_verbose("WOOHOO!!!\n");
1378         if (iks_find_with_attrib(pak->x, GOOGLE_NODE, "type", JINGLE_INITIATE)) {
1379                 /* New call */
1380                 jingle_newcall(client, pak);
1381         } else if (iks_find_with_attrib(pak->x, GOOGLE_NODE, "type", GOOGLE_NEGOTIATE)) {
1382                 ast_log(LOG_DEBUG, "About to add candidate!\n");
1383                 jingle_add_candidate(client, pak);
1384                 ast_log(LOG_DEBUG, "Candidate Added!\n");
1385         } else if (iks_find_with_attrib(pak->x, GOOGLE_NODE, "type", GOOGLE_ACCEPT)) {
1386                 jingle_is_answered(client, pak);
1387         } else if (iks_find_with_attrib(pak->x, GOOGLE_NODE, "type", "terminate")) {
1388                 ast_verbose("not this\n");
1389                 jingle_hangup_farend(client, pak);
1390         } else if (iks_find_with_attrib(pak->x, GOOGLE_NODE, "type", "reject")) {
1391                 ast_verbose("not this\n");
1392                 jingle_hangup_farend(client, pak);
1393         }
1394         ASTOBJ_UNREF(client, jingle_member_destroy);
1395         return IKS_FILTER_EAT;
1396 }
1397
1398 static struct jingle_candidate *jingle_create_candidate(char *args)
1399 {
1400         char *name, *type, *preference, *protocol;
1401         struct jingle_candidate *res;
1402         res = malloc(sizeof(struct jingle_candidate));
1403         memset(res, 0, sizeof(struct jingle_candidate));
1404         if (args)
1405                 name = args;
1406         if ((args = strchr(args, ','))) {
1407                 *args = '\0';
1408                 args++;
1409                 preference = args;
1410         }
1411         if ((args = strchr(args, ','))) {
1412                 *args = '\0';
1413                 args++;
1414                 protocol = args;
1415         }
1416         if ((args = strchr(args, ','))) {
1417                 *args = '\0';
1418                 args++;
1419                 type = args;
1420         }
1421         if (name)
1422                 ast_copy_string(res->name, name, sizeof(res->name));
1423         if (preference) {
1424                 res->preference = atof(preference);
1425         }
1426         if (protocol) {
1427                 if (!strcasecmp("udp", protocol))
1428                         res->protocol = AJI_PROTOCOL_UDP;
1429                 if (!strcasecmp("ssltcp", protocol))
1430                         res->protocol = AJI_PROTOCOL_SSLTCP;
1431         }
1432         if (type) {
1433                 if (!strcasecmp("stun", type))
1434                         res->type = AJI_CONNECT_STUN;
1435                 if (!strcasecmp("local", type))
1436                         res->type = AJI_CONNECT_LOCAL;
1437                 if (!strcasecmp("relay", type))
1438                         res->type = AJI_CONNECT_RELAY;
1439         }
1440
1441         return res;
1442 }
1443
1444 static int jingle_create_member(char *label, struct ast_variable *var, int allowguest,
1445                                                                 struct ast_codec_pref prefs, char *context,
1446                                                                 struct jingle *member)
1447 {
1448         struct aji_client *client;
1449         if (!member)
1450                 ast_log(LOG_WARNING, "Out of memory.\n");
1451
1452         ast_copy_string(member->name, label, sizeof(member->name));
1453         ast_copy_string(member->user, label, sizeof(member->user));
1454         ast_copy_string(member->context, context, sizeof(member->context));
1455         member->allowguest = allowguest;
1456         member->prefs = prefs;
1457         while (var) {
1458 #if 0
1459                 struct jingle_candidate *candidate = NULL;
1460 #endif
1461                 if (!strcasecmp(var->name, "username"))
1462                         ast_copy_string(member->user, var->value, sizeof(member->user));
1463                 else if (!strcasecmp(var->name, "disallow"))
1464                         ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 0);
1465                 else if (!strcasecmp(var->name, "allow"))
1466                         ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 1);
1467                 else if (!strcasecmp(var->name, "context"))
1468                         ast_copy_string(member->context, var->value, sizeof(member->context));
1469 #if 0
1470                 else if (!strcasecmp(var->name, "candidate")) {
1471                         candidate = jingle_create_candidate(var->value);
1472                         if (candidate) {
1473                                 candidate->next = member->ourcandidates;
1474                                 member->ourcandidates = candidate;
1475                         }
1476                 }
1477 #endif
1478                 else if (!strcasecmp(var->name, "connection")) {
1479                         if ((client = ast_aji_get_client(var->value))) {
1480                                 member->connection = client;
1481                                 iks_filter_add_rule(client->f, jingle_parser, member, IKS_RULE_TYPE,
1482                                                                         IKS_PAK_IQ, IKS_RULE_FROM_PARTIAL, member->user,
1483                                                                         IKS_RULE_NS, "http://www.google.com/session",
1484                                                                         IKS_RULE_DONE);
1485                         } else {
1486                                 ast_log(LOG_ERROR, "connection referenced not found!\n");
1487                                 return 0;
1488                         }
1489                 }
1490                 var = var->next;
1491         }
1492         if (member->connection && member->user)
1493                 member->buddy = ASTOBJ_CONTAINER_FIND(&member->connection->buddies, member->user);
1494         else {
1495                 ast_log(LOG_ERROR, "No Connection or Username!\n");
1496         }
1497         ast_verbose("LABEL: %s\n member->name %s\n member->user %s\n", label, member->name,
1498                                 member->user);
1499         return 1;
1500 }
1501
1502 static int jingle_load_config(void)
1503 {
1504         char *cat = NULL;
1505         struct ast_config *cfg = NULL;
1506         char context[100];
1507         int allowguest = 1;
1508         struct ast_variable *var;
1509         struct jingle *member;
1510         struct ast_codec_pref prefs;
1511         struct aji_client_container *clients;
1512         struct jingle_candidate *global_candidates = NULL;
1513
1514         cfg = ast_config_load(JINGLE_CONFIG);
1515         if (!cfg) {
1516                 ast_log(LOG_WARNING, "No such configuration file %s\n", JINGLE_CONFIG);
1517                 return 0;
1518         }
1519
1520         cat = ast_category_browse(cfg, NULL);
1521         for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
1522                 if (!strcasecmp(var->name, "allowguest"))
1523                         allowguest =
1524                                 (ast_true(ast_variable_retrieve(cfg, "general", "allowguest"))) ? 1 : 0;
1525                 else if (!strcasecmp(var->name, "disallow"))
1526                         ast_parse_allow_disallow(&prefs, &global_capability, var->value, 0);
1527                 else if (!strcasecmp(var->name, "allow"))
1528                         ast_parse_allow_disallow(&prefs, &global_capability, var->value, 1);
1529                 else if (!strcasecmp(var->name, "context"))
1530                         ast_copy_string(context, var->value, sizeof(context));
1531                 else if (!strcasecmp(var->name, "externip"))
1532                         ast_copy_string(externip, var->value, sizeof(externip));
1533 #if 0
1534                 else if (!strcasecmp(var->name, "candidate")) {
1535                         candidate = jingle_create_candidate(var->value);
1536                         if (candidate) {
1537                                 candidate->next = global_candidates;
1538                                 global_candidates = candidate;
1539                         }
1540                 }
1541 #endif
1542         }
1543         while (cat) {
1544                 if (strcasecmp(cat, "general")) {
1545                         var = ast_variable_browse(cfg, cat);
1546                         member = (struct jingle *) malloc(sizeof(struct jingle));
1547                         memset(member, 0, sizeof(struct jingle));
1548                         ASTOBJ_INIT(member);
1549                         ASTOBJ_WRLOCK(member);
1550                         if (!strcasecmp(cat, "guest")) {
1551                                 ast_copy_string(member->name, "guest", sizeof(member->name));
1552                                 ast_copy_string(member->user, "guest", sizeof(member->user));
1553                                 ast_copy_string(member->context, context, sizeof(member->context));
1554                                 member->allowguest = allowguest;
1555 #if 0
1556                                 member->ourcandidates = jingle_dup_candidates(global_candidates);
1557 #endif
1558                                 member->prefs = prefs;
1559                                 while (var) {
1560                                         if (!strcasecmp(var->name, "disallow"))
1561                                                 ast_parse_allow_disallow(&member->prefs, &member->capability,
1562                                                                                                  var->value, 0);
1563                                         else if (!strcasecmp(var->name, "allow"))
1564                                                 ast_parse_allow_disallow(&member->prefs, &member->capability,
1565                                                                                                  var->value, 1);
1566                                         else if (!strcasecmp(var->name, "context"))
1567                                                 ast_copy_string(member->context, var->value,
1568                                                                                 sizeof(member->context));
1569 #if 0
1570                                         else if (!strcasecmp(var->name, "candidate")) {
1571                                                 candidate = jingle_create_candidate(var->value);
1572                                                 if (candidate) {
1573                                                         candidate->next = member->ourcandidates;
1574                                                         member->ourcandidates = candidate;
1575                                                 }
1576                                         }
1577 #endif
1578                                         var = var->next;
1579                                 }
1580                                 ASTOBJ_UNLOCK(member);
1581                                 clients = ast_aji_get_clients();
1582                                 if (clients) {
1583                                         ASTOBJ_CONTAINER_TRAVERSE(clients, 1, {
1584                                                 ASTOBJ_WRLOCK(iterator);
1585                                                 ASTOBJ_WRLOCK(member);
1586                                                 member->connection = iterator;
1587                                                 iks_filter_add_rule(iterator->f, jingle_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS,
1588                                                                                 "http://www.google.com/session", IKS_RULE_DONE);
1589                                                 ASTOBJ_UNLOCK(member);
1590                                                 ASTOBJ_CONTAINER_LINK(&jingles, member);
1591                                                 ASTOBJ_UNLOCK(iterator);
1592                                         });
1593                                 } else {
1594                                         ASTOBJ_UNLOCK(member);
1595                                         ASTOBJ_UNREF(member, jingle_member_destroy);
1596                                 }
1597                         } else {
1598                                 if (jingle_create_member(cat, var, allowguest, prefs, context, member)) {
1599                                         ast_verbose("step member\n");
1600                                         ASTOBJ_UNLOCK(member);
1601                                         ASTOBJ_CONTAINER_LINK(&jingles, member);
1602                                         ASTOBJ_UNREF(member, jingle_member_destroy);
1603                                 } else {
1604                                         ASTOBJ_UNLOCK(member);
1605                                         ASTOBJ_UNREF(member, jingle_member_destroy);
1606                                 }
1607                         }
1608                 }
1609                 cat = ast_category_browse(cfg, cat);
1610         }
1611         jingle_free_candidates(global_candidates);
1612         return 1;
1613 }
1614
1615 /*! \brief Load module into PBX, register channel */
1616 static int load_module(void *mod)
1617 {
1618         ast_verbose("step 1\n");
1619         ASTOBJ_CONTAINER_INIT(&jingles);
1620         if (!jingle_load_config()) {
1621                 ast_log(LOG_ERROR, "Unable to read config file %s\n", JINGLE_CONFIG);
1622                 return -1;
1623         }
1624
1625         sched = sched_context_create();
1626
1627         if (!sched) {
1628                 ast_log(LOG_WARNING, "Unable to create schedule context\n");
1629         }
1630
1631         io = io_context_create();
1632         if (!io) {
1633                 ast_log(LOG_WARNING, "Unable to create I/O context\n");
1634         }
1635
1636         if (ast_find_ourip(&__ourip, bindaddr)) {
1637                 ast_log(LOG_WARNING, "Unable to get own IP address, Jingle disabled\n");
1638                 return 0;
1639         }
1640
1641         ast_rtp_proto_register(&jingle_rtp);
1642
1643         /* Make sure we can register our channel type */
1644         if (ast_channel_register(&jingle_tech)) {
1645                 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
1646                 return -1;
1647         }
1648 //  ast_cli_register(&cli_show_xmpps);
1649         return 0;
1650 }
1651
1652 /*! \brief Reload module */
1653 static int reload(void *mod)
1654 {
1655         return 0;
1656 }
1657
1658 /*! \brief Unload the jingle channel from Asterisk */
1659 static int unload_module(void *mod)
1660 {
1661 //  struct jingle_pvt *p = NULL;
1662         struct aji_client *client = NULL;
1663         client = ast_aji_get_client("asterisk");
1664         /* First, take us out of the channel loop */
1665 //  ast_cli_unregister(&cli_show_xmpps);
1666         ast_channel_unregister(&jingle_tech);
1667         ast_rtp_proto_unregister(&jingle_rtp);
1668         if (!ast_mutex_lock(&jinglelock)) {
1669                 /* Hangup all interfaces if they have an owner */
1670                 //  p = jingles->p;
1671                 //  while(p) {
1672                 //      if (p->owner)
1673                 //          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
1674                 //      p = p->next;
1675                 //  }
1676                 //  jingles->p = NULL;
1677                 ast_mutex_unlock(&jinglelock);
1678         } else {
1679                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
1680                 return -1;
1681         }
1682         return 0;
1683 }
1684
1685 static const char *key(void)
1686 {
1687         return ASTERISK_GPL_KEY;
1688 }
1689
1690 static const char *description(void)
1691 {
1692         return desc;
1693 }
1694
1695 STD_MOD(MOD_1, reload, NULL, NULL);