#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, 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 format_t | jingle_get_codec (struct ast_channel *chan) |
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, format_t format, const struct ast_channel *requestor, 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_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, format_t 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_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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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 format_t | 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_glue | jingle_rtp_glue |
static struct ast_channel_tech | jingle_tech |
PBX interface structure for channel registration. | |
static ast_mutex_t | jinglelock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } |
static struct 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 90 of file chan_jingle.c.
00090 { 00091 AJI_CONNECT_HOST, 00092 AJI_CONNECT_PRFLX, 00093 AJI_CONNECT_RELAY, 00094 AJI_CONNECT_SRFLX, 00095 };
enum jingle_protocol |
Definition at line 85 of file chan_jingle.c.
00085 { 00086 AJI_PROTOCOL_UDP, 00087 AJI_PROTOCOL_SSLTCP, 00088 };
static void __reg_module | ( | void | ) | [static] |
Definition at line 1976 of file chan_jingle.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 1976 of file chan_jingle.c.
static void add_codec_to_answer | ( | const struct jingle_pvt * | p, | |
int | codec, | |||
iks * | dcodecs | |||
) | [static] |
Definition at line 258 of file chan_jingle.c.
References ast_getformatname(), and format.
00259 { 00260 char *format = ast_getformatname(codec); 00261 00262 if (!strcasecmp("ulaw", format)) { 00263 iks *payload_eg711u, *payload_pcmu; 00264 payload_pcmu = iks_new("payload-type"); 00265 iks_insert_attrib(payload_pcmu, "id", "0"); 00266 iks_insert_attrib(payload_pcmu, "name", "PCMU"); 00267 payload_eg711u = iks_new("payload-type"); 00268 iks_insert_attrib(payload_eg711u, "id", "100"); 00269 iks_insert_attrib(payload_eg711u, "name", "EG711U"); 00270 iks_insert_node(dcodecs, payload_pcmu); 00271 iks_insert_node(dcodecs, payload_eg711u); 00272 } 00273 if (!strcasecmp("alaw", format)) { 00274 iks *payload_eg711a; 00275 iks *payload_pcma = iks_new("payload-type"); 00276 iks_insert_attrib(payload_pcma, "id", "8"); 00277 iks_insert_attrib(payload_pcma, "name", "PCMA"); 00278 payload_eg711a = iks_new("payload-type"); 00279 iks_insert_attrib(payload_eg711a, "id", "101"); 00280 iks_insert_attrib(payload_eg711a, "name", "EG711A"); 00281 iks_insert_node(dcodecs, payload_pcma); 00282 iks_insert_node(dcodecs, payload_eg711a); 00283 } 00284 if (!strcasecmp("ilbc", format)) { 00285 iks *payload_ilbc = iks_new("payload-type"); 00286 iks_insert_attrib(payload_ilbc, "id", "97"); 00287 iks_insert_attrib(payload_ilbc, "name", "iLBC"); 00288 iks_insert_node(dcodecs, payload_ilbc); 00289 } 00290 if (!strcasecmp("g723", format)) { 00291 iks *payload_g723 = iks_new("payload-type"); 00292 iks_insert_attrib(payload_g723, "id", "4"); 00293 iks_insert_attrib(payload_g723, "name", "G723"); 00294 iks_insert_node(dcodecs, payload_g723); 00295 } 00296 }
static struct jingle* find_jingle | ( | char * | name, | |
char * | connection | |||
) | [static] |
Definition at line 232 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().
00233 { 00234 struct jingle *jingle = NULL; 00235 00236 jingle = ASTOBJ_CONTAINER_FIND(&jingle_list, name); 00237 if (!jingle && strchr(name, '@')) 00238 jingle = ASTOBJ_CONTAINER_FIND_FULL(&jingle_list, name, user,,, strcasecmp); 00239 00240 if (!jingle) { 00241 /* guest call */ 00242 ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, { 00243 ASTOBJ_RDLOCK(iterator); 00244 if (!strcasecmp(iterator->name, "guest")) { 00245 jingle = iterator; 00246 } 00247 ASTOBJ_UNLOCK(iterator); 00248 00249 if (jingle) 00250 break; 00251 }); 00252 00253 } 00254 return jingle; 00255 }
static int jingle_accept_call | ( | struct jingle * | client, | |
struct jingle_pvt * | p | |||
) | [static] |
Definition at line 298 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().
00299 { 00300 struct jingle_pvt *tmp = client->p; 00301 struct aji_client *c = client->connection; 00302 iks *iq, *jingle, *dcodecs, *payload_red, *payload_audio, *payload_cn; 00303 int x; 00304 format_t pref_codec = 0; 00305 int alreadysent = 0; 00306 00307 if (p->initiator) 00308 return 1; 00309 00310 iq = iks_new("iq"); 00311 jingle = iks_new(JINGLE_NODE); 00312 dcodecs = iks_new("description"); 00313 if (iq && jingle && dcodecs) { 00314 iks_insert_attrib(dcodecs, "xmlns", JINGLE_AUDIO_RTP_NS); 00315 00316 for (x = 0; x < 64; x++) { 00317 if (!(pref_codec = ast_codec_pref_index(&client->prefs, x))) 00318 break; 00319 if (!(client->capability & pref_codec)) 00320 continue; 00321 if (alreadysent & pref_codec) 00322 continue; 00323 add_codec_to_answer(p, pref_codec, dcodecs); 00324 alreadysent |= pref_codec; 00325 } 00326 payload_red = iks_new("payload-type"); 00327 iks_insert_attrib(payload_red, "id", "117"); 00328 iks_insert_attrib(payload_red, "name", "red"); 00329 payload_audio = iks_new("payload-type"); 00330 iks_insert_attrib(payload_audio, "id", "106"); 00331 iks_insert_attrib(payload_audio, "name", "audio/telephone-event"); 00332 payload_cn = iks_new("payload-type"); 00333 iks_insert_attrib(payload_cn, "id", "13"); 00334 iks_insert_attrib(payload_cn, "name", "CN"); 00335 00336 00337 iks_insert_attrib(iq, "type", "set"); 00338 iks_insert_attrib(iq, "to", (p->them) ? p->them : client->user); 00339 iks_insert_attrib(iq, "id", client->connection->mid); 00340 ast_aji_increment_mid(client->connection->mid); 00341 00342 iks_insert_attrib(jingle, "xmlns", JINGLE_NS); 00343 iks_insert_attrib(jingle, "action", JINGLE_ACCEPT); 00344 iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them); 00345 iks_insert_attrib(jingle, JINGLE_SID, tmp->sid); 00346 iks_insert_node(iq, jingle); 00347 iks_insert_node(jingle, dcodecs); 00348 iks_insert_node(dcodecs, payload_red); 00349 iks_insert_node(dcodecs, payload_audio); 00350 iks_insert_node(dcodecs, payload_cn); 00351 00352 ast_aji_send(c, iq); 00353 00354 iks_delete(payload_red); 00355 iks_delete(payload_audio); 00356 iks_delete(payload_cn); 00357 iks_delete(dcodecs); 00358 iks_delete(jingle); 00359 iks_delete(iq); 00360 } 00361 return 1; 00362 }
static int jingle_action | ( | struct jingle * | client, | |
struct jingle_pvt * | p, | |||
const char * | action | |||
) | [static] |
Definition at line 891 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().
00892 { 00893 iks *iq, *jingle = NULL; 00894 int res = -1; 00895 00896 iq = iks_new("iq"); 00897 jingle = iks_new("jingle"); 00898 00899 if (iq) { 00900 iks_insert_attrib(iq, "type", "set"); 00901 iks_insert_attrib(iq, "from", client->connection->jid->full); 00902 iks_insert_attrib(iq, "to", p->them); 00903 iks_insert_attrib(iq, "id", client->connection->mid); 00904 ast_aji_increment_mid(client->connection->mid); 00905 if (jingle) { 00906 iks_insert_attrib(jingle, "action", action); 00907 iks_insert_attrib(jingle, JINGLE_SID, p->sid); 00908 iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them); 00909 iks_insert_attrib(jingle, "xmlns", JINGLE_NS); 00910 00911 iks_insert_node(iq, jingle); 00912 00913 ast_aji_send(client->connection, iq); 00914 res = 0; 00915 } 00916 } 00917 00918 iks_delete(jingle); 00919 iks_delete(iq); 00920 00921 return res; 00922 }
static int jingle_add_candidate | ( | struct jingle * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 1099 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().
01100 { 01101 struct jingle_pvt *p = NULL, *tmp = NULL; 01102 struct aji_client *c = client->connection; 01103 struct jingle_candidate *newcandidate = NULL; 01104 iks *traversenodes = NULL, *receipt = NULL; 01105 01106 for (tmp = client->p; tmp; tmp = tmp->next) { 01107 if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) { 01108 p = tmp; 01109 break; 01110 } 01111 } 01112 01113 if (!p) 01114 return -1; 01115 01116 traversenodes = pak->query; 01117 while(traversenodes) { 01118 if(!strcasecmp(iks_name(traversenodes), "jingle")) { 01119 traversenodes = iks_child(traversenodes); 01120 continue; 01121 } 01122 if(!strcasecmp(iks_name(traversenodes), "content")) { 01123 traversenodes = iks_child(traversenodes); 01124 continue; 01125 } 01126 if(!strcasecmp(iks_name(traversenodes), "transport")) { 01127 traversenodes = iks_child(traversenodes); 01128 continue; 01129 } 01130 01131 if(!strcasecmp(iks_name(traversenodes), "candidate")) { 01132 newcandidate = ast_calloc(1, sizeof(*newcandidate)); 01133 if (!newcandidate) 01134 return 0; 01135 ast_copy_string(newcandidate->ip, iks_find_attrib(traversenodes, "ip"), sizeof(newcandidate->ip)); 01136 newcandidate->port = atoi(iks_find_attrib(traversenodes, "port")); 01137 ast_copy_string(newcandidate->password, iks_find_attrib(traversenodes, "pwd"), sizeof(newcandidate->password)); 01138 if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "udp")) 01139 newcandidate->protocol = AJI_PROTOCOL_UDP; 01140 else if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "ssltcp")) 01141 newcandidate->protocol = AJI_PROTOCOL_SSLTCP; 01142 01143 if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "host")) 01144 newcandidate->type = AJI_CONNECT_HOST; 01145 else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "prflx")) 01146 newcandidate->type = AJI_CONNECT_PRFLX; 01147 else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "relay")) 01148 newcandidate->type = AJI_CONNECT_RELAY; 01149 else if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "srflx")) 01150 newcandidate->type = AJI_CONNECT_SRFLX; 01151 01152 newcandidate->network = atoi(iks_find_attrib(traversenodes, "network")); 01153 newcandidate->generation = atoi(iks_find_attrib(traversenodes, "generation")); 01154 newcandidate->next = NULL; 01155 01156 newcandidate->next = p->theircandidates; 01157 p->theircandidates = newcandidate; 01158 p->laststun = 0; 01159 jingle_update_stun(p->parent, p); 01160 newcandidate = NULL; 01161 } 01162 traversenodes = iks_next(traversenodes); 01163 } 01164 01165 receipt = iks_new("iq"); 01166 iks_insert_attrib(receipt, "type", "result"); 01167 iks_insert_attrib(receipt, "from", c->jid->full); 01168 iks_insert_attrib(receipt, "to", iks_find_attrib(pak->x, "from")); 01169 iks_insert_attrib(receipt, "id", iks_find_attrib(pak->x, "id")); 01170 ast_aji_send(c, receipt); 01171 01172 iks_delete(receipt); 01173 01174 return 1; 01175 }
static struct jingle_pvt * jingle_alloc | ( | struct jingle * | client, | |
const char * | from, | |||
const char * | sid | |||
) | [static] |
Definition at line 742 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_instance_new(), ast_sockaddr_from_sin, ASTOBJ_CONTAINER_FIND, bindaddr, aji_client::buddies, jingle::buddy, aji_resource::cap, jingle::connection, 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().
00743 { 00744 struct jingle_pvt *tmp = NULL; 00745 struct aji_resource *resources = NULL; 00746 struct aji_buddy *buddy; 00747 char idroster[200]; 00748 struct ast_sockaddr bindaddr_tmp; 00749 00750 ast_debug(1, "The client is %s for alloc\n", client->name); 00751 if (!sid && !strchr(from, '/')) { /* I started call! */ 00752 if (!strcasecmp(client->name, "guest")) { 00753 buddy = ASTOBJ_CONTAINER_FIND(&client->connection->buddies, from); 00754 if (buddy) 00755 resources = buddy->resources; 00756 } else if (client->buddy) 00757 resources = client->buddy->resources; 00758 while (resources) { 00759 if (resources->cap->jingle) { 00760 break; 00761 } 00762 resources = resources->next; 00763 } 00764 if (resources) 00765 snprintf(idroster, sizeof(idroster), "%s/%s", from, resources->resource); 00766 else { 00767 ast_log(LOG_ERROR, "no jingle capable clients to talk to.\n"); 00768 return NULL; 00769 } 00770 } 00771 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { 00772 return NULL; 00773 } 00774 00775 memcpy(&tmp->prefs, &client->prefs, sizeof(tmp->prefs)); 00776 00777 if (sid) { 00778 ast_copy_string(tmp->sid, sid, sizeof(tmp->sid)); 00779 ast_copy_string(tmp->them, from, sizeof(tmp->them)); 00780 } else { 00781 snprintf(tmp->sid, sizeof(tmp->sid), "%08lx%08lx", ast_random(), ast_random()); 00782 ast_copy_string(tmp->them, idroster, sizeof(tmp->them)); 00783 tmp->initiator = 1; 00784 } 00785 ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr); 00786 tmp->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL); 00787 tmp->parent = client; 00788 if (!tmp->rtp) { 00789 ast_log(LOG_WARNING, "Out of RTP sessions?\n"); 00790 ast_free(tmp); 00791 return NULL; 00792 } 00793 ast_copy_string(tmp->exten, "s", sizeof(tmp->exten)); 00794 ast_mutex_init(&tmp->lock); 00795 ast_mutex_lock(&jinglelock); 00796 tmp->next = client->p; 00797 client->p = tmp; 00798 ast_mutex_unlock(&jinglelock); 00799 return tmp; 00800 }
static int jingle_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 376 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.
00377 { 00378 struct jingle_pvt *p = ast->tech_pvt; 00379 struct jingle *client = p->parent; 00380 int res = 0; 00381 00382 ast_debug(1, "Answer!\n"); 00383 ast_mutex_lock(&p->lock); 00384 jingle_accept_call(client, p); 00385 ast_mutex_unlock(&p->lock); 00386 return res; 00387 }
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 1457 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.
01458 { 01459 struct jingle_pvt *p = ast->tech_pvt; 01460 01461 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 01462 ast_log(LOG_WARNING, "jingle_call called on %s, neither down nor reserved\n", ast->name); 01463 return -1; 01464 } 01465 01466 ast_setstate(ast, AST_STATE_RING); 01467 p->jointcapability = p->capability; 01468 if (!p->ringrule) { 01469 ast_copy_string(p->ring, p->parent->connection->mid, sizeof(p->ring)); 01470 p->ringrule = iks_filter_add_rule(p->parent->connection->f, jingle_ringing_ack, p, 01471 IKS_RULE_ID, p->ring, IKS_RULE_DONE); 01472 } else 01473 ast_log(LOG_WARNING, "Whoa, already have a ring rule!\n"); 01474 01475 jingle_transmit_invite(p); 01476 jingle_create_candidates(p->parent, p, p->sid, p->them); 01477 01478 return 0; 01479 }
static int jingle_create_candidates | ( | struct jingle * | client, | |
struct jingle_pvt * | p, | |||
char * | sid, | |||
char * | from | |||
) | [static] |
Definition at line 578 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_instance_get_local_address(), ast_sockaddr_from_sin, ast_sockaddr_ipv4(), ast_sockaddr_to_sin, 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().
00579 { 00580 struct jingle_candidate *tmp; 00581 struct aji_client *c = client->connection; 00582 struct jingle_candidate *ours1 = NULL, *ours2 = NULL; 00583 struct sockaddr_in sin = { 0, }; 00584 struct ast_sockaddr sin_tmp; 00585 struct ast_sockaddr us_tmp; 00586 struct ast_sockaddr bindaddr_tmp; 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_instance_get_local_address(p->rtp, &sin_tmp); 00624 ast_sockaddr_to_sin(&sin_tmp, &sin); 00625 ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr); 00626 ast_find_ourip(&us_tmp, &bindaddr_tmp, AF_INET); 00627 us.s_addr = htonl(ast_sockaddr_ipv4(&us_tmp)); 00628 00629 /* Setup our first jingle candidate */ 00630 ours1->component = 1; 00631 ours1->foundation = (unsigned int)bindaddr.sin_addr.s_addr | AJI_CONNECT_HOST | AJI_PROTOCOL_UDP; 00632 ours1->generation = 0; 00633 ast_copy_string(ours1->ip, ast_inet_ntoa(us), sizeof(ours1->ip)); 00634 ours1->network = 0; 00635 ours1->port = ntohs(sin.sin_port); 00636 ours1->priority = 1678246398; 00637 ours1->protocol = AJI_PROTOCOL_UDP; 00638 snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random()); 00639 ast_copy_string(ours1->password, pass, sizeof(ours1->password)); 00640 ours1->type = AJI_CONNECT_HOST; 00641 snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random()); 00642 ast_copy_string(ours1->ufrag, user, sizeof(ours1->ufrag)); 00643 p->ourcandidates = ours1; 00644 00645 if (!ast_strlen_zero(externip)) { 00646 /* XXX We should really stun for this one not just go with externip XXX */ 00647 if (inet_aton(externip, &externaddr)) 00648 ast_log(LOG_WARNING, "Invalid extern IP : %s\n", externip); 00649 00650 ours2->component = 1; 00651 ours2->foundation = (unsigned int)externaddr.s_addr | AJI_CONNECT_PRFLX | AJI_PROTOCOL_UDP; 00652 ours2->generation = 0; 00653 ast_copy_string(ours2->ip, externip, sizeof(ours2->ip)); 00654 ours2->network = 0; 00655 ours2->port = ntohs(sin.sin_port); 00656 ours2->priority = 1678246397; 00657 ours2->protocol = AJI_PROTOCOL_UDP; 00658 snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random()); 00659 ast_copy_string(ours2->password, pass, sizeof(ours2->password)); 00660 ours2->type = AJI_CONNECT_PRFLX; 00661 00662 snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random()); 00663 ast_copy_string(ours2->ufrag, user, sizeof(ours2->ufrag)); 00664 ours1->next = ours2; 00665 ours2 = NULL; 00666 } 00667 ours1 = NULL; 00668 dest.sin_addr = __ourip; 00669 dest.sin_port = sin.sin_port; 00670 00671 00672 for (tmp = p->ourcandidates; tmp; tmp = tmp->next) { 00673 snprintf(component, sizeof(component), "%u", tmp->component); 00674 snprintf(foundation, sizeof(foundation), "%u", tmp->foundation); 00675 snprintf(generation, sizeof(generation), "%u", tmp->generation); 00676 snprintf(network, sizeof(network), "%u", tmp->network); 00677 snprintf(port, sizeof(port), "%u", tmp->port); 00678 snprintf(priority, sizeof(priority), "%u", tmp->priority); 00679 00680 iks_insert_attrib(iq, "from", c->jid->full); 00681 iks_insert_attrib(iq, "to", from); 00682 iks_insert_attrib(iq, "type", "set"); 00683 iks_insert_attrib(iq, "id", c->mid); 00684 ast_aji_increment_mid(c->mid); 00685 iks_insert_attrib(jingle, "action", JINGLE_NEGOTIATE); 00686 iks_insert_attrib(jingle, JINGLE_SID, sid); 00687 iks_insert_attrib(jingle, "initiator", (p->initiator) ? c->jid->full : from); 00688 iks_insert_attrib(jingle, "xmlns", JINGLE_NS); 00689 iks_insert_attrib(content, "creator", p->initiator ? "initiator" : "responder"); 00690 iks_insert_attrib(content, "name", "asterisk-audio-content"); 00691 iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS); 00692 iks_insert_attrib(candidate, "component", component); 00693 iks_insert_attrib(candidate, "foundation", foundation); 00694 iks_insert_attrib(candidate, "generation", generation); 00695 iks_insert_attrib(candidate, "ip", tmp->ip); 00696 iks_insert_attrib(candidate, "network", network); 00697 iks_insert_attrib(candidate, "port", port); 00698 iks_insert_attrib(candidate, "priority", priority); 00699 switch (tmp->protocol) { 00700 case AJI_PROTOCOL_UDP: 00701 iks_insert_attrib(candidate, "protocol", "udp"); 00702 break; 00703 case AJI_PROTOCOL_SSLTCP: 00704 iks_insert_attrib(candidate, "protocol", "ssltcp"); 00705 break; 00706 } 00707 iks_insert_attrib(candidate, "pwd", tmp->password); 00708 switch (tmp->type) { 00709 case AJI_CONNECT_HOST: 00710 iks_insert_attrib(candidate, "type", "host"); 00711 break; 00712 case AJI_CONNECT_PRFLX: 00713 iks_insert_attrib(candidate, "type", "prflx"); 00714 break; 00715 case AJI_CONNECT_RELAY: 00716 iks_insert_attrib(candidate, "type", "relay"); 00717 break; 00718 case AJI_CONNECT_SRFLX: 00719 iks_insert_attrib(candidate, "type", "srflx"); 00720 break; 00721 } 00722 iks_insert_attrib(candidate, "ufrag", tmp->ufrag); 00723 00724 ast_aji_send(c, iq); 00725 } 00726 p->laststun = 0; 00727 00728 safeout: 00729 if (ours1) 00730 ast_free(ours1); 00731 if (ours2) 00732 ast_free(ours2); 00733 iks_delete(iq); 00734 iks_delete(jingle); 00735 iks_delete(content); 00736 iks_delete(transport); 00737 iks_delete(candidate); 00738 00739 return 1; 00740 }
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 1699 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.
01702 { 01703 struct aji_client *client; 01704 01705 if (!member) 01706 ast_log(LOG_WARNING, "Out of memory.\n"); 01707 01708 ast_copy_string(member->name, label, sizeof(member->name)); 01709 ast_copy_string(member->user, label, sizeof(member->user)); 01710 ast_copy_string(member->context, context, sizeof(member->context)); 01711 member->allowguest = allowguest; 01712 member->prefs = prefs; 01713 while (var) { 01714 #if 0 01715 struct jingle_candidate *candidate = NULL; 01716 #endif 01717 if (!strcasecmp(var->name, "username")) 01718 ast_copy_string(member->user, var->value, sizeof(member->user)); 01719 else if (!strcasecmp(var->name, "disallow")) 01720 ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 0); 01721 else if (!strcasecmp(var->name, "allow")) 01722 ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 1); 01723 else if (!strcasecmp(var->name, "context")) 01724 ast_copy_string(member->context, var->value, sizeof(member->context)); 01725 #if 0 01726 else if (!strcasecmp(var->name, "candidate")) { 01727 candidate = jingle_create_candidate(var->value); 01728 if (candidate) { 01729 candidate->next = member->ourcandidates; 01730 member->ourcandidates = candidate; 01731 } 01732 } 01733 #endif 01734 else if (!strcasecmp(var->name, "connection")) { 01735 if ((client = ast_aji_get_client(var->value))) { 01736 member->connection = client; 01737 iks_filter_add_rule(client->f, jingle_parser, member, 01738 IKS_RULE_TYPE, IKS_PAK_IQ, 01739 IKS_RULE_FROM_PARTIAL, member->user, 01740 IKS_RULE_NS, JINGLE_NS, 01741 IKS_RULE_DONE); 01742 } else { 01743 ast_log(LOG_ERROR, "connection referenced not found!\n"); 01744 return 0; 01745 } 01746 } 01747 var = var->next; 01748 } 01749 if (member->connection && member->user) 01750 member->buddy = ASTOBJ_CONTAINER_FIND(&member->connection->buddies, member->user); 01751 else { 01752 ast_log(LOG_ERROR, "No Connection or Username!\n"); 01753 } 01754 return 1; 01755 }
static int jingle_digit | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 1317 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().
01318 { 01319 struct jingle_pvt *p = ast->tech_pvt; 01320 struct jingle *client = p->parent; 01321 iks *iq, *jingle, *dtmf; 01322 char buffer[2] = {digit, '\0'}; 01323 iq = iks_new("iq"); 01324 jingle = iks_new("jingle"); 01325 dtmf = iks_new("dtmf"); 01326 if(!iq || !jingle || !dtmf) { 01327 iks_delete(iq); 01328 iks_delete(jingle); 01329 iks_delete(dtmf); 01330 ast_log(LOG_ERROR, "Did not send dtmf do to memory issue\n"); 01331 return -1; 01332 } 01333 01334 iks_insert_attrib(iq, "type", "set"); 01335 iks_insert_attrib(iq, "to", p->them); 01336 iks_insert_attrib(iq, "from", client->connection->jid->full); 01337 iks_insert_attrib(iq, "id", client->connection->mid); 01338 ast_aji_increment_mid(client->connection->mid); 01339 iks_insert_attrib(jingle, "xmlns", JINGLE_NS); 01340 iks_insert_attrib(jingle, "action", "session-info"); 01341 iks_insert_attrib(jingle, "initiator", p->initiator ? client->connection->jid->full : p->them); 01342 iks_insert_attrib(jingle, "sid", p->sid); 01343 iks_insert_attrib(dtmf, "xmlns", JINGLE_DTMF_NS); 01344 iks_insert_attrib(dtmf, "code", buffer); 01345 iks_insert_node(iq, jingle); 01346 iks_insert_node(jingle, dtmf); 01347 01348 ast_mutex_lock(&p->lock); 01349 if (ast->dtmff.frametype == AST_FRAME_DTMF_BEGIN || duration == 0) { 01350 iks_insert_attrib(dtmf, "action", "button-down"); 01351 } else if (ast->dtmff.frametype == AST_FRAME_DTMF_END || duration != 0) { 01352 iks_insert_attrib(dtmf, "action", "button-up"); 01353 } 01354 ast_aji_send(client->connection, iq); 01355 01356 iks_delete(iq); 01357 iks_delete(jingle); 01358 iks_delete(dtmf); 01359 ast_mutex_unlock(&p->lock); 01360 return 0; 01361 }
static int jingle_digit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 1363 of file chan_jingle.c.
References jingle_digit().
01364 { 01365 return jingle_digit(chan, digit, 0); 01366 }
static int jingle_digit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 1368 of file chan_jingle.c.
References jingle_digit().
01369 { 01370 return jingle_digit(ast, digit, duration); 01371 }
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 1610 of file chan_jingle.c.
References CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.
01611 { 01612 switch (cmd) { 01613 case CLI_INIT: 01614 e->command = "jingle reload"; 01615 e->usage = 01616 "Usage: jingle reload\n" 01617 " Reload jingle channel driver.\n"; 01618 return NULL; 01619 case CLI_GENERATE: 01620 return NULL; 01621 } 01622 01623 return CLI_SUCCESS; 01624 }
static int jingle_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 1263 of file chan_jingle.c.
References ast_mutex_lock, ast_mutex_unlock, jingle_pvt::lock, jingle_pvt::owner, and ast_channel::tech_pvt.
01264 { 01265 struct jingle_pvt *p = newchan->tech_pvt; 01266 ast_mutex_lock(&p->lock); 01267 01268 if ((p->owner != oldchan)) { 01269 ast_mutex_unlock(&p->lock); 01270 return -1; 01271 } 01272 if (p->owner == oldchan) 01273 p->owner = newchan; 01274 ast_mutex_unlock(&p->lock); 01275 return 0; 01276 }
static void jingle_free_candidates | ( | struct jingle_candidate * | candidate | ) | [static] |
Definition at line 924 of file chan_jingle.c.
References ast_free, last, and jingle_candidate::next.
Referenced by jingle_free_pvt().
00925 { 00926 struct jingle_candidate *last; 00927 while (candidate) { 00928 last = candidate; 00929 candidate = candidate->next; 00930 ast_free(last); 00931 } 00932 }
static void jingle_free_pvt | ( | struct jingle * | client, | |
struct jingle_pvt * | p | |||
) | [static] |
Definition at line 934 of file chan_jingle.c.
References ast_free, ast_log(), ast_rtp_instance_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().
00935 { 00936 struct jingle_pvt *cur, *prev = NULL; 00937 cur = client->p; 00938 while (cur) { 00939 if (cur == p) { 00940 if (prev) 00941 prev->next = p->next; 00942 else 00943 client->p = p->next; 00944 break; 00945 } 00946 prev = cur; 00947 cur = cur->next; 00948 } 00949 if (p->ringrule) 00950 iks_filter_remove_rule(p->parent->connection->f, p->ringrule); 00951 if (p->owner) 00952 ast_log(LOG_WARNING, "Uh oh, there's an owner, this is going to be messy.\n"); 00953 if (p->rtp) 00954 ast_rtp_instance_destroy(p->rtp); 00955 if (p->vrtp) 00956 ast_rtp_instance_destroy(p->vrtp); 00957 jingle_free_candidates(p->theircandidates); 00958 ast_free(p); 00959 }
static format_t jingle_get_codec | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 408 of file chan_jingle.c.
References jingle_pvt::peercapability, and ast_channel::tech_pvt.
00409 { 00410 struct jingle_pvt *p = chan->tech_pvt; 00411 return p->peercapability; 00412 }
static enum ast_rtp_glue_result jingle_get_rtp_peer | ( | struct ast_channel * | chan, | |
struct ast_rtp_instance ** | instance | |||
) | [static] |
Definition at line 389 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.
00390 { 00391 struct jingle_pvt *p = chan->tech_pvt; 00392 enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_FORBID; 00393 00394 if (!p) 00395 return res; 00396 00397 ast_mutex_lock(&p->lock); 00398 if (p->rtp) { 00399 ao2_ref(p->rtp, +1); 00400 *instance = p->rtp; 00401 res = AST_RTP_GLUE_RESULT_LOCAL; 00402 } 00403 ast_mutex_unlock(&p->lock); 00404 00405 return res; 00406 }
static int jingle_handle_dtmf | ( | struct jingle * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 493 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().
00494 { 00495 struct jingle_pvt *tmp; 00496 iks *dtmfnode = NULL, *dtmfchild = NULL; 00497 char *dtmf; 00498 /* Make sure our new call doesn't exist yet */ 00499 for (tmp = client->p; tmp; tmp = tmp->next) { 00500 if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) 00501 break; 00502 } 00503 00504 if (tmp) { 00505 if(iks_find_with_attrib(pak->x, "dtmf-method", "method", "rtp")) { 00506 jingle_response(client,pak, 00507 "feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'", 00508 "unsupported-dtmf-method xmlns='http://www.xmpp.org/extensions/xep-0181.html#ns-errors'"); 00509 return -1; 00510 } 00511 if ((dtmfnode = iks_find(pak->x, "dtmf"))) { 00512 if((dtmf = iks_find_attrib(dtmfnode, "code"))) { 00513 if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-up")) { 00514 struct ast_frame f = {AST_FRAME_DTMF_BEGIN, }; 00515 f.subclass.integer = dtmf[0]; 00516 ast_queue_frame(tmp->owner, &f); 00517 ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer); 00518 } else if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-down")) { 00519 struct ast_frame f = {AST_FRAME_DTMF_END, }; 00520 f.subclass.integer = dtmf[0]; 00521 ast_queue_frame(tmp->owner, &f); 00522 ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer); 00523 } else if(iks_find_attrib(pak->x, "dtmf")) { /* 250 millasecond default */ 00524 struct ast_frame f = {AST_FRAME_DTMF, }; 00525 f.subclass.integer = dtmf[0]; 00526 ast_queue_frame(tmp->owner, &f); 00527 ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer); 00528 } 00529 } 00530 } else if ((dtmfnode = iks_find_with_attrib(pak->x, JINGLE_NODE, "action", "session-info"))) { 00531 if((dtmfchild = iks_find(dtmfnode, "dtmf"))) { 00532 if((dtmf = iks_find_attrib(dtmfchild, "code"))) { 00533 if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-up")) { 00534 struct ast_frame f = {AST_FRAME_DTMF_END, }; 00535 f.subclass.integer = dtmf[0]; 00536 ast_queue_frame(tmp->owner, &f); 00537 ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer); 00538 } else if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-down")) { 00539 struct ast_frame f = {AST_FRAME_DTMF_BEGIN, }; 00540 f.subclass.integer = dtmf[0]; 00541 ast_queue_frame(tmp->owner, &f); 00542 ast_verbose("JINGLE! DTMF-relay event received: %c\n", f.subclass.integer); 00543 } 00544 } 00545 } 00546 } 00547 jingle_response(client, pak, NULL, NULL); 00548 return 1; 00549 } else 00550 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n"); 00551 00552 jingle_response(client, pak, NULL, NULL); 00553 return 1; 00554 }
static int jingle_hangup | ( | struct ast_channel * | ast | ) | [static] |
Hangup a call through the jingle proxy channel.
Definition at line 1482 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.
01483 { 01484 struct jingle_pvt *p = ast->tech_pvt; 01485 struct jingle *client; 01486 01487 ast_mutex_lock(&p->lock); 01488 client = p->parent; 01489 p->owner = NULL; 01490 ast->tech_pvt = NULL; 01491 if (!p->alreadygone) 01492 jingle_action(client, p, JINGLE_TERMINATE); 01493 ast_mutex_unlock(&p->lock); 01494 01495 jingle_free_pvt(client, p); 01496 01497 return 0; 01498 }
static int jingle_hangup_farend | ( | struct jingle * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 557 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().
00558 { 00559 struct jingle_pvt *tmp; 00560 00561 ast_debug(1, "The client is %s\n", client->name); 00562 /* Make sure our new call doesn't exist yet */ 00563 for (tmp = client->p; tmp; tmp = tmp->next) { 00564 if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) 00565 break; 00566 } 00567 00568 if (tmp) { 00569 tmp->alreadygone = 1; 00570 if (tmp->owner) 00571 ast_queue_hangup(tmp->owner); 00572 } else 00573 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n"); 00574 jingle_response(client, pak, NULL, NULL); 00575 return 1; 00576 }
static int jingle_indicate | ( | struct ast_channel * | ast, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 1278 of file chan_jingle.c.
References AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), and LOG_NOTICE.
01279 { 01280 int res = 0; 01281 01282 switch (condition) { 01283 case AST_CONTROL_HOLD: 01284 ast_moh_start(ast, data, NULL); 01285 break; 01286 case AST_CONTROL_UNHOLD: 01287 ast_moh_stop(ast); 01288 break; 01289 default: 01290 ast_log(LOG_NOTICE, "Don't know how to indicate condition '%d'\n", condition); 01291 res = -1; 01292 } 01293 01294 return res; 01295 }
static int jingle_is_answered | ( | struct jingle * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 473 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().
00474 { 00475 struct jingle_pvt *tmp; 00476 00477 ast_debug(1, "The client is %s\n", client->name); 00478 /* Make sure our new call doesn't exist yet */ 00479 for (tmp = client->p; tmp; tmp = tmp->next) { 00480 if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) 00481 break; 00482 } 00483 00484 if (tmp) { 00485 if (tmp->owner) 00486 ast_queue_control(tmp->owner, AST_CONTROL_ANSWER); 00487 } else 00488 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n"); 00489 jingle_response(client, pak, NULL, NULL); 00490 return 1; 00491 }
static int jingle_load_config | ( | void | ) | [static] |
Definition at line 1757 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, config_flags, CONFIG_STATUS_FILEINVALID, context, default_jbconf, externip, global_capability, global_jbconf, hp, JINGLE_CONFIG, LOG_WARNING, prefs, and var.
Referenced by load_module().
01758 { 01759 char *cat = NULL; 01760 struct ast_config *cfg = NULL; 01761 char context[100]; 01762 int allowguest = 1; 01763 struct ast_variable *var; 01764 struct jingle *member; 01765 struct hostent *hp; 01766 struct ast_hostent ahp; 01767 struct ast_codec_pref prefs; 01768 struct aji_client_container *clients; 01769 struct jingle_candidate *global_candidates = NULL; 01770 struct ast_flags config_flags = { 0 }; 01771 01772 cfg = ast_config_load(JINGLE_CONFIG, config_flags); 01773 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) { 01774 return 0; 01775 } 01776 01777 /* Copy the default jb config over global_jbconf */ 01778 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 01779 01780 cat = ast_category_browse(cfg, NULL); 01781 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) { 01782 /* handle jb conf */ 01783 if (!ast_jb_read_conf(&global_jbconf, var->name, var->value)) 01784 continue; 01785 01786 if (!strcasecmp(var->name, "allowguest")) 01787 allowguest = 01788 (ast_true(ast_variable_retrieve(cfg, "general", "allowguest"))) ? 1 : 0; 01789 else if (!strcasecmp(var->name, "disallow")) 01790 ast_parse_allow_disallow(&prefs, &global_capability, var->value, 0); 01791 else if (!strcasecmp(var->name, "allow")) 01792 ast_parse_allow_disallow(&prefs, &global_capability, var->value, 1); 01793 else if (!strcasecmp(var->name, "context")) 01794 ast_copy_string(context, var->value, sizeof(context)); 01795 else if (!strcasecmp(var->name, "externip")) 01796 ast_copy_string(externip, var->value, sizeof(externip)); 01797 else if (!strcasecmp(var->name, "bindaddr")) { 01798 if (!(hp = ast_gethostbyname(var->value, &ahp))) { 01799 ast_log(LOG_WARNING, "Invalid address: %s\n", var->value); 01800 } else { 01801 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr)); 01802 } 01803 } 01804 /* Idea to allow for custom candidates */ 01805 /* 01806 else if (!strcasecmp(var->name, "candidate")) { 01807 candidate = jingle_create_candidate(var->value); 01808 if (candidate) { 01809 candidate->next = global_candidates; 01810 global_candidates = candidate; 01811 } 01812 } 01813 */ 01814 } 01815 while (cat) { 01816 if (strcasecmp(cat, "general")) { 01817 var = ast_variable_browse(cfg, cat); 01818 member = ast_calloc(1, sizeof(*member)); 01819 ASTOBJ_INIT(member); 01820 ASTOBJ_WRLOCK(member); 01821 if (!strcasecmp(cat, "guest")) { 01822 ast_copy_string(member->name, "guest", sizeof(member->name)); 01823 ast_copy_string(member->user, "guest", sizeof(member->user)); 01824 ast_copy_string(member->context, context, sizeof(member->context)); 01825 member->allowguest = allowguest; 01826 member->prefs = prefs; 01827 while (var) { 01828 if (!strcasecmp(var->name, "disallow")) 01829 ast_parse_allow_disallow(&member->prefs, &member->capability, 01830 var->value, 0); 01831 else if (!strcasecmp(var->name, "allow")) 01832 ast_parse_allow_disallow(&member->prefs, &member->capability, 01833 var->value, 1); 01834 else if (!strcasecmp(var->name, "context")) 01835 ast_copy_string(member->context, var->value, 01836 sizeof(member->context)); 01837 else if (!strcasecmp(var->name, "parkinglot")) 01838 ast_copy_string(member->parkinglot, var->value, 01839 sizeof(member->parkinglot)); 01840 /* Idea to allow for custom candidates */ 01841 /* 01842 else if (!strcasecmp(var->name, "candidate")) { 01843 candidate = jingle_create_candidate(var->value); 01844 if (candidate) { 01845 candidate->next = member->ourcandidates; 01846 member->ourcandidates = candidate; 01847 } 01848 } 01849 */ 01850 var = var->next; 01851 } 01852 ASTOBJ_UNLOCK(member); 01853 clients = ast_aji_get_clients(); 01854 if (clients) { 01855 ASTOBJ_CONTAINER_TRAVERSE(clients, 1, { 01856 ASTOBJ_WRLOCK(iterator); 01857 ASTOBJ_WRLOCK(member); 01858 member->connection = NULL; 01859 iks_filter_add_rule(iterator->f, jingle_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, JINGLE_NS, IKS_RULE_DONE); 01860 iks_filter_add_rule(iterator->f, jingle_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, JINGLE_DTMF_NS, IKS_RULE_DONE); 01861 ASTOBJ_UNLOCK(member); 01862 ASTOBJ_UNLOCK(iterator); 01863 }); 01864 ASTOBJ_CONTAINER_LINK(&jingle_list, member); 01865 } else { 01866 ASTOBJ_UNLOCK(member); 01867 ASTOBJ_UNREF(member, jingle_member_destroy); 01868 } 01869 } else { 01870 ASTOBJ_UNLOCK(member); 01871 if (jingle_create_member(cat, var, allowguest, prefs, context, member)) 01872 ASTOBJ_CONTAINER_LINK(&jingle_list, member); 01873 ASTOBJ_UNREF(member, jingle_member_destroy); 01874 } 01875 } 01876 cat = ast_category_browse(cfg, cat); 01877 } 01878 jingle_free_candidates(global_candidates); 01879 return 1; 01880 }
static void jingle_member_destroy | ( | struct jingle * | obj | ) | [static] |
Definition at line 227 of file chan_jingle.c.
References ast_free.
Referenced by jingle_parser(), and unload_module().
00228 { 00229 ast_free(obj); 00230 }
static struct ast_channel* jingle_new | ( | struct jingle * | client, | |
struct jingle_pvt * | i, | |||
int | state, | |||
const char * | title, | |||
const char * | linkedid | |||
) | [static] |
Start new jingle channel.
Definition at line 803 of file chan_jingle.c.
References accountcode, 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_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_rtp_codecs_packetization_set(), ast_rtp_instance_fd(), ast_rtp_instance_get_codecs(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_channel::caller, jingle::callgroup, ast_channel::callgroup, jingle::callingpres, jingle_pvt::capability, jingle_pvt::cid_name, jingle_pvt::cid_num, jingle::context, ast_channel::context, ast_channel::dialed, jingle_pvt::exten, ast_channel::exten, global_capability, global_jbconf, ast_channel::hangupcause, ast_party_caller::id, jingle_tech, jingle_pvt::jointcapability, language, jingle::language, LOG_WARNING, musicclass, jingle::musicclass, ast_channel::name, 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().
00804 { 00805 struct ast_channel *tmp; 00806 int fmt; 00807 int what; 00808 const char *str; 00809 00810 if (title) 00811 str = title; 00812 else 00813 str = i->them; 00814 tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", "", "", linkedid, 0, "Jingle/%s-%04lx", str, ast_random() & 0xffff); 00815 if (!tmp) { 00816 ast_log(LOG_WARNING, "Unable to allocate Jingle channel structure!\n"); 00817 return NULL; 00818 } 00819 tmp->tech = &jingle_tech; 00820 00821 /* Select our native format based on codec preference until we receive 00822 something from another device to the contrary. */ 00823 if (i->jointcapability) 00824 what = i->jointcapability; 00825 else if (i->capability) 00826 what = i->capability; 00827 else 00828 what = global_capability; 00829 00830 /* Set Frame packetization */ 00831 if (i->rtp) 00832 ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(i->rtp), i->rtp, &i->prefs); 00833 00834 tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | (i->jointcapability & AST_FORMAT_VIDEO_MASK); 00835 fmt = ast_best_codec(tmp->nativeformats); 00836 00837 if (i->rtp) { 00838 ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(i->rtp, 0)); 00839 ast_channel_set_fd(tmp, 1, ast_rtp_instance_fd(i->rtp, 1)); 00840 } 00841 if (i->vrtp) { 00842 ast_channel_set_fd(tmp, 2, ast_rtp_instance_fd(i->vrtp, 0)); 00843 ast_channel_set_fd(tmp, 3, ast_rtp_instance_fd(i->vrtp, 1)); 00844 } 00845 if (state == AST_STATE_RING) 00846 tmp->rings = 1; 00847 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 00848 tmp->writeformat = fmt; 00849 tmp->rawwriteformat = fmt; 00850 tmp->readformat = fmt; 00851 tmp->rawreadformat = fmt; 00852 tmp->tech_pvt = i; 00853 00854 tmp->callgroup = client->callgroup; 00855 tmp->pickupgroup = client->pickupgroup; 00856 tmp->caller.id.name.presentation = client->callingpres; 00857 tmp->caller.id.number.presentation = client->callingpres; 00858 if (!ast_strlen_zero(client->accountcode)) 00859 ast_string_field_set(tmp, accountcode, client->accountcode); 00860 if (client->amaflags) 00861 tmp->amaflags = client->amaflags; 00862 if (!ast_strlen_zero(client->language)) 00863 ast_string_field_set(tmp, language, client->language); 00864 if (!ast_strlen_zero(client->musicclass)) 00865 ast_string_field_set(tmp, musicclass, client->musicclass); 00866 i->owner = tmp; 00867 ast_copy_string(tmp->context, client->context, sizeof(tmp->context)); 00868 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 00869 /* Don't use ast_set_callerid() here because it will 00870 * generate an unnecessary NewCallerID event */ 00871 if (!ast_strlen_zero(i->cid_num)) { 00872 tmp->caller.ani.number.valid = 1; 00873 tmp->caller.ani.number.str = ast_strdup(i->cid_num); 00874 } 00875 if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s")) { 00876 tmp->dialed.number.str = ast_strdup(i->exten); 00877 } 00878 tmp->priority = 1; 00879 if (i->rtp) 00880 ast_jb_configure(tmp, &global_jbconf); 00881 if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) { 00882 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 00883 tmp->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 00884 ast_hangup(tmp); 00885 tmp = NULL; 00886 } 00887 00888 return tmp; 00889 }
static int jingle_newcall | ( | struct jingle * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 962 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_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, 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().
00963 { 00964 struct jingle_pvt *p, *tmp = client->p; 00965 struct ast_channel *chan; 00966 int res; 00967 iks *codec, *content, *description; 00968 char *from = NULL; 00969 00970 /* Make sure our new call doesn't exist yet */ 00971 from = iks_find_attrib(pak->x,"to"); 00972 if(!from) 00973 from = client->connection->jid->full; 00974 00975 while (tmp) { 00976 if (iks_find_with_attrib(pak->x, JINGLE_NODE, JINGLE_SID, tmp->sid)) { 00977 ast_log(LOG_NOTICE, "Ignoring duplicate call setup on SID %s\n", tmp->sid); 00978 jingle_response(client, pak, "out-of-order", NULL); 00979 return -1; 00980 } 00981 tmp = tmp->next; 00982 } 00983 00984 if (!strcasecmp(client->name, "guest")){ 00985 /* the guest account is not tied to any configured XMPP client, 00986 let's set it now */ 00987 client->connection = ast_aji_get_client(from); 00988 if (!client->connection) { 00989 ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", from); 00990 return -1; 00991 } 00992 } 00993 00994 p = jingle_alloc(client, pak->from->partial, iks_find_attrib(pak->query, JINGLE_SID)); 00995 if (!p) { 00996 ast_log(LOG_WARNING, "Unable to allocate jingle structure!\n"); 00997 return -1; 00998 } 00999 chan = jingle_new(client, p, AST_STATE_DOWN, pak->from->user, NULL); 01000 if (!chan) { 01001 jingle_free_pvt(client, p); 01002 return -1; 01003 } 01004 ast_mutex_lock(&p->lock); 01005 ast_copy_string(p->them, pak->from->full, sizeof(p->them)); 01006 if (iks_find_attrib(pak->query, JINGLE_SID)) { 01007 ast_copy_string(p->sid, iks_find_attrib(pak->query, JINGLE_SID), 01008 sizeof(p->sid)); 01009 } 01010 01011 /* content points to the first <content/> tag */ 01012 content = iks_child(iks_child(pak->x)); 01013 while (content) { 01014 description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_AUDIO_RTP_NS); 01015 if (description) { 01016 /* audio content found */ 01017 codec = iks_child(iks_child(content)); 01018 ast_copy_string(p->audio_content_name, iks_find_attrib(content, "name"), sizeof(p->audio_content_name)); 01019 01020 while (codec) { 01021 ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id"))); 01022 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); 01023 codec = iks_next(codec); 01024 } 01025 } 01026 01027 description = NULL; 01028 codec = NULL; 01029 01030 description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_VIDEO_RTP_NS); 01031 if (description) { 01032 /* video content found */ 01033 codec = iks_child(iks_child(content)); 01034 ast_copy_string(p->video_content_name, iks_find_attrib(content, "name"), sizeof(p->video_content_name)); 01035 01036 while (codec) { 01037 ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id"))); 01038 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); 01039 codec = iks_next(codec); 01040 } 01041 } 01042 01043 content = iks_next(content); 01044 } 01045 01046 ast_mutex_unlock(&p->lock); 01047 ast_setstate(chan, AST_STATE_RING); 01048 res = ast_pbx_start(chan); 01049 01050 switch (res) { 01051 case AST_PBX_FAILED: 01052 ast_log(LOG_WARNING, "Failed to start PBX :(\n"); 01053 jingle_response(client, pak, "service-unavailable", NULL); 01054 break; 01055 case AST_PBX_CALL_LIMIT: 01056 ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n"); 01057 jingle_response(client, pak, "service-unavailable", NULL); 01058 break; 01059 case AST_PBX_SUCCESS: 01060 jingle_response(client, pak, NULL, NULL); 01061 jingle_create_candidates(client, p, 01062 iks_find_attrib(pak->query, JINGLE_SID), 01063 iks_find_attrib(pak->x, "from")); 01064 /* nothing to do */ 01065 break; 01066 } 01067 01068 return 1; 01069 }
static int jingle_parser | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 1626 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().
01627 { 01628 struct jingle *client = ASTOBJ_REF((struct jingle *) data); 01629 ast_log(LOG_NOTICE, "Filter matched\n"); 01630 01631 if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INITIATE)) { 01632 /* New call */ 01633 jingle_newcall(client, pak); 01634 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_NEGOTIATE)) { 01635 ast_debug(3, "About to add candidate!\n"); 01636 jingle_add_candidate(client, pak); 01637 ast_debug(3, "Candidate Added!\n"); 01638 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_ACCEPT)) { 01639 jingle_is_answered(client, pak); 01640 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_INFO)) { 01641 jingle_handle_dtmf(client, pak); 01642 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", JINGLE_TERMINATE)) { 01643 jingle_hangup_farend(client, pak); 01644 } else if (iks_find_with_attrib(pak->x, JINGLE_NODE, "action", "reject")) { 01645 jingle_hangup_farend(client, pak); 01646 } 01647 ASTOBJ_UNREF(client, jingle_member_destroy); 01648 return IKS_FILTER_EAT; 01649 }
static struct ast_frame * jingle_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 1205 of file chan_jingle.c.
References ast_mutex_lock, ast_mutex_unlock, jingle_rtp_read(), jingle_pvt::lock, and ast_channel::tech_pvt.
01206 { 01207 struct ast_frame *fr; 01208 struct jingle_pvt *p = ast->tech_pvt; 01209 01210 ast_mutex_lock(&p->lock); 01211 fr = jingle_rtp_read(ast, p); 01212 ast_mutex_unlock(&p->lock); 01213 return fr; 01214 }
static struct ast_channel * jingle_request | ( | const char * | type, | |
format_t | format, | |||
const struct ast_channel * | requestor, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Part of PBX interface.
Definition at line 1501 of file chan_jingle.c.
References ast_aji_get_client(), ast_log(), AST_STATE_DOWN, ast_strdupa, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, jingle::connection, find_jingle(), jingle_alloc(), jingle_new(), ast_channel::linkedid, LOG_ERROR, LOG_WARNING, jingle::name, and strsep().
01502 { 01503 struct jingle_pvt *p = NULL; 01504 struct jingle *client = NULL; 01505 char *sender = NULL, *to = NULL, *s = NULL; 01506 struct ast_channel *chan = NULL; 01507 01508 if (data) { 01509 s = ast_strdupa(data); 01510 if (s) { 01511 sender = strsep(&s, "/"); 01512 if (sender && (sender[0] != '\0')) 01513 to = strsep(&s, "/"); 01514 if (!to) { 01515 ast_log(LOG_ERROR, "Bad arguments in Jingle Dialstring: %s\n", (char*) data); 01516 return NULL; 01517 } 01518 } 01519 } 01520 01521 client = find_jingle(to, sender); 01522 if (!client) { 01523 ast_log(LOG_WARNING, "Could not find recipient.\n"); 01524 return NULL; 01525 } 01526 if (!strcasecmp(client->name, "guest")){ 01527 /* the guest account is not tied to any configured XMPP client, 01528 let's set it now */ 01529 client->connection = ast_aji_get_client(sender); 01530 if (!client->connection) { 01531 ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", sender); 01532 return NULL; 01533 } 01534 } 01535 01536 ASTOBJ_WRLOCK(client); 01537 p = jingle_alloc(client, to, NULL); 01538 if (p) 01539 chan = jingle_new(client, p, AST_STATE_DOWN, to, requestor ? requestor->linkedid : NULL); 01540 ASTOBJ_UNLOCK(client); 01541 01542 return chan; 01543 }
static int jingle_response | ( | struct jingle * | client, | |
ikspak * | pak, | |||
const char * | reasonstr, | |||
const char * | reasonstr2 | |||
) | [static] |
Definition at line 441 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().
00442 { 00443 iks *response = NULL, *error = NULL, *reason = NULL; 00444 int res = -1; 00445 00446 response = iks_new("iq"); 00447 if (response) { 00448 iks_insert_attrib(response, "type", "result"); 00449 iks_insert_attrib(response, "from", client->connection->jid->full); 00450 iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from")); 00451 iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id")); 00452 if (reasonstr) { 00453 error = iks_new("error"); 00454 if (error) { 00455 iks_insert_attrib(error, "type", "cancel"); 00456 reason = iks_new(reasonstr); 00457 if (reason) 00458 iks_insert_node(error, reason); 00459 iks_insert_node(response, error); 00460 } 00461 } 00462 ast_aji_send(client->connection, response); 00463 res = 0; 00464 } 00465 00466 iks_delete(reason); 00467 iks_delete(error); 00468 iks_delete(response); 00469 00470 return res; 00471 }
static int jingle_ringing_ack | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 364 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().
00365 { 00366 struct jingle_pvt *p = data; 00367 00368 if (p->ringrule) 00369 iks_filter_remove_rule(p->parent->connection->f, p->ringrule); 00370 p->ringrule = NULL; 00371 if (p->owner) 00372 ast_queue_control(p->owner, AST_CONTROL_RINGING); 00373 return IKS_FILTER_EAT; 00374 }
static struct ast_frame* jingle_rtp_read | ( | struct ast_channel * | ast, | |
struct jingle_pvt * | p | |||
) | [static] |
Definition at line 1177 of file chan_jingle.c.
References ast_debug, AST_FORMAT_AUDIO_MASK, AST_FORMAT_VIDEO_MASK, AST_FRAME_VOICE, ast_getformatname(), ast_null_frame, ast_rtp_instance_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().
01178 { 01179 struct ast_frame *f; 01180 01181 if (!p->rtp) 01182 return &ast_null_frame; 01183 f = ast_rtp_instance_read(p->rtp, 0); 01184 jingle_update_stun(p->parent, p); 01185 if (p->owner) { 01186 /* We already hold the channel lock */ 01187 if (f->frametype == AST_FRAME_VOICE) { 01188 if (f->subclass.codec != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) { 01189 ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(f->subclass.codec)); 01190 p->owner->nativeformats = 01191 (p->owner->nativeformats & AST_FORMAT_VIDEO_MASK) | f->subclass.codec; 01192 ast_set_read_format(p->owner, p->owner->readformat); 01193 ast_set_write_format(p->owner, p->owner->writeformat); 01194 } 01195 /* if ((ast_test_flag(p, SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) { 01196 f = ast_dsp_process(p->owner, p->vad, f); 01197 if (f && (f->frametype == AST_FRAME_DTMF)) 01198 ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass.codec); 01199 } */ 01200 } 01201 } 01202 return f; 01203 }
static int jingle_sendhtml | ( | struct ast_channel * | ast, | |
int | subclass, | |||
const char * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 1373 of file chan_jingle.c.
References ast_log(), and LOG_NOTICE.
01374 { 01375 ast_log(LOG_NOTICE, "XXX Implement jingle sendhtml XXX\n"); 01376 01377 return -1; 01378 }
static int jingle_sendtext | ( | struct ast_channel * | ast, | |
const char * | text | |||
) | [static] |
Definition at line 1297 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.
01298 { 01299 int res = 0; 01300 struct aji_client *client = NULL; 01301 struct jingle_pvt *p = chan->tech_pvt; 01302 01303 01304 if (!p->parent) { 01305 ast_log(LOG_ERROR, "Parent channel not found\n"); 01306 return -1; 01307 } 01308 if (!p->parent->connection) { 01309 ast_log(LOG_ERROR, "XMPP client not found\n"); 01310 return -1; 01311 } 01312 client = p->parent->connection; 01313 res = ast_aji_send_chat(client, p->them, text); 01314 return res; 01315 }
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, | |||
format_t | codecs, | |||
int | nat_active | |||
) | [static] |
Definition at line 414 of file chan_jingle.c.
References ast_mutex_lock, ast_mutex_unlock, jingle_pvt::lock, and ast_channel::tech_pvt.
00415 { 00416 struct jingle_pvt *p; 00417 00418 p = chan->tech_pvt; 00419 if (!p) 00420 return -1; 00421 ast_mutex_lock(&p->lock); 00422 00423 /* if (rtp) 00424 ast_rtp_get_peer(rtp, &p->redirip); 00425 else 00426 memset(&p->redirip, 0, sizeof(p->redirip)); 00427 p->redircodecs = codecs; */ 00428 00429 /* Reset lastrtprx timer */ 00430 ast_mutex_unlock(&p->lock); 00431 return 0; 00432 }
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 1546 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, 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.
01547 { 01548 #define FORMAT "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n" 01549 struct jingle_pvt *p; 01550 struct ast_channel *chan; 01551 int numchans = 0; 01552 char them[AJI_MAX_JIDLEN]; 01553 char *jid = NULL; 01554 char *resource = NULL; 01555 01556 switch (cmd) { 01557 case CLI_INIT: 01558 e->command = "jingle show channels"; 01559 e->usage = 01560 "Usage: jingle show channels\n" 01561 " Shows current state of the Jingle channels.\n"; 01562 return NULL; 01563 case CLI_GENERATE: 01564 return NULL; 01565 } 01566 01567 if (a->argc != 3) 01568 return CLI_SHOWUSAGE; 01569 01570 ast_mutex_lock(&jinglelock); 01571 ast_cli(a->fd, FORMAT, "Channel", "Jabber ID", "Resource", "Read", "Write"); 01572 ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, { 01573 ASTOBJ_WRLOCK(iterator); 01574 p = iterator->p; 01575 while(p) { 01576 chan = p->owner; 01577 ast_copy_string(them, p->them, sizeof(them)); 01578 jid = them; 01579 resource = strchr(them, '/'); 01580 if (!resource) 01581 resource = "None"; 01582 else { 01583 *resource = '\0'; 01584 resource ++; 01585 } 01586 if (chan) 01587 ast_cli(a->fd, FORMAT, 01588 chan->name, 01589 jid, 01590 resource, 01591 ast_getformatname(chan->readformat), 01592 ast_getformatname(chan->writeformat) 01593 ); 01594 else 01595 ast_log(LOG_WARNING, "No available channel\n"); 01596 numchans ++; 01597 p = p->next; 01598 } 01599 ASTOBJ_UNLOCK(iterator); 01600 }); 01601 01602 ast_mutex_unlock(&jinglelock); 01603 01604 ast_cli(a->fd, "%d active jingle channel%s\n", numchans, (numchans != 1) ? "s" : ""); 01605 return CLI_SUCCESS; 01606 #undef FORMAT 01607 }
static int jingle_transmit_invite | ( | struct jingle_pvt * | p | ) | [static] |
Definition at line 1379 of file chan_jingle.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_copy_string(), jingle::connection, 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().
01380 { 01381 struct jingle *aux = NULL; 01382 struct aji_client *client = NULL; 01383 iks *iq, *jingle, *content, *description, *transport; 01384 iks *payload_eg711u, *payload_pcmu; 01385 01386 aux = p->parent; 01387 client = aux->connection; 01388 iq = iks_new("iq"); 01389 jingle = iks_new(JINGLE_NODE); 01390 content = iks_new("content"); 01391 description = iks_new("description"); 01392 transport = iks_new("transport"); 01393 payload_pcmu = iks_new("payload-type"); 01394 payload_eg711u = iks_new("payload-type"); 01395 01396 ast_copy_string(p->audio_content_name, "asterisk-audio-content", sizeof(p->audio_content_name)); 01397 01398 iks_insert_attrib(iq, "type", "set"); 01399 iks_insert_attrib(iq, "to", p->them); 01400 iks_insert_attrib(iq, "from", client->jid->full); 01401 iks_insert_attrib(iq, "id", client->mid); 01402 ast_aji_increment_mid(client->mid); 01403 iks_insert_attrib(jingle, "action", JINGLE_INITIATE); 01404 iks_insert_attrib(jingle, JINGLE_SID, p->sid); 01405 iks_insert_attrib(jingle, "initiator", client->jid->full); 01406 iks_insert_attrib(jingle, "xmlns", JINGLE_NS); 01407 01408 /* For now, we only send one audio based content */ 01409 iks_insert_attrib(content, "creator", "initiator"); 01410 iks_insert_attrib(content, "name", p->audio_content_name); 01411 iks_insert_attrib(content, "profile", "RTP/AVP"); 01412 iks_insert_attrib(description, "xmlns", JINGLE_AUDIO_RTP_NS); 01413 iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS); 01414 iks_insert_attrib(payload_pcmu, "id", "0"); 01415 iks_insert_attrib(payload_pcmu, "name", "PCMU"); 01416 iks_insert_attrib(payload_eg711u, "id", "100"); 01417 iks_insert_attrib(payload_eg711u, "name", "EG711U"); 01418 iks_insert_node(description, payload_pcmu); 01419 iks_insert_node(description, payload_eg711u); 01420 iks_insert_node(content, description); 01421 iks_insert_node(content, transport); 01422 iks_insert_node(jingle, content); 01423 iks_insert_node(iq, jingle); 01424 01425 ast_aji_send(client, iq); 01426 01427 iks_delete(iq); 01428 iks_delete(jingle); 01429 iks_delete(content); 01430 iks_delete(description); 01431 iks_delete(transport); 01432 iks_delete(payload_eg711u); 01433 iks_delete(payload_pcmu); 01434 return 0; 01435 }
static int jingle_update_stun | ( | struct jingle * | client, | |
struct jingle_pvt * | p | |||
) | [static] |
Definition at line 1071 of file chan_jingle.c.
References ahp, 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().
01072 { 01073 struct jingle_candidate *tmp; 01074 struct hostent *hp; 01075 struct ast_hostent ahp; 01076 struct sockaddr_in sin; 01077 struct ast_sockaddr sin_tmp; 01078 01079 if (time(NULL) == p->laststun) 01080 return 0; 01081 01082 tmp = p->theircandidates; 01083 p->laststun = time(NULL); 01084 while (tmp) { 01085 char username[256]; 01086 hp = ast_gethostbyname(tmp->ip, &ahp); 01087 sin.sin_family = AF_INET; 01088 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); 01089 sin.sin_port = htons(tmp->port); 01090 snprintf(username, sizeof(username), "%s:%s", tmp->ufrag, p->ourcandidates->ufrag); 01091 01092 ast_sockaddr_from_sin(&sin_tmp, &sin); 01093 ast_rtp_instance_stun_request(p->rtp, &sin_tmp, username); 01094 tmp = tmp->next; 01095 } 01096 return 1; 01097 }
static int jingle_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | f | |||
) | [static] |
Send frame to media channel (rtp).
Definition at line 1217 of file chan_jingle.c.
References 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::codec, 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.
01218 { 01219 struct jingle_pvt *p = ast->tech_pvt; 01220 int res = 0; 01221 char buf[256]; 01222 01223 switch (frame->frametype) { 01224 case AST_FRAME_VOICE: 01225 if (!(frame->subclass.codec & ast->nativeformats)) { 01226 ast_log(LOG_WARNING, 01227 "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n", 01228 ast_getformatname(frame->subclass.codec), 01229 ast_getformatname_multiple(buf, sizeof(buf), ast->nativeformats), 01230 ast_getformatname(ast->readformat), 01231 ast_getformatname(ast->writeformat)); 01232 return 0; 01233 } 01234 if (p) { 01235 ast_mutex_lock(&p->lock); 01236 if (p->rtp) { 01237 res = ast_rtp_instance_write(p->rtp, frame); 01238 } 01239 ast_mutex_unlock(&p->lock); 01240 } 01241 break; 01242 case AST_FRAME_VIDEO: 01243 if (p) { 01244 ast_mutex_lock(&p->lock); 01245 if (p->vrtp) { 01246 res = ast_rtp_instance_write(p->vrtp, frame); 01247 } 01248 ast_mutex_unlock(&p->lock); 01249 } 01250 break; 01251 case AST_FRAME_IMAGE: 01252 return 0; 01253 break; 01254 default: 01255 ast_log(LOG_WARNING, "Can't send %d type frames with Jingle write\n", 01256 frame->frametype); 01257 return 0; 01258 } 01259 01260 return res; 01261 }
static int load_module | ( | void | ) | [static] |
Load module into PBX, register channel.
Definition at line 1883 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_glue_register, ast_sockaddr_from_sin, ast_sockaddr_ipv4(), ASTOBJ_CONTAINER_INIT, bindaddr, channel_type, free, io, io_context_create(), jingle_cli, JINGLE_CONFIG, jingle_list, jingle_load_config(), jingle_rtp_glue, jingle_tech, LOG_ERROR, LOG_WARNING, and sched_context_create().
01884 { 01885 struct ast_sockaddr ourip_tmp; 01886 struct ast_sockaddr bindaddr_tmp; 01887 01888 char *jabber_loaded = ast_module_helper("", "res_jabber.so", 0, 0, 0, 0); 01889 free(jabber_loaded); 01890 if (!jabber_loaded) { 01891 /* Dependency module has a different name, if embedded */ 01892 jabber_loaded = ast_module_helper("", "res_jabber", 0, 0, 0, 0); 01893 free(jabber_loaded); 01894 if (!jabber_loaded) { 01895 ast_log(LOG_ERROR, "chan_jingle.so depends upon res_jabber.so\n"); 01896 return AST_MODULE_LOAD_DECLINE; 01897 } 01898 } 01899 01900 ASTOBJ_CONTAINER_INIT(&jingle_list); 01901 if (!jingle_load_config()) { 01902 ast_log(LOG_ERROR, "Unable to read config file %s. Not loading module.\n", JINGLE_CONFIG); 01903 return AST_MODULE_LOAD_DECLINE; 01904 } 01905 01906 sched = sched_context_create(); 01907 if (!sched) { 01908 ast_log(LOG_WARNING, "Unable to create schedule context\n"); 01909 } 01910 01911 io = io_context_create(); 01912 if (!io) { 01913 ast_log(LOG_WARNING, "Unable to create I/O context\n"); 01914 } 01915 01916 ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr); 01917 if (ast_find_ourip(&ourip_tmp, &bindaddr_tmp, AF_INET)) { 01918 ast_log(LOG_WARNING, "Unable to get own IP address, Jingle disabled\n"); 01919 return 0; 01920 } 01921 __ourip.s_addr = htonl(ast_sockaddr_ipv4(&ourip_tmp)); 01922 01923 ast_rtp_glue_register(&jingle_rtp_glue); 01924 ast_cli_register_multiple(jingle_cli, ARRAY_LEN(jingle_cli)); 01925 /* Make sure we can register our channel type */ 01926 if (ast_channel_register(&jingle_tech)) { 01927 ast_log(LOG_ERROR, "Unable to register channel class %s\n", channel_type); 01928 return -1; 01929 } 01930 return 0; 01931 }
static int reload | ( | void | ) | [static] |
static int unload_module | ( | void | ) | [static] |
Unload the jingle channel from Asterisk.
Definition at line 1940 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_glue_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_glue, jingle_tech, jinglelock, LOG_WARNING, jingle_pvt::next, and jingle_pvt::owner.
01941 { 01942 struct jingle_pvt *privates = NULL; 01943 ast_cli_unregister_multiple(jingle_cli, ARRAY_LEN(jingle_cli)); 01944 /* First, take us out of the channel loop */ 01945 ast_channel_unregister(&jingle_tech); 01946 ast_rtp_glue_unregister(&jingle_rtp_glue); 01947 01948 if (!ast_mutex_lock(&jinglelock)) { 01949 /* Hangup all interfaces if they have an owner */ 01950 ASTOBJ_CONTAINER_TRAVERSE(&jingle_list, 1, { 01951 ASTOBJ_WRLOCK(iterator); 01952 privates = iterator->p; 01953 while(privates) { 01954 if (privates->owner) 01955 ast_softhangup(privates->owner, AST_SOFTHANGUP_APPUNLOAD); 01956 privates = privates->next; 01957 } 01958 iterator->p = NULL; 01959 ASTOBJ_UNLOCK(iterator); 01960 }); 01961 ast_mutex_unlock(&jinglelock); 01962 } else { 01963 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 01964 return -1; 01965 } 01966 ASTOBJ_CONTAINER_DESTROYALL(&jingle_list, jingle_member_destroy); 01967 ASTOBJ_CONTAINER_DESTROY(&jingle_list); 01968 return 0; 01969 }
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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, } [static] |
Definition at line 1976 of file chan_jingle.c.
struct in_addr __ourip [static] |
Definition at line 215 of file chan_jingle.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 1976 of file chan_jingle.c.
struct sockaddr_in bindaddr = { 0, } [static] |
The address we bind to
Definition at line 211 of file chan_jingle.c.
const char channel_type[] = "Jingle" [static] |
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 164 of file chan_jingle.c.
char externip[16] [static] |
Definition at line 223 of file chan_jingle.c.
format_t global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263 [static] |
Definition at line 167 of file chan_jingle.c.
struct ast_jb_conf global_jbconf [static] |
Definition at line 83 of file chan_jingle.c.
struct io_context* io [static] |
The IO context
Definition at line 214 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 217 of file chan_jingle.c.
Referenced by load_module(), and unload_module().
struct jingle_container jingle_list [static] |
Definition at line 225 of file chan_jingle.c.
Referenced by find_jingle(), jingle_show_channels(), load_module(), and unload_module().
struct ast_rtp_glue jingle_rtp_glue [static] |
struct ast_channel_tech jingle_tech [static] |
PBX interface structure for channel registration.
Definition at line 190 of file chan_jingle.c.
Referenced by jingle_new(), load_module(), and unload_module().
ast_mutex_t jinglelock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [static] |
Protect the interface list (of jingle_pvt's)
Definition at line 169 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 213 of file chan_jingle.c.