#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.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, int 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, 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 int | jingle_get_codec (struct ast_channel *chan) |
static enum ast_rtp_get_result | jingle_get_rtp_peer (struct ast_channel *chan, struct ast_rtp **rtp) |
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) |
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, int format, void *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_set_rtp_peer (struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *tpeer, int codecs, 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_DEFAULT , .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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, .reload = reload, } |
static struct in_addr | __ourip |
static const struct ast_module_info * | ast_module_info = &__mod_info |
static struct sockaddr_in | bindaddr = { 0, } |
static struct ast_jb_conf | default_jbconf |
static const char | desc [] = "Jingle Channel" |
static char | externip [16] |
static int | global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263 |
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_protocol | jingle_rtp |
RTP driver interface. | |
static struct ast_channel_tech | jingle_tech |
PBX interface structure for channel registration. | |
static ast_mutex_t | jinglelock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
static struct sched_context * | sched |
static const char | type [] = "Jingle" |
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 89 of file chan_jingle.c.
00089 { 00090 AJI_CONNECT_HOST, 00091 AJI_CONNECT_PRFLX, 00092 AJI_CONNECT_RELAY, 00093 AJI_CONNECT_SRFLX, 00094 };
enum jingle_protocol |
Definition at line 84 of file chan_jingle.c.
00084 { 00085 AJI_PROTOCOL_UDP, 00086 AJI_PROTOCOL_SSLTCP, 00087 };
static void __reg_module | ( | void | ) | [static] |
Definition at line 1929 of file chan_jingle.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 1929 of file chan_jingle.c.
static void add_codec_to_answer | ( | const struct jingle_pvt * | p, | |
int | codec, | |||
iks * | dcodecs | |||
) | [static] |
Definition at line 268 of file chan_jingle.c.
References ast_getformatname(), ast_rtp_lookup_code(), format, jingle::p, and jingle_pvt::rtp.
00269 { 00270 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 ast_rtp_lookup_code(p->rtp, 1, codec); 00307 }
static struct jingle* find_jingle | ( | char * | name, | |
char * | connection | |||
) | [static] |
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 309 of file chan_jingle.c.
References add_codec_to_answer(), ast_aji_increment_mid(), ast_aji_send(), ast_codec_pref_index(), jingle::capability, jingle::connection, aji_client::jid, JINGLE_ACCEPT, JINGLE_AUDIO_RTP_NS, JINGLE_NODE, JINGLE_NS, JINGLE_SID, aji_client::mid, aji_client::p, jingle::p, jingle::prefs, jingle_pvt::sid, and jingle::user.
Referenced by jingle_answer().
00310 { 00311 struct jingle_pvt *tmp = client->p; 00312 struct aji_client *c = client->connection; 00313 iks *iq, *jingle, *dcodecs, *payload_red, *payload_audio, *payload_cn; 00314 int x; 00315 int pref_codec = 0; 00316 int alreadysent = 0; 00317 00318 if (p->initiator) 00319 return 1; 00320 00321 iq = iks_new("iq"); 00322 jingle = iks_new(JINGLE_NODE); 00323 dcodecs = iks_new("description"); 00324 if (iq && jingle && dcodecs) { 00325 iks_insert_attrib(dcodecs, "xmlns", JINGLE_AUDIO_RTP_NS); 00326 00327 for (x = 0; x < 32; x++) { 00328 if (!(pref_codec = ast_codec_pref_index(&client->prefs, x))) 00329 break; 00330 if (!(client->capability & pref_codec)) 00331 continue; 00332 if (alreadysent & pref_codec) 00333 continue; 00334 add_codec_to_answer(p, pref_codec, dcodecs); 00335 alreadysent |= pref_codec; 00336 } 00337 payload_red = iks_new("payload-type"); 00338 iks_insert_attrib(payload_red, "id", "117"); 00339 iks_insert_attrib(payload_red, "name", "red"); 00340 payload_audio = iks_new("payload-type"); 00341 iks_insert_attrib(payload_audio, "id", "106"); 00342 iks_insert_attrib(payload_audio, "name", "audio/telephone-event"); 00343 payload_cn = iks_new("payload-type"); 00344 iks_insert_attrib(payload_cn, "id", "13"); 00345 iks_insert_attrib(payload_cn, "name", "CN"); 00346 00347 00348 iks_insert_attrib(iq, "type", "set"); 00349 iks_insert_attrib(iq, "to", (p->them) ? p->them : client->user); 00350 iks_insert_attrib(iq, "id", client->connection->mid); 00351 ast_aji_increment_mid(client->connection->mid); 00352 00353 iks_insert_attrib(jingle, "xmlns", JINGLE_NS); 00354 iks_insert_attrib(jingle, "action", JINGLE_ACCEPT); 00355 iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them); 00356 iks_insert_attrib(jingle, JINGLE_SID, tmp->sid); 00357 iks_insert_node(iq, jingle); 00358 iks_insert_node(jingle, dcodecs); 00359 iks_insert_node(dcodecs, payload_red); 00360 iks_insert_node(dcodecs, payload_audio); 00361 iks_insert_node(dcodecs, payload_cn); 00362 00363 ast_aji_send(c, iq); 00364 00365 iks_delete(payload_red); 00366 iks_delete(payload_audio); 00367 iks_delete(payload_cn); 00368 iks_delete(dcodecs); 00369 iks_delete(jingle); 00370 iks_delete(iq); 00371 } 00372 return 1; 00373 }
static int jingle_action | ( | struct jingle * | client, | |
struct jingle_pvt * | p, | |||
const char * | action | |||
) | [static] |
Definition at line 881 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().
00882 { 00883 iks *iq, *jingle = NULL; 00884 int res = -1; 00885 00886 iq = iks_new("iq"); 00887 jingle = iks_new("jingle"); 00888 00889 if (iq) { 00890 iks_insert_attrib(iq, "type", "set"); 00891 iks_insert_attrib(iq, "from", client->connection->jid->full); 00892 iks_insert_attrib(iq, "to", p->them); 00893 iks_insert_attrib(iq, "id", client->connection->mid); 00894 ast_aji_increment_mid(client->connection->mid); 00895 if (jingle) { 00896 iks_insert_attrib(jingle, "action", action); 00897 iks_insert_attrib(jingle, JINGLE_SID, p->sid); 00898 iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them); 00899 iks_insert_attrib(jingle, "xmlns", JINGLE_NS); 00900 00901 iks_insert_node(iq, jingle); 00902 00903 ast_aji_send(client->connection, iq); 00904 res = 0; 00905 } 00906 } 00907 00908 iks_delete(jingle); 00909 iks_delete(iq); 00910 00911 return res; 00912 }
static int jingle_add_candidate | ( | struct jingle * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 1087 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, aji_client::jid, JINGLE_NODE, JINGLE_SID, jingle_update_stun(), jingle_pvt::laststun, jingle_pvt::next, jingle::p, jingle_pvt::parent, and jingle_pvt::theircandidates.
Referenced by jingle_parser().
01088 { 01089 struct jingle_pvt *p = NULL, *tmp = NULL; 01090 struct aji_client *c = client->connection; 01091 struct jingle_candidate *newcandidate = NULL; 01092 iks *traversenodes = NULL, *receipt = NULL; 01093 01094 for (tmp = client->p; tmp; tmp = tmp->next) { 01095 if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) { 01096 p = tmp; 01097 break; 01098 } 01099 } 01100 01101 if (!p) 01102 return -1; 01103 01104 traversenodes = pak->query; 01105 while(traversenodes) { 01106 if(!strcasecmp(iks_name(traversenodes), "jingle")) { 01107 traversenodes = iks_child(traversenodes); 01108 continue; 01109 } 01110 if(!strcasecmp(iks_name(traversenodes), "content")) { 01111 traversenodes = iks_child(traversenodes); 01112 continue; 01113 } 01114 if(!strcasecmp(iks_name(traversenodes), "transport")) { 01115 traversenodes = iks_child(traversenodes); 01116 continue; 01117 } 01118 01119 if(!strcasecmp(iks_name(traversenodes), "candidate")) { 01120 newcandidate = ast_calloc(1, sizeof(*newcandidate)); 01121 if (!newcandidate) 01122 return 0; 01123 ast_copy_string(newcandidate->ip, iks_find_attrib(traversenodes, "ip"), sizeof(newcandidate->ip)); 01124 newcandidate->port = atoi(iks_find_attrib(traversenodes, "port")); 01125 ast_copy_string(newcandidate->password, iks_find_attrib(traversenodes, "pwd"), sizeof(newcandidate->password)); 01126 if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "udp")) 01127 newcandidate->protocol = AJI_PROTOCOL_UDP; 01128 else if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "ssltcp")) 01129 newcandidate->protocol = AJI_PROTOCOL_SSLTCP; 01130 01131 if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "host")) 01132 newcandidate->type = AJI_CONNECT_HOST; 01133 else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "prflx")) 01134 newcandidate->type = AJI_CONNECT_PRFLX; 01135 else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "relay")) 01136 newcandidate->type = AJI_CONNECT_RELAY; 01137 else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "srflx")) 01138 newcandidate->type = AJI_CONNECT_SRFLX; 01139 01140 newcandidate->network = atoi(iks_find_attrib(traversenodes, "network")); 01141 newcandidate->generation = atoi(iks_find_attrib(traversenodes, "generation")); 01142 newcandidate->next = NULL; 01143 01144 newcandidate->next = p->theircandidates; 01145 p->theircandidates = newcandidate; 01146 p->laststun = 0; 01147 jingle_update_stun(p->parent, p); 01148 newcandidate = NULL; 01149 } 01150 traversenodes = iks_next(traversenodes); 01151 } 01152 01153 receipt = iks_new("iq"); 01154 iks_insert_attrib(receipt, "type", "result"); 01155 iks_insert_attrib(receipt, "from", c->jid->full); 01156 iks_insert_attrib(receipt, "to", iks_find_attrib(pak->x, "from")); 01157 iks_insert_attrib(receipt, "id", iks_find_attrib(pak->x, "id")); 01158 ast_aji_send(c, receipt); 01159 01160 iks_delete(receipt); 01161 01162 return 1; 01163 }
static struct jingle_pvt * jingle_alloc | ( | struct jingle * | client, | |
const char * | from, | |||
const char * | sid | |||
) | [static] |
Definition at line 739 of file chan_jingle.c.
References ast_calloc, ast_copy_string(), ast_debug, ast_free, ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_rtp_new_with_bindaddr(), ASTOBJ_CONTAINER_FIND, bindaddr, aji_client::buddies, jingle::buddy, aji_resource::cap, jingle::connection, io, aji_version::jingle, jinglelock, LOG_ERROR, LOG_WARNING, jingle::name, aji_resource::next, jingle::p, jingle::prefs, aji_resource::resource, and aji_buddy::resources.
Referenced by jingle_newcall(), and jingle_request().
00740 { 00741 struct jingle_pvt *tmp = NULL; 00742 struct aji_resource *resources = NULL; 00743 struct aji_buddy *buddy; 00744 char idroster[200]; 00745 00746 ast_debug(1, "The client is %s for alloc\n", client->name); 00747 if (!sid && !strchr(from, '/')) { /* I started call! */ 00748 if (!strcasecmp(client->name, "guest")) { 00749 buddy = ASTOBJ_CONTAINER_FIND(&client->connection->buddies, from); 00750 if (buddy) 00751 resources = buddy->resources; 00752 } else if (client->buddy) 00753 resources = client->buddy->resources; 00754 while (resources) { 00755 if (resources->cap->jingle) { 00756 break; 00757 } 00758 resources = resources->next; 00759 } 00760 if (resources) 00761 snprintf(idroster, sizeof(idroster), "%s/%s", from, resources->resource); 00762 else { 00763 ast_log(LOG_ERROR, "no jingle capable clients to talk to.\n"); 00764 return NULL; 00765 } 00766 } 00767 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { 00768 return NULL; 00769 } 00770 00771 memcpy(&tmp->prefs, &client->prefs, sizeof(tmp->prefs)); 00772 00773 if (sid) { 00774 ast_copy_string(tmp->sid, sid, sizeof(tmp->sid)); 00775 ast_copy_string(tmp->them, from, sizeof(tmp->them)); 00776 } else { 00777 snprintf(tmp->sid, sizeof(tmp->sid), "%08lx%08lx", ast_random(), ast_random()); 00778 ast_copy_string(tmp->them, idroster, sizeof(tmp->them)); 00779 tmp->initiator = 1; 00780 } 00781 tmp->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); 00782 tmp->parent = client; 00783 if (!tmp->rtp) { 00784 ast_log(LOG_WARNING, "Out of RTP sessions?\n"); 00785 ast_free(tmp); 00786 return NULL; 00787 } 00788 ast_copy_string(tmp->exten, "s", sizeof(tmp->exten)); 00789 ast_mutex_init(&tmp->lock); 00790 ast_mutex_lock(&jinglelock); 00791 tmp->next = client->p; 00792 client->p = tmp; 00793 ast_mutex_unlock(&jinglelock); 00794 return tmp; 00795 }
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::p, 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, | |
char * | dest, | |||
int | timeout | |||
) | [static] |
Initiate new call, part of PBX interface dest is the dial string.
Definition at line 1422 of file chan_jingle.c.
References ast_channel::_state, ast_copy_string(), ast_log(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RING, jingle_pvt::capability, jingle::connection, aji_client::f, jingle_create_candidates(), jingle_ringing_ack(), jingle_transmit_invite(), jingle_pvt::jointcapability, LOG_WARNING, aji_client::mid, ast_channel::name, jingle_pvt::parent, jingle_pvt::ring, jingle_pvt::ringrule, jingle_pvt::sid, ast_channel::tech_pvt, and jingle_pvt::them.
01423 { 01424 struct jingle_pvt *p = ast->tech_pvt; 01425 01426 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 01427 ast_log(LOG_WARNING, "jingle_call called on %s, neither down nor reserved\n", ast->name); 01428 return -1; 01429 } 01430 01431 ast_setstate(ast, AST_STATE_RING); 01432 p->jointcapability = p->capability; 01433 if (!p->ringrule) { 01434 ast_copy_string(p->ring, p->parent->connection->mid, sizeof(p->ring)); 01435 p->ringrule = iks_filter_add_rule(p->parent->connection->f, jingle_ringing_ack, p, 01436 IKS_RULE_ID, p->ring, IKS_RULE_DONE); 01437 } else 01438 ast_log(LOG_WARNING, "Whoa, already have a ring rule!\n"); 01439 01440 jingle_transmit_invite(p); 01441 jingle_create_candidates(p->parent, p, p->sid, p->them); 01442 01443 return 0; 01444 }
static int jingle_create_candidates | ( | struct jingle * | client, | |
struct jingle_pvt * | p, | |||
char * | sid, | |||
char * | from | |||
) | [static] |
Definition at line 581 of file chan_jingle.c.
References __ourip, 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_get_us(), ast_strlen_zero(), bindaddr, jingle_candidate::component, jingle::connection, externip, 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().
00582 { 00583 struct jingle_candidate *tmp; 00584 struct aji_client *c = client->connection; 00585 struct jingle_candidate *ours1 = NULL, *ours2 = NULL; 00586 struct sockaddr_in sin; 00587 struct sockaddr_in dest; 00588 struct in_addr us; 00589 struct in_addr externaddr; 00590 iks *iq, *jingle, *content, *transport, *candidate; 00591 char component[16], foundation[16], generation[16], network[16], pass[16], port[7], priority[16], user[16]; 00592 00593 00594 iq = iks_new("iq"); 00595 jingle = iks_new(JINGLE_NODE); 00596 content = iks_new("content"); 00597 transport = iks_new("transport"); 00598 candidate = iks_new("candidate"); 00599 if (!iq || !jingle || !content || !transport || !candidate) { 00600 ast_log(LOG_ERROR, "Memory allocation error\n"); 00601 goto safeout; 00602 } 00603 ours1 = ast_calloc(1, sizeof(*ours1)); 00604 ours2 = ast_calloc(1, sizeof(*ours2)); 00605 if (!ours1 || !ours2) 00606 goto safeout; 00607 00608 iks_insert_node(iq, jingle); 00609 iks_insert_node(jingle, content); 00610 iks_insert_node(content, transport); 00611 iks_insert_node(transport, candidate); 00612 00613 for (; p; p = p->next) { 00614 if (!strcasecmp(p->sid, sid)) 00615 break; 00616 } 00617 00618 if (!p) { 00619 ast_log(LOG_NOTICE, "No matching jingle session - SID %s!\n", sid); 00620 goto safeout; 00621 } 00622 00623 ast_rtp_get_us(p->rtp, &sin); 00624 ast_find_ourip(&us, bindaddr); 00625 00626 /* Setup our first jingle candidate */ 00627 ours1->component = 1; 00628 ours1->foundation = (unsigned int)bindaddr.sin_addr.s_addr | AJI_CONNECT_HOST | AJI_PROTOCOL_UDP; 00629 ours1->generation = 0; 00630 ast_copy_string(ours1->ip, ast_inet_ntoa(us), sizeof(ours1->ip)); 00631 ours1->network = 0; 00632 ours1->port = ntohs(sin.sin_port); 00633 ours1->priority = 1678246398; 00634 ours1->protocol = AJI_PROTOCOL_UDP; 00635 snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random()); 00636 ast_copy_string(ours1->password, pass, sizeof(ours1->password)); 00637 ours1->type = AJI_CONNECT_HOST; 00638 snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random()); 00639 ast_copy_string(ours1->ufrag, user, sizeof(ours1->ufrag)); 00640 p->ourcandidates = ours1; 00641 00642 if (!ast_strlen_zero(externip)) { 00643 /* XXX We should really stun for this one not just go with externip XXX */ 00644 if (inet_aton(externip, &externaddr)) 00645 ast_log(LOG_WARNING, "Invalid extern IP : %s\n", externip); 00646 00647 ours2->component = 1; 00648 ours2->foundation = (unsigned int)externaddr.s_addr | AJI_CONNECT_PRFLX | AJI_PROTOCOL_UDP; 00649 ours2->generation = 0; 00650 ast_copy_string(ours2->ip, externip, sizeof(ours2->ip)); 00651 ours2->network = 0; 00652 ours2->port = ntohs(sin.sin_port); 00653 ours2->priority = 1678246397; 00654 ours2->protocol = AJI_PROTOCOL_UDP; 00655 snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random()); 00656 ast_copy_string(ours2->password, pass, sizeof(ours2->password)); 00657 ours2->type = AJI_CONNECT_PRFLX; 00658 00659 snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random()); 00660 ast_copy_string(ours2->ufrag, user, sizeof(ours2->ufrag)); 00661 ours1->next = ours2; 00662 ours2 = NULL; 00663 } 00664 ours1 = NULL; 00665 dest.sin_addr = __ourip; 00666 dest.sin_port = sin.sin_port; 00667 00668 00669 for (tmp = p->ourcandidates; tmp; tmp = tmp->next) { 00670 snprintf(component, sizeof(component), "%u", tmp->component); 00671 snprintf(foundation, sizeof(foundation), "%u", tmp->foundation); 00672 snprintf(generation, sizeof(generation), "%u", tmp->generation); 00673 snprintf(network, sizeof(network), "%u", tmp->network); 00674 snprintf(port, sizeof(port), "%u", tmp->port); 00675 snprintf(priority, sizeof(priority), "%u", tmp->priority); 00676 00677 iks_insert_attrib(iq, "from", c->jid->full); 00678 iks_insert_attrib(iq, "to", from); 00679 iks_insert_attrib(iq, "type", "set"); 00680 iks_insert_attrib(iq, "id", c->mid); 00681 ast_aji_increment_mid(c->mid); 00682 iks_insert_attrib(jingle, "action", JINGLE_NEGOTIATE); 00683 iks_insert_attrib(jingle, JINGLE_SID, sid); 00684 iks_insert_attrib(jingle, "initiator", (p->initiator) ? c->jid->full : from); 00685 iks_insert_attrib(jingle, "xmlns", JINGLE_NS); 00686 iks_insert_attrib(content, "creator", p->initiator ? "initiator" : "responder"); 00687 iks_insert_attrib(content, "name", "asterisk-audio-content"); 00688 iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS); 00689 iks_insert_attrib(candidate, "component", component); 00690 iks_insert_attrib(candidate, "foundation", foundation); 00691 iks_insert_attrib(candidate, "generation", generation); 00692 iks_insert_attrib(candidate, "ip", tmp->ip); 00693 iks_insert_attrib(candidate, "network", network); 00694 iks_insert_attrib(candidate, "port", port); 00695 iks_insert_attrib(candidate, "priority", priority); 00696 switch (tmp->protocol) { 00697 case AJI_PROTOCOL_UDP: 00698 iks_insert_attrib(candidate, "protocol", "udp"); 00699 break; 00700 case AJI_PROTOCOL_SSLTCP: 00701 iks_insert_attrib(candidate, "protocol", "ssltcp"); 00702 break; 00703 } 00704 iks_insert_attrib(candidate, "pwd", tmp->password); 00705 switch (tmp->type) { 00706 case AJI_CONNECT_HOST: 00707 iks_insert_attrib(candidate, "type", "host"); 00708 break; 00709 case AJI_CONNECT_PRFLX: 00710 iks_insert_attrib(candidate, "type", "prflx"); 00711 break; 00712 case AJI_CONNECT_RELAY: 00713 iks_insert_attrib(candidate, "type", "relay"); 00714 break; 00715 case AJI_CONNECT_SRFLX: 00716 iks_insert_attrib(candidate, "type", "srflx"); 00717 break; 00718 } 00719 iks_insert_attrib(candidate, "ufrag", tmp->ufrag); 00720 00721 ast_aji_send(c, iq); 00722 } 00723 p->laststun = 0; 00724 00725 safeout: 00726 if (ours1) 00727 ast_free(ours1); 00728 if (ours2) 00729 ast_free(ours2); 00730 iks_delete(iq); 00731 iks_delete(jingle); 00732 iks_delete(content); 00733 iks_delete(transport); 00734 iks_delete(candidate); 00735 00736 return 1; 00737 }
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 1664 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::capability, jingle::connection, jingle::context, aji_client::f, JINGLE_NS, jingle_parser(), LOG_ERROR, LOG_WARNING, jingle::name, jingle_candidate::next, prefs, jingle::prefs, jingle::user, and var.
01667 { 01668 struct aji_client *client; 01669 01670 if (!member) 01671 ast_log(LOG_WARNING, "Out of memory.\n"); 01672 01673 ast_copy_string(member->name, label, sizeof(member->name)); 01674 ast_copy_string(member->user, label, sizeof(member->user)); 01675 ast_copy_string(member->context, context, sizeof(member->context)); 01676 member->allowguest = allowguest; 01677 member->prefs = prefs; 01678 while (var) { 01679 #if 0 01680 struct jingle_candidate *candidate = NULL; 01681 #endif 01682 if (!strcasecmp(var->name, "username")) 01683 ast_copy_string(member->user, var->value, sizeof(member->user)); 01684 else if (!strcasecmp(var->name, "disallow")) 01685 ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 0); 01686 else if (!strcasecmp(var->name, "allow")) 01687 ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 1); 01688 else if (!strcasecmp(var->name, "context")) 01689 ast_copy_string(member->context, var->value, sizeof(member->context)); 01690 #if 0 01691 else if (!strcasecmp(var->name, "candidate")) { 01692 candidate = jingle_create_candidate(var->value); 01693 if (candidate) { 01694 candidate->next = member->ourcandidates; 01695 member->ourcandidates = candidate; 01696 } 01697 } 01698 #endif 01699 else if (!strcasecmp(var->name, "connection")) { 01700 if ((client = ast_aji_get_client(var->value))) { 01701 member->connection = client; 01702 iks_filter_add_rule(client->f, jingle_parser, member, 01703 IKS_RULE_TYPE, IKS_PAK_IQ, 01704 IKS_RULE_FROM_PARTIAL, member->user, 01705 IKS_RULE_NS, JINGLE_NS, 01706 IKS_RULE_DONE); 01707 } else { 01708 ast_log(LOG_ERROR, "connection referenced not found!\n"); 01709 return 0; 01710 } 01711 } 01712 var = var->next; 01713 } 01714 if (member->connection && member->user) 01715 member->buddy = ASTOBJ_CONTAINER_FIND(&member->connection->buddies, member->user); 01716 else { 01717 ast_log(LOG_ERROR, "No Connection or Username!\n"); 01718 } 01719 return 1; 01720 }
static int jingle_digit | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 1282 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::p, jingle_pvt::parent, jingle_pvt::sid, ast_channel::tech_pvt, and jingle_pvt::them.
Referenced by jingle_digit_begin(), and jingle_digit_end().
01283 { 01284 struct jingle_pvt *p = ast->tech_pvt; 01285 struct jingle *client = p->parent; 01286 iks *iq, *jingle, *dtmf; 01287 char buffer[2] = {digit, '\0'}; 01288 iq = iks_new("iq"); 01289 jingle = iks_new("jingle"); 01290 dtmf = iks_new("dtmf"); 01291 if(!iq || !jingle || !dtmf) { 01292 iks_delete(iq); 01293 iks_delete(jingle); 01294 iks_delete(dtmf); 01295 ast_log(LOG_ERROR, "Did not send dtmf do to memory issue\n"); 01296 return -1; 01297 } 01298 01299 iks_insert_attrib(iq, "type", "set"); 01300 iks_insert_attrib(iq, "to", p->them); 01301 iks_insert_attrib(iq, "from", client->connection->jid->full); 01302 iks_insert_attrib(iq, "id", client->connection->mid); 01303 ast_aji_increment_mid(client->connection->mid); 01304 iks_insert_attrib(jingle, "xmlns", JINGLE_NS); 01305 iks_insert_attrib(jingle, "action", "session-info"); 01306 iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them); 01307 iks_insert_attrib(jingle, "sid", p->sid); 01308 iks_insert_attrib(dtmf, "xmlns", JINGLE_DTMF_NS); 01309 iks_insert_attrib(dtmf, "code", buffer); 01310 iks_insert_node(iq, jingle); 01311 iks_insert_node(jingle, dtmf); 01312 01313 ast_mutex_lock(&p->lock); 01314 if (ast->dtmff.frametype == AST_FRAME_DTMF_BEGIN || duration == 0) { 01315 iks_insert_attrib(dtmf, "action", "button-down"); 01316 } else if (ast->dtmff.frametype == AST_FRAME_DTMF_END || duration != 0) { 01317 iks_insert_attrib(dtmf, "action", "button-up"); 01318 } 01319 ast_aji_send(client->connection, iq); 01320 01321 iks_delete(iq); 01322 iks_delete(jingle); 01323 iks_delete(dtmf); 01324 ast_mutex_unlock(&p->lock); 01325 return 0; 01326 }
static int jingle_digit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 1328 of file chan_jingle.c.
References chan, and jingle_digit().
01329 { 01330 return jingle_digit(chan, digit, 0); 01331 }
static int jingle_digit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 1333 of file chan_jingle.c.
References jingle_digit().
01334 { 01335 return jingle_digit(ast, digit, duration); 01336 }
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 1575 of file chan_jingle.c.
References CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.
01576 { 01577 switch (cmd) { 01578 case CLI_INIT: 01579 e->command = "jingle reload"; 01580 e->usage = 01581 "Usage: jingle reload\n" 01582 " Reload jingle channel driver.\n"; 01583 return NULL; 01584 case CLI_GENERATE: 01585 return NULL; 01586 } 01587 01588 return CLI_SUCCESS; 01589 }
static int jingle_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 1248 of file chan_jingle.c.
References ast_mutex_lock(), ast_mutex_unlock(), jingle_pvt::lock, jingle_pvt::owner, and ast_channel::tech_pvt.
01249 { 01250 struct jingle_pvt *p = newchan->tech_pvt; 01251 ast_mutex_lock(&p->lock); 01252 01253 if ((p->owner != oldchan)) { 01254 ast_mutex_unlock(&p->lock); 01255 return -1; 01256 } 01257 if (p->owner == oldchan) 01258 p->owner = newchan; 01259 ast_mutex_unlock(&p->lock); 01260 return 0; 01261 }
static void jingle_free_candidates | ( | struct jingle_candidate * | candidate | ) | [static] |
Definition at line 914 of file chan_jingle.c.
References ast_free, last, and jingle_candidate::next.
Referenced by jingle_free_pvt().
00915 { 00916 struct jingle_candidate *last; 00917 while (candidate) { 00918 last = candidate; 00919 candidate = candidate->next; 00920 ast_free(last); 00921 } 00922 }
static void jingle_free_pvt | ( | struct jingle * | client, | |
struct jingle_pvt * | p | |||
) | [static] |
Definition at line 924 of file chan_jingle.c.
References ast_free, ast_log(), ast_rtp_destroy(), jingle::connection, aji_client::f, jingle_free_candidates(), LOG_WARNING, jingle_pvt::next, jingle_pvt::owner, jingle::p, jingle_pvt::parent, jingle_pvt::ringrule, jingle_pvt::rtp, jingle_pvt::theircandidates, and jingle_pvt::vrtp.
Referenced by jingle_hangup(), and jingle_newcall().
00925 { 00926 struct jingle_pvt *cur, *prev = NULL; 00927 cur = client->p; 00928 while (cur) { 00929 if (cur == p) { 00930 if (prev) 00931 prev->next = p->next; 00932 else 00933 client->p = p->next; 00934 break; 00935 } 00936 prev = cur; 00937 cur = cur->next; 00938 } 00939 if (p->ringrule) 00940 iks_filter_remove_rule(p->parent->connection->f, p->ringrule); 00941 if (p->owner) 00942 ast_log(LOG_WARNING, "Uh oh, there's an owner, this is going to be messy.\n"); 00943 if (p->rtp) 00944 ast_rtp_destroy(p->rtp); 00945 if (p->vrtp) 00946 ast_rtp_destroy(p->vrtp); 00947 jingle_free_candidates(p->theircandidates); 00948 ast_free(p); 00949 }
static int jingle_get_codec | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 418 of file chan_jingle.c.
References chan, jingle_pvt::peercapability, and ast_channel::tech_pvt.
00419 { 00420 struct jingle_pvt *p = chan->tech_pvt; 00421 return p->peercapability; 00422 }
static enum ast_rtp_get_result jingle_get_rtp_peer | ( | struct ast_channel * | chan, | |
struct ast_rtp ** | rtp | |||
) | [static] |
Definition at line 400 of file chan_jingle.c.
References ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_GET_FAILED, AST_RTP_TRY_PARTIAL, chan, jingle_pvt::lock, jingle_pvt::rtp, and ast_channel::tech_pvt.
00401 { 00402 struct jingle_pvt *p = chan->tech_pvt; 00403 enum ast_rtp_get_result res = AST_RTP_GET_FAILED; 00404 00405 if (!p) 00406 return res; 00407 00408 ast_mutex_lock(&p->lock); 00409 if (p->rtp) { 00410 *rtp = p->rtp; 00411 res = AST_RTP_TRY_PARTIAL; 00412 } 00413 ast_mutex_unlock(&p->lock); 00414 00415 return res; 00416 }
static int jingle_handle_dtmf | ( | struct jingle * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 496 of file chan_jingle.c.
References AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_queue_frame(), ast_verbose(), f, JINGLE_NODE, jingle_response(), JINGLE_SID, LOG_NOTICE, jingle_pvt::next, jingle_pvt::owner, jingle::p, and jingle_pvt::sid.
Referenced by jingle_parser().
00497 { 00498 struct jingle_pvt *tmp; 00499 iks *dtmfnode = NULL, *dtmfchild = NULL; 00500 char *dtmf; 00501 /* Make sure our new call doesn't exist yet */ 00502 for (tmp = client->p; tmp; tmp = tmp->next) { 00503 if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) 00504 break; 00505 } 00506 00507 if (tmp) { 00508 if(iks_find_with_attrib(pak->x, "dtmf-method", "method", "rtp")) { 00509 jingle_response(client,pak, 00510 "feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'", 00511 "unsupported-dtmf-method xmlns='http://www.xmpp.org/extensions/xep-0181.html#ns-errors'"); 00512 return -1; 00513 } 00514 if ((dtmfnode = iks_find(pak->x, "dtmf"))) { 00515 if((dtmf = iks_find_attrib(dtmfnode, "code"))) { 00516 if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-up")) { 00517 struct ast_frame f = {AST_FRAME_DTMF_BEGIN, }; 00518 f.subclass = dtmf[0]; 00519 ast_queue_frame(tmp->owner, &f); 00520 ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass); 00521 } else if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-down")) { 00522 struct ast_frame f = {AST_FRAME_DTMF_END, }; 00523 f.subclass = dtmf[0]; 00524 ast_queue_frame(tmp->owner, &f); 00525 ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass); 00526 } else if(iks_find_attrib(pak->x, "dtmf")) { /* 250 millasecond default */ 00527 struct ast_frame f = {AST_FRAME_DTMF, }; 00528 f.subclass = dtmf[0]; 00529 ast_queue_frame(tmp->owner, &f); 00530 ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass); 00531 } 00532 } 00533 } else if ((dtmfnode = iks_find_with_attrib(pak->x, JINGLE_NODE, "action", "session-info"))) { 00534 if((dtmfchild = iks_find(dtmfnode, "dtmf"))) { 00535 if((dtmf = iks_find_attrib(dtmfchild, "code"))) { 00536 if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-up")) { 00537 struct ast_frame f = {AST_FRAME_DTMF_END, }; 00538 f.subclass = dtmf[0]; 00539 ast_queue_frame(tmp->owner, &f); 00540 ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass); 00541 } else if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-down")) { 00542 struct ast_frame f = {AST_FRAME_DTMF_BEGIN, }; 00543 f.subclass = dtmf[0]; 00544 ast_queue_frame(tmp->owner, &f); 00545 ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass); 00546 } 00547 } 00548 } 00549 } 00550 jingle_response(client, pak, NULL, NULL); 00551 return 1; 00552 } else 00553 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n"); 00554 00555 jingle_response(client, pak, NULL, NULL); 00556 return 1; 00557 }
static int jingle_hangup | ( | struct ast_channel * | ast | ) | [static] |
Hangup a call through the jingle proxy channel.
Definition at line 1447 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::p, jingle_pvt::parent, and ast_channel::tech_pvt.
01448 { 01449 struct jingle_pvt *p = ast->tech_pvt; 01450 struct jingle *client; 01451 01452 ast_mutex_lock(&p->lock); 01453 client = p->parent; 01454 p->owner = NULL; 01455 ast->tech_pvt = NULL; 01456 if (!p->alreadygone) 01457 jingle_action(client, p, JINGLE_TERMINATE); 01458 ast_mutex_unlock(&p->lock); 01459 01460 jingle_free_pvt(client, p); 01461 01462 return 0; 01463 }
static int jingle_hangup_farend | ( | struct jingle * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 560 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().
00561 { 00562 struct jingle_pvt *tmp; 00563 00564 ast_debug(1, "The client is %s\n", client->name); 00565 /* Make sure our new call doesn't exist yet */ 00566 for (tmp = client->p; tmp; tmp = tmp->next) { 00567 if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) 00568 break; 00569 } 00570 00571 if (tmp) { 00572 tmp->alreadygone = 1; 00573 if (tmp->owner) 00574 ast_queue_hangup(tmp->owner); 00575 } else 00576 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n"); 00577 jingle_response(client, pak, NULL, NULL); 00578 return 1; 00579 }
static int jingle_indicate | ( | struct ast_channel * | ast, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 1263 of file chan_jingle.c.
References AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), and LOG_NOTICE.
01264 { 01265 int res = 0; 01266 01267 switch (condition) { 01268 case AST_CONTROL_HOLD: 01269 ast_moh_start(ast, data, NULL); 01270 break; 01271 case AST_CONTROL_UNHOLD: 01272 ast_moh_stop(ast); 01273 break; 01274 default: 01275 ast_log(LOG_NOTICE, "Don't know how to indicate condition '%d'\n", condition); 01276 res = -1; 01277 } 01278 01279 return res; 01280 }
static int jingle_is_answered | ( | struct jingle * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 476 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().
00477 { 00478 struct jingle_pvt *tmp; 00479 00480 ast_debug(1, "The client is %s\n", client->name); 00481 /* Make sure our new call doesn't exist yet */ 00482 for (tmp = client->p; tmp; tmp = tmp->next) { 00483 if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) 00484 break; 00485 } 00486 00487 if (tmp) { 00488 if (tmp->owner) 00489 ast_queue_control(tmp->owner, AST_CONTROL_ANSWER); 00490 } else 00491 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n"); 00492 jingle_response(client, pak, NULL, NULL); 00493 return 1; 00494 }
static int jingle_load_config | ( | void | ) | [static] |
Definition at line 1722 of file chan_jingle.c.
References ahp, ast_category_browse(), ast_config_load, ast_copy_string(), ast_gethostbyname(), ast_jb_read_conf(), ast_log(), ast_parse_allow_disallow(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), bindaddr, clients, context, default_jbconf, externip, global_capability, global_jbconf, hp, JINGLE_CONFIG, LOG_WARNING, prefs, and var.
Referenced by load_module().
01723 { 01724 char *cat = NULL; 01725 struct ast_config *cfg = NULL; 01726 char context[100]; 01727 int allowguest = 1; 01728 struct ast_variable *var; 01729 struct jingle *member; 01730 struct hostent *hp; 01731 struct ast_hostent ahp; 01732 struct ast_codec_pref prefs; 01733 struct aji_client_container *clients; 01734 struct jingle_candidate *global_candidates = NULL; 01735 struct ast_flags config_flags = { 0 }; 01736 01737 cfg = ast_config_load(JINGLE_CONFIG, config_flags); 01738 if (!cfg) 01739 return 0; 01740 01741 /* Copy the default jb config over global_jbconf */ 01742 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 01743 01744 cat = ast_category_browse(cfg, NULL); 01745 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) { 01746 /* handle jb conf */ 01747 if (!ast_jb_read_conf(&global_jbconf, var->name, var->value)) 01748 continue; 01749 01750 if (!strcasecmp(var->name, "allowguest")) 01751 allowguest = 01752 (ast_true(ast_variable_retrieve(cfg, "general", "allowguest"))) ? 1 : 0; 01753 else if (!strcasecmp(var->name, "disallow")) 01754 ast_parse_allow_disallow(&prefs, &global_capability, var->value, 0); 01755 else if (!strcasecmp(var->name, "allow")) 01756 ast_parse_allow_disallow(&prefs, &global_capability, var->value, 1); 01757 else if (!strcasecmp(var->name, "context")) 01758 ast_copy_string(context, var->value, sizeof(context)); 01759 else if (!strcasecmp(var->name, "externip")) 01760 ast_copy_string(externip, var->value, sizeof(externip)); 01761 else if (!strcasecmp(var->name, "bindaddr")) { 01762 if (!(hp = ast_gethostbyname(var->value, &ahp))) { 01763 ast_log(LOG_WARNING, "Invalid address: %s\n", var->value); 01764 } else { 01765 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr)); 01766 } 01767 } 01768 /* Idea to allow for custom candidates */ 01769 /* 01770 else if (!strcasecmp(var->name, "candidate")) { 01771 candidate = jingle_create_candidate(var->value); 01772 if (candidate) { 01773 candidate->next = global_candidates; 01774 global_candidates = candidate; 01775 } 01776 } 01777 */ 01778 } 01779 while (cat) { 01780 if (strcasecmp(cat, "general")) { 01781 var = ast_variable_browse(cfg, cat); 01782 member = ast_calloc(1, sizeof(*member)); 01783 ASTOBJ_INIT(member); 01784 ASTOBJ_WRLOCK(member); 01785 if (!strcasecmp(cat, "guest")) { 01786 ast_copy_string(member->name, "guest", sizeof(member->name)); 01787 ast_copy_string(member->user, "guest", sizeof(member->user)); 01788 ast_copy_string(member->context, context, sizeof(member->context)); 01789 member->allowguest = allowguest; 01790 member->prefs = prefs; 01791 while (var) { 01792 if (!strcasecmp(var->name, "disallow")) 01793 ast_parse_allow_disallow(&member->prefs, &member->capability, 01794 var->value, 0); 01795 else if (!strcasecmp(var->name, "allow")) 01796 ast_parse_allow_disallow(&member->prefs, &member->capability, 01797 var->value, 1); 01798 else if (!strcasecmp(var->name, "context")) 01799 ast_copy_string(member->context, var->value, 01800 sizeof(member->context)); 01801 /* Idea to allow for custom candidates */ 01802 /* 01803 else if (!strcasecmp(var->name, "candidate")) { 01804 candidate = jingle_create_candidate(var->value); 01805 if (candidate) { 01806 candidate->next = member->ourcandidates; 01807 member->ourcandidates = candidate; 01808 } 01809 } 01810 */ 01811 var = var->next; 01812 } 01813 ASTOBJ_UNLOCK(member); 01814 clients = ast_aji_get_clients(); 01815 if (clients) { 01816 ASTOBJ_CONTAINER_TRAVERSE(clients, 1, { 01817 ASTOBJ_WRLOCK(iterator); 01818 ASTOBJ_WRLOCK(member); 01819 member->connection = NULL; 01820 iks_filter_add_rule(iterator->f, jingle_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, JINGLE_NS, IKS_RULE_DONE); 01821 iks_filter_add_rule(iterator->f, jingle_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, JINGLE_DTMF_NS, IKS_RULE_DONE); 01822 ASTOBJ_UNLOCK(member); 01823 ASTOBJ_UNLOCK(iterator); 01824 }); 01825 ASTOBJ_CONTAINER_LINK(&jingle_list, member); 01826 } else { 01827 ASTOBJ_UNLOCK(member); 01828 ASTOBJ_UNREF(member, jingle_member_destroy); 01829 } 01830 } else { 01831 ASTOBJ_UNLOCK(member); 01832 if (jingle_create_member(cat, var, allowguest, prefs, context, member)) 01833 ASTOBJ_CONTAINER_LINK(&jingle_list, member); 01834 ASTOBJ_UNREF(member, jingle_member_destroy); 01835 } 01836 } 01837 cat = ast_category_browse(cfg, cat); 01838 } 01839 jingle_free_candidates(global_candidates); 01840 return 1; 01841 }
static void jingle_member_destroy | ( | struct jingle * | obj | ) | [static] |
Definition at line 237 of file chan_jingle.c.
References ast_free.
Referenced by jingle_parser(), and unload_module().
00238 { 00239 ast_free(obj); 00240 }
static struct ast_channel* jingle_new | ( | struct jingle * | client, | |
struct jingle_pvt * | i, | |||
int | state, | |||
const char * | title | |||
) | [static] |
Start new jingle channel.
Definition at line 798 of file chan_jingle.c.
References accountcode, jingle::accountcode, ast_channel::adsicpe, ast_channel::amaflags, jingle::amaflags, AST_ADSI_UNAVAILABLE, ast_best_codec(), AST_CAUSE_SWITCH_CONGESTION, ast_channel_alloc, ast_channel_set_fd(), ast_codec_choose(), ast_copy_string(), AST_FORMAT_VIDEO_MASK, ast_hangup(), ast_jb_configure(), ast_log(), ast_pbx_start(), ast_random(), ast_rtcp_fd(), ast_rtp_codec_setpref(), ast_rtp_fd(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), jingle::callgroup, ast_channel::callgroup, jingle::callingpres, jingle_pvt::capability, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, jingle_pvt::cid_name, jingle_pvt::cid_num, ast_callerid::cid_pres, jingle::context, ast_channel::context, jingle_pvt::exten, ast_channel::exten, global_capability, global_jbconf, ast_channel::hangupcause, jingle_tech, jingle_pvt::jointcapability, language, jingle::language, LOG_WARNING, musicclass, jingle::musicclass, ast_channel::name, ast_channel::nativeformats, jingle_pvt::owner, jingle::pickupgroup, ast_channel::pickupgroup, jingle_pvt::prefs, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, jingle_pvt::rtp, str, ast_channel::tech, ast_channel::tech_pvt, jingle_pvt::them, jingle_pvt::vrtp, and ast_channel::writeformat.
Referenced by jingle_newcall(), and jingle_request().
00799 { 00800 struct ast_channel *tmp; 00801 int fmt; 00802 int what; 00803 const char *str; 00804 00805 if (title) 00806 str = title; 00807 else 00808 str = i->them; 00809 tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", "", "", 0, "Jingle/%s-%04lx", str, ast_random() & 0xffff); 00810 if (!tmp) { 00811 ast_log(LOG_WARNING, "Unable to allocate Jingle channel structure!\n"); 00812 return NULL; 00813 } 00814 tmp->tech = &jingle_tech; 00815 00816 /* Select our native format based on codec preference until we receive 00817 something from another device to the contrary. */ 00818 if (i->jointcapability) 00819 what = i->jointcapability; 00820 else if (i->capability) 00821 what = i->capability; 00822 else 00823 what = global_capability; 00824 00825 /* Set Frame packetization */ 00826 if (i->rtp) 00827 ast_rtp_codec_setpref(i->rtp, &i->prefs); 00828 00829 tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | (i->jointcapability & AST_FORMAT_VIDEO_MASK); 00830 fmt = ast_best_codec(tmp->nativeformats); 00831 00832 if (i->rtp) { 00833 ast_channel_set_fd(tmp, 0, ast_rtp_fd(i->rtp)); 00834 ast_channel_set_fd(tmp, 1, ast_rtcp_fd(i->rtp)); 00835 } 00836 if (i->vrtp) { 00837 ast_channel_set_fd(tmp, 2, ast_rtp_fd(i->vrtp)); 00838 ast_channel_set_fd(tmp, 3, ast_rtcp_fd(i->vrtp)); 00839 } 00840 if (state == AST_STATE_RING) 00841 tmp->rings = 1; 00842 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 00843 tmp->writeformat = fmt; 00844 tmp->rawwriteformat = fmt; 00845 tmp->readformat = fmt; 00846 tmp->rawreadformat = fmt; 00847 tmp->tech_pvt = i; 00848 00849 tmp->callgroup = client->callgroup; 00850 tmp->pickupgroup = client->pickupgroup; 00851 tmp->cid.cid_pres = client->callingpres; 00852 if (!ast_strlen_zero(client->accountcode)) 00853 ast_string_field_set(tmp, accountcode, client->accountcode); 00854 if (client->amaflags) 00855 tmp->amaflags = client->amaflags; 00856 if (!ast_strlen_zero(client->language)) 00857 ast_string_field_set(tmp, language, client->language); 00858 if (!ast_strlen_zero(client->musicclass)) 00859 ast_string_field_set(tmp, musicclass, client->musicclass); 00860 i->owner = tmp; 00861 ast_copy_string(tmp->context, client->context, sizeof(tmp->context)); 00862 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 00863 /* Don't use ast_set_callerid() here because it will 00864 * generate an unnecessary NewCallerID event */ 00865 tmp->cid.cid_ani = ast_strdup(i->cid_num); 00866 if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s")) 00867 tmp->cid.cid_dnid = ast_strdup(i->exten); 00868 tmp->priority = 1; 00869 if (i->rtp) 00870 ast_jb_configure(tmp, &global_jbconf); 00871 if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) { 00872 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 00873 tmp->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 00874 ast_hangup(tmp); 00875 tmp = NULL; 00876 } 00877 00878 return tmp; 00879 }
static int jingle_newcall | ( | struct jingle * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 952 of file chan_jingle.c.
References 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_set_m_type(), ast_rtp_set_rtpmap_type(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RING, jingle_pvt::audio_content_name, chan, jingle::connection, description, 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().
00953 { 00954 struct jingle_pvt *p, *tmp = client->p; 00955 struct ast_channel *chan; 00956 int res; 00957 iks *codec, *content, *description; 00958 char *from = NULL; 00959 00960 /* Make sure our new call doesn't exist yet */ 00961 from = iks_find_attrib(pak->x,"to"); 00962 if(!from) 00963 from = client->connection->jid->full; 00964 00965 while (tmp) { 00966 if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) { 00967 ast_log(LOG_NOTICE, "Ignoring duplicate call setup on SID %s\n", tmp->sid); 00968 jingle_response(client, pak, "out-of-order", NULL); 00969 return -1; 00970 } 00971 tmp = tmp->next; 00972 } 00973 00974 if (!strcasecmp(client->name, "guest")){ 00975 /* the guest account is not tied to any configured XMPP client, 00976 let's set it now */ 00977 client->connection = ast_aji_get_client(from); 00978 if (!client->connection) { 00979 ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", from); 00980 return -1; 00981 } 00982 } 00983 00984 p = jingle_alloc(client, pak->from->partial, iks_find_attrib(pak->query, JINGLE_SID)); 00985 if (!p) { 00986 ast_log(LOG_WARNING, "Unable to allocate jingle structure!\n"); 00987 return -1; 00988 } 00989 chan = jingle_new(client, p, AST_STATE_DOWN, pak->from->user); 00990 if (!chan) { 00991 jingle_free_pvt(client, p); 00992 return -1; 00993 } 00994 ast_mutex_lock(&p->lock); 00995 ast_copy_string(p->them, pak->from->full, sizeof(p->them)); 00996 if (iks_find_attrib(pak->query, JINGLE_SID)) { 00997 ast_copy_string(p->sid, iks_find_attrib(pak->query, JINGLE_SID), 00998 sizeof(p->sid)); 00999 } 01000 01001 /* content points to the first <content/> tag */ 01002 content = iks_child(iks_child(pak->x)); 01003 while (content) { 01004 description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_AUDIO_RTP_NS); 01005 if (description) { 01006 /* audio content found */ 01007 codec = iks_child(iks_child(content)); 01008 ast_copy_string(p->audio_content_name, iks_find_attrib(content, "name"), sizeof(p->audio_content_name)); 01009 01010 while (codec) { 01011 ast_rtp_set_m_type(p->rtp, atoi(iks_find_attrib(codec, "id"))); 01012 ast_rtp_set_rtpmap_type(p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0); 01013 codec = iks_next(codec); 01014 } 01015 } 01016 01017 description = NULL; 01018 codec = NULL; 01019 01020 description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_VIDEO_RTP_NS); 01021 if (description) { 01022 /* video content found */ 01023 codec = iks_child(iks_child(content)); 01024 ast_copy_string(p->video_content_name, iks_find_attrib(content, "name"), sizeof(p->video_content_name)); 01025 01026 while (codec) { 01027 ast_rtp_set_m_type(p->rtp, atoi(iks_find_attrib(codec, "id"))); 01028 ast_rtp_set_rtpmap_type(p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0); 01029 codec = iks_next(codec); 01030 } 01031 } 01032 01033 content = iks_next(content); 01034 } 01035 01036 ast_mutex_unlock(&p->lock); 01037 ast_setstate(chan, AST_STATE_RING); 01038 res = ast_pbx_start(chan); 01039 01040 switch (res) { 01041 case AST_PBX_FAILED: 01042 ast_log(LOG_WARNING, "Failed to start PBX :(\n"); 01043 jingle_response(client, pak, "service-unavailable", NULL); 01044 break; 01045 case AST_PBX_CALL_LIMIT: 01046 ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n"); 01047 jingle_response(client, pak, "service-unavailable", NULL); 01048 break; 01049 case AST_PBX_SUCCESS: 01050 jingle_response(client, pak, NULL, NULL); 01051 jingle_create_candidates(client, p, 01052 iks_find_attrib(pak->query, JINGLE_SID), 01053 iks_find_attrib(pak->x, "from")); 01054 /* nothing to do */ 01055 break; 01056 } 01057 01058 return 1; 01059 }
static int jingle_parser | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 1591 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().
01592 { 01593 struct jingle *client = ASTOBJ_REF((struct jingle *) data); 01594 ast_log(LOG_NOTICE, "Filter matched\n"); 01595 01596 if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INITIATE)) { 01597 /* New call */ 01598 jingle_newcall(client, pak); 01599 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_NEGOTIATE)) { 01600 ast_debug(3, "About to add candidate!\n"); 01601 jingle_add_candidate(client, pak); 01602 ast_debug(3, "Candidate Added!\n"); 01603 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_ACCEPT)) { 01604 jingle_is_answered(client, pak); 01605 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INFO)) { 01606 jingle_handle_dtmf(client, pak); 01607 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_TERMINATE)) { 01608 jingle_hangup_farend(client, pak); 01609 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", "reject")) { 01610 jingle_hangup_farend(client, pak); 01611 } 01612 ASTOBJ_UNREF(client, jingle_member_destroy); 01613 return IKS_FILTER_EAT; 01614 }
static struct ast_frame * jingle_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 1193 of file chan_jingle.c.
References ast_mutex_lock(), ast_mutex_unlock(), jingle_rtp_read(), jingle_pvt::lock, and ast_channel::tech_pvt.
01194 { 01195 struct ast_frame *fr; 01196 struct jingle_pvt *p = ast->tech_pvt; 01197 01198 ast_mutex_lock(&p->lock); 01199 fr = jingle_rtp_read(ast, p); 01200 ast_mutex_unlock(&p->lock); 01201 return fr; 01202 }
static struct ast_channel * jingle_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Part of PBX interface.
Definition at line 1466 of file chan_jingle.c.
References ast_aji_get_client(), ast_log(), AST_STATE_DOWN, ast_strdupa, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, chan, jingle::connection, find_jingle(), jingle_alloc(), jingle_new(), LOG_ERROR, LOG_WARNING, jingle::name, s, and strsep().
01467 { 01468 struct jingle_pvt *p = NULL; 01469 struct jingle *client = NULL; 01470 char *sender = NULL, *to = NULL, *s = NULL; 01471 struct ast_channel *chan = NULL; 01472 01473 if (data) { 01474 s = ast_strdupa(data); 01475 if (s) { 01476 sender = strsep(&s, "/"); 01477 if (sender && (sender[0] != '\0')) 01478 to = strsep(&s, "/"); 01479 if (!to) { 01480 ast_log(LOG_ERROR, "Bad arguments in Jingle Dialstring: %s\n", (char*) data); 01481 return NULL; 01482 } 01483 } 01484 } 01485 01486 client = find_jingle(to, sender); 01487 if (!client) { 01488 ast_log(LOG_WARNING, "Could not find recipient.\n"); 01489 return NULL; 01490 } 01491 if (!strcasecmp(client->name, "guest")){ 01492 /* the guest account is not tied to any configured XMPP client, 01493 let's set it now */ 01494 client->connection = ast_aji_get_client(sender); 01495 if (!client->connection) { 01496 ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", sender); 01497 return NULL; 01498 } 01499 } 01500 01501 ASTOBJ_WRLOCK(client); 01502 p = jingle_alloc(client, to, NULL); 01503 if (p) 01504 chan = jingle_new(client, p, AST_STATE_DOWN, to); 01505 ASTOBJ_UNLOCK(client); 01506 01507 return chan; 01508 }
static int jingle_response | ( | struct jingle * | client, | |
ikspak * | pak, | |||
const char * | reasonstr, | |||
const char * | reasonstr2 | |||
) | [static] |
Definition at line 444 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().
00445 { 00446 iks *response = NULL, *error = NULL, *reason = NULL; 00447 int res = -1; 00448 00449 response = iks_new("iq"); 00450 if (response) { 00451 iks_insert_attrib(response, "type", "result"); 00452 iks_insert_attrib(response, "from", client->connection->jid->full); 00453 iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from")); 00454 iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id")); 00455 if (reasonstr) { 00456 error = iks_new("error"); 00457 if (error) { 00458 iks_insert_attrib(error, "type", "cancel"); 00459 reason = iks_new(reasonstr); 00460 if (reason) 00461 iks_insert_node(error, reason); 00462 iks_insert_node(response, error); 00463 } 00464 } 00465 ast_aji_send(client->connection, response); 00466 res = 0; 00467 } 00468 00469 iks_delete(reason); 00470 iks_delete(error); 00471 iks_delete(response); 00472 00473 return res; 00474 }
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] |
Definition at line 1165 of file chan_jingle.c.
References ast_debug, AST_FORMAT_AUDIO_MASK, AST_FORMAT_VIDEO_MASK, AST_FRAME_VOICE, ast_null_frame, ast_rtp_read(), ast_set_read_format(), ast_set_write_format(), f, jingle_update_stun(), ast_channel::nativeformats, jingle_pvt::owner, jingle_pvt::parent, ast_channel::readformat, jingle_pvt::rtp, and ast_channel::writeformat.
Referenced by jingle_read().
01166 { 01167 struct ast_frame *f; 01168 01169 if (!p->rtp) 01170 return &ast_null_frame; 01171 f = ast_rtp_read(p->rtp); 01172 jingle_update_stun(p->parent, p); 01173 if (p->owner) { 01174 /* We already hold the channel lock */ 01175 if (f->frametype == AST_FRAME_VOICE) { 01176 if (f->subclass != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) { 01177 ast_debug(1, "Oooh, format changed to %d\n", f->subclass); 01178 p->owner->nativeformats = 01179 (p->owner->nativeformats & AST_FORMAT_VIDEO_MASK) | f->subclass; 01180 ast_set_read_format(p->owner, p->owner->readformat); 01181 ast_set_write_format(p->owner, p->owner->writeformat); 01182 } 01183 /* if ((ast_test_flag(p, SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) { 01184 f = ast_dsp_process(p->owner, p->vad, f); 01185 if (f && (f->frametype == AST_FRAME_DTMF)) 01186 ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass); 01187 } */ 01188 } 01189 } 01190 return f; 01191 }
static int jingle_sendhtml | ( | struct ast_channel * | ast, | |
int | subclass, | |||
const char * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 1338 of file chan_jingle.c.
References ast_log(), and LOG_NOTICE.
01339 { 01340 ast_log(LOG_NOTICE, "XXX Implement jingle sendhtml XXX\n"); 01341 01342 return -1; 01343 }
static int jingle_set_rtp_peer | ( | struct ast_channel * | chan, | |
struct ast_rtp * | rtp, | |||
struct ast_rtp * | vrtp, | |||
struct ast_rtp * | tpeer, | |||
int | codecs, | |||
int | nat_active | |||
) | [static] |
Definition at line 424 of file chan_jingle.c.
References ast_mutex_lock(), ast_mutex_unlock(), chan, jingle_pvt::lock, and ast_channel::tech_pvt.
00425 { 00426 struct jingle_pvt *p; 00427 00428 p = chan->tech_pvt; 00429 if (!p) 00430 return -1; 00431 ast_mutex_lock(&p->lock); 00432 00433 /* if (rtp) 00434 ast_rtp_get_peer(rtp, &p->redirip); 00435 else 00436 memset(&p->redirip, 0, sizeof(p->redirip)); 00437 p->redircodecs = codecs; */ 00438 00439 /* Reset lastrtprx timer */ 00440 ast_mutex_unlock(&p->lock); 00441 return 0; 00442 }
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 1511 of file chan_jingle.c.
References AJI_MAX_JIDLEN, ast_cli_args::argc, ast_cli(), ast_copy_string(), ast_getformatname(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, chan, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, FORMAT, jingle_list, jinglelock, LOG_WARNING, ast_channel::name, jingle_pvt::next, jingle_pvt::owner, ast_channel::readformat, jingle_pvt::them, ast_cli_entry::usage, and ast_channel::writeformat.
01512 { 01513 #define FORMAT "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n" 01514 struct jingle_pvt *p; 01515 struct ast_channel *chan; 01516 int numchans = 0; 01517 char them[AJI_MAX_JIDLEN]; 01518 char *jid = NULL; 01519 char *resource = NULL; 01520 01521 switch (cmd) { 01522 case CLI_INIT: 01523 e->command = "jingle show channels"; 01524 e->usage = 01525 "Usage: jingle show channels\n" 01526 " Shows current state of the Jingle channels.\n"; 01527 return NULL; 01528 case CLI_GENERATE: 01529 return NULL; 01530 } 01531 01532 if (a->argc != 3) 01533 return CLI_SHOWUSAGE; 01534 01535 ast_mutex_lock(&jinglelock); 01536 ast_cli(a->fd, FORMAT, "Channel", "Jabber ID", "Resource", "Read", "Write"); 01537 ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, { 01538 ASTOBJ_WRLOCK(iterator); 01539 p = iterator->p; 01540 while(p) { 01541 chan = p->owner; 01542 ast_copy_string(them, p->them, sizeof(them)); 01543 jid = them; 01544 resource = strchr(them, '/'); 01545 if (!resource) 01546 resource = "None"; 01547 else { 01548 *resource = '\0'; 01549 resource ++; 01550 } 01551 if (chan) 01552 ast_cli(a->fd, FORMAT, 01553 chan->name, 01554 jid, 01555 resource, 01556 ast_getformatname(chan->readformat), 01557 ast_getformatname(chan->writeformat) 01558 ); 01559 else 01560 ast_log(LOG_WARNING, "No available channel\n"); 01561 numchans ++; 01562 p = p->next; 01563 } 01564 ASTOBJ_UNLOCK(iterator); 01565 }); 01566 01567 ast_mutex_unlock(&jinglelock); 01568 01569 ast_cli(a->fd, "%d active jingle channel%s\n", numchans, (numchans != 1) ? "s" : ""); 01570 return CLI_SUCCESS; 01571 #undef FORMAT 01572 }
static int jingle_transmit_invite | ( | struct jingle_pvt * | p | ) | [static] |
Definition at line 1344 of file chan_jingle.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_copy_string(), jingle::connection, description, aji_client::jid, JINGLE_AUDIO_RTP_NS, JINGLE_ICE_UDP_NS, JINGLE_INITIATE, JINGLE_NODE, JINGLE_NS, JINGLE_SID, aji_client::mid, and aji_client::p.
Referenced by jingle_call().
01345 { 01346 struct jingle *aux = NULL; 01347 struct aji_client *client = NULL; 01348 iks *iq, *jingle, *content, *description, *transport; 01349 iks *payload_eg711u, *payload_pcmu; 01350 01351 aux = p->parent; 01352 client = aux->connection; 01353 iq = iks_new("iq"); 01354 jingle = iks_new(JINGLE_NODE); 01355 content = iks_new("content"); 01356 description = iks_new("description"); 01357 transport = iks_new("transport"); 01358 payload_pcmu = iks_new("payload-type"); 01359 payload_eg711u = iks_new("payload-type"); 01360 01361 ast_copy_string(p->audio_content_name, "asterisk-audio-content", sizeof(p->audio_content_name)); 01362 01363 iks_insert_attrib(iq, "type", "set"); 01364 iks_insert_attrib(iq, "to", p->them); 01365 iks_insert_attrib(iq, "from", client->jid->full); 01366 iks_insert_attrib(iq, "id", client->mid); 01367 ast_aji_increment_mid(client->mid); 01368 iks_insert_attrib(jingle, "action", JINGLE_INITIATE); 01369 iks_insert_attrib(jingle, JINGLE_SID, p->sid); 01370 iks_insert_attrib(jingle, "initiator", client->jid->full); 01371 iks_insert_attrib(jingle, "xmlns", JINGLE_NS); 01372 01373 /* For now, we only send one audio based content */ 01374 iks_insert_attrib(content, "creator", "initiator"); 01375 iks_insert_attrib(content, "name", p->audio_content_name); 01376 iks_insert_attrib(content, "profile", "RTP/AVP"); 01377 iks_insert_attrib(description, "xmlns", JINGLE_AUDIO_RTP_NS); 01378 iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS); 01379 iks_insert_attrib(payload_pcmu, "id", "0"); 01380 iks_insert_attrib(payload_pcmu, "name", "PCMU"); 01381 iks_insert_attrib(payload_eg711u, "id", "100"); 01382 iks_insert_attrib(payload_eg711u, "name", "EG711U"); 01383 iks_insert_node(description, payload_pcmu); 01384 iks_insert_node(description, payload_eg711u); 01385 iks_insert_node(content, description); 01386 iks_insert_node(content, transport); 01387 iks_insert_node(jingle, content); 01388 iks_insert_node(iq, jingle); 01389 01390 ast_aji_send(client, iq); 01391 01392 iks_delete(iq); 01393 iks_delete(jingle); 01394 iks_delete(content); 01395 iks_delete(description); 01396 iks_delete(transport); 01397 iks_delete(payload_eg711u); 01398 iks_delete(payload_pcmu); 01399 return 0; 01400 }
static int jingle_update_stun | ( | struct jingle * | client, | |
struct jingle_pvt * | p | |||
) | [static] |
Definition at line 1061 of file chan_jingle.c.
References ahp, ast_gethostbyname(), ast_rtp_stun_request(), 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().
01062 { 01063 struct jingle_candidate *tmp; 01064 struct hostent *hp; 01065 struct ast_hostent ahp; 01066 struct sockaddr_in sin; 01067 01068 if (time(NULL) == p->laststun) 01069 return 0; 01070 01071 tmp = p->theircandidates; 01072 p->laststun = time(NULL); 01073 while (tmp) { 01074 char username[256]; 01075 hp = ast_gethostbyname(tmp->ip, &ahp); 01076 sin.sin_family = AF_INET; 01077 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); 01078 sin.sin_port = htons(tmp->port); 01079 snprintf(username, sizeof(username), "%s:%s", tmp->ufrag, p->ourcandidates->ufrag); 01080 01081 ast_rtp_stun_request(p->rtp, &sin, username); 01082 tmp = tmp->next; 01083 } 01084 return 1; 01085 }
static int jingle_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | f | |||
) | [static] |
Send frame to media channel (rtp).
Definition at line 1205 of file chan_jingle.c.
References AST_FRAME_IMAGE, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_write(), 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.
01206 { 01207 struct jingle_pvt *p = ast->tech_pvt; 01208 int res = 0; 01209 01210 switch (frame->frametype) { 01211 case AST_FRAME_VOICE: 01212 if (!(frame->subclass & ast->nativeformats)) { 01213 ast_log(LOG_WARNING, 01214 "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n", 01215 frame->subclass, ast->nativeformats, ast->readformat, 01216 ast->writeformat); 01217 return 0; 01218 } 01219 if (p) { 01220 ast_mutex_lock(&p->lock); 01221 if (p->rtp) { 01222 res = ast_rtp_write(p->rtp, frame); 01223 } 01224 ast_mutex_unlock(&p->lock); 01225 } 01226 break; 01227 case AST_FRAME_VIDEO: 01228 if (p) { 01229 ast_mutex_lock(&p->lock); 01230 if (p->vrtp) { 01231 res = ast_rtp_write(p->vrtp, frame); 01232 } 01233 ast_mutex_unlock(&p->lock); 01234 } 01235 break; 01236 case AST_FRAME_IMAGE: 01237 return 0; 01238 break; 01239 default: 01240 ast_log(LOG_WARNING, "Can't send %d type frames with Jingle write\n", 01241 frame->frametype); 01242 return 0; 01243 } 01244 01245 return res; 01246 }
static int load_module | ( | void | ) | [static] |
Load module into PBX, register channel.
Definition at line 1844 of file chan_jingle.c.
References __ourip, ARRAY_LEN, ast_channel_register(), ast_cli_register_multiple(), ast_find_ourip(), ast_log(), ast_module_helper(), AST_MODULE_LOAD_DECLINE, ast_rtp_proto_register(), ASTOBJ_CONTAINER_INIT, bindaddr, free, io, io_context_create(), jingle_cli, JINGLE_CONFIG, jingle_list, jingle_load_config(), jingle_rtp, jingle_tech, LOG_ERROR, LOG_WARNING, sched_context_create(), and type.
01845 { 01846 char *jabber_loaded = ast_module_helper("", "res_jabber.so", 0, 0, 0, 0); 01847 free(jabber_loaded); 01848 if (!jabber_loaded) { 01849 /* Dependency module has a different name, if embedded */ 01850 jabber_loaded = ast_module_helper("", "res_jabber", 0, 0, 0, 0); 01851 free(jabber_loaded); 01852 if (!jabber_loaded) { 01853 ast_log(LOG_ERROR, "chan_jingle.so depends upon res_jabber.so\n"); 01854 return AST_MODULE_LOAD_DECLINE; 01855 } 01856 } 01857 01858 ASTOBJ_CONTAINER_INIT(&jingle_list); 01859 if (!jingle_load_config()) { 01860 ast_log(LOG_ERROR, "Unable to read config file %s. Not loading module.\n", JINGLE_CONFIG); 01861 return AST_MODULE_LOAD_DECLINE; 01862 } 01863 01864 sched = sched_context_create(); 01865 if (!sched) 01866 ast_log(LOG_WARNING, "Unable to create schedule context\n"); 01867 01868 io = io_context_create(); 01869 if (!io) 01870 ast_log(LOG_WARNING, "Unable to create I/O context\n"); 01871 01872 if (ast_find_ourip(&__ourip, bindaddr)) { 01873 ast_log(LOG_WARNING, "Unable to get own IP address, Jingle disabled\n"); 01874 return 0; 01875 } 01876 01877 ast_rtp_proto_register(&jingle_rtp); 01878 ast_cli_register_multiple(jingle_cli, ARRAY_LEN(jingle_cli)); 01879 /* Make sure we can register our channel type */ 01880 if (ast_channel_register(&jingle_tech)) { 01881 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type); 01882 return -1; 01883 } 01884 return 0; 01885 }
static int reload | ( | void | ) | [static] |
static int unload_module | ( | void | ) | [static] |
Unload the jingle channel from Asterisk.
Definition at line 1894 of file chan_jingle.c.
References ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_proto_unregister(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, jingle_cli, jingle_list, jingle_member_destroy(), jingle_rtp, jingle_tech, jinglelock, LOG_WARNING, jingle_pvt::next, and jingle_pvt::owner.
01895 { 01896 struct jingle_pvt *privates = NULL; 01897 ast_cli_unregister_multiple(jingle_cli, ARRAY_LEN(jingle_cli)); 01898 /* First, take us out of the channel loop */ 01899 ast_channel_unregister(&jingle_tech); 01900 ast_rtp_proto_unregister(&jingle_rtp); 01901 01902 if (!ast_mutex_lock(&jinglelock)) { 01903 /* Hangup all interfaces if they have an owner */ 01904 ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, { 01905 ASTOBJ_WRLOCK(iterator); 01906 privates = iterator->p; 01907 while(privates) { 01908 if (privates->owner) 01909 ast_softhangup(privates->owner, AST_SOFTHANGUP_APPUNLOAD); 01910 privates = privates->next; 01911 } 01912 iterator->p = NULL; 01913 ASTOBJ_UNLOCK(iterator); 01914 }); 01915 ast_mutex_unlock(&jinglelock); 01916 } else { 01917 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 01918 return -1; 01919 } 01920 ASTOBJ_CONTAINER_DESTROYALL(&jingle_list, jingle_member_destroy); 01921 ASTOBJ_CONTAINER_DESTROY(&jingle_list); 01922 return 0; 01923 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 1929 of file chan_jingle.c.
struct in_addr __ourip [static] |
Definition at line 216 of file chan_jingle.c.
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 1929 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.
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 75 of file chan_jingle.c.
const char desc[] = "Jingle Channel" [static] |
Definition at line 162 of file chan_jingle.c.
char externip[16] [static] |
Definition at line 233 of file chan_jingle.c.
int global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263 [static] |
Definition at line 165 of file chan_jingle.c.
struct ast_jb_conf global_jbconf [static] |
Definition at line 82 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:
{ { .handler = jingle_do_reload , .summary = "Reload Jingle configuration" ,__VA_ARGS__ }, { .handler = jingle_show_channels , .summary = "Show Jingle channels" ,__VA_ARGS__ }, }
Definition at line 227 of file chan_jingle.c.
Referenced by load_module(), and unload_module().
struct jingle_container jingle_list [static] |
Definition at line 235 of file chan_jingle.c.
Referenced by find_jingle(), jingle_show_channels(), load_module(), and unload_module().
struct ast_rtp_protocol jingle_rtp [static] |
RTP driver interface.
Definition at line 220 of file chan_jingle.c.
Referenced by load_module(), and unload_module().
struct ast_channel_tech jingle_tech [static] |
PBX interface structure for channel registration.
Definition at line 192 of file chan_jingle.c.
Referenced by jingle_new(), load_module(), and unload_module().
ast_mutex_t jinglelock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Protect the interface list (of jingle_pvt's)
Definition at line 167 of file chan_jingle.c.
Referenced by jingle_alloc(), jingle_show_channels(), and unload_module().
struct sched_context* sched [static] |
The scheduling context
Definition at line 214 of file chan_jingle.c.
const char type[] = "Jingle" [static] |
Definition at line 163 of file chan_jingle.c.