#include "asterisk.h"
#include <sys/socket.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/signal.h>
#include <iksemel.h>
#include <pthread.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/file.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/musiconhold.h"
#include "asterisk/manager.h"
#include "asterisk/stringfields.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/astobj.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/jabber.h"
#include "asterisk/jingle.h"

Go to the source code of this file.
Data Structures | |
| struct | jingle |
| struct | jingle_candidate |
| struct | jingle_container |
| struct | jingle_pvt |
Defines | |
| #define | FORMAT "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n" |
| #define | JINGLE_CONFIG "jingle.conf" |
Enumerations | |
| enum | jingle_connect_type { AJI_CONNECT_HOST, AJI_CONNECT_PRFLX, AJI_CONNECT_RELAY, AJI_CONNECT_SRFLX } |
| enum | jingle_protocol { AJI_PROTOCOL_UDP, AJI_PROTOCOL_SSLTCP } |
Functions | |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| static void | add_codec_to_answer (const struct jingle_pvt *p, struct ast_format *codec, iks *dcodecs) |
| static struct jingle * | find_jingle (char *name, char *connection) |
| static int | jingle_accept_call (struct jingle *client, struct jingle_pvt *p) |
| static int | jingle_action (struct jingle *client, struct jingle_pvt *p, const char *action) |
| static int | jingle_add_candidate (struct jingle *client, ikspak *pak) |
| static struct jingle_pvt * | jingle_alloc (struct jingle *client, const char *from, const char *sid) |
| static int | jingle_answer (struct ast_channel *ast) |
| static int | jingle_call (struct ast_channel *ast, const char *dest, int timeout) |
| Initiate new call, part of PBX interface dest is the dial string. | |
| static int | jingle_create_candidates (struct jingle *client, struct jingle_pvt *p, char *sid, char *from) |
| static int | jingle_create_member (char *label, struct ast_variable *var, int allowguest, struct ast_codec_pref prefs, char *context, struct jingle *member) |
| static int | jingle_digit (struct ast_channel *ast, char digit, unsigned int duration) |
| static int | jingle_digit_begin (struct ast_channel *ast, char digit) |
| static int | jingle_digit_end (struct ast_channel *ast, char digit, unsigned int duration) |
| static char * | jingle_do_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI command "jingle reload". | |
| static int | jingle_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
| static void | jingle_free_candidates (struct jingle_candidate *candidate) |
| static void | jingle_free_pvt (struct jingle *client, struct jingle_pvt *p) |
| static void | jingle_get_codec (struct ast_channel *chan, struct ast_format_cap *result) |
| static enum ast_rtp_glue_result | jingle_get_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance **instance) |
| static int | jingle_handle_dtmf (struct jingle *client, ikspak *pak) |
| static int | jingle_hangup (struct ast_channel *ast) |
| Hangup a call through the jingle proxy channel. | |
| static int | jingle_hangup_farend (struct jingle *client, ikspak *pak) |
| static int | jingle_indicate (struct ast_channel *ast, int condition, const void *data, size_t datalen) |
| static int | jingle_is_answered (struct jingle *client, ikspak *pak) |
| static int | jingle_load_config (void) |
| static void | jingle_member_destroy (struct jingle *obj) |
| static struct ast_channel * | jingle_new (struct jingle *client, struct jingle_pvt *i, int state, const char *title, const char *linkedid) |
| Start new jingle channel. | |
| static int | jingle_newcall (struct jingle *client, ikspak *pak) |
| static int | jingle_parser (void *data, ikspak *pak) |
| static struct ast_frame * | jingle_read (struct ast_channel *ast) |
| static struct ast_channel * | jingle_request (const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause) |
| Part of PBX interface. | |
| static int | jingle_response (struct jingle *client, ikspak *pak, const char *reasonstr, const char *reasonstr2) |
| static int | jingle_ringing_ack (void *data, ikspak *pak) |
| static struct ast_frame * | jingle_rtp_read (struct ast_channel *ast, struct jingle_pvt *p) |
| static int | jingle_sendhtml (struct ast_channel *ast, int subclass, const char *data, int datalen) |
| static int | jingle_sendtext (struct ast_channel *ast, const char *text) |
| 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) |
| static char * | jingle_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI command "jingle show channels". | |
| static int | jingle_transmit_invite (struct jingle_pvt *p) |
| static int | jingle_update_stun (struct jingle *client, struct jingle_pvt *p) |
| static int | jingle_write (struct ast_channel *ast, struct ast_frame *frame) |
| Send frame to media channel (rtp). | |
| static int | load_module (void) |
| Load module into PBX, register channel. | |
| static int | reload (void) |
| Reload module. | |
| static int | unload_module (void) |
| Unload the jingle channel from Asterisk. | |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Jingle Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, } |
| static struct in_addr | __ourip |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct sockaddr_in | bindaddr = { 0, } |
| static const char | channel_type [] = "Jingle" |
| static struct ast_jb_conf | default_jbconf |
| static const char | desc [] = "Jingle Channel" |
| static char | externip [16] |
| static struct ast_format_cap * | global_capability |
| static struct ast_jb_conf | global_jbconf |
| static struct io_context * | io |
| static struct ast_cli_entry | jingle_cli [] |
| static struct jingle_container | jingle_list |
| static struct ast_rtp_glue | jingle_rtp_glue |
| static struct ast_channel_tech | jingle_tech |
| PBX interface structure for channel registration. | |
| static ast_mutex_t | jinglelock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } |
| static struct ast_sched_context * | sched |
Definition in file chan_jingle.c.
| #define FORMAT "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n" |
| #define JINGLE_CONFIG "jingle.conf" |
| enum jingle_connect_type |
Definition at line 92 of file chan_jingle.c.
00092 { 00093 AJI_CONNECT_HOST, 00094 AJI_CONNECT_PRFLX, 00095 AJI_CONNECT_RELAY, 00096 AJI_CONNECT_SRFLX, 00097 };
| enum jingle_protocol |
Definition at line 87 of file chan_jingle.c.
00087 { 00088 AJI_PROTOCOL_UDP, 00089 AJI_PROTOCOL_SSLTCP, 00090 };
| static void __reg_module | ( | void | ) | [static] |
Definition at line 2044 of file chan_jingle.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 2044 of file chan_jingle.c.
| static void add_codec_to_answer | ( | const struct jingle_pvt * | p, | |
| struct ast_format * | codec, | |||
| iks * | dcodecs | |||
| ) | [static] |
Definition at line 268 of file chan_jingle.c.
References ast_getformatname(), and format.
00269 { 00270 const char *format = ast_getformatname(codec); 00271 00272 if (!strcasecmp("ulaw", format)) { 00273 iks *payload_eg711u, *payload_pcmu; 00274 payload_pcmu = iks_new("payload-type"); 00275 iks_insert_attrib(payload_pcmu, "id", "0"); 00276 iks_insert_attrib(payload_pcmu, "name", "PCMU"); 00277 payload_eg711u = iks_new("payload-type"); 00278 iks_insert_attrib(payload_eg711u, "id", "100"); 00279 iks_insert_attrib(payload_eg711u, "name", "EG711U"); 00280 iks_insert_node(dcodecs, payload_pcmu); 00281 iks_insert_node(dcodecs, payload_eg711u); 00282 } 00283 if (!strcasecmp("alaw", format)) { 00284 iks *payload_eg711a; 00285 iks *payload_pcma = iks_new("payload-type"); 00286 iks_insert_attrib(payload_pcma, "id", "8"); 00287 iks_insert_attrib(payload_pcma, "name", "PCMA"); 00288 payload_eg711a = iks_new("payload-type"); 00289 iks_insert_attrib(payload_eg711a, "id", "101"); 00290 iks_insert_attrib(payload_eg711a, "name", "EG711A"); 00291 iks_insert_node(dcodecs, payload_pcma); 00292 iks_insert_node(dcodecs, payload_eg711a); 00293 } 00294 if (!strcasecmp("ilbc", format)) { 00295 iks *payload_ilbc = iks_new("payload-type"); 00296 iks_insert_attrib(payload_ilbc, "id", "97"); 00297 iks_insert_attrib(payload_ilbc, "name", "iLBC"); 00298 iks_insert_node(dcodecs, payload_ilbc); 00299 } 00300 if (!strcasecmp("g723", format)) { 00301 iks *payload_g723 = iks_new("payload-type"); 00302 iks_insert_attrib(payload_g723, "id", "4"); 00303 iks_insert_attrib(payload_g723, "name", "G723"); 00304 iks_insert_node(dcodecs, payload_g723); 00305 } 00306 }
| static struct jingle* find_jingle | ( | char * | name, | |
| char * | connection | |||
| ) | [static, read] |
Definition at line 242 of file chan_jingle.c.
References ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_FIND_FULL, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, and jingle_list.
Referenced by jingle_request().
00243 { 00244 struct jingle *jingle = NULL; 00245 00246 jingle = ASTOBJ_CONTAINER_FIND(&jingle_list, name); 00247 if (!jingle && strchr(name, '@')) 00248 jingle = ASTOBJ_CONTAINER_FIND_FULL(&jingle_list, name, user,,, strcasecmp); 00249 00250 if (!jingle) { 00251 /* guest call */ 00252 ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, { 00253 ASTOBJ_RDLOCK(iterator); 00254 if (!strcasecmp(iterator->name, "guest")) { 00255 jingle = iterator; 00256 } 00257 ASTOBJ_UNLOCK(iterator); 00258 00259 if (jingle) 00260 break; 00261 }); 00262 00263 } 00264 return jingle; 00265 }
| static int jingle_accept_call | ( | struct jingle * | client, | |
| struct jingle_pvt * | p | |||
| ) | [static] |
Definition at line 308 of file chan_jingle.c.
References add_codec_to_answer(), ast_aji_increment_mid(), ast_aji_send(), ast_codec_pref_index(), AST_CODEC_PREF_SIZE, ast_format_cap_add(), ast_format_cap_alloc_nolock(), ast_format_cap_destroy(), ast_format_cap_iscompatible(), jingle::cap, jingle::connection, jingle_pvt::initiator, aji_client::jid, JINGLE_ACCEPT, JINGLE_AUDIO_RTP_NS, JINGLE_NODE, JINGLE_NS, JINGLE_SID, aji_client::mid, jingle::p, jingle::prefs, jingle_pvt::sid, jingle_pvt::them, and jingle::user.
Referenced by jingle_answer().
00309 { 00310 struct jingle_pvt *tmp = client->p; 00311 struct aji_client *c = client->connection; 00312 iks *iq, *jingle, *dcodecs, *payload_red, *payload_audio, *payload_cn; 00313 int x; 00314 struct ast_format pref_codec; 00315 struct ast_format_cap *alreadysent = ast_format_cap_alloc_nolock(); 00316 00317 if (p->initiator || !alreadysent) 00318 return 1; 00319 00320 iq = iks_new("iq"); 00321 jingle = iks_new(JINGLE_NODE); 00322 dcodecs = iks_new("description"); 00323 if (iq && jingle && dcodecs) { 00324 iks_insert_attrib(dcodecs, "xmlns", JINGLE_AUDIO_RTP_NS); 00325 00326 for (x = 0; x < AST_CODEC_PREF_SIZE; x++) { 00327 if (!(ast_codec_pref_index(&client->prefs, x, &pref_codec))) 00328 break; 00329 if (!(ast_format_cap_iscompatible(client->cap, &pref_codec))) 00330 continue; 00331 if ((ast_format_cap_iscompatible(alreadysent, &pref_codec))) 00332 continue; 00333 add_codec_to_answer(p, &pref_codec, dcodecs); 00334 ast_format_cap_add(alreadysent, &pref_codec); 00335 } 00336 payload_red = iks_new("payload-type"); 00337 iks_insert_attrib(payload_red, "id", "117"); 00338 iks_insert_attrib(payload_red, "name", "red"); 00339 payload_audio = iks_new("payload-type"); 00340 iks_insert_attrib(payload_audio, "id", "106"); 00341 iks_insert_attrib(payload_audio, "name", "audio/telephone-event"); 00342 payload_cn = iks_new("payload-type"); 00343 iks_insert_attrib(payload_cn, "id", "13"); 00344 iks_insert_attrib(payload_cn, "name", "CN"); 00345 00346 00347 iks_insert_attrib(iq, "type", "set"); 00348 iks_insert_attrib(iq, "to", (p->them) ? p->them : client->user); 00349 iks_insert_attrib(iq, "id", client->connection->mid); 00350 ast_aji_increment_mid(client->connection->mid); 00351 00352 iks_insert_attrib(jingle, "xmlns", JINGLE_NS); 00353 iks_insert_attrib(jingle, "action", JINGLE_ACCEPT); 00354 iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them); 00355 iks_insert_attrib(jingle, JINGLE_SID, tmp->sid); 00356 iks_insert_node(iq, jingle); 00357 iks_insert_node(jingle, dcodecs); 00358 iks_insert_node(dcodecs, payload_red); 00359 iks_insert_node(dcodecs, payload_audio); 00360 iks_insert_node(dcodecs, payload_cn); 00361 00362 ast_aji_send(c, iq); 00363 00364 iks_delete(payload_red); 00365 iks_delete(payload_audio); 00366 iks_delete(payload_cn); 00367 iks_delete(dcodecs); 00368 iks_delete(jingle); 00369 iks_delete(iq); 00370 } 00371 alreadysent = ast_format_cap_destroy(alreadysent); 00372 return 1; 00373 }
| static int jingle_action | ( | struct jingle * | client, | |
| struct jingle_pvt * | p, | |||
| const char * | action | |||
| ) | [static] |
Definition at line 928 of file chan_jingle.c.
References ast_aji_increment_mid(), ast_aji_send(), jingle::connection, jingle_pvt::initiator, aji_client::jid, JINGLE_NS, JINGLE_SID, aji_client::mid, jingle_pvt::sid, and jingle_pvt::them.
Referenced by jingle_hangup().
00929 { 00930 iks *iq, *jingle = NULL; 00931 int res = -1; 00932 00933 iq = iks_new("iq"); 00934 jingle = iks_new("jingle"); 00935 00936 if (iq) { 00937 iks_insert_attrib(iq, "type", "set"); 00938 iks_insert_attrib(iq, "from", client->connection->jid->full); 00939 iks_insert_attrib(iq, "to", p->them); 00940 iks_insert_attrib(iq, "id", client->connection->mid); 00941 ast_aji_increment_mid(client->connection->mid); 00942 if (jingle) { 00943 iks_insert_attrib(jingle, "action", action); 00944 iks_insert_attrib(jingle, JINGLE_SID, p->sid); 00945 iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them); 00946 iks_insert_attrib(jingle, "xmlns", JINGLE_NS); 00947 00948 iks_insert_node(iq, jingle); 00949 00950 ast_aji_send(client->connection, iq); 00951 res = 0; 00952 } 00953 } 00954 00955 iks_delete(jingle); 00956 iks_delete(iq); 00957 00958 return res; 00959 }
| static int jingle_add_candidate | ( | struct jingle * | client, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 1143 of file chan_jingle.c.
References AJI_CONNECT_HOST, AJI_CONNECT_PRFLX, AJI_CONNECT_RELAY, AJI_CONNECT_SRFLX, AJI_PROTOCOL_SSLTCP, AJI_PROTOCOL_UDP, ast_aji_send(), ast_calloc, ast_copy_string(), jingle::connection, jingle_candidate::generation, jingle_candidate::ip, aji_client::jid, JINGLE_NODE, JINGLE_SID, jingle_update_stun(), jingle_pvt::laststun, jingle_candidate::network, jingle_candidate::next, jingle_pvt::next, jingle::p, jingle_pvt::parent, jingle_candidate::password, jingle_candidate::port, jingle_candidate::protocol, jingle_pvt::theircandidates, and jingle_candidate::type.
Referenced by jingle_parser().
01144 { 01145 struct jingle_pvt *p = NULL, *tmp = NULL; 01146 struct aji_client *c = client->connection; 01147 struct jingle_candidate *newcandidate = NULL; 01148 iks *traversenodes = NULL, *receipt = NULL; 01149 01150 for (tmp = client->p; tmp; tmp = tmp->next) { 01151 if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) { 01152 p = tmp; 01153 break; 01154 } 01155 } 01156 01157 if (!p) 01158 return -1; 01159 01160 traversenodes = pak->query; 01161 while(traversenodes) { 01162 if(!strcasecmp(iks_name(traversenodes), "jingle")) { 01163 traversenodes = iks_child(traversenodes); 01164 continue; 01165 } 01166 if(!strcasecmp(iks_name(traversenodes), "content")) { 01167 traversenodes = iks_child(traversenodes); 01168 continue; 01169 } 01170 if(!strcasecmp(iks_name(traversenodes), "transport")) { 01171 traversenodes = iks_child(traversenodes); 01172 continue; 01173 } 01174 01175 if(!strcasecmp(iks_name(traversenodes), "candidate")) { 01176 newcandidate = ast_calloc(1, sizeof(*newcandidate)); 01177 if (!newcandidate) 01178 return 0; 01179 ast_copy_string(newcandidate->ip, iks_find_attrib(traversenodes, "ip"), sizeof(newcandidate->ip)); 01180 newcandidate->port = atoi(iks_find_attrib(traversenodes, "port")); 01181 ast_copy_string(newcandidate->password, iks_find_attrib(traversenodes, "pwd"), sizeof(newcandidate->password)); 01182 if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "udp")) 01183 newcandidate->protocol = AJI_PROTOCOL_UDP; 01184 else if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "ssltcp")) 01185 newcandidate->protocol = AJI_PROTOCOL_SSLTCP; 01186 01187 if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "host")) 01188 newcandidate->type = AJI_CONNECT_HOST; 01189 else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "prflx")) 01190 newcandidate->type = AJI_CONNECT_PRFLX; 01191 else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "relay")) 01192 newcandidate->type = AJI_CONNECT_RELAY; 01193 else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "srflx")) 01194 newcandidate->type = AJI_CONNECT_SRFLX; 01195 01196 newcandidate->network = atoi(iks_find_attrib(traversenodes, "network")); 01197 newcandidate->generation = atoi(iks_find_attrib(traversenodes, "generation")); 01198 newcandidate->next = NULL; 01199 01200 newcandidate->next = p->theircandidates; 01201 p->theircandidates = newcandidate; 01202 p->laststun = 0; 01203 jingle_update_stun(p->parent, p); 01204 newcandidate = NULL; 01205 } 01206 traversenodes = iks_next(traversenodes); 01207 } 01208 01209 receipt = iks_new("iq"); 01210 iks_insert_attrib(receipt, "type", "result"); 01211 iks_insert_attrib(receipt, "from", c->jid->full); 01212 iks_insert_attrib(receipt, "to", iks_find_attrib(pak->x, "from")); 01213 iks_insert_attrib(receipt, "id", iks_find_attrib(pak->x, "id")); 01214 ast_aji_send(c, receipt); 01215 01216 iks_delete(receipt); 01217 01218 return 1; 01219 }
| static struct jingle_pvt * jingle_alloc | ( | struct jingle * | client, | |
| const char * | from, | |||
| const char * | sid | |||
| ) | [static, read] |
Definition at line 751 of file chan_jingle.c.
References ast_aji_buddy_destroy(), ast_calloc, ast_copy_string(), ast_debug, ast_format_cap_alloc_nolock(), ast_format_cap_destroy(), ast_free, ast_log(), ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_random(), ast_rtp_instance_new(), ast_sockaddr_from_sin, ASTOBJ_CONTAINER_FIND, ASTOBJ_UNREF, aji_client::buddies, jingle::buddy, jingle_pvt::cap, aji_resource::cap, jingle::connection, jingle_pvt::exten, jingle_pvt::initiator, aji_version::jingle, jinglelock, jingle_pvt::jointcap, jingle_pvt::lock, LOG_ERROR, LOG_WARNING, jingle::name, jingle_pvt::next, aji_resource::next, jingle::p, jingle_pvt::parent, jingle_pvt::peercap, jingle::prefs, jingle_pvt::prefs, aji_resource::resource, aji_buddy::resources, jingle_pvt::rtp, jingle_pvt::sid, and jingle_pvt::them.
Referenced by jingle_newcall(), and jingle_request().
00752 { 00753 struct jingle_pvt *tmp = NULL; 00754 struct aji_resource *resources = NULL; 00755 struct aji_buddy *buddy = NULL; 00756 char idroster[200]; 00757 struct ast_sockaddr bindaddr_tmp; 00758 00759 ast_debug(1, "The client is %s for alloc\n", client->name); 00760 if (!sid && !strchr(from, '/')) { /* I started call! */ 00761 if (!strcasecmp(client->name, "guest")) { 00762 buddy = ASTOBJ_CONTAINER_FIND(&client->connection->buddies, from); 00763 if (buddy) { 00764 resources = buddy->resources; 00765 } 00766 } else if (client->buddy) 00767 resources = client->buddy->resources; 00768 while (resources) { 00769 if (resources->cap->jingle) { 00770 break; 00771 } 00772 resources = resources->next; 00773 } 00774 if (resources) 00775 snprintf(idroster, sizeof(idroster), "%s/%s", from, resources->resource); 00776 else { 00777 ast_log(LOG_ERROR, "no jingle capable clients to talk to.\n"); 00778 if (buddy) { 00779 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 00780 } 00781 return NULL; 00782 } 00783 if (buddy) { 00784 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 00785 } 00786 } 00787 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { 00788 return NULL; 00789 } 00790 00791 tmp->cap = ast_format_cap_alloc_nolock(); 00792 tmp->jointcap = ast_format_cap_alloc_nolock(); 00793 tmp->peercap = ast_format_cap_alloc_nolock(); 00794 if (!tmp->cap || !tmp->jointcap || !tmp->peercap) { 00795 tmp->cap = ast_format_cap_destroy(tmp->cap); 00796 tmp->jointcap = ast_format_cap_destroy(tmp->jointcap); 00797 tmp->peercap = ast_format_cap_destroy(tmp->peercap); 00798 ast_free(tmp); 00799 return NULL; 00800 } 00801 memcpy(&tmp->prefs, &client->prefs, sizeof(tmp->prefs)); 00802 00803 if (sid) { 00804 ast_copy_string(tmp->sid, sid, sizeof(tmp->sid)); 00805 ast_copy_string(tmp->them, from, sizeof(tmp->them)); 00806 } else { 00807 snprintf(tmp->sid, sizeof(tmp->sid), "%08lx%08lx", ast_random(), ast_random()); 00808 ast_copy_string(tmp->them, idroster, sizeof(tmp->them)); 00809 tmp->initiator = 1; 00810 } 00811 ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr); 00812 tmp->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL); 00813 tmp->parent = client; 00814 if (!tmp->rtp) { 00815 ast_log(LOG_WARNING, "Out of RTP sessions?\n"); 00816 ast_free(tmp); 00817 return NULL; 00818 } 00819 ast_copy_string(tmp->exten, "s", sizeof(tmp->exten)); 00820 ast_mutex_init(&tmp->lock); 00821 ast_mutex_lock(&jinglelock); 00822 tmp->next = client->p; 00823 client->p = tmp; 00824 ast_mutex_unlock(&jinglelock); 00825 return tmp; 00826 }
| static int jingle_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 387 of file chan_jingle.c.
References ast_debug, ast_mutex_lock, ast_mutex_unlock, jingle_accept_call(), jingle_pvt::lock, jingle_pvt::parent, and ast_channel::tech_pvt.
00388 { 00389 struct jingle_pvt *p = ast->tech_pvt; 00390 struct jingle *client = p->parent; 00391 int res = 0; 00392 00393 ast_debug(1, "Answer!\n"); 00394 ast_mutex_lock(&p->lock); 00395 jingle_accept_call(client, p); 00396 ast_mutex_unlock(&p->lock); 00397 return res; 00398 }
| static int jingle_call | ( | struct ast_channel * | ast, | |
| const char * | dest, | |||
| int | timeout | |||
| ) | [static] |
Initiate new call, part of PBX interface dest is the dial string.
Definition at line 1501 of file chan_jingle.c.
References ast_channel::_state, ast_channel_name(), ast_copy_string(), ast_format_cap_copy(), ast_log(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RING, jingle_pvt::cap, jingle::connection, aji_client::f, jingle_create_candidates(), jingle_ringing_ack(), jingle_transmit_invite(), jingle_pvt::jointcap, LOG_WARNING, aji_client::mid, jingle_pvt::parent, jingle_pvt::ring, jingle_pvt::ringrule, jingle_pvt::sid, ast_channel::tech_pvt, and jingle_pvt::them.
01502 { 01503 struct jingle_pvt *p = ast->tech_pvt; 01504 01505 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 01506 ast_log(LOG_WARNING, "jingle_call called on %s, neither down nor reserved\n", ast_channel_name(ast)); 01507 return -1; 01508 } 01509 01510 ast_setstate(ast, AST_STATE_RING); 01511 ast_format_cap_copy(p->jointcap, p->cap); 01512 if (!p->ringrule) { 01513 ast_copy_string(p->ring, p->parent->connection->mid, sizeof(p->ring)); 01514 p->ringrule = iks_filter_add_rule(p->parent->connection->f, jingle_ringing_ack, p, 01515 IKS_RULE_ID, p->ring, IKS_RULE_DONE); 01516 } else 01517 ast_log(LOG_WARNING, "Whoa, already have a ring rule!\n"); 01518 01519 jingle_transmit_invite(p); 01520 jingle_create_candidates(p->parent, p, p->sid, p->them); 01521 01522 return 0; 01523 }
| static int jingle_create_candidates | ( | struct jingle * | client, | |
| struct jingle_pvt * | p, | |||
| char * | sid, | |||
| char * | from | |||
| ) | [static] |
Definition at line 591 of file chan_jingle.c.
References AJI_CONNECT_HOST, AJI_CONNECT_PRFLX, AJI_CONNECT_RELAY, AJI_CONNECT_SRFLX, AJI_PROTOCOL_SSLTCP, AJI_PROTOCOL_UDP, ast_aji_increment_mid(), ast_aji_send(), ast_calloc, ast_copy_string(), ast_find_ourip(), ast_free, ast_inet_ntoa(), ast_log(), ast_random(), ast_rtp_instance_get_local_address(), ast_sockaddr_from_sin, ast_sockaddr_ipv4(), ast_sockaddr_to_sin, ast_strlen_zero(), jingle_candidate::component, jingle::connection, jingle_candidate::foundation, jingle_candidate::generation, inet_aton(), jingle_pvt::initiator, jingle_candidate::ip, aji_client::jid, JINGLE_ICE_UDP_NS, JINGLE_NEGOTIATE, JINGLE_NODE, JINGLE_NS, JINGLE_SID, jingle_pvt::laststun, LOG_ERROR, LOG_NOTICE, LOG_WARNING, aji_client::mid, jingle_candidate::network, jingle_candidate::next, jingle_pvt::next, jingle_pvt::ourcandidates, pass, jingle_candidate::password, jingle_candidate::port, jingle_candidate::priority, jingle_candidate::protocol, jingle_pvt::rtp, jingle_pvt::sid, jingle_candidate::type, and jingle_candidate::ufrag.
Referenced by jingle_call(), and jingle_newcall().
00592 { 00593 struct jingle_candidate *tmp; 00594 struct aji_client *c = client->connection; 00595 struct jingle_candidate *ours1 = NULL, *ours2 = NULL; 00596 struct sockaddr_in sin = { 0, }; 00597 struct ast_sockaddr sin_tmp; 00598 struct ast_sockaddr us_tmp; 00599 struct ast_sockaddr bindaddr_tmp; 00600 struct in_addr us; 00601 struct in_addr externaddr; 00602 iks *iq, *jingle, *content, *transport, *candidate; 00603 char component[16], foundation[16], generation[16], network[16], pass[16], port[7], priority[16], user[16]; 00604 00605 00606 iq = iks_new("iq"); 00607 jingle = iks_new(JINGLE_NODE); 00608 content = iks_new("content"); 00609 transport = iks_new("transport"); 00610 candidate = iks_new("candidate"); 00611 if (!iq || !jingle || !content || !transport || !candidate) { 00612 ast_log(LOG_ERROR, "Memory allocation error\n"); 00613 goto safeout; 00614 } 00615 ours1 = ast_calloc(1, sizeof(*ours1)); 00616 ours2 = ast_calloc(1, sizeof(*ours2)); 00617 if (!ours1 || !ours2) 00618 goto safeout; 00619 00620 iks_insert_node(iq, jingle); 00621 iks_insert_node(jingle, content); 00622 iks_insert_node(content, transport); 00623 iks_insert_node(transport, candidate); 00624 00625 for (; p; p = p->next) { 00626 if (!strcasecmp(p->sid, sid)) 00627 break; 00628 } 00629 00630 if (!p) { 00631 ast_log(LOG_NOTICE, "No matching jingle session - SID %s!\n", sid); 00632 goto safeout; 00633 } 00634 00635 ast_rtp_instance_get_local_address(p->rtp, &sin_tmp); 00636 ast_sockaddr_to_sin(&sin_tmp, &sin); 00637 ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr); 00638 ast_find_ourip(&us_tmp, &bindaddr_tmp, AF_INET); 00639 us.s_addr = htonl(ast_sockaddr_ipv4(&us_tmp)); 00640 00641 /* Setup our first jingle candidate */ 00642 ours1->component = 1; 00643 ours1->foundation = (unsigned int)bindaddr.sin_addr.s_addr | AJI_CONNECT_HOST | AJI_PROTOCOL_UDP; 00644 ours1->generation = 0; 00645 ast_copy_string(ours1->ip, ast_inet_ntoa(us), sizeof(ours1->ip)); 00646 ours1->network = 0; 00647 ours1->port = ntohs(sin.sin_port); 00648 ours1->priority = 1678246398; 00649 ours1->protocol = AJI_PROTOCOL_UDP; 00650 snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random()); 00651 ast_copy_string(ours1->password, pass, sizeof(ours1->password)); 00652 ours1->type = AJI_CONNECT_HOST; 00653 snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random()); 00654 ast_copy_string(ours1->ufrag, user, sizeof(ours1->ufrag)); 00655 p->ourcandidates = ours1; 00656 00657 if (!ast_strlen_zero(externip)) { 00658 /* XXX We should really stun for this one not just go with externip XXX */ 00659 if (inet_aton(externip, &externaddr)) 00660 ast_log(LOG_WARNING, "Invalid extern IP : %s\n", externip); 00661 00662 ours2->component = 1; 00663 ours2->foundation = (unsigned int)externaddr.s_addr | AJI_CONNECT_PRFLX | AJI_PROTOCOL_UDP; 00664 ours2->generation = 0; 00665 ast_copy_string(ours2->ip, externip, sizeof(ours2->ip)); 00666 ours2->network = 0; 00667 ours2->port = ntohs(sin.sin_port); 00668 ours2->priority = 1678246397; 00669 ours2->protocol = AJI_PROTOCOL_UDP; 00670 snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random()); 00671 ast_copy_string(ours2->password, pass, sizeof(ours2->password)); 00672 ours2->type = AJI_CONNECT_PRFLX; 00673 00674 snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random()); 00675 ast_copy_string(ours2->ufrag, user, sizeof(ours2->ufrag)); 00676 ours1->next = ours2; 00677 ours2 = NULL; 00678 } 00679 ours1 = NULL; 00680 00681 for (tmp = p->ourcandidates; tmp; tmp = tmp->next) { 00682 snprintf(component, sizeof(component), "%u", tmp->component); 00683 snprintf(foundation, sizeof(foundation), "%u", tmp->foundation); 00684 snprintf(generation, sizeof(generation), "%u", tmp->generation); 00685 snprintf(network, sizeof(network), "%u", tmp->network); 00686 snprintf(port, sizeof(port), "%u", tmp->port); 00687 snprintf(priority, sizeof(priority), "%u", tmp->priority); 00688 00689 iks_insert_attrib(iq, "from", c->jid->full); 00690 iks_insert_attrib(iq, "to", from); 00691 iks_insert_attrib(iq, "type", "set"); 00692 iks_insert_attrib(iq, "id", c->mid); 00693 ast_aji_increment_mid(c->mid); 00694 iks_insert_attrib(jingle, "action", JINGLE_NEGOTIATE); 00695 iks_insert_attrib(jingle, JINGLE_SID, sid); 00696 iks_insert_attrib(jingle, "initiator", (p->initiator) ? c->jid->full : from); 00697 iks_insert_attrib(jingle, "xmlns", JINGLE_NS); 00698 iks_insert_attrib(content, "creator", p->initiator ? "initiator" : "responder"); 00699 iks_insert_attrib(content, "name", "asterisk-audio-content"); 00700 iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS); 00701 iks_insert_attrib(candidate, "component", component); 00702 iks_insert_attrib(candidate, "foundation", foundation); 00703 iks_insert_attrib(candidate, "generation", generation); 00704 iks_insert_attrib(candidate, "ip", tmp->ip); 00705 iks_insert_attrib(candidate, "network", network); 00706 iks_insert_attrib(candidate, "port", port); 00707 iks_insert_attrib(candidate, "priority", priority); 00708 switch (tmp->protocol) { 00709 case AJI_PROTOCOL_UDP: 00710 iks_insert_attrib(candidate, "protocol", "udp"); 00711 break; 00712 case AJI_PROTOCOL_SSLTCP: 00713 iks_insert_attrib(candidate, "protocol", "ssltcp"); 00714 break; 00715 } 00716 iks_insert_attrib(candidate, "pwd", tmp->password); 00717 switch (tmp->type) { 00718 case AJI_CONNECT_HOST: 00719 iks_insert_attrib(candidate, "type", "host"); 00720 break; 00721 case AJI_CONNECT_PRFLX: 00722 iks_insert_attrib(candidate, "type", "prflx"); 00723 break; 00724 case AJI_CONNECT_RELAY: 00725 iks_insert_attrib(candidate, "type", "relay"); 00726 break; 00727 case AJI_CONNECT_SRFLX: 00728 iks_insert_attrib(candidate, "type", "srflx"); 00729 break; 00730 } 00731 iks_insert_attrib(candidate, "ufrag", tmp->ufrag); 00732 00733 ast_aji_send(c, iq); 00734 } 00735 p->laststun = 0; 00736 00737 safeout: 00738 if (ours1) 00739 ast_free(ours1); 00740 if (ours2) 00741 ast_free(ours2); 00742 iks_delete(iq); 00743 iks_delete(jingle); 00744 iks_delete(content); 00745 iks_delete(transport); 00746 iks_delete(candidate); 00747 00748 return 1; 00749 }
| static int jingle_create_member | ( | char * | label, | |
| struct ast_variable * | var, | |||
| int | allowguest, | |||
| struct ast_codec_pref | prefs, | |||
| char * | context, | |||
| struct jingle * | member | |||
| ) | [static] |
Definition at line 1746 of file chan_jingle.c.
References jingle::allowguest, ast_aji_get_client(), ast_copy_string(), ast_log(), ast_parse_allow_disallow(), ASTOBJ_CONTAINER_FIND, aji_client::buddies, jingle::buddy, jingle::cap, jingle::connection, jingle::context, aji_client::f, JINGLE_NS, jingle_parser(), LOG_ERROR, LOG_WARNING, ast_variable::name, jingle::name, ast_variable::next, jingle_candidate::next, jingle::prefs, jingle::user, and ast_variable::value.
Referenced by jingle_load_config().
01749 { 01750 struct aji_client *client; 01751 01752 if (!member) 01753 ast_log(LOG_WARNING, "Out of memory.\n"); 01754 01755 ast_copy_string(member->name, label, sizeof(member->name)); 01756 ast_copy_string(member->user, label, sizeof(member->user)); 01757 ast_copy_string(member->context, context, sizeof(member->context)); 01758 member->allowguest = allowguest; 01759 member->prefs = prefs; 01760 while (var) { 01761 #if 0 01762 struct jingle_candidate *candidate = NULL; 01763 #endif 01764 if (!strcasecmp(var->name, "username")) 01765 ast_copy_string(member->user, var->value, sizeof(member->user)); 01766 else if (!strcasecmp(var->name, "disallow")) 01767 ast_parse_allow_disallow(&member->prefs, member->cap, var->value, 0); 01768 else if (!strcasecmp(var->name, "allow")) 01769 ast_parse_allow_disallow(&member->prefs, member->cap, var->value, 1); 01770 else if (!strcasecmp(var->name, "context")) 01771 ast_copy_string(member->context, var->value, sizeof(member->context)); 01772 #if 0 01773 else if (!strcasecmp(var->name, "candidate")) { 01774 candidate = jingle_create_candidate(var->value); 01775 if (candidate) { 01776 candidate->next = member->ourcandidates; 01777 member->ourcandidates = candidate; 01778 } 01779 } 01780 #endif 01781 else if (!strcasecmp(var->name, "connection")) { 01782 if ((client = ast_aji_get_client(var->value))) { 01783 member->connection = client; 01784 iks_filter_add_rule(client->f, jingle_parser, member, 01785 IKS_RULE_TYPE, IKS_PAK_IQ, 01786 IKS_RULE_FROM_PARTIAL, member->user, 01787 IKS_RULE_NS, JINGLE_NS, 01788 IKS_RULE_DONE); 01789 } else { 01790 ast_log(LOG_ERROR, "connection referenced not found!\n"); 01791 return 0; 01792 } 01793 } 01794 var = var->next; 01795 } 01796 if (member->connection && member->user) 01797 member->buddy = ASTOBJ_CONTAINER_FIND(&member->connection->buddies, member->user); 01798 else { 01799 ast_log(LOG_ERROR, "No Connection or Username!\n"); 01800 } 01801 return 1; 01802 }
| static int jingle_digit | ( | struct ast_channel * | ast, | |
| char | digit, | |||
| unsigned int | duration | |||
| ) | [static] |
Definition at line 1361 of file chan_jingle.c.
References ast_aji_increment_mid(), ast_aji_send(), AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_mutex_lock, ast_mutex_unlock, jingle::connection, ast_channel::dtmff, ast_frame::frametype, jingle_pvt::initiator, aji_client::jid, JINGLE_DTMF_NS, JINGLE_NS, jingle_pvt::lock, LOG_ERROR, aji_client::mid, jingle_pvt::parent, jingle_pvt::sid, ast_channel::tech_pvt, and jingle_pvt::them.
Referenced by jingle_digit_begin(), and jingle_digit_end().
01362 { 01363 struct jingle_pvt *p = ast->tech_pvt; 01364 struct jingle *client = p->parent; 01365 iks *iq, *jingle, *dtmf; 01366 char buffer[2] = {digit, '\0'}; 01367 iq = iks_new("iq"); 01368 jingle = iks_new("jingle"); 01369 dtmf = iks_new("dtmf"); 01370 if(!iq || !jingle || !dtmf) { 01371 iks_delete(iq); 01372 iks_delete(jingle); 01373 iks_delete(dtmf); 01374 ast_log(LOG_ERROR, "Did not send dtmf do to memory issue\n"); 01375 return -1; 01376 } 01377 01378 iks_insert_attrib(iq, "type", "set"); 01379 iks_insert_attrib(iq, "to", p->them); 01380 iks_insert_attrib(iq, "from", client->connection->jid->full); 01381 iks_insert_attrib(iq, "id", client->connection->mid); 01382 ast_aji_increment_mid(client->connection->mid); 01383 iks_insert_attrib(jingle, "xmlns", JINGLE_NS); 01384 iks_insert_attrib(jingle, "action", "session-info"); 01385 iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them); 01386 iks_insert_attrib(jingle, "sid", p->sid); 01387 iks_insert_attrib(dtmf, "xmlns", JINGLE_DTMF_NS); 01388 iks_insert_attrib(dtmf, "code", buffer); 01389 iks_insert_node(iq, jingle); 01390 iks_insert_node(jingle, dtmf); 01391 01392 ast_mutex_lock(&p->lock); 01393 if (ast->dtmff.frametype == AST_FRAME_DTMF_BEGIN || duration == 0) { 01394 iks_insert_attrib(dtmf, "action", "button-down"); 01395 } else if (ast->dtmff.frametype == AST_FRAME_DTMF_END || duration != 0) { 01396 iks_insert_attrib(dtmf, "action", "button-up"); 01397 } 01398 ast_aji_send(client->connection, iq); 01399 01400 iks_delete(iq); 01401 iks_delete(jingle); 01402 iks_delete(dtmf); 01403 ast_mutex_unlock(&p->lock); 01404 return 0; 01405 }
| static int jingle_digit_begin | ( | struct ast_channel * | ast, | |
| char | digit | |||
| ) | [static] |
Definition at line 1407 of file chan_jingle.c.
References jingle_digit().
01408 { 01409 return jingle_digit(chan, digit, 0); 01410 }
| static int jingle_digit_end | ( | struct ast_channel * | ast, | |
| char | digit, | |||
| unsigned int | duration | |||
| ) | [static] |
Definition at line 1412 of file chan_jingle.c.
References jingle_digit().
01413 { 01414 return jingle_digit(ast, digit, duration); 01415 }
| static char * jingle_do_reload | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
CLI command "jingle reload".
Definition at line 1657 of file chan_jingle.c.
References CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.
01658 { 01659 switch (cmd) { 01660 case CLI_INIT: 01661 e->command = "jingle reload"; 01662 e->usage = 01663 "Usage: jingle reload\n" 01664 " Reload jingle channel driver.\n"; 01665 return NULL; 01666 case CLI_GENERATE: 01667 return NULL; 01668 } 01669 01670 return CLI_SUCCESS; 01671 }
| static int jingle_fixup | ( | struct ast_channel * | oldchan, | |
| struct ast_channel * | newchan | |||
| ) | [static] |
Definition at line 1307 of file chan_jingle.c.
References ast_mutex_lock, ast_mutex_unlock, jingle_pvt::lock, jingle_pvt::owner, and ast_channel::tech_pvt.
01308 { 01309 struct jingle_pvt *p = newchan->tech_pvt; 01310 ast_mutex_lock(&p->lock); 01311 01312 if ((p->owner != oldchan)) { 01313 ast_mutex_unlock(&p->lock); 01314 return -1; 01315 } 01316 if (p->owner == oldchan) 01317 p->owner = newchan; 01318 ast_mutex_unlock(&p->lock); 01319 return 0; 01320 }
| static void jingle_free_candidates | ( | struct jingle_candidate * | candidate | ) | [static] |
Definition at line 961 of file chan_jingle.c.
References ast_free, last, and jingle_candidate::next.
Referenced by jingle_free_pvt(), and jingle_load_config().
00962 { 00963 struct jingle_candidate *last; 00964 while (candidate) { 00965 last = candidate; 00966 candidate = candidate->next; 00967 ast_free(last); 00968 } 00969 }
| static void jingle_free_pvt | ( | struct jingle * | client, | |
| struct jingle_pvt * | p | |||
| ) | [static] |
Definition at line 971 of file chan_jingle.c.
References ast_format_cap_destroy(), ast_free, ast_log(), ast_rtp_instance_destroy(), jingle_pvt::cap, jingle::connection, aji_client::f, jingle_free_candidates(), jingle_pvt::jointcap, LOG_WARNING, jingle_pvt::next, jingle_pvt::owner, jingle::p, jingle_pvt::parent, jingle_pvt::peercap, jingle_pvt::ringrule, jingle_pvt::rtp, jingle_pvt::theircandidates, and jingle_pvt::vrtp.
Referenced by jingle_hangup(), and jingle_newcall().
00972 { 00973 struct jingle_pvt *cur, *prev = NULL; 00974 cur = client->p; 00975 while (cur) { 00976 if (cur == p) { 00977 if (prev) 00978 prev->next = p->next; 00979 else 00980 client->p = p->next; 00981 break; 00982 } 00983 prev = cur; 00984 cur = cur->next; 00985 } 00986 if (p->ringrule) 00987 iks_filter_remove_rule(p->parent->connection->f, p->ringrule); 00988 if (p->owner) 00989 ast_log(LOG_WARNING, "Uh oh, there's an owner, this is going to be messy.\n"); 00990 if (p->rtp) 00991 ast_rtp_instance_destroy(p->rtp); 00992 if (p->vrtp) 00993 ast_rtp_instance_destroy(p->vrtp); 00994 jingle_free_candidates(p->theircandidates); 00995 p->cap = ast_format_cap_destroy(p->cap); 00996 p->jointcap = ast_format_cap_destroy(p->jointcap); 00997 p->peercap = ast_format_cap_destroy(p->peercap); 00998 00999 ast_free(p); 01000 }
| static void jingle_get_codec | ( | struct ast_channel * | chan, | |
| struct ast_format_cap * | result | |||
| ) | [static] |
Definition at line 419 of file chan_jingle.c.
References ast_format_cap_copy(), ast_mutex_lock, ast_mutex_unlock, jingle_pvt::lock, jingle_pvt::peercap, and ast_channel::tech_pvt.
00420 { 00421 struct jingle_pvt *p = chan->tech_pvt; 00422 ast_mutex_lock(&p->lock); 00423 ast_format_cap_copy(result, p->peercap); 00424 ast_mutex_unlock(&p->lock); 00425 }
| static enum ast_rtp_glue_result jingle_get_rtp_peer | ( | struct ast_channel * | chan, | |
| struct ast_rtp_instance ** | instance | |||
| ) | [static] |
Definition at line 400 of file chan_jingle.c.
References ao2_ref, ast_mutex_lock, ast_mutex_unlock, AST_RTP_GLUE_RESULT_FORBID, AST_RTP_GLUE_RESULT_LOCAL, jingle_pvt::lock, jingle_pvt::rtp, and ast_channel::tech_pvt.
00401 { 00402 struct jingle_pvt *p = chan->tech_pvt; 00403 enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_FORBID; 00404 00405 if (!p) 00406 return res; 00407 00408 ast_mutex_lock(&p->lock); 00409 if (p->rtp) { 00410 ao2_ref(p->rtp, +1); 00411 *instance = p->rtp; 00412 res = AST_RTP_GLUE_RESULT_LOCAL; 00413 } 00414 ast_mutex_unlock(&p->lock); 00415 00416 return res; 00417 }
| static int jingle_handle_dtmf | ( | struct jingle * | client, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 506 of file chan_jingle.c.
References AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_queue_frame(), ast_verbose, ast_frame_subclass::integer, JINGLE_NODE, jingle_response(), JINGLE_SID, LOG_NOTICE, jingle_pvt::next, jingle_pvt::owner, jingle::p, jingle_pvt::sid, and ast_frame::subclass.
Referenced by jingle_parser().
00507 { 00508 struct jingle_pvt *tmp; 00509 iks *dtmfnode = NULL, *dtmfchild = NULL; 00510 char *dtmf; 00511 /* Make sure our new call doesn't exist yet */ 00512 for (tmp = client->p; tmp; tmp = tmp->next) { 00513 if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) 00514 break; 00515 } 00516 00517 if (tmp) { 00518 if(iks_find_with_attrib(pak->x, "dtmf-method", "method", "rtp")) { 00519 jingle_response(client,pak, 00520 "feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'", 00521 "unsupported-dtmf-method xmlns='http://www.xmpp.org/extensions/xep-0181.html#ns-errors'"); 00522 return -1; 00523 } 00524 if ((dtmfnode = iks_find(pak->x, "dtmf"))) { 00525 if((dtmf = iks_find_attrib(dtmfnode, "code"))) { 00526 if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-up")) { 00527 struct ast_frame f = {AST_FRAME_DTMF_BEGIN, }; 00528 f.subclass.integer = dtmf[0]; 00529 ast_queue_frame(tmp->owner, &f); 00530 ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer); 00531 } else if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-down")) { 00532 struct ast_frame f = {AST_FRAME_DTMF_END, }; 00533 f.subclass.integer = dtmf[0]; 00534 ast_queue_frame(tmp->owner, &f); 00535 ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer); 00536 } else if(iks_find_attrib(pak->x, "dtmf")) { /* 250 millasecond default */ 00537 struct ast_frame f = {AST_FRAME_DTMF, }; 00538 f.subclass.integer = dtmf[0]; 00539 ast_queue_frame(tmp->owner, &f); 00540 ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer); 00541 } 00542 } 00543 } else if ((dtmfnode = iks_find_with_attrib(pak->x, JINGLE_NODE, "action", "session-info"))) { 00544 if((dtmfchild = iks_find(dtmfnode, "dtmf"))) { 00545 if((dtmf = iks_find_attrib(dtmfchild, "code"))) { 00546 if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-up")) { 00547 struct ast_frame f = {AST_FRAME_DTMF_END, }; 00548 f.subclass.integer = dtmf[0]; 00549 ast_queue_frame(tmp->owner, &f); 00550 ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer); 00551 } else if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-down")) { 00552 struct ast_frame f = {AST_FRAME_DTMF_BEGIN, }; 00553 f.subclass.integer = dtmf[0]; 00554 ast_queue_frame(tmp->owner, &f); 00555 ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer); 00556 } 00557 } 00558 } 00559 } 00560 jingle_response(client, pak, NULL, NULL); 00561 return 1; 00562 } else 00563 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n"); 00564 00565 jingle_response(client, pak, NULL, NULL); 00566 return 1; 00567 }
| static int jingle_hangup | ( | struct ast_channel * | ast | ) | [static] |
Hangup a call through the jingle proxy channel.
Definition at line 1526 of file chan_jingle.c.
References jingle_pvt::alreadygone, ast_mutex_lock, ast_mutex_unlock, jingle_action(), jingle_free_pvt(), JINGLE_TERMINATE, jingle_pvt::lock, jingle_pvt::owner, jingle_pvt::parent, and ast_channel::tech_pvt.
01527 { 01528 struct jingle_pvt *p = ast->tech_pvt; 01529 struct jingle *client; 01530 01531 ast_mutex_lock(&p->lock); 01532 client = p->parent; 01533 p->owner = NULL; 01534 ast->tech_pvt = NULL; 01535 if (!p->alreadygone) 01536 jingle_action(client, p, JINGLE_TERMINATE); 01537 ast_mutex_unlock(&p->lock); 01538 01539 jingle_free_pvt(client, p); 01540 01541 return 0; 01542 }
| static int jingle_hangup_farend | ( | struct jingle * | client, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 570 of file chan_jingle.c.
References jingle_pvt::alreadygone, ast_debug, ast_log(), ast_queue_hangup(), JINGLE_NODE, jingle_response(), JINGLE_SID, LOG_NOTICE, jingle::name, jingle_pvt::next, jingle_pvt::owner, jingle::p, and jingle_pvt::sid.
Referenced by jingle_parser().
00571 { 00572 struct jingle_pvt *tmp; 00573 00574 ast_debug(1, "The client is %s\n", client->name); 00575 /* Make sure our new call doesn't exist yet */ 00576 for (tmp = client->p; tmp; tmp = tmp->next) { 00577 if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) 00578 break; 00579 } 00580 00581 if (tmp) { 00582 tmp->alreadygone = 1; 00583 if (tmp->owner) 00584 ast_queue_hangup(tmp->owner); 00585 } else 00586 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n"); 00587 jingle_response(client, pak, NULL, NULL); 00588 return 1; 00589 }
| static int jingle_indicate | ( | struct ast_channel * | ast, | |
| int | condition, | |||
| const void * | data, | |||
| size_t | datalen | |||
| ) | [static] |
Definition at line 1322 of file chan_jingle.c.
References AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), and LOG_NOTICE.
01323 { 01324 int res = 0; 01325 01326 switch (condition) { 01327 case AST_CONTROL_HOLD: 01328 ast_moh_start(ast, data, NULL); 01329 break; 01330 case AST_CONTROL_UNHOLD: 01331 ast_moh_stop(ast); 01332 break; 01333 default: 01334 ast_log(LOG_NOTICE, "Don't know how to indicate condition '%d'\n", condition); 01335 res = -1; 01336 } 01337 01338 return res; 01339 }
| static int jingle_is_answered | ( | struct jingle * | client, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 486 of file chan_jingle.c.
References AST_CONTROL_ANSWER, ast_debug, ast_log(), ast_queue_control(), JINGLE_NODE, jingle_response(), JINGLE_SID, LOG_NOTICE, jingle::name, jingle_pvt::next, jingle_pvt::owner, jingle::p, and jingle_pvt::sid.
Referenced by jingle_parser().
00487 { 00488 struct jingle_pvt *tmp; 00489 00490 ast_debug(1, "The client is %s\n", client->name); 00491 /* Make sure our new call doesn't exist yet */ 00492 for (tmp = client->p; tmp; tmp = tmp->next) { 00493 if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) 00494 break; 00495 } 00496 00497 if (tmp) { 00498 if (tmp->owner) 00499 ast_queue_control(tmp->owner, AST_CONTROL_ANSWER); 00500 } else 00501 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n"); 00502 jingle_response(client, pak, NULL, NULL); 00503 return 1; 00504 }
| static int jingle_load_config | ( | void | ) | [static] |
Definition at line 1804 of file chan_jingle.c.
References jingle::allowguest, ast_aji_client_destroy(), ast_aji_get_clients(), ast_calloc, ast_category_browse(), ast_config_load, ast_copy_string(), ast_format_cap_alloc_nolock(), ast_gethostbyname(), ast_jb_read_conf(), ast_log(), ast_parse_allow_disallow(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ASTOBJ_CONTAINER_LINK, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_INIT, ASTOBJ_UNLOCK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, jingle::cap, clients, CONFIG_STATUS_FILEINVALID, jingle::connection, jingle::context, context, global_jbconf, hp, JINGLE_CONFIG, jingle_create_member(), JINGLE_DTMF_NS, jingle_free_candidates(), jingle_list, jingle_member_destroy(), JINGLE_NS, jingle_parser(), LOG_WARNING, jingle::name, ast_variable::name, ast_variable::next, jingle::parkinglot, jingle::prefs, jingle::user, ast_variable::value, and var.
Referenced by load_module().
01805 { 01806 char *cat = NULL; 01807 struct ast_config *cfg = NULL; 01808 char context[100]; 01809 int allowguest = 1; 01810 struct ast_variable *var; 01811 struct jingle *member; 01812 struct hostent *hp; 01813 struct ast_hostent ahp; 01814 struct ast_codec_pref prefs; 01815 struct aji_client_container *clients; 01816 struct jingle_candidate *global_candidates = NULL; 01817 struct ast_flags config_flags = { 0 }; 01818 01819 cfg = ast_config_load(JINGLE_CONFIG, config_flags); 01820 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) { 01821 return 0; 01822 } 01823 01824 /* Copy the default jb config over global_jbconf */ 01825 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 01826 01827 cat = ast_category_browse(cfg, NULL); 01828 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) { 01829 /* handle jb conf */ 01830 if (!ast_jb_read_conf(&global_jbconf, var->name, var->value)) 01831 continue; 01832 01833 if (!strcasecmp(var->name, "allowguest")) 01834 allowguest = 01835 (ast_true(ast_variable_retrieve(cfg, "general", "allowguest"))) ? 1 : 0; 01836 else if (!strcasecmp(var->name, "disallow")) 01837 ast_parse_allow_disallow(&prefs, global_capability, var->value, 0); 01838 else if (!strcasecmp(var->name, "allow")) 01839 ast_parse_allow_disallow(&prefs, global_capability, var->value, 1); 01840 else if (!strcasecmp(var->name, "context")) 01841 ast_copy_string(context, var->value, sizeof(context)); 01842 else if (!strcasecmp(var->name, "externip")) 01843 ast_copy_string(externip, var->value, sizeof(externip)); 01844 else if (!strcasecmp(var->name, "bindaddr")) { 01845 if (!(hp = ast_gethostbyname(var->value, &ahp))) { 01846 ast_log(LOG_WARNING, "Invalid address: %s\n", var->value); 01847 } else { 01848 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr)); 01849 } 01850 } 01851 /* Idea to allow for custom candidates */ 01852 /* 01853 else if (!strcasecmp(var->name, "candidate")) { 01854 candidate = jingle_create_candidate(var->value); 01855 if (candidate) { 01856 candidate->next = global_candidates; 01857 global_candidates = candidate; 01858 } 01859 } 01860 */ 01861 } 01862 while (cat) { 01863 if (strcasecmp(cat, "general")) { 01864 var = ast_variable_browse(cfg, cat); 01865 member = ast_calloc(1, sizeof(*member)); 01866 ASTOBJ_INIT(member); 01867 ASTOBJ_WRLOCK(member); 01868 member->cap = ast_format_cap_alloc_nolock(); 01869 if (!strcasecmp(cat, "guest")) { 01870 ast_copy_string(member->name, "guest", sizeof(member->name)); 01871 ast_copy_string(member->user, "guest", sizeof(member->user)); 01872 ast_copy_string(member->context, context, sizeof(member->context)); 01873 member->allowguest = allowguest; 01874 member->prefs = prefs; 01875 while (var) { 01876 if (!strcasecmp(var->name, "disallow")) 01877 ast_parse_allow_disallow(&member->prefs, member->cap, 01878 var->value, 0); 01879 else if (!strcasecmp(var->name, "allow")) 01880 ast_parse_allow_disallow(&member->prefs, member->cap, 01881 var->value, 1); 01882 else if (!strcasecmp(var->name, "context")) 01883 ast_copy_string(member->context, var->value, 01884 sizeof(member->context)); 01885 else if (!strcasecmp(var->name, "parkinglot")) 01886 ast_copy_string(member->parkinglot, var->value, 01887 sizeof(member->parkinglot)); 01888 /* Idea to allow for custom candidates */ 01889 /* 01890 else if (!strcasecmp(var->name, "candidate")) { 01891 candidate = jingle_create_candidate(var->value); 01892 if (candidate) { 01893 candidate->next = member->ourcandidates; 01894 member->ourcandidates = candidate; 01895 } 01896 } 01897 */ 01898 var = var->next; 01899 } 01900 ASTOBJ_UNLOCK(member); 01901 clients = ast_aji_get_clients(); 01902 if (clients) { 01903 ASTOBJ_CONTAINER_TRAVERSE(clients, 1, { 01904 ASTOBJ_WRLOCK(iterator); 01905 ASTOBJ_WRLOCK(member); 01906 if (member->connection) { 01907 ASTOBJ_UNREF(member->connection, ast_aji_client_destroy); 01908 } 01909 member->connection = NULL; 01910 iks_filter_add_rule(iterator->f, jingle_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, JINGLE_NS, IKS_RULE_DONE); 01911 iks_filter_add_rule(iterator->f, jingle_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, JINGLE_DTMF_NS, IKS_RULE_DONE); 01912 ASTOBJ_UNLOCK(member); 01913 ASTOBJ_UNLOCK(iterator); 01914 }); 01915 ASTOBJ_CONTAINER_LINK(&jingle_list, member); 01916 } else { 01917 ASTOBJ_UNLOCK(member); 01918 ASTOBJ_UNREF(member, jingle_member_destroy); 01919 } 01920 } else { 01921 ASTOBJ_UNLOCK(member); 01922 if (jingle_create_member(cat, var, allowguest, prefs, context, member)) 01923 ASTOBJ_CONTAINER_LINK(&jingle_list, member); 01924 ASTOBJ_UNREF(member, jingle_member_destroy); 01925 } 01926 } 01927 cat = ast_category_browse(cfg, cat); 01928 } 01929 jingle_free_candidates(global_candidates); 01930 return 1; 01931 }
| static void jingle_member_destroy | ( | struct jingle * | obj | ) | [static] |
Definition at line 228 of file chan_jingle.c.
References ast_aji_buddy_destroy(), ast_aji_client_destroy(), ast_format_cap_destroy(), ast_free, ASTOBJ_UNREF, jingle::buddy, jingle::cap, and jingle::connection.
Referenced by jingle_load_config(), jingle_parser(), and unload_module().
00229 { 00230 obj->cap = ast_format_cap_destroy(obj->cap); 00231 if (obj->connection) { 00232 ASTOBJ_UNREF(obj->connection, ast_aji_client_destroy); 00233 } 00234 if (obj->buddy) { 00235 ASTOBJ_UNREF(obj->buddy, ast_aji_buddy_destroy); 00236 } 00237 ast_free(obj); 00238 }
| static struct ast_channel* jingle_new | ( | struct jingle * | client, | |
| struct jingle_pvt * | i, | |||
| int | state, | |||
| const char * | title, | |||
| const char * | linkedid | |||
| ) | [static, read] |
Start new jingle channel.
Definition at line 829 of file chan_jingle.c.
References jingle::accountcode, ast_channel::adsicpe, ast_channel::amaflags, jingle::amaflags, ast_party_caller::ani, AST_ADSI_UNAVAILABLE, ast_best_codec(), AST_CAUSE_SWITCH_CONGESTION, ast_channel_alloc, ast_channel_name(), ast_channel_set_fd(), ast_codec_choose(), ast_copy_string(), ast_format_cap_add(), ast_format_cap_is_empty(), ast_format_cap_iter_end(), ast_format_cap_iter_next(), ast_format_cap_iter_start(), ast_format_copy(), AST_FORMAT_GET_TYPE, AST_FORMAT_TYPE_VIDEO, ast_hangup(), ast_jb_configure(), ast_log(), ast_pbx_start(), ast_random(), ast_rtp_codecs_packetization_set(), ast_rtp_instance_fd(), ast_rtp_instance_get_codecs(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_strlen_zero(), ast_channel::caller, jingle::callgroup, ast_channel::callgroup, jingle::callingpres, jingle_pvt::cap, jingle_pvt::cid_name, jingle_pvt::cid_num, jingle::context, ast_channel::context, ast_channel::dialed, jingle_pvt::exten, ast_channel::exten, global_jbconf, ast_channel::hangupcause, ast_party_caller::id, ast_format::id, jingle_pvt::jointcap, jingle::language, LOG_WARNING, jingle::musicclass, ast_party_id::name, ast_channel::nativeformats, ast_party_dialed::number, ast_party_id::number, jingle_pvt::owner, jingle::pickupgroup, ast_channel::pickupgroup, jingle_pvt::prefs, ast_party_number::presentation, ast_party_name::presentation, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, jingle_pvt::rtp, ast_party_dialed::str, ast_party_number::str, str, ast_channel::tech, ast_channel::tech_pvt, jingle_pvt::them, ast_party_number::valid, jingle_pvt::vrtp, and ast_channel::writeformat.
Referenced by jingle_newcall(), and jingle_request().
00830 { 00831 struct ast_channel *tmp; 00832 struct ast_format_cap *what; /* SHALLOW COPY DO NOT DESTROY */ 00833 struct ast_format tmpfmt; 00834 const char *str; 00835 00836 if (title) 00837 str = title; 00838 else 00839 str = i->them; 00840 tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", "", "", linkedid, 0, "Jingle/%s-%04lx", str, ast_random() & 0xffff); 00841 if (!tmp) { 00842 ast_log(LOG_WARNING, "Unable to allocate Jingle channel structure!\n"); 00843 return NULL; 00844 } 00845 tmp->tech = &jingle_tech; 00846 00847 /* Select our native format based on codec preference until we receive 00848 something from another device to the contrary. */ 00849 if (!ast_format_cap_is_empty(i->jointcap)) 00850 what = i->jointcap; 00851 else if (!(ast_format_cap_is_empty(i->cap))) 00852 what = i->cap; 00853 else 00854 what = global_capability; 00855 00856 /* Set Frame packetization */ 00857 if (i->rtp) 00858 ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(i->rtp), i->rtp, &i->prefs); 00859 00860 ast_codec_choose(&i->prefs, what, 1, &tmpfmt); 00861 ast_format_cap_add(tmp->nativeformats, &tmpfmt); 00862 00863 ast_format_cap_iter_start(i->jointcap); 00864 while (!(ast_format_cap_iter_next(i->jointcap, &tmpfmt))) { 00865 if (AST_FORMAT_GET_TYPE(tmpfmt.id) == AST_FORMAT_TYPE_VIDEO) { 00866 ast_format_cap_add(tmp->nativeformats, &tmpfmt); 00867 } 00868 } 00869 ast_format_cap_iter_end(i->jointcap); 00870 00871 if (i->rtp) { 00872 ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(i->rtp, 0)); 00873 ast_channel_set_fd(tmp, 1, ast_rtp_instance_fd(i->rtp, 1)); 00874 } 00875 if (i->vrtp) { 00876 ast_channel_set_fd(tmp, 2, ast_rtp_instance_fd(i->vrtp, 0)); 00877 ast_channel_set_fd(tmp, 3, ast_rtp_instance_fd(i->vrtp, 1)); 00878 } 00879 if (state == AST_STATE_RING) 00880 tmp->rings = 1; 00881 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 00882 00883 00884 ast_best_codec(tmp->nativeformats, &tmpfmt); 00885 ast_format_copy(&tmp->writeformat, &tmpfmt); 00886 ast_format_copy(&tmp->rawwriteformat, &tmpfmt); 00887 ast_format_copy(&tmp->readformat, &tmpfmt); 00888 ast_format_copy(&tmp->rawreadformat, &tmpfmt); 00889 tmp->tech_pvt = i; 00890 00891 tmp->callgroup = client->callgroup; 00892 tmp->pickupgroup = client->pickupgroup; 00893 tmp->caller.id.name.presentation = client->callingpres; 00894 tmp->caller.id.number.presentation = client->callingpres; 00895 if (!ast_strlen_zero(client->accountcode)) 00896 ast_channel_accountcode_set(tmp, client->accountcode); 00897 if (client->amaflags) 00898 tmp->amaflags = client->amaflags; 00899 if (!ast_strlen_zero(client->language)) 00900 ast_channel_language_set(tmp, client->language); 00901 if (!ast_strlen_zero(client->musicclass)) 00902 ast_channel_musicclass_set(tmp, client->musicclass); 00903 i->owner = tmp; 00904 ast_copy_string(tmp->context, client->context, sizeof(tmp->context)); 00905 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 00906 /* Don't use ast_set_callerid() here because it will 00907 * generate an unnecessary NewCallerID event */ 00908 if (!ast_strlen_zero(i->cid_num)) { 00909 tmp->caller.ani.number.valid = 1; 00910 tmp->caller.ani.number.str = ast_strdup(i->cid_num); 00911 } 00912 if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s")) { 00913 tmp->dialed.number.str = ast_strdup(i->exten); 00914 } 00915 tmp->priority = 1; 00916 if (i->rtp) 00917 ast_jb_configure(tmp, &global_jbconf); 00918 if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) { 00919 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp)); 00920 tmp->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 00921 ast_hangup(tmp); 00922 tmp = NULL; 00923 } 00924 00925 return tmp; 00926 }
| static int jingle_newcall | ( | struct jingle * | client, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 1003 of file chan_jingle.c.
References ast_aji_client_destroy(), ast_aji_get_client(), ast_copy_string(), ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, ast_pbx_start(), AST_PBX_SUCCESS, ast_rtp_codecs_payloads_set_m_type(), ast_rtp_codecs_payloads_set_rtpmap_type(), ast_rtp_instance_get_codecs(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RING, ASTOBJ_UNREF, jingle_pvt::audio_content_name, jingle::connection, aji_client::jid, jingle_alloc(), JINGLE_AUDIO_RTP_NS, jingle_create_candidates(), jingle_free_pvt(), jingle_new(), JINGLE_NODE, jingle_response(), JINGLE_SID, JINGLE_VIDEO_RTP_NS, jingle_pvt::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, jingle::name, jingle_pvt::next, jingle::p, jingle_pvt::rtp, jingle_pvt::sid, jingle_pvt::them, and jingle_pvt::video_content_name.
Referenced by jingle_parser().
01004 { 01005 struct jingle_pvt *p, *tmp = client->p; 01006 struct ast_channel *chan; 01007 int res; 01008 iks *codec, *content, *description; 01009 char *from = NULL; 01010 01011 /* Make sure our new call doesn't exist yet */ 01012 from = iks_find_attrib(pak->x,"to"); 01013 if(!from) 01014 from = client->connection->jid->full; 01015 01016 while (tmp) { 01017 if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) { 01018 ast_log(LOG_NOTICE, "Ignoring duplicate call setup on SID %s\n", tmp->sid); 01019 jingle_response(client, pak, "out-of-order", NULL); 01020 return -1; 01021 } 01022 tmp = tmp->next; 01023 } 01024 01025 if (!strcasecmp(client->name, "guest")){ 01026 /* the guest account is not tied to any configured XMPP client, 01027 let's set it now */ 01028 if (client->connection) { 01029 ASTOBJ_UNREF(client->connection, ast_aji_client_destroy); 01030 } 01031 client->connection = ast_aji_get_client(from); 01032 if (!client->connection) { 01033 ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", from); 01034 return -1; 01035 } 01036 } 01037 01038 p = jingle_alloc(client, pak->from->partial, iks_find_attrib(pak->query, JINGLE_SID)); 01039 if (!p) { 01040 ast_log(LOG_WARNING, "Unable to allocate jingle structure!\n"); 01041 return -1; 01042 } 01043 chan = jingle_new(client, p, AST_STATE_DOWN, pak->from->user, NULL); 01044 if (!chan) { 01045 jingle_free_pvt(client, p); 01046 return -1; 01047 } 01048 ast_mutex_lock(&p->lock); 01049 ast_copy_string(p->them, pak->from->full, sizeof(p->them)); 01050 if (iks_find_attrib(pak->query, JINGLE_SID)) { 01051 ast_copy_string(p->sid, iks_find_attrib(pak->query, JINGLE_SID), 01052 sizeof(p->sid)); 01053 } 01054 01055 /* content points to the first <content/> tag */ 01056 content = iks_child(iks_child(pak->x)); 01057 while (content) { 01058 description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_AUDIO_RTP_NS); 01059 if (description) { 01060 /* audio content found */ 01061 codec = iks_child(iks_child(content)); 01062 ast_copy_string(p->audio_content_name, iks_find_attrib(content, "name"), sizeof(p->audio_content_name)); 01063 01064 while (codec) { 01065 ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id"))); 01066 ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0); 01067 codec = iks_next(codec); 01068 } 01069 } 01070 01071 description = NULL; 01072 codec = NULL; 01073 01074 description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_VIDEO_RTP_NS); 01075 if (description) { 01076 /* video content found */ 01077 codec = iks_child(iks_child(content)); 01078 ast_copy_string(p->video_content_name, iks_find_attrib(content, "name"), sizeof(p->video_content_name)); 01079 01080 while (codec) { 01081 ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id"))); 01082 ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0); 01083 codec = iks_next(codec); 01084 } 01085 } 01086 01087 content = iks_next(content); 01088 } 01089 01090 ast_mutex_unlock(&p->lock); 01091 ast_setstate(chan, AST_STATE_RING); 01092 res = ast_pbx_start(chan); 01093 01094 switch (res) { 01095 case AST_PBX_FAILED: 01096 ast_log(LOG_WARNING, "Failed to start PBX :(\n"); 01097 jingle_response(client, pak, "service-unavailable", NULL); 01098 break; 01099 case AST_PBX_CALL_LIMIT: 01100 ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n"); 01101 jingle_response(client, pak, "service-unavailable", NULL); 01102 break; 01103 case AST_PBX_SUCCESS: 01104 jingle_response(client, pak, NULL, NULL); 01105 jingle_create_candidates(client, p, 01106 iks_find_attrib(pak->query, JINGLE_SID), 01107 iks_find_attrib(pak->x, "from")); 01108 /* nothing to do */ 01109 break; 01110 } 01111 01112 return 1; 01113 }
| static int jingle_parser | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 1673 of file chan_jingle.c.
References ast_debug, ast_log(), ASTOBJ_REF, ASTOBJ_UNREF, JINGLE_ACCEPT, jingle_add_candidate(), jingle_handle_dtmf(), jingle_hangup_farend(), JINGLE_INFO, JINGLE_INITIATE, jingle_is_answered(), jingle_member_destroy(), JINGLE_NEGOTIATE, jingle_newcall(), JINGLE_NODE, JINGLE_TERMINATE, and LOG_NOTICE.
Referenced by jingle_create_member(), and jingle_load_config().
01674 { 01675 struct jingle *client = ASTOBJ_REF((struct jingle *) data); 01676 ast_log(LOG_NOTICE, "Filter matched\n"); 01677 01678 if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INITIATE)) { 01679 /* New call */ 01680 jingle_newcall(client, pak); 01681 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_NEGOTIATE)) { 01682 ast_debug(3, "About to add candidate!\n"); 01683 jingle_add_candidate(client, pak); 01684 ast_debug(3, "Candidate Added!\n"); 01685 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_ACCEPT)) { 01686 jingle_is_answered(client, pak); 01687 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INFO)) { 01688 jingle_handle_dtmf(client, pak); 01689 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_TERMINATE)) { 01690 jingle_hangup_farend(client, pak); 01691 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", "reject")) { 01692 jingle_hangup_farend(client, pak); 01693 } 01694 ASTOBJ_UNREF(client, jingle_member_destroy); 01695 return IKS_FILTER_EAT; 01696 }
| static struct ast_frame * jingle_read | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 1249 of file chan_jingle.c.
References ast_mutex_lock, ast_mutex_unlock, jingle_rtp_read(), jingle_pvt::lock, and ast_channel::tech_pvt.
01250 { 01251 struct ast_frame *fr; 01252 struct jingle_pvt *p = ast->tech_pvt; 01253 01254 ast_mutex_lock(&p->lock); 01255 fr = jingle_rtp_read(ast, p); 01256 ast_mutex_unlock(&p->lock); 01257 return fr; 01258 }
| static struct ast_channel * jingle_request | ( | const char * | type, | |
| struct ast_format_cap * | cap, | |||
| const struct ast_channel * | requestor, | |||
| const char * | data, | |||
| int * | cause | |||
| ) | [static, read] |
Part of PBX interface.
Definition at line 1545 of file chan_jingle.c.
References ast_aji_client_destroy(), ast_aji_get_client(), ast_channel_linkedid(), ast_log(), AST_STATE_DOWN, ast_strdupa, ASTOBJ_UNLOCK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, jingle::connection, find_jingle(), jingle_alloc(), jingle_new(), LOG_ERROR, LOG_WARNING, jingle::name, and strsep().
01546 { 01547 struct jingle_pvt *p = NULL; 01548 struct jingle *client = NULL; 01549 char *sender = NULL, *to = NULL, *s = NULL; 01550 struct ast_channel *chan = NULL; 01551 01552 if (data) { 01553 s = ast_strdupa(data); 01554 if (s) { 01555 sender = strsep(&s, "/"); 01556 if (sender && (sender[0] != '\0')) 01557 to = strsep(&s, "/"); 01558 if (!to) { 01559 ast_log(LOG_ERROR, "Bad arguments in Jingle Dialstring: %s\n", data); 01560 return NULL; 01561 } 01562 } 01563 } 01564 01565 client = find_jingle(to, sender); 01566 if (!client) { 01567 ast_log(LOG_WARNING, "Could not find recipient.\n"); 01568 return NULL; 01569 } 01570 if (!strcasecmp(client->name, "guest")){ 01571 /* the guest account is not tied to any configured XMPP client, 01572 let's set it now */ 01573 if (client->connection) { 01574 ASTOBJ_UNREF(client->connection, ast_aji_client_destroy); 01575 } 01576 client->connection = ast_aji_get_client(sender); 01577 if (!client->connection) { 01578 ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", sender); 01579 return NULL; 01580 } 01581 } 01582 01583 ASTOBJ_WRLOCK(client); 01584 p = jingle_alloc(client, to, NULL); 01585 if (p) 01586 chan = jingle_new(client, p, AST_STATE_DOWN, to, requestor ? ast_channel_linkedid(requestor) : NULL); 01587 ASTOBJ_UNLOCK(client); 01588 01589 return chan; 01590 }
| static int jingle_response | ( | struct jingle * | client, | |
| ikspak * | pak, | |||
| const char * | reasonstr, | |||
| const char * | reasonstr2 | |||
| ) | [static] |
Definition at line 454 of file chan_jingle.c.
References ast_aji_send(), jingle::connection, and aji_client::jid.
Referenced by jingle_handle_dtmf(), jingle_hangup_farend(), jingle_is_answered(), and jingle_newcall().
00455 { 00456 iks *response = NULL, *error = NULL, *reason = NULL; 00457 int res = -1; 00458 00459 response = iks_new("iq"); 00460 if (response) { 00461 iks_insert_attrib(response, "type", "result"); 00462 iks_insert_attrib(response, "from", client->connection->jid->full); 00463 iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from")); 00464 iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id")); 00465 if (reasonstr) { 00466 error = iks_new("error"); 00467 if (error) { 00468 iks_insert_attrib(error, "type", "cancel"); 00469 reason = iks_new(reasonstr); 00470 if (reason) 00471 iks_insert_node(error, reason); 00472 iks_insert_node(response, error); 00473 } 00474 } 00475 ast_aji_send(client->connection, response); 00476 res = 0; 00477 } 00478 00479 iks_delete(reason); 00480 iks_delete(error); 00481 iks_delete(response); 00482 00483 return res; 00484 }
| static int jingle_ringing_ack | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 375 of file chan_jingle.c.
References AST_CONTROL_RINGING, ast_queue_control(), jingle::connection, aji_client::f, jingle_pvt::owner, jingle_pvt::parent, and jingle_pvt::ringrule.
Referenced by jingle_call().
00376 { 00377 struct jingle_pvt *p = data; 00378 00379 if (p->ringrule) 00380 iks_filter_remove_rule(p->parent->connection->f, p->ringrule); 00381 p->ringrule = NULL; 00382 if (p->owner) 00383 ast_queue_control(p->owner, AST_CONTROL_RINGING); 00384 return IKS_FILTER_EAT; 00385 }
| static struct ast_frame* jingle_rtp_read | ( | struct ast_channel * | ast, | |
| struct jingle_pvt * | p | |||
| ) | [static, read] |
Definition at line 1221 of file chan_jingle.c.
References ast_debug, ast_format_cap_add(), ast_format_cap_iscompatible(), ast_format_cap_remove_bytype(), AST_FORMAT_TYPE_AUDIO, AST_FRAME_VOICE, ast_getformatname(), ast_null_frame, ast_rtp_instance_read(), ast_set_read_format(), ast_set_write_format(), f, ast_frame_subclass::format, ast_frame::frametype, jingle_update_stun(), ast_channel::nativeformats, jingle_pvt::owner, jingle_pvt::parent, ast_channel::readformat, jingle_pvt::rtp, ast_frame::subclass, and ast_channel::writeformat.
Referenced by jingle_read().
01222 { 01223 struct ast_frame *f; 01224 01225 if (!p->rtp) 01226 return &ast_null_frame; 01227 f = ast_rtp_instance_read(p->rtp, 0); 01228 jingle_update_stun(p->parent, p); 01229 if (p->owner) { 01230 /* We already hold the channel lock */ 01231 if (f->frametype == AST_FRAME_VOICE) { 01232 if (!(ast_format_cap_iscompatible(p->owner->nativeformats, &f->subclass.format))) { 01233 ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(&f->subclass.format)); 01234 ast_format_cap_remove_bytype(p->owner->nativeformats, AST_FORMAT_TYPE_AUDIO); 01235 ast_format_cap_add(p->owner->nativeformats, &f->subclass.format); 01236 ast_set_read_format(p->owner, &p->owner->readformat); 01237 ast_set_write_format(p->owner, &p->owner->writeformat); 01238 } 01239 /* if ((ast_test_flag(p, SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) { 01240 f = ast_dsp_process(p->owner, p->vad, f); 01241 if (f && (f->frametype == AST_FRAME_DTMF)) 01242 ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass.codec); 01243 } */ 01244 } 01245 } 01246 return f; 01247 }
| static int jingle_sendhtml | ( | struct ast_channel * | ast, | |
| int | subclass, | |||
| const char * | data, | |||
| int | datalen | |||
| ) | [static] |
Definition at line 1417 of file chan_jingle.c.
References ast_log(), and LOG_NOTICE.
01418 { 01419 ast_log(LOG_NOTICE, "XXX Implement jingle sendhtml XXX\n"); 01420 01421 return -1; 01422 }
| static int jingle_sendtext | ( | struct ast_channel * | ast, | |
| const char * | text | |||
| ) | [static] |
Definition at line 1341 of file chan_jingle.c.
References ast_aji_send_chat(), ast_log(), jingle::connection, LOG_ERROR, jingle_pvt::parent, ast_channel::tech_pvt, and jingle_pvt::them.
01342 { 01343 int res = 0; 01344 struct aji_client *client = NULL; 01345 struct jingle_pvt *p = chan->tech_pvt; 01346 01347 01348 if (!p->parent) { 01349 ast_log(LOG_ERROR, "Parent channel not found\n"); 01350 return -1; 01351 } 01352 if (!p->parent->connection) { 01353 ast_log(LOG_ERROR, "XMPP client not found\n"); 01354 return -1; 01355 } 01356 client = p->parent->connection; 01357 res = ast_aji_send_chat(client, p->them, text); 01358 return res; 01359 }
| 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 | |||
| ) | [static] |
Definition at line 427 of file chan_jingle.c.
References ast_mutex_lock, ast_mutex_unlock, jingle_pvt::lock, and ast_channel::tech_pvt.
00428 { 00429 struct jingle_pvt *p; 00430 00431 p = chan->tech_pvt; 00432 if (!p) 00433 return -1; 00434 ast_mutex_lock(&p->lock); 00435 00436 /* if (rtp) 00437 ast_rtp_get_peer(rtp, &p->redirip); 00438 else 00439 memset(&p->redirip, 0, sizeof(p->redirip)); 00440 p->redircodecs = codecs; */ 00441 00442 /* Reset lastrtprx timer */ 00443 ast_mutex_unlock(&p->lock); 00444 return 0; 00445 }
| static char * jingle_show_channels | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
CLI command "jingle show channels".
Definition at line 1593 of file chan_jingle.c.
References AJI_MAX_JIDLEN, ast_cli_args::argc, ast_channel_name(), ast_cli(), ast_copy_string(), ast_getformatname(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, FORMAT, jingle_list, jinglelock, LOG_WARNING, jingle_pvt::next, jingle_pvt::owner, ast_channel::readformat, jingle_pvt::them, ast_cli_entry::usage, and ast_channel::writeformat.
01594 { 01595 #define FORMAT "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n" 01596 struct jingle_pvt *p; 01597 struct ast_channel *chan; 01598 int numchans = 0; 01599 char them[AJI_MAX_JIDLEN]; 01600 char *jid = NULL; 01601 char *resource = NULL; 01602 01603 switch (cmd) { 01604 case CLI_INIT: 01605 e->command = "jingle show channels"; 01606 e->usage = 01607 "Usage: jingle show channels\n" 01608 " Shows current state of the Jingle channels.\n"; 01609 return NULL; 01610 case CLI_GENERATE: 01611 return NULL; 01612 } 01613 01614 if (a->argc != 3) 01615 return CLI_SHOWUSAGE; 01616 01617 ast_mutex_lock(&jinglelock); 01618 ast_cli(a->fd, FORMAT, "Channel", "Jabber ID", "Resource", "Read", "Write"); 01619 ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, { 01620 ASTOBJ_WRLOCK(iterator); 01621 p = iterator->p; 01622 while(p) { 01623 chan = p->owner; 01624 ast_copy_string(them, p->them, sizeof(them)); 01625 jid = them; 01626 resource = strchr(them, '/'); 01627 if (!resource) 01628 resource = "None"; 01629 else { 01630 *resource = '\0'; 01631 resource ++; 01632 } 01633 if (chan) 01634 ast_cli(a->fd, FORMAT, 01635 ast_channel_name(chan), 01636 jid, 01637 resource, 01638 ast_getformatname(&chan->readformat), 01639 ast_getformatname(&chan->writeformat) 01640 ); 01641 else 01642 ast_log(LOG_WARNING, "No available channel\n"); 01643 numchans ++; 01644 p = p->next; 01645 } 01646 ASTOBJ_UNLOCK(iterator); 01647 }); 01648 01649 ast_mutex_unlock(&jinglelock); 01650 01651 ast_cli(a->fd, "%d active jingle channel%s\n", numchans, (numchans != 1) ? "s" : ""); 01652 return CLI_SUCCESS; 01653 #undef FORMAT 01654 }
| static int jingle_transmit_invite | ( | struct jingle_pvt * | p | ) | [static] |
Definition at line 1423 of file chan_jingle.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_copy_string(), jingle_pvt::audio_content_name, jingle::connection, aji_client::jid, JINGLE_AUDIO_RTP_NS, JINGLE_ICE_UDP_NS, JINGLE_INITIATE, JINGLE_NODE, JINGLE_NS, JINGLE_SID, aji_client::mid, jingle_pvt::parent, jingle_pvt::sid, and jingle_pvt::them.
Referenced by jingle_call().
01424 { 01425 struct jingle *aux = NULL; 01426 struct aji_client *client = NULL; 01427 iks *iq, *jingle, *content, *description, *transport; 01428 iks *payload_eg711u, *payload_pcmu; 01429 01430 aux = p->parent; 01431 client = aux->connection; 01432 iq = iks_new("iq"); 01433 jingle = iks_new(JINGLE_NODE); 01434 content = iks_new("content"); 01435 description = iks_new("description"); 01436 transport = iks_new("transport"); 01437 payload_pcmu = iks_new("payload-type"); 01438 payload_eg711u = iks_new("payload-type"); 01439 01440 ast_copy_string(p->audio_content_name, "asterisk-audio-content", sizeof(p->audio_content_name)); 01441 01442 iks_insert_attrib(iq, "type", "set"); 01443 iks_insert_attrib(iq, "to", p->them); 01444 iks_insert_attrib(iq, "from", client->jid->full); 01445 iks_insert_attrib(iq, "id", client->mid); 01446 ast_aji_increment_mid(client->mid); 01447 iks_insert_attrib(jingle, "action", JINGLE_INITIATE); 01448 iks_insert_attrib(jingle, JINGLE_SID, p->sid); 01449 iks_insert_attrib(jingle, "initiator", client->jid->full); 01450 iks_insert_attrib(jingle, "xmlns", JINGLE_NS); 01451 01452 /* For now, we only send one audio based content */ 01453 iks_insert_attrib(content, "creator", "initiator"); 01454 iks_insert_attrib(content, "name", p->audio_content_name); 01455 iks_insert_attrib(content, "profile", "RTP/AVP"); 01456 iks_insert_attrib(description, "xmlns", JINGLE_AUDIO_RTP_NS); 01457 iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS); 01458 iks_insert_attrib(payload_pcmu, "id", "0"); 01459 iks_insert_attrib(payload_pcmu, "name", "PCMU"); 01460 iks_insert_attrib(payload_eg711u, "id", "100"); 01461 iks_insert_attrib(payload_eg711u, "name", "EG711U"); 01462 iks_insert_node(description, payload_pcmu); 01463 iks_insert_node(description, payload_eg711u); 01464 iks_insert_node(content, description); 01465 iks_insert_node(content, transport); 01466 iks_insert_node(jingle, content); 01467 iks_insert_node(iq, jingle); 01468 01469 ast_aji_send(client, iq); 01470 01471 iks_delete(iq); 01472 iks_delete(jingle); 01473 iks_delete(content); 01474 iks_delete(description); 01475 iks_delete(transport); 01476 iks_delete(payload_eg711u); 01477 iks_delete(payload_pcmu); 01478 return 0; 01479 }
| static int jingle_update_stun | ( | struct jingle * | client, | |
| struct jingle_pvt * | p | |||
| ) | [static] |
Definition at line 1115 of file chan_jingle.c.
References ast_gethostbyname(), ast_rtp_instance_stun_request(), ast_sockaddr_from_sin, hp, jingle_candidate::ip, jingle_pvt::laststun, jingle_candidate::next, jingle_pvt::ourcandidates, jingle_candidate::port, jingle_pvt::rtp, jingle_pvt::theircandidates, and jingle_candidate::ufrag.
Referenced by jingle_add_candidate(), and jingle_rtp_read().
01116 { 01117 struct jingle_candidate *tmp; 01118 struct hostent *hp; 01119 struct ast_hostent ahp; 01120 struct sockaddr_in sin; 01121 struct ast_sockaddr sin_tmp; 01122 01123 if (time(NULL) == p->laststun) 01124 return 0; 01125 01126 tmp = p->theircandidates; 01127 p->laststun = time(NULL); 01128 while (tmp) { 01129 char username[256]; 01130 hp = ast_gethostbyname(tmp->ip, &ahp); 01131 sin.sin_family = AF_INET; 01132 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); 01133 sin.sin_port = htons(tmp->port); 01134 snprintf(username, sizeof(username), "%s:%s", tmp->ufrag, p->ourcandidates->ufrag); 01135 01136 ast_sockaddr_from_sin(&sin_tmp, &sin); 01137 ast_rtp_instance_stun_request(p->rtp, &sin_tmp, username); 01138 tmp = tmp->next; 01139 } 01140 return 1; 01141 }
| static int jingle_write | ( | struct ast_channel * | ast, | |
| struct ast_frame * | f | |||
| ) | [static] |
Send frame to media channel (rtp).
Definition at line 1261 of file chan_jingle.c.
References ast_format_cap_iscompatible(), AST_FRAME_IMAGE, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_getformatname(), ast_getformatname_multiple(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_write(), ast_frame_subclass::format, ast_frame::frametype, jingle_pvt::lock, LOG_WARNING, ast_channel::nativeformats, ast_channel::readformat, jingle_pvt::rtp, ast_frame::subclass, ast_channel::tech_pvt, jingle_pvt::vrtp, and ast_channel::writeformat.
01262 { 01263 struct jingle_pvt *p = ast->tech_pvt; 01264 int res = 0; 01265 char buf[256]; 01266 01267 switch (frame->frametype) { 01268 case AST_FRAME_VOICE: 01269 if (!(ast_format_cap_iscompatible(ast->nativeformats, &frame->subclass.format))) { 01270 ast_log(LOG_WARNING, 01271 "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n", 01272 ast_getformatname(&frame->subclass.format), 01273 ast_getformatname_multiple(buf, sizeof(buf), ast->nativeformats), 01274 ast_getformatname(&ast->readformat), 01275 ast_getformatname(&ast->writeformat)); 01276 return 0; 01277 } 01278 if (p) { 01279 ast_mutex_lock(&p->lock); 01280 if (p->rtp) { 01281 res = ast_rtp_instance_write(p->rtp, frame); 01282 } 01283 ast_mutex_unlock(&p->lock); 01284 } 01285 break; 01286 case AST_FRAME_VIDEO: 01287 if (p) { 01288 ast_mutex_lock(&p->lock); 01289 if (p->vrtp) { 01290 res = ast_rtp_instance_write(p->vrtp, frame); 01291 } 01292 ast_mutex_unlock(&p->lock); 01293 } 01294 break; 01295 case AST_FRAME_IMAGE: 01296 return 0; 01297 break; 01298 default: 01299 ast_log(LOG_WARNING, "Can't send %d type frames with Jingle write\n", 01300 frame->frametype); 01301 return 0; 01302 } 01303 01304 return res; 01305 }
| static int load_module | ( | void | ) | [static] |
Load module into PBX, register channel.
Definition at line 1934 of file chan_jingle.c.
References __ourip, ARRAY_LEN, ast_channel_register(), ast_cli_register_multiple(), ast_find_ourip(), AST_FORMAT_ALAW, ast_format_cap_add(), ast_format_cap_add_all_by_type(), ast_format_cap_alloc(), AST_FORMAT_GSM, AST_FORMAT_H263, ast_format_set(), AST_FORMAT_TYPE_AUDIO, AST_FORMAT_ULAW, ast_log(), ast_module_helper(), AST_MODULE_LOAD_DECLINE, ast_rtp_glue_register, ast_sched_context_create(), ast_sockaddr_from_sin, ast_sockaddr_ipv4(), ASTOBJ_CONTAINER_INIT, ast_channel_tech::capabilities, free, io_context_create(), JINGLE_CONFIG, jingle_list, jingle_load_config(), LOG_ERROR, and LOG_WARNING.
01935 { 01936 struct ast_sockaddr ourip_tmp; 01937 struct ast_sockaddr bindaddr_tmp; 01938 struct ast_format tmpfmt; 01939 01940 char *jabber_loaded = ast_module_helper("", "res_jabber.so", 0, 0, 0, 0); 01941 01942 if (!(jingle_tech.capabilities = ast_format_cap_alloc())) { 01943 return AST_MODULE_LOAD_DECLINE; 01944 } 01945 01946 ast_format_cap_add_all_by_type(jingle_tech.capabilities, AST_FORMAT_TYPE_AUDIO); 01947 if (!(global_capability = ast_format_cap_alloc())) { 01948 return AST_MODULE_LOAD_DECLINE; 01949 } 01950 ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0)); 01951 ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_GSM, 0)); 01952 ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0)); 01953 ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_H263, 0)); 01954 01955 free(jabber_loaded); 01956 if (!jabber_loaded) { 01957 /* Dependency module has a different name, if embedded */ 01958 jabber_loaded = ast_module_helper("", "res_jabber", 0, 0, 0, 0); 01959 free(jabber_loaded); 01960 if (!jabber_loaded) { 01961 ast_log(LOG_ERROR, "chan_jingle.so depends upon res_jabber.so\n"); 01962 return AST_MODULE_LOAD_DECLINE; 01963 } 01964 } 01965 01966 ASTOBJ_CONTAINER_INIT(&jingle_list); 01967 if (!jingle_load_config()) { 01968 ast_log(LOG_ERROR, "Unable to read config file %s. Not loading module.\n", JINGLE_CONFIG); 01969 return AST_MODULE_LOAD_DECLINE; 01970 } 01971 01972 sched = ast_sched_context_create(); 01973 if (!sched) { 01974 ast_log(LOG_WARNING, "Unable to create schedule context\n"); 01975 } 01976 01977 io = io_context_create(); 01978 if (!io) { 01979 ast_log(LOG_WARNING, "Unable to create I/O context\n"); 01980 } 01981 01982 ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr); 01983 if (ast_find_ourip(&ourip_tmp, &bindaddr_tmp, AF_INET)) { 01984 ast_log(LOG_WARNING, "Unable to get own IP address, Jingle disabled\n"); 01985 return 0; 01986 } 01987 __ourip.s_addr = htonl(ast_sockaddr_ipv4(&ourip_tmp)); 01988 01989 ast_rtp_glue_register(&jingle_rtp_glue); 01990 ast_cli_register_multiple(jingle_cli, ARRAY_LEN(jingle_cli)); 01991 /* Make sure we can register our channel type */ 01992 if (ast_channel_register(&jingle_tech)) { 01993 ast_log(LOG_ERROR, "Unable to register channel class %s\n", channel_type); 01994 return -1; 01995 } 01996 return 0; 01997 }
| static int reload | ( | void | ) | [static] |
| static int unload_module | ( | void | ) | [static] |
Unload the jingle channel from Asterisk.
Definition at line 2006 of file chan_jingle.c.
References ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_format_cap_destroy(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_glue_unregister(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, jingle_list, jingle_member_destroy(), jinglelock, LOG_WARNING, jingle_pvt::next, and jingle_pvt::owner.
02007 { 02008 struct jingle_pvt *privates = NULL; 02009 ast_cli_unregister_multiple(jingle_cli, ARRAY_LEN(jingle_cli)); 02010 /* First, take us out of the channel loop */ 02011 ast_channel_unregister(&jingle_tech); 02012 ast_rtp_glue_unregister(&jingle_rtp_glue); 02013 02014 if (!ast_mutex_lock(&jinglelock)) { 02015 /* Hangup all interfaces if they have an owner */ 02016 ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, { 02017 ASTOBJ_WRLOCK(iterator); 02018 privates = iterator->p; 02019 while(privates) { 02020 if (privates->owner) 02021 ast_softhangup(privates->owner, AST_SOFTHANGUP_APPUNLOAD); 02022 privates = privates->next; 02023 } 02024 iterator->p = NULL; 02025 ASTOBJ_UNLOCK(iterator); 02026 }); 02027 ast_mutex_unlock(&jinglelock); 02028 } else { 02029 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 02030 return -1; 02031 } 02032 ASTOBJ_CONTAINER_DESTROYALL(&jingle_list, jingle_member_destroy); 02033 ASTOBJ_CONTAINER_DESTROY(&jingle_list); 02034 02035 global_capability = ast_format_cap_destroy(global_capability); 02036 return 0; 02037 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Jingle Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, } [static] |
Definition at line 2044 of file chan_jingle.c.
struct in_addr __ourip [static] |
Definition at line 216 of file chan_jingle.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 2044 of file chan_jingle.c.
struct sockaddr_in bindaddr = { 0, } [static] |
The address we bind to
Definition at line 212 of file chan_jingle.c.
const char channel_type[] = "Jingle" [static] |
Definition at line 167 of file chan_jingle.c.
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 77 of file chan_jingle.c.
const char desc[] = "Jingle Channel" [static] |
Definition at line 166 of file chan_jingle.c.
char externip[16] [static] |
Definition at line 224 of file chan_jingle.c.
struct ast_format_cap* global_capability [static] |
Definition at line 169 of file chan_jingle.c.
struct ast_jb_conf global_jbconf [static] |
Definition at line 85 of file chan_jingle.c.
struct io_context* io [static] |
The IO context
Definition at line 215 of file chan_jingle.c.
struct ast_cli_entry jingle_cli[] [static] |
Initial value:
{
AST_CLI_DEFINE(jingle_do_reload, "Reload Jingle configuration"),
AST_CLI_DEFINE(jingle_show_channels, "Show Jingle channels"),
}
Definition at line 218 of file chan_jingle.c.
struct jingle_container jingle_list [static] |
Definition at line 226 of file chan_jingle.c.
Referenced by find_jingle(), jingle_load_config(), jingle_show_channels(), load_module(), and unload_module().
struct ast_rtp_glue jingle_rtp_glue [static] |
Definition at line 447 of file chan_jingle.c.
struct ast_channel_tech jingle_tech [static] |
ast_mutex_t jinglelock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static] |
Protect the interface list (of jingle_pvt's)
Definition at line 171 of file chan_jingle.c.
Referenced by jingle_alloc(), jingle_show_channels(), and unload_module().
struct ast_sched_context* sched [static] |
The scheduling context
Definition at line 214 of file chan_jingle.c.
1.5.6