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