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