chan_motif.c 92 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2012, Digium, Inc.
  5. *
  6. * Joshua Colp <jcolp@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*! \file
  19. *
  20. * \author Joshua Colp <jcolp@digium.com>
  21. *
  22. * \brief Motif Jingle Channel Driver
  23. *
  24. * \extref Iksemel http://iksemel.jabberstudio.org/
  25. *
  26. * \ingroup channel_drivers
  27. */
  28. /*** MODULEINFO
  29. <depend>iksemel</depend>
  30. <depend>res_xmpp</depend>
  31. <use type="external">openssl</use>
  32. <support_level>core</support_level>
  33. ***/
  34. #include "asterisk.h"
  35. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  36. #include <sys/socket.h>
  37. #include <fcntl.h>
  38. #include <netdb.h>
  39. #include <netinet/in.h>
  40. #include <arpa/inet.h>
  41. #include <sys/signal.h>
  42. #include <iksemel.h>
  43. #include <pthread.h>
  44. #include "asterisk/lock.h"
  45. #include "asterisk/channel.h"
  46. #include "asterisk/config_options.h"
  47. #include "asterisk/module.h"
  48. #include "asterisk/pbx.h"
  49. #include "asterisk/sched.h"
  50. #include "asterisk/io.h"
  51. #include "asterisk/rtp_engine.h"
  52. #include "asterisk/acl.h"
  53. #include "asterisk/callerid.h"
  54. #include "asterisk/file.h"
  55. #include "asterisk/cli.h"
  56. #include "asterisk/app.h"
  57. #include "asterisk/musiconhold.h"
  58. #include "asterisk/manager.h"
  59. #include "asterisk/stringfields.h"
  60. #include "asterisk/utils.h"
  61. #include "asterisk/causes.h"
  62. #include "asterisk/astobj.h"
  63. #include "asterisk/abstract_jb.h"
  64. #include "asterisk/xmpp.h"
  65. /*! \brief Default maximum number of ICE candidates we will offer */
  66. #define DEFAULT_MAX_ICE_CANDIDATES "10"
  67. /*! \brief Default maximum number of payloads we will offer */
  68. #define DEFAULT_MAX_PAYLOADS "30"
  69. /*! \brief Number of buckets for endpoints */
  70. #define ENDPOINT_BUCKETS 37
  71. /*! \brief Number of buckets for sessions, on a per-endpoint basis */
  72. #define SESSION_BUCKETS 37
  73. /*! \brief Namespace for Jingle itself */
  74. #define JINGLE_NS "urn:xmpp:jingle:1"
  75. /*! \brief Namespace for Jingle RTP sessions */
  76. #define JINGLE_RTP_NS "urn:xmpp:jingle:apps:rtp:1"
  77. /*! \brief Namespace for Jingle RTP info */
  78. #define JINGLE_RTP_INFO_NS "urn:xmpp:jingle:apps:rtp:info:1"
  79. /*! \brief Namespace for Jingle ICE-UDP */
  80. #define JINGLE_ICE_UDP_NS "urn:xmpp:jingle:transports:ice-udp:1"
  81. /*! \brief Namespace for Google Talk ICE-UDP */
  82. #define GOOGLE_TRANSPORT_NS "http://www.google.com/transport/p2p"
  83. /*! \brief Namespace for Google Talk Raw UDP */
  84. #define GOOGLE_TRANSPORT_RAW_NS "http://www.google.com/transport/raw-udp"
  85. /*! \brief Namespace for Google Session */
  86. #define GOOGLE_SESSION_NS "http://www.google.com/session"
  87. /*! \brief Namespace for Google Phone description */
  88. #define GOOGLE_PHONE_NS "http://www.google.com/session/phone"
  89. /*! \brief Namespace for Google Video description */
  90. #define GOOGLE_VIDEO_NS "http://www.google.com/session/video"
  91. /*! \brief Namespace for XMPP stanzas */
  92. #define XMPP_STANZAS_NS "urn:ietf:params:xml:ns:xmpp-stanzas"
  93. /*! \brief The various transport methods supported, from highest priority to lowest priority when doing fallback */
  94. enum jingle_transport {
  95. JINGLE_TRANSPORT_ICE_UDP = 3, /*!< XEP-0176 */
  96. JINGLE_TRANSPORT_GOOGLE_V2 = 2, /*!< https://developers.google.com/talk/call_signaling */
  97. JINGLE_TRANSPORT_GOOGLE_V1 = 1, /*!< Undocumented initial Google specification */
  98. JINGLE_TRANSPORT_NONE = 0, /*!< No transport specified */
  99. };
  100. /*! \brief Endpoint state information */
  101. struct jingle_endpoint_state {
  102. struct ao2_container *sessions; /*!< Active sessions to or from the endpoint */
  103. };
  104. /*! \brief Endpoint which contains configuration information and active sessions */
  105. struct jingle_endpoint {
  106. AST_DECLARE_STRING_FIELDS(
  107. AST_STRING_FIELD(name); /*!< Name of the endpoint */
  108. AST_STRING_FIELD(context); /*!< Context to place incoming calls into */
  109. AST_STRING_FIELD(accountcode); /*!< Account code */
  110. AST_STRING_FIELD(language); /*!< Default language for prompts */
  111. AST_STRING_FIELD(musicclass); /*!< Configured music on hold class */
  112. AST_STRING_FIELD(parkinglot); /*!< Configured parking lot */
  113. );
  114. struct ast_xmpp_client *connection; /*!< Connection to use for traffic */
  115. iksrule *rule; /*!< Active matching rule */
  116. unsigned int maxicecandidates; /*!< Maximum number of ICE candidates we will offer */
  117. unsigned int maxpayloads; /*!< Maximum number of payloads we will offer */
  118. struct ast_codec_pref prefs; /*!< Codec preferences */
  119. struct ast_format_cap *cap; /*!< Formats to use */
  120. ast_group_t callgroup; /*!< Call group */
  121. ast_group_t pickupgroup; /*!< Pickup group */
  122. enum jingle_transport transport; /*!< Default transport to use on outgoing sessions */
  123. struct jingle_endpoint_state *state; /*!< Endpoint state information */
  124. };
  125. /*! \brief Session which contains information about an active session */
  126. struct jingle_session {
  127. AST_DECLARE_STRING_FIELDS(
  128. AST_STRING_FIELD(sid); /*!< Session identifier */
  129. AST_STRING_FIELD(audio_name); /*!< Name of the audio content */
  130. AST_STRING_FIELD(video_name); /*!< Name of the video content */
  131. );
  132. struct jingle_endpoint_state *state; /*!< Endpoint we are associated with */
  133. struct ast_xmpp_client *connection; /*!< Connection to use for traffic */
  134. enum jingle_transport transport; /*!< Transport type to use for this session */
  135. unsigned int maxicecandidates; /*!< Maximum number of ICE candidates we will offer */
  136. unsigned int maxpayloads; /*!< Maximum number of payloads we will offer */
  137. char remote_original[XMPP_MAX_JIDLEN];/*!< Identifier of the original remote party (remote may have changed due to redirect) */
  138. char remote[XMPP_MAX_JIDLEN]; /*!< Identifier of the remote party */
  139. iksrule *rule; /*!< Session matching rule */
  140. struct ast_codec_pref prefs; /*!< Codec preferences */
  141. struct ast_channel *owner; /*!< Master Channel */
  142. struct ast_rtp_instance *rtp; /*!< RTP audio session */
  143. struct ast_rtp_instance *vrtp; /*!< RTP video session */
  144. struct ast_format_cap *cap; /*!< Local codec capabilities */
  145. struct ast_format_cap *jointcap; /*!< Joint codec capabilities */
  146. struct ast_format_cap *peercap; /*!< Peer codec capabilities */
  147. unsigned int outgoing:1; /*!< Whether this is an outgoing leg or not */
  148. unsigned int gone:1; /*!< In the eyes of Jingle this session is already gone */
  149. struct ast_callid *callid; /*!< Bound session call-id */
  150. };
  151. static const char desc[] = "Motif Jingle Channel";
  152. static const char channel_type[] = "Motif";
  153. struct jingle_config {
  154. struct ao2_container *endpoints; /*!< Configured endpoints */
  155. };
  156. static AO2_GLOBAL_OBJ_STATIC(globals);
  157. static struct ast_sched_context *sched; /*!< Scheduling context for RTCP */
  158. /* \brief Asterisk core interaction functions */
  159. static struct ast_channel *jingle_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause);
  160. static int jingle_sendtext(struct ast_channel *ast, const char *text);
  161. static int jingle_digit_begin(struct ast_channel *ast, char digit);
  162. static int jingle_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
  163. static int jingle_call(struct ast_channel *ast, const char *dest, int timeout);
  164. static int jingle_hangup(struct ast_channel *ast);
  165. static int jingle_answer(struct ast_channel *ast);
  166. static struct ast_frame *jingle_read(struct ast_channel *ast);
  167. static int jingle_write(struct ast_channel *ast, struct ast_frame *f);
  168. static int jingle_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
  169. static int jingle_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
  170. static struct jingle_session *jingle_alloc(struct jingle_endpoint *endpoint, const char *from, const char *sid);
  171. /*! \brief Action handlers */
  172. static void jingle_action_session_initiate(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak);
  173. static void jingle_action_transport_info(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak);
  174. static void jingle_action_session_accept(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak);
  175. static void jingle_action_session_info(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak);
  176. static void jingle_action_session_terminate(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak);
  177. /*! \brief PBX interface structure for channel registration */
  178. static struct ast_channel_tech jingle_tech = {
  179. .type = "Motif",
  180. .description = "Motif Jingle Channel Driver",
  181. .requester = jingle_request,
  182. .send_text = jingle_sendtext,
  183. .send_digit_begin = jingle_digit_begin,
  184. .send_digit_end = jingle_digit_end,
  185. .bridge = ast_rtp_instance_bridge,
  186. .call = jingle_call,
  187. .hangup = jingle_hangup,
  188. .answer = jingle_answer,
  189. .read = jingle_read,
  190. .write = jingle_write,
  191. .write_video = jingle_write,
  192. .exception = jingle_read,
  193. .indicate = jingle_indicate,
  194. .fixup = jingle_fixup,
  195. .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER
  196. };
  197. /*! \brief Defined handlers for different Jingle actions */
  198. static const struct jingle_action_handler {
  199. const char *action;
  200. void (*handler)(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak);
  201. } jingle_action_handlers[] = {
  202. /* Jingle actions */
  203. { "session-initiate", jingle_action_session_initiate, },
  204. { "transport-info", jingle_action_transport_info, },
  205. { "session-accept", jingle_action_session_accept, },
  206. { "session-info", jingle_action_session_info, },
  207. { "session-terminate", jingle_action_session_terminate, },
  208. /* Google-V1 actions */
  209. { "initiate", jingle_action_session_initiate, },
  210. { "candidates", jingle_action_transport_info, },
  211. { "accept", jingle_action_session_accept, },
  212. { "terminate", jingle_action_session_terminate, },
  213. { "reject", jingle_action_session_terminate, },
  214. };
  215. /*! \brief Reason text <-> cause code mapping */
  216. static const struct jingle_reason_mapping {
  217. const char *reason;
  218. int cause;
  219. } jingle_reason_mappings[] = {
  220. { "busy", AST_CAUSE_BUSY, },
  221. { "cancel", AST_CAUSE_CALL_REJECTED, },
  222. { "connectivity-error", AST_CAUSE_INTERWORKING, },
  223. { "decline", AST_CAUSE_CALL_REJECTED, },
  224. { "expired", AST_CAUSE_NO_USER_RESPONSE, },
  225. { "failed-transport", AST_CAUSE_PROTOCOL_ERROR, },
  226. { "failed-application", AST_CAUSE_SWITCH_CONGESTION, },
  227. { "general-error", AST_CAUSE_CONGESTION, },
  228. { "gone", AST_CAUSE_NORMAL_CLEARING, },
  229. { "incompatible-parameters", AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, },
  230. { "media-error", AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, },
  231. { "security-error", AST_CAUSE_PROTOCOL_ERROR, },
  232. { "success", AST_CAUSE_NORMAL_CLEARING, },
  233. { "timeout", AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE, },
  234. { "unsupported-applications", AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, },
  235. { "unsupported-transports", AST_CAUSE_FACILITY_NOT_IMPLEMENTED, },
  236. };
  237. /*! \brief Hashing function for Jingle sessions */
  238. static int jingle_session_hash(const void *obj, const int flags)
  239. {
  240. const struct jingle_session *session = obj;
  241. const char *sid = obj;
  242. return ast_str_hash(flags & OBJ_KEY ? sid : session->sid);
  243. }
  244. /*! \brief Comparator function for Jingle sessions */
  245. static int jingle_session_cmp(void *obj, void *arg, int flags)
  246. {
  247. struct jingle_session *session1 = obj, *session2 = arg;
  248. const char *sid = arg;
  249. return !strcmp(session1->sid, flags & OBJ_KEY ? sid : session2->sid) ? CMP_MATCH | CMP_STOP : 0;
  250. }
  251. /*! \brief Destructor for Jingle endpoint state */
  252. static void jingle_endpoint_state_destructor(void *obj)
  253. {
  254. struct jingle_endpoint_state *state = obj;
  255. ao2_ref(state->sessions, -1);
  256. }
  257. /*! \brief Destructor for Jingle endpoints */
  258. static void jingle_endpoint_destructor(void *obj)
  259. {
  260. struct jingle_endpoint *endpoint = obj;
  261. if (endpoint->rule) {
  262. iks_filter_remove_rule(endpoint->connection->filter, endpoint->rule);
  263. }
  264. if (endpoint->connection) {
  265. ast_xmpp_client_unref(endpoint->connection);
  266. }
  267. ast_format_cap_destroy(endpoint->cap);
  268. ao2_ref(endpoint->state, -1);
  269. ast_string_field_free_memory(endpoint);
  270. }
  271. /*! \brief Find function for Jingle endpoints */
  272. static void *jingle_endpoint_find(struct ao2_container *tmp_container, const char *category)
  273. {
  274. return ao2_find(tmp_container, category, OBJ_KEY);
  275. }
  276. /*! \brief Allocator function for Jingle endpoint state */
  277. static struct jingle_endpoint_state *jingle_endpoint_state_create(void)
  278. {
  279. struct jingle_endpoint_state *state;
  280. if (!(state = ao2_alloc(sizeof(*state), jingle_endpoint_state_destructor))) {
  281. return NULL;
  282. }
  283. if (!(state->sessions = ao2_container_alloc(SESSION_BUCKETS, jingle_session_hash, jingle_session_cmp))) {
  284. ao2_ref(state, -1);
  285. return NULL;
  286. }
  287. return state;
  288. }
  289. /*! \brief State find/create function */
  290. static struct jingle_endpoint_state *jingle_endpoint_state_find_or_create(const char *category)
  291. {
  292. RAII_VAR(struct jingle_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
  293. RAII_VAR(struct jingle_endpoint *, endpoint, NULL, ao2_cleanup);
  294. if (!cfg || !cfg->endpoints || !(endpoint = jingle_endpoint_find(cfg->endpoints, category))) {
  295. return jingle_endpoint_state_create();
  296. }
  297. ao2_ref(endpoint->state, +1);
  298. return endpoint->state;
  299. }
  300. /*! \brief Allocator function for Jingle endpoints */
  301. static void *jingle_endpoint_alloc(const char *cat)
  302. {
  303. struct jingle_endpoint *endpoint;
  304. if (!(endpoint = ao2_alloc(sizeof(*endpoint), jingle_endpoint_destructor))) {
  305. return NULL;
  306. }
  307. if (ast_string_field_init(endpoint, 512)) {
  308. ao2_ref(endpoint, -1);
  309. return NULL;
  310. }
  311. if (!(endpoint->state = jingle_endpoint_state_find_or_create(cat))) {
  312. ao2_ref(endpoint, -1);
  313. return NULL;
  314. }
  315. ast_string_field_set(endpoint, name, cat);
  316. endpoint->cap = ast_format_cap_alloc_nolock();
  317. endpoint->transport = JINGLE_TRANSPORT_ICE_UDP;
  318. return endpoint;
  319. }
  320. /*! \brief Hashing function for Jingle endpoints */
  321. static int jingle_endpoint_hash(const void *obj, const int flags)
  322. {
  323. const struct jingle_endpoint *endpoint = obj;
  324. const char *name = obj;
  325. return ast_str_hash(flags & OBJ_KEY ? name : endpoint->name);
  326. }
  327. /*! \brief Comparator function for Jingle endpoints */
  328. static int jingle_endpoint_cmp(void *obj, void *arg, int flags)
  329. {
  330. struct jingle_endpoint *endpoint1 = obj, *endpoint2 = arg;
  331. const char *name = arg;
  332. return !strcmp(endpoint1->name, flags & OBJ_KEY ? name : endpoint2->name) ? CMP_MATCH | CMP_STOP : 0;
  333. }
  334. static struct aco_type endpoint_option = {
  335. .type = ACO_ITEM,
  336. .category_match = ACO_BLACKLIST,
  337. .category = "^general$",
  338. .item_alloc = jingle_endpoint_alloc,
  339. .item_find = jingle_endpoint_find,
  340. .item_offset = offsetof(struct jingle_config, endpoints),
  341. };
  342. struct aco_type *endpoint_options[] = ACO_TYPES(&endpoint_option);
  343. struct aco_file jingle_conf = {
  344. .filename = "motif.conf",
  345. .types = ACO_TYPES(&endpoint_option),
  346. };
  347. /*! \brief Destructor for Jingle sessions */
  348. static void jingle_session_destructor(void *obj)
  349. {
  350. struct jingle_session *session = obj;
  351. if (session->rule) {
  352. iks_filter_remove_rule(session->connection->filter, session->rule);
  353. }
  354. if (session->connection) {
  355. ast_xmpp_client_unref(session->connection);
  356. }
  357. if (session->rtp) {
  358. ast_rtp_instance_stop(session->rtp);
  359. ast_rtp_instance_destroy(session->rtp);
  360. }
  361. if (session->vrtp) {
  362. ast_rtp_instance_stop(session->vrtp);
  363. ast_rtp_instance_destroy(session->vrtp);
  364. }
  365. ast_format_cap_destroy(session->cap);
  366. ast_format_cap_destroy(session->jointcap);
  367. ast_format_cap_destroy(session->peercap);
  368. if (session->callid) {
  369. ast_callid_unref(session->callid);
  370. }
  371. ast_string_field_free_memory(session);
  372. }
  373. /*! \brief Destructor called when module configuration goes away */
  374. static void jingle_config_destructor(void *obj)
  375. {
  376. struct jingle_config *cfg = obj;
  377. ao2_cleanup(cfg->endpoints);
  378. }
  379. /*! \brief Allocator called when module configuration should appear */
  380. static void *jingle_config_alloc(void)
  381. {
  382. struct jingle_config *cfg;
  383. if (!(cfg = ao2_alloc(sizeof(*cfg), jingle_config_destructor))) {
  384. return NULL;
  385. }
  386. if (!(cfg->endpoints = ao2_container_alloc(ENDPOINT_BUCKETS, jingle_endpoint_hash, jingle_endpoint_cmp))) {
  387. ao2_ref(cfg, -1);
  388. return NULL;
  389. }
  390. return cfg;
  391. }
  392. CONFIG_INFO_STANDARD(cfg_info, globals, jingle_config_alloc,
  393. .files = ACO_FILES(&jingle_conf),
  394. );
  395. /*! \brief Function called by RTP engine to get local RTP peer */
  396. static enum ast_rtp_glue_result jingle_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
  397. {
  398. struct jingle_session *session = ast_channel_tech_pvt(chan);
  399. enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_LOCAL;
  400. if (!session->rtp) {
  401. return AST_RTP_GLUE_RESULT_FORBID;
  402. }
  403. ao2_ref(session->rtp, +1);
  404. *instance = session->rtp;
  405. return res;
  406. }
  407. /*! \brief Function called by RTP engine to get peer capabilities */
  408. static void jingle_get_codec(struct ast_channel *chan, struct ast_format_cap *result)
  409. {
  410. }
  411. /*! \brief Function called by RTP engine to change where the remote party should send media */
  412. static int jingle_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *tpeer, const struct ast_format_cap *cap, int nat_active)
  413. {
  414. return -1;
  415. }
  416. /*! \brief Local glue for interacting with the RTP engine core */
  417. static struct ast_rtp_glue jingle_rtp_glue = {
  418. .type = "Motif",
  419. .get_rtp_info = jingle_get_rtp_peer,
  420. .get_codec = jingle_get_codec,
  421. .update_peer = jingle_set_rtp_peer,
  422. };
  423. /*! \brief Internal helper function which enables video support on a sesson if possible */
  424. static void jingle_enable_video(struct jingle_session *session)
  425. {
  426. struct ast_sockaddr tmp;
  427. struct ast_rtp_engine_ice *ice;
  428. /* If video is already present don't do anything */
  429. if (session->vrtp) {
  430. return;
  431. }
  432. /* If there are no configured video codecs do not turn video support on, it just won't work */
  433. if (!ast_format_cap_has_type(session->cap, AST_FORMAT_TYPE_VIDEO)) {
  434. return;
  435. }
  436. ast_sockaddr_parse(&tmp, "0.0.0.0", 0);
  437. if (!(session->vrtp = ast_rtp_instance_new("asterisk", sched, &tmp, NULL))) {
  438. return;
  439. }
  440. ast_rtp_instance_set_prop(session->vrtp, AST_RTP_PROPERTY_RTCP, 1);
  441. ast_channel_set_fd(session->owner, 2, ast_rtp_instance_fd(session->vrtp, 0));
  442. ast_channel_set_fd(session->owner, 3, ast_rtp_instance_fd(session->vrtp, 1));
  443. ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(session->vrtp), session->vrtp, &session->prefs);
  444. if (session->transport == JINGLE_TRANSPORT_GOOGLE_V2 && (ice = ast_rtp_instance_get_ice(session->vrtp))) {
  445. ice->stop(session->vrtp);
  446. }
  447. }
  448. /*! \brief Internal helper function used to allocate Jingle session on an endpoint */
  449. static struct jingle_session *jingle_alloc(struct jingle_endpoint *endpoint, const char *from, const char *sid)
  450. {
  451. struct jingle_session *session;
  452. struct ast_callid *callid;
  453. struct ast_sockaddr tmp;
  454. if (!(session = ao2_alloc(sizeof(*session), jingle_session_destructor))) {
  455. return NULL;
  456. }
  457. callid = ast_read_threadstorage_callid();
  458. session->callid = (callid ? callid : ast_create_callid());
  459. if (ast_string_field_init(session, 512)) {
  460. ao2_ref(session, -1);
  461. return NULL;
  462. }
  463. if (!ast_strlen_zero(from)) {
  464. ast_copy_string(session->remote_original, from, sizeof(session->remote_original));
  465. ast_copy_string(session->remote, from, sizeof(session->remote));
  466. }
  467. if (ast_strlen_zero(sid)) {
  468. ast_string_field_build(session, sid, "%08lx%08lx", (unsigned long)ast_random(), (unsigned long)ast_random());
  469. session->outgoing = 1;
  470. ast_string_field_set(session, audio_name, "audio");
  471. ast_string_field_set(session, video_name, "video");
  472. } else {
  473. ast_string_field_set(session, sid, sid);
  474. }
  475. ao2_ref(endpoint->state, +1);
  476. session->state = endpoint->state;
  477. ao2_ref(endpoint->connection, +1);
  478. session->connection = endpoint->connection;
  479. session->transport = endpoint->transport;
  480. if (!(session->cap = ast_format_cap_alloc_nolock()) ||
  481. !(session->jointcap = ast_format_cap_alloc_nolock()) ||
  482. !(session->peercap = ast_format_cap_alloc_nolock()) ||
  483. !session->callid) {
  484. ao2_ref(session, -1);
  485. return NULL;
  486. }
  487. ast_format_cap_copy(session->cap, endpoint->cap);
  488. /* While we rely on res_xmpp for communication we still need a temporary ast_sockaddr to tell the RTP engine
  489. * that we want IPv4 */
  490. ast_sockaddr_parse(&tmp, "0.0.0.0", 0);
  491. /* Sessions always carry audio, but video is optional so don't enable it here */
  492. if (!(session->rtp = ast_rtp_instance_new("asterisk", sched, &tmp, NULL))) {
  493. ao2_ref(session, -1);
  494. return NULL;
  495. }
  496. ast_rtp_instance_set_prop(session->rtp, AST_RTP_PROPERTY_RTCP, 1);
  497. ast_rtp_instance_set_prop(session->rtp, AST_RTP_PROPERTY_DTMF, 1);
  498. memcpy(&session->prefs, &endpoint->prefs, sizeof(session->prefs));
  499. session->maxicecandidates = endpoint->maxicecandidates;
  500. session->maxpayloads = endpoint->maxpayloads;
  501. return session;
  502. }
  503. /*! \brief Function called to create a new Jingle Asterisk channel */
  504. static struct ast_channel *jingle_new(struct jingle_endpoint *endpoint, struct jingle_session *session, int state, const char *title, const char *linkedid, const char *cid_name)
  505. {
  506. struct ast_channel *chan;
  507. const char *str = S_OR(title, session->remote);
  508. struct ast_format tmpfmt;
  509. if (ast_format_cap_is_empty(session->cap)) {
  510. return NULL;
  511. }
  512. if (!(chan = ast_channel_alloc(1, state, S_OR(title, ""), S_OR(cid_name, ""), "", "", "", linkedid, 0, "Motif/%s-%04lx", str, (unsigned long)(ast_random() & 0xffff)))) {
  513. return NULL;
  514. }
  515. ast_channel_tech_set(chan, &jingle_tech);
  516. ast_channel_tech_pvt_set(chan, session);
  517. session->owner = chan;
  518. ast_channel_callid_set(chan, session->callid);
  519. ast_format_cap_copy(ast_channel_nativeformats(chan), session->cap);
  520. ast_codec_choose(&session->prefs, session->cap, 1, &tmpfmt);
  521. if (session->rtp) {
  522. struct ast_rtp_engine_ice *ice;
  523. ast_channel_set_fd(chan, 0, ast_rtp_instance_fd(session->rtp, 0));
  524. ast_channel_set_fd(chan, 1, ast_rtp_instance_fd(session->rtp, 1));
  525. ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(session->rtp), session->rtp, &session->prefs);
  526. if (((session->transport == JINGLE_TRANSPORT_GOOGLE_V2) ||
  527. (session->transport == JINGLE_TRANSPORT_GOOGLE_V1)) &&
  528. (ice = ast_rtp_instance_get_ice(session->rtp))) {
  529. /* We stop built in ICE support because we need to fall back to old old old STUN support */
  530. ice->stop(session->rtp);
  531. }
  532. }
  533. if (state == AST_STATE_RING) {
  534. ast_channel_rings_set(chan, 1);
  535. }
  536. ast_channel_adsicpe_set(chan, AST_ADSI_UNAVAILABLE);
  537. ast_best_codec(ast_channel_nativeformats(chan), &tmpfmt);
  538. ast_format_copy(ast_channel_writeformat(chan), &tmpfmt);
  539. ast_format_copy(ast_channel_rawwriteformat(chan), &tmpfmt);
  540. ast_format_copy(ast_channel_readformat(chan), &tmpfmt);
  541. ast_format_copy(ast_channel_rawreadformat(chan), &tmpfmt);
  542. ao2_lock(endpoint);
  543. ast_channel_callgroup_set(chan, endpoint->callgroup);
  544. ast_channel_pickupgroup_set(chan, endpoint->pickupgroup);
  545. if (!ast_strlen_zero(endpoint->accountcode)) {
  546. ast_channel_accountcode_set(chan, endpoint->accountcode);
  547. }
  548. if (!ast_strlen_zero(endpoint->language)) {
  549. ast_channel_language_set(chan, endpoint->language);
  550. }
  551. if (!ast_strlen_zero(endpoint->musicclass)) {
  552. ast_channel_musicclass_set(chan, endpoint->musicclass);
  553. }
  554. ast_channel_context_set(chan, endpoint->context);
  555. if (ast_exists_extension(NULL, endpoint->context, endpoint->name, 1, NULL)) {
  556. ast_channel_exten_set(chan, endpoint->name);
  557. } else {
  558. ast_channel_exten_set(chan, "s");
  559. }
  560. ast_channel_priority_set(chan, 1);
  561. ao2_unlock(endpoint);
  562. return chan;
  563. }
  564. /*! \brief Internal helper function which sends a response */
  565. static void jingle_send_response(struct ast_xmpp_client *connection, ikspak *pak)
  566. {
  567. iks *response;
  568. if (!(response = iks_new("iq"))) {
  569. ast_log(LOG_ERROR, "Unable to allocate an IKS response stanza\n");
  570. return;
  571. }
  572. iks_insert_attrib(response, "type", "result");
  573. iks_insert_attrib(response, "from", connection->jid->full);
  574. iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from"));
  575. iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id"));
  576. ast_xmpp_client_send(connection, response);
  577. iks_delete(response);
  578. }
  579. /*! \brief Internal helper function which sends an error response */
  580. static void jingle_send_error_response(struct ast_xmpp_client *connection, ikspak *pak, const char *type, const char *reasonstr, const char *reasonstr2)
  581. {
  582. iks *response, *error = NULL, *reason = NULL, *reason2 = NULL;
  583. if (!(response = iks_new("iq")) ||
  584. !(error = iks_new("error")) ||
  585. !(reason = iks_new(reasonstr))) {
  586. ast_log(LOG_ERROR, "Unable to allocate IKS error response stanzas\n");
  587. goto end;
  588. }
  589. iks_insert_attrib(response, "type", "error");
  590. iks_insert_attrib(response, "from", connection->jid->full);
  591. iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from"));
  592. iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id"));
  593. iks_insert_attrib(error, "type", type);
  594. iks_insert_node(error, reason);
  595. if (!ast_strlen_zero(reasonstr2) && (reason2 = iks_new(reasonstr2))) {
  596. iks_insert_node(error, reason2);
  597. }
  598. iks_insert_node(response, error);
  599. ast_xmpp_client_send(connection, response);
  600. end:
  601. iks_delete(reason2);
  602. iks_delete(reason);
  603. iks_delete(error);
  604. iks_delete(response);
  605. }
  606. /*! \brief Internal helper function which adds ICE-UDP candidates to a transport node */
  607. static int jingle_add_ice_udp_candidates_to_transport(struct ast_rtp_instance *rtp, iks *transport, iks **candidates, unsigned int maximum)
  608. {
  609. struct ast_rtp_engine_ice *ice;
  610. struct ao2_container *local_candidates;
  611. struct ao2_iterator it;
  612. struct ast_rtp_engine_ice_candidate *candidate;
  613. int i = 0, res = 0;
  614. if (!(ice = ast_rtp_instance_get_ice(rtp)) || !(local_candidates = ice->get_local_candidates(rtp))) {
  615. ast_log(LOG_ERROR, "Unable to add ICE-UDP candidates as ICE support not available or no candidates available\n");
  616. return -1;
  617. }
  618. iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS);
  619. iks_insert_attrib(transport, "pwd", ice->get_password(rtp));
  620. iks_insert_attrib(transport, "ufrag", ice->get_ufrag(rtp));
  621. it = ao2_iterator_init(local_candidates, 0);
  622. while ((candidate = ao2_iterator_next(&it)) && (i < maximum)) {
  623. iks *local_candidate;
  624. char tmp[30];
  625. if (!(local_candidate = iks_new("candidate"))) {
  626. res = -1;
  627. ast_log(LOG_ERROR, "Unable to allocate IKS candidate stanza for ICE-UDP transport\n");
  628. break;
  629. }
  630. snprintf(tmp, sizeof(tmp), "%u", candidate->id);
  631. iks_insert_attrib(local_candidate, "component", tmp);
  632. snprintf(tmp, sizeof(tmp), "%d", ast_str_hash(candidate->foundation));
  633. iks_insert_attrib(local_candidate, "foundation", tmp);
  634. iks_insert_attrib(local_candidate, "generation", "0");
  635. iks_insert_attrib(local_candidate, "network", "0");
  636. snprintf(tmp, sizeof(tmp), "%04lx", (unsigned long)(ast_random() & 0xffff));
  637. iks_insert_attrib(local_candidate, "id", tmp);
  638. iks_insert_attrib(local_candidate, "ip", ast_sockaddr_stringify_host(&candidate->address));
  639. iks_insert_attrib(local_candidate, "port", ast_sockaddr_stringify_port(&candidate->address));
  640. snprintf(tmp, sizeof(tmp), "%d", candidate->priority);
  641. iks_insert_attrib(local_candidate, "priority", tmp);
  642. iks_insert_attrib(local_candidate, "protocol", "udp");
  643. if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_HOST) {
  644. iks_insert_attrib(local_candidate, "type", "host");
  645. } else if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_SRFLX) {
  646. iks_insert_attrib(local_candidate, "type", "srflx");
  647. } else if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_RELAYED) {
  648. iks_insert_attrib(local_candidate, "type", "relay");
  649. }
  650. iks_insert_node(transport, local_candidate);
  651. candidates[i++] = local_candidate;
  652. }
  653. ao2_iterator_destroy(&it);
  654. ao2_ref(local_candidates, -1);
  655. return res;
  656. }
  657. /*! \brief Internal helper function which adds Google candidates to a transport node */
  658. static int jingle_add_google_candidates_to_transport(struct ast_rtp_instance *rtp, iks *transport, iks **candidates, unsigned int video, enum jingle_transport transport_type, unsigned int maximum)
  659. {
  660. struct ast_rtp_engine_ice *ice;
  661. struct ao2_container *local_candidates;
  662. struct ao2_iterator it;
  663. struct ast_rtp_engine_ice_candidate *candidate;
  664. int i = 0, res = 0;
  665. if (!(ice = ast_rtp_instance_get_ice(rtp)) || !(local_candidates = ice->get_local_candidates(rtp))) {
  666. ast_log(LOG_ERROR, "Unable to add Google ICE candidates as ICE support not available or no candidates available\n");
  667. return -1;
  668. }
  669. if (transport_type != JINGLE_TRANSPORT_GOOGLE_V1) {
  670. iks_insert_attrib(transport, "xmlns", GOOGLE_TRANSPORT_NS);
  671. }
  672. it = ao2_iterator_init(local_candidates, 0);
  673. while ((candidate = ao2_iterator_next(&it)) && (i < maximum)) {
  674. iks *local_candidate;
  675. /* In Google land a username is 16 bytes, explicitly */
  676. char ufrag[17] = "";
  677. if (!(local_candidate = iks_new("candidate"))) {
  678. res = -1;
  679. ast_log(LOG_ERROR, "Unable to allocate IKS candidate stanza for Google ICE transport\n");
  680. break;
  681. }
  682. if (candidate->id == 1) {
  683. iks_insert_attrib(local_candidate, "name", !video ? "rtp" : "video_rtp");
  684. } else if (candidate->id == 2) {
  685. iks_insert_attrib(local_candidate, "name", !video ? "rtcp" : "video_rtcp");
  686. } else {
  687. iks_delete(local_candidate);
  688. continue;
  689. }
  690. iks_insert_attrib(local_candidate, "address", ast_sockaddr_stringify_host(&candidate->address));
  691. iks_insert_attrib(local_candidate, "port", ast_sockaddr_stringify_port(&candidate->address));
  692. if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_HOST) {
  693. iks_insert_attrib(local_candidate, "preference", "0.95");
  694. iks_insert_attrib(local_candidate, "type", "local");
  695. } else if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_SRFLX) {
  696. iks_insert_attrib(local_candidate, "preference", "0.9");
  697. iks_insert_attrib(local_candidate, "type", "stun");
  698. }
  699. iks_insert_attrib(local_candidate, "protocol", "udp");
  700. iks_insert_attrib(local_candidate, "network", "0");
  701. snprintf(ufrag, sizeof(ufrag), "%s", ice->get_ufrag(rtp));
  702. iks_insert_attrib(local_candidate, "username", ufrag);
  703. iks_insert_attrib(local_candidate, "generation", "0");
  704. if (transport_type == JINGLE_TRANSPORT_GOOGLE_V1) {
  705. iks_insert_attrib(local_candidate, "password", "");
  706. iks_insert_attrib(local_candidate, "foundation", "0");
  707. iks_insert_attrib(local_candidate, "component", "1");
  708. } else {
  709. iks_insert_attrib(local_candidate, "password", ice->get_password(rtp));
  710. }
  711. /* You may notice a lack of relay support up above - this is because we don't support it for use with
  712. * the Google talk transport due to their arcane support. */
  713. iks_insert_node(transport, local_candidate);
  714. candidates[i++] = local_candidate;
  715. }
  716. ao2_iterator_destroy(&it);
  717. ao2_ref(local_candidates, -1);
  718. return res;
  719. }
  720. /*! \brief Internal function which sends a session-terminate message */
  721. static void jingle_send_session_terminate(struct jingle_session *session, const char *reasontext)
  722. {
  723. iks *iq = NULL, *jingle = NULL, *reason = NULL, *text = NULL;
  724. if (!(iq = iks_new("iq")) || !(jingle = iks_new(session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "session" : "jingle")) ||
  725. !(reason = iks_new("reason")) || !(text = iks_new(reasontext))) {
  726. ast_log(LOG_ERROR, "Failed to allocate stanzas for session-terminate message on session '%s'\n", session->sid);
  727. goto end;
  728. }
  729. iks_insert_attrib(iq, "to", session->remote);
  730. iks_insert_attrib(iq, "type", "set");
  731. iks_insert_attrib(iq, "id", session->connection->mid);
  732. ast_xmpp_increment_mid(session->connection->mid);
  733. if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
  734. iks_insert_attrib(jingle, "type", "terminate");
  735. iks_insert_attrib(jingle, "id", session->sid);
  736. iks_insert_attrib(jingle, "xmlns", GOOGLE_SESSION_NS);
  737. iks_insert_attrib(jingle, "initiator", session->outgoing ? session->connection->jid->full : session->remote);
  738. } else {
  739. iks_insert_attrib(jingle, "action", "session-terminate");
  740. iks_insert_attrib(jingle, "sid", session->sid);
  741. iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
  742. }
  743. iks_insert_node(iq, jingle);
  744. iks_insert_node(jingle, reason);
  745. iks_insert_node(reason, text);
  746. ast_xmpp_client_send(session->connection, iq);
  747. end:
  748. iks_delete(text);
  749. iks_delete(reason);
  750. iks_delete(jingle);
  751. iks_delete(iq);
  752. }
  753. /*! \brief Internal function which sends a session-info message */
  754. static void jingle_send_session_info(struct jingle_session *session, const char *info)
  755. {
  756. iks *iq = NULL, *jingle = NULL, *text = NULL;
  757. /* Google-V1 has no way to send informational messages so don't even bother trying */
  758. if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
  759. return;
  760. }
  761. if (!(iq = iks_new("iq")) || !(jingle = iks_new("jingle")) || !(text = iks_new(info))) {
  762. ast_log(LOG_ERROR, "Failed to allocate stanzas for session-info message on session '%s'\n", session->sid);
  763. goto end;
  764. }
  765. iks_insert_attrib(iq, "to", session->remote);
  766. iks_insert_attrib(iq, "type", "set");
  767. iks_insert_attrib(iq, "id", session->connection->mid);
  768. ast_xmpp_increment_mid(session->connection->mid);
  769. iks_insert_attrib(jingle, "action", "session-info");
  770. iks_insert_attrib(jingle, "sid", session->sid);
  771. iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
  772. iks_insert_node(iq, jingle);
  773. iks_insert_node(jingle, text);
  774. ast_xmpp_client_send(session->connection, iq);
  775. end:
  776. iks_delete(text);
  777. iks_delete(jingle);
  778. iks_delete(iq);
  779. }
  780. /*! \internal
  781. *
  782. * \brief Locks both pvt and pvt owner if owner is present.
  783. *
  784. * \note This function gives a ref to pvt->owner if it is present and locked.
  785. * This reference must be decremented after pvt->owner is unlocked.
  786. *
  787. * \note This function will never give you up,
  788. * \note This function will never let you down.
  789. * \note This function will run around and desert you.
  790. *
  791. * \pre pvt is not locked
  792. * \post pvt is locked
  793. * \post pvt->owner is locked and its reference count is increased (if pvt->owner is not NULL)
  794. *
  795. * \returns a pointer to the locked and reffed pvt->owner channel if it exists.
  796. */
  797. static struct ast_channel *jingle_session_lock_full(struct jingle_session *pvt)
  798. {
  799. struct ast_channel *chan;
  800. /* Locking is simple when it is done right. If you see a deadlock resulting
  801. * in this function, it is not this function's fault, Your problem exists elsewhere.
  802. * This function is perfect... seriously. */
  803. for (;;) {
  804. /* First, get the channel and grab a reference to it */
  805. ao2_lock(pvt);
  806. chan = pvt->owner;
  807. if (chan) {
  808. /* The channel can not go away while we hold the pvt lock.
  809. * Give the channel a ref so it will not go away after we let
  810. * the pvt lock go. */
  811. ast_channel_ref(chan);
  812. } else {
  813. /* no channel, return pvt locked */
  814. return NULL;
  815. }
  816. /* We had to hold the pvt lock while getting a ref to the owner channel
  817. * but now we have to let this lock go in order to preserve proper
  818. * locking order when grabbing the channel lock */
  819. ao2_unlock(pvt);
  820. /* Look, no deadlock avoidance, hooray! */
  821. ast_channel_lock(chan);
  822. ao2_lock(pvt);
  823. if (pvt->owner == chan) {
  824. /* done */
  825. break;
  826. }
  827. /* If the owner changed while everything was unlocked, no problem,
  828. * just start over and everthing will work. This is rare, do not be
  829. * confused by this loop and think this it is an expensive operation.
  830. * The majority of the calls to this function will never involve multiple
  831. * executions of this loop. */
  832. ast_channel_unlock(chan);
  833. ast_channel_unref(chan);
  834. ao2_unlock(pvt);
  835. }
  836. /* If owner exists, it is locked and reffed */
  837. return pvt->owner;
  838. }
  839. /*! \brief Helper function which queues a hangup frame with cause code */
  840. static void jingle_queue_hangup_with_cause(struct jingle_session *session, int cause)
  841. {
  842. struct ast_channel *chan;
  843. if ((chan = jingle_session_lock_full(session))) {
  844. ast_debug(3, "Hanging up channel '%s' with cause '%d'\n", ast_channel_name(chan), cause);
  845. ast_queue_hangup_with_cause(chan, cause);
  846. ast_channel_unlock(chan);
  847. ast_channel_unref(chan);
  848. }
  849. ao2_unlock(session);
  850. }
  851. /*! \brief Internal function which sends a transport-info message */
  852. static void jingle_send_transport_info(struct jingle_session *session, const char *from)
  853. {
  854. iks *iq, *jingle = NULL, *audio = NULL, *audio_transport = NULL, *video = NULL, *video_transport = NULL;
  855. iks *audio_candidates[session->maxicecandidates], *video_candidates[session->maxicecandidates];
  856. int i, res = 0;
  857. if (!(iq = iks_new("iq")) ||
  858. !(jingle = iks_new(session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "session" : "jingle"))) {
  859. iks_delete(iq);
  860. jingle_queue_hangup_with_cause(session, AST_CAUSE_SWITCH_CONGESTION);
  861. ast_log(LOG_ERROR, "Failed to allocate stanzas for transport-info message, hanging up session '%s'\n", session->sid);
  862. return;
  863. }
  864. memset(audio_candidates, 0, sizeof(audio_candidates));
  865. memset(video_candidates, 0, sizeof(video_candidates));
  866. iks_insert_attrib(iq, "from", session->connection->jid->full);
  867. iks_insert_attrib(iq, "to", from);
  868. iks_insert_attrib(iq, "type", "set");
  869. iks_insert_attrib(iq, "id", session->connection->mid);
  870. ast_xmpp_increment_mid(session->connection->mid);
  871. if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
  872. iks_insert_attrib(jingle, "type", "candidates");
  873. iks_insert_attrib(jingle, "id", session->sid);
  874. iks_insert_attrib(jingle, "xmlns", GOOGLE_SESSION_NS);
  875. iks_insert_attrib(jingle, "initiator", session->outgoing ? session->connection->jid->full : from);
  876. } else {
  877. iks_insert_attrib(jingle, "action", "transport-info");
  878. iks_insert_attrib(jingle, "sid", session->sid);
  879. iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
  880. }
  881. iks_insert_node(iq, jingle);
  882. if (session->rtp) {
  883. if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
  884. /* V1 protocol has the candidates directly in the session */
  885. res = jingle_add_google_candidates_to_transport(session->rtp, jingle, audio_candidates, 0, session->transport, session->maxicecandidates);
  886. } else if ((audio = iks_new("content")) && (audio_transport = iks_new("transport"))) {
  887. iks_insert_attrib(audio, "creator", session->outgoing ? "initiator" : "responder");
  888. iks_insert_attrib(audio, "name", session->audio_name);
  889. iks_insert_node(jingle, audio);
  890. iks_insert_node(audio, audio_transport);
  891. if (session->transport == JINGLE_TRANSPORT_ICE_UDP) {
  892. res = jingle_add_ice_udp_candidates_to_transport(session->rtp, audio_transport, audio_candidates, session->maxicecandidates);
  893. } else if (session->transport == JINGLE_TRANSPORT_GOOGLE_V2) {
  894. res = jingle_add_google_candidates_to_transport(session->rtp, audio_transport, audio_candidates, 0, session->transport,
  895. session->maxicecandidates);
  896. }
  897. } else {
  898. res = -1;
  899. }
  900. }
  901. if ((session->transport != JINGLE_TRANSPORT_GOOGLE_V1) && !res && session->vrtp) {
  902. if ((video = iks_new("content")) && (video_transport = iks_new("transport"))) {
  903. iks_insert_attrib(video, "creator", session->outgoing ? "initiator" : "responder");
  904. iks_insert_attrib(video, "name", session->video_name);
  905. iks_insert_node(jingle, video);
  906. iks_insert_node(video, video_transport);
  907. if (session->transport == JINGLE_TRANSPORT_ICE_UDP) {
  908. res = jingle_add_ice_udp_candidates_to_transport(session->vrtp, video_transport, video_candidates, session->maxicecandidates);
  909. } else if (session->transport == JINGLE_TRANSPORT_GOOGLE_V2) {
  910. res = jingle_add_google_candidates_to_transport(session->vrtp, video_transport, video_candidates, 1, session->transport,
  911. session->maxicecandidates);
  912. }
  913. } else {
  914. res = -1;
  915. }
  916. }
  917. if (!res) {
  918. ast_xmpp_client_send(session->connection, iq);
  919. } else {
  920. jingle_queue_hangup_with_cause(session, AST_CAUSE_SWITCH_CONGESTION);
  921. }
  922. /* Clean up after ourselves */
  923. for (i = 0; i < session->maxicecandidates; i++) {
  924. iks_delete(video_candidates[i]);
  925. iks_delete(audio_candidates[i]);
  926. }
  927. iks_delete(video_transport);
  928. iks_delete(video);
  929. iks_delete(audio_transport);
  930. iks_delete(audio);
  931. iks_delete(jingle);
  932. iks_delete(iq);
  933. }
  934. /*! \brief Internal helper function which adds payloads to a description */
  935. static int jingle_add_payloads_to_description(struct jingle_session *session, struct ast_rtp_instance *rtp, iks *description, iks **payloads, enum ast_format_type type)
  936. {
  937. struct ast_format format;
  938. int x = 0, i = 0, res = 0;
  939. for (x = 0; (x < AST_CODEC_PREF_SIZE) && (i < (session->maxpayloads - 2)); x++) {
  940. int rtp_code;
  941. iks *payload;
  942. char tmp[32];
  943. if (!ast_codec_pref_index(&session->prefs, x, &format)) {
  944. break;
  945. }
  946. if (AST_FORMAT_GET_TYPE(format.id) != type) {
  947. continue;
  948. }
  949. if (!ast_format_cap_iscompatible(session->jointcap, &format)) {
  950. continue;
  951. }
  952. if (((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(rtp), 1, &format, 0)) == -1) ||
  953. (!(payload = iks_new("payload-type")))) {
  954. return -1;
  955. }
  956. if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
  957. iks_insert_attrib(payload, "xmlns", GOOGLE_PHONE_NS);
  958. }
  959. snprintf(tmp, sizeof(tmp), "%d", rtp_code);
  960. iks_insert_attrib(payload, "id", tmp);
  961. iks_insert_attrib(payload, "name", ast_rtp_lookup_mime_subtype2(1, &format, 0, 0));
  962. iks_insert_attrib(payload, "channels", "1");
  963. if ((format.id == AST_FORMAT_G722) && ((session->transport == JINGLE_TRANSPORT_GOOGLE_V1) || (session->transport == JINGLE_TRANSPORT_GOOGLE_V2))) {
  964. iks_insert_attrib(payload, "clockrate", "16000");
  965. } else {
  966. snprintf(tmp, sizeof(tmp), "%u", ast_rtp_lookup_sample_rate2(1, &format, 0));
  967. iks_insert_attrib(payload, "clockrate", tmp);
  968. }
  969. if ((type == AST_FORMAT_TYPE_VIDEO) && (session->transport == JINGLE_TRANSPORT_GOOGLE_V2)) {
  970. iks *parameter;
  971. /* Google requires these parameters to be set, but alas we can not give accurate values so use some safe defaults */
  972. if ((parameter = iks_new("parameter"))) {
  973. iks_insert_attrib(parameter, "name", "width");
  974. iks_insert_attrib(parameter, "value", "640");
  975. iks_insert_node(payload, parameter);
  976. }
  977. if ((parameter = iks_new("parameter"))) {
  978. iks_insert_attrib(parameter, "name", "height");
  979. iks_insert_attrib(parameter, "value", "480");
  980. iks_insert_node(payload, parameter);
  981. }
  982. if ((parameter = iks_new("parameter"))) {
  983. iks_insert_attrib(parameter, "name", "framerate");
  984. iks_insert_attrib(parameter, "value", "30");
  985. iks_insert_node(payload, parameter);
  986. }
  987. }
  988. iks_insert_node(description, payload);
  989. payloads[i++] = payload;
  990. }
  991. /* If this is for audio and there is room for RFC2833 add it in */
  992. if ((type == AST_FORMAT_TYPE_AUDIO) && (i < session->maxpayloads)) {
  993. iks *payload;
  994. if ((payload = iks_new("payload-type"))) {
  995. if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
  996. iks_insert_attrib(payload, "xmlns", GOOGLE_PHONE_NS);
  997. }
  998. iks_insert_attrib(payload, "id", "101");
  999. iks_insert_attrib(payload, "name", "telephone-event");
  1000. iks_insert_attrib(payload, "channels", "1");
  1001. iks_insert_attrib(payload, "clockrate", "8000");
  1002. iks_insert_node(description, payload);
  1003. payloads[i++] = payload;
  1004. }
  1005. }
  1006. return res;
  1007. }
  1008. /*! \brief Helper function which adds content to a description */
  1009. static int jingle_add_content(struct jingle_session *session, iks *jingle, iks *content, iks *description, iks *transport,
  1010. const char *name, enum ast_format_type type, struct ast_rtp_instance *rtp, iks **payloads)
  1011. {
  1012. int res = 0;
  1013. if (session->transport != JINGLE_TRANSPORT_GOOGLE_V1) {
  1014. iks_insert_attrib(content, "creator", session->outgoing ? "initiator" : "responder");
  1015. iks_insert_attrib(content, "name", name);
  1016. iks_insert_node(jingle, content);
  1017. iks_insert_attrib(description, "xmlns", JINGLE_RTP_NS);
  1018. if (type == AST_FORMAT_TYPE_AUDIO) {
  1019. iks_insert_attrib(description, "media", "audio");
  1020. } else if (type == AST_FORMAT_TYPE_VIDEO) {
  1021. iks_insert_attrib(description, "media", "video");
  1022. } else {
  1023. return -1;
  1024. }
  1025. iks_insert_node(content, description);
  1026. } else {
  1027. iks_insert_attrib(description, "xmlns", GOOGLE_PHONE_NS);
  1028. iks_insert_node(jingle, description);
  1029. }
  1030. if (!(res = jingle_add_payloads_to_description(session, rtp, description, payloads, type))) {
  1031. if (session->transport == JINGLE_TRANSPORT_ICE_UDP) {
  1032. iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS);
  1033. iks_insert_node(content, transport);
  1034. } else if (session->transport == JINGLE_TRANSPORT_GOOGLE_V2) {
  1035. iks_insert_attrib(transport, "xmlns", GOOGLE_TRANSPORT_NS);
  1036. iks_insert_node(content, transport);
  1037. }
  1038. }
  1039. return res;
  1040. }
  1041. /*! \brief Internal function which sends a complete session message */
  1042. static void jingle_send_session_action(struct jingle_session *session, const char *action)
  1043. {
  1044. iks *iq, *jingle, *audio = NULL, *audio_description = NULL, *video = NULL, *video_description = NULL;
  1045. iks *audio_payloads[session->maxpayloads], *video_payloads[session->maxpayloads];
  1046. iks *audio_transport = NULL, *video_transport = NULL;
  1047. int i, res = 0;
  1048. if (!(iq = iks_new("iq")) ||
  1049. !(jingle = iks_new(session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "session" : "jingle"))) {
  1050. jingle_queue_hangup_with_cause(session, AST_CAUSE_SWITCH_CONGESTION);
  1051. iks_delete(iq);
  1052. return;
  1053. }
  1054. memset(audio_payloads, 0, sizeof(audio_payloads));
  1055. memset(video_payloads, 0, sizeof(video_payloads));
  1056. iks_insert_attrib(iq, "from", session->connection->jid->full);
  1057. iks_insert_attrib(iq, "to", session->remote);
  1058. iks_insert_attrib(iq, "type", "set");
  1059. iks_insert_attrib(iq, "id", session->connection->mid);
  1060. ast_xmpp_increment_mid(session->connection->mid);
  1061. if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
  1062. iks_insert_attrib(jingle, "type", action);
  1063. iks_insert_attrib(jingle, "id", session->sid);
  1064. iks_insert_attrib(jingle, "xmlns", GOOGLE_SESSION_NS);
  1065. } else {
  1066. iks_insert_attrib(jingle, "action", action);
  1067. iks_insert_attrib(jingle, "sid", session->sid);
  1068. iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
  1069. }
  1070. if (!strcasecmp(action, "session-initiate") || !strcasecmp(action, "initiate") || !strcasecmp(action, "accept")) {
  1071. iks_insert_attrib(jingle, "initiator", session->outgoing ? session->connection->jid->full : session->remote);
  1072. }
  1073. iks_insert_node(iq, jingle);
  1074. if (session->rtp && (audio = iks_new("content")) && (audio_description = iks_new("description")) &&
  1075. (audio_transport = iks_new("transport"))) {
  1076. res = jingle_add_content(session, jingle, audio, audio_description, audio_transport, session->audio_name,
  1077. AST_FORMAT_TYPE_AUDIO, session->rtp, audio_payloads);
  1078. } else {
  1079. ast_log(LOG_ERROR, "Failed to allocate audio content stanzas for session '%s', hanging up\n", session->sid);
  1080. res = -1;
  1081. }
  1082. if ((session->transport != JINGLE_TRANSPORT_GOOGLE_V1) && !res && session->vrtp) {
  1083. if ((video = iks_new("content")) && (video_description = iks_new("description")) &&
  1084. (video_transport = iks_new("transport"))) {
  1085. res = jingle_add_content(session, jingle, video, video_description, video_transport, session->video_name,
  1086. AST_FORMAT_TYPE_VIDEO, session->vrtp, video_payloads);
  1087. } else {
  1088. ast_log(LOG_ERROR, "Failed to allocate video content stanzas for session '%s', hanging up\n", session->sid);
  1089. res = -1;
  1090. }
  1091. }
  1092. if (!res) {
  1093. ast_xmpp_client_send(session->connection, iq);
  1094. } else {
  1095. jingle_queue_hangup_with_cause(session, AST_CAUSE_SWITCH_CONGESTION);
  1096. }
  1097. iks_delete(video_transport);
  1098. iks_delete(audio_transport);
  1099. for (i = 0; i < session->maxpayloads; i++) {
  1100. iks_delete(video_payloads[i]);
  1101. iks_delete(audio_payloads[i]);
  1102. }
  1103. iks_delete(video_description);
  1104. iks_delete(video);
  1105. iks_delete(audio_description);
  1106. iks_delete(audio);
  1107. iks_delete(jingle);
  1108. iks_delete(iq);
  1109. }
  1110. /*! \brief Internal function which sends a session-inititate message */
  1111. static void jingle_send_session_initiate(struct jingle_session *session)
  1112. {
  1113. jingle_send_session_action(session, session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "initiate" : "session-initiate");
  1114. }
  1115. /*! \brief Internal function which sends a session-accept message */
  1116. static void jingle_send_session_accept(struct jingle_session *session)
  1117. {
  1118. jingle_send_session_action(session, session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "accept" : "session-accept");
  1119. }
  1120. /*! \brief Callback for when a response is received for an outgoing session-initiate message */
  1121. static int jingle_outgoing_hook(void *data, ikspak *pak)
  1122. {
  1123. struct jingle_session *session = data;
  1124. iks *error = iks_find(pak->x, "error"), *redirect;
  1125. /* In all cases this hook is done with */
  1126. iks_filter_remove_rule(session->connection->filter, session->rule);
  1127. session->rule = NULL;
  1128. ast_callid_threadassoc_add(session->callid);
  1129. /* If no error occurred they accepted our session-initiate message happily */
  1130. if (!error) {
  1131. struct ast_channel *chan;
  1132. if ((chan = jingle_session_lock_full(session))) {
  1133. ast_queue_control(chan, AST_CONTROL_PROCEEDING);
  1134. ast_channel_unlock(chan);
  1135. ast_channel_unref(chan);
  1136. }
  1137. ao2_unlock(session);
  1138. jingle_send_transport_info(session, iks_find_attrib(pak->x, "from"));
  1139. goto end;
  1140. }
  1141. /* Assume that because this is an error the session is gone, there is only one case where this is incorrect - a redirect */
  1142. session->gone = 1;
  1143. /* Map the error we received to an appropriate cause code and hang up the channel */
  1144. if ((redirect = iks_find_with_attrib(error, "redirect", "xmlns", XMPP_STANZAS_NS))) {
  1145. iks *to = iks_child(redirect);
  1146. char *target;
  1147. if (to && (target = iks_name(to)) && !ast_strlen_zero(target)) {
  1148. /* Make the xmpp: go away if it is present */
  1149. if (!strncmp(target, "xmpp:", 5)) {
  1150. target += 5;
  1151. }
  1152. /* This is actually a fairly simple operation - we update the remote and send another session-initiate */
  1153. ast_copy_string(session->remote, target, sizeof(session->remote));
  1154. /* Add a new hook so we can get the status of redirected session */
  1155. session->rule = iks_filter_add_rule(session->connection->filter, jingle_outgoing_hook, session,
  1156. IKS_RULE_ID, session->connection->mid, IKS_RULE_DONE);
  1157. jingle_send_session_initiate(session);
  1158. session->gone = 0;
  1159. } else {
  1160. jingle_queue_hangup_with_cause(session, AST_CAUSE_PROTOCOL_ERROR);
  1161. }
  1162. } else if (iks_find_with_attrib(error, "service-unavailable", "xmlns", XMPP_STANZAS_NS)) {
  1163. jingle_queue_hangup_with_cause(session, AST_CAUSE_CONGESTION);
  1164. } else if (iks_find_with_attrib(error, "resource-constraint", "xmlns", XMPP_STANZAS_NS)) {
  1165. jingle_queue_hangup_with_cause(session, AST_CAUSE_REQUESTED_CHAN_UNAVAIL);
  1166. } else if (iks_find_with_attrib(error, "bad-request", "xmlns", XMPP_STANZAS_NS)) {
  1167. jingle_queue_hangup_with_cause(session, AST_CAUSE_PROTOCOL_ERROR);
  1168. } else if (iks_find_with_attrib(error, "remote-server-not-found", "xmlns", XMPP_STANZAS_NS)) {
  1169. jingle_queue_hangup_with_cause(session, AST_CAUSE_NO_ROUTE_DESTINATION);
  1170. } else if (iks_find_with_attrib(error, "feature-not-implemented", "xmlns", XMPP_STANZAS_NS)) {
  1171. /* Assume that this occurred because the remote side does not support our transport, so drop it down one and try again */
  1172. session->transport--;
  1173. /* If we still have a viable transport mechanism re-send the session-initiate */
  1174. if (session->transport != JINGLE_TRANSPORT_NONE) {
  1175. struct ast_rtp_engine_ice *ice;
  1176. if (((session->transport == JINGLE_TRANSPORT_GOOGLE_V2) ||
  1177. (session->transport == JINGLE_TRANSPORT_GOOGLE_V1)) &&
  1178. (ice = ast_rtp_instance_get_ice(session->rtp))) {
  1179. /* We stop built in ICE support because we need to fall back to old old old STUN support */
  1180. ice->stop(session->rtp);
  1181. }
  1182. /* Re-send the message to the *original* target and not a redirected one */
  1183. ast_copy_string(session->remote, session->remote_original, sizeof(session->remote));
  1184. session->rule = iks_filter_add_rule(session->connection->filter, jingle_outgoing_hook, session,
  1185. IKS_RULE_ID, session->connection->mid, IKS_RULE_DONE);
  1186. jingle_send_session_initiate(session);
  1187. session->gone = 0;
  1188. } else {
  1189. /* Otherwise we have exhausted all transports */
  1190. jingle_queue_hangup_with_cause(session, AST_CAUSE_FACILITY_NOT_IMPLEMENTED);
  1191. }
  1192. } else {
  1193. jingle_queue_hangup_with_cause(session, AST_CAUSE_PROTOCOL_ERROR);
  1194. }
  1195. end:
  1196. ast_callid_threadassoc_remove();
  1197. return IKS_FILTER_EAT;
  1198. }
  1199. /*! \brief Function called by core when we should answer a Jingle session */
  1200. static int jingle_answer(struct ast_channel *ast)
  1201. {
  1202. struct jingle_session *session = ast_channel_tech_pvt(ast);
  1203. /* The channel has already been answered so we don't need to do anything */
  1204. if (ast_channel_state(ast) == AST_STATE_UP) {
  1205. return 0;
  1206. }
  1207. jingle_send_session_accept(session);
  1208. return 0;
  1209. }
  1210. /*! \brief Function called by core to read any waiting frames */
  1211. static struct ast_frame *jingle_read(struct ast_channel *ast)
  1212. {
  1213. struct jingle_session *session = ast_channel_tech_pvt(ast);
  1214. struct ast_frame *frame = &ast_null_frame;
  1215. switch (ast_channel_fdno(ast)) {
  1216. case 0:
  1217. if (session->rtp) {
  1218. frame = ast_rtp_instance_read(session->rtp, 0);
  1219. }
  1220. break;
  1221. case 1:
  1222. if (session->rtp) {
  1223. frame = ast_rtp_instance_read(session->rtp, 1);
  1224. }
  1225. break;
  1226. case 2:
  1227. if (session->vrtp) {
  1228. frame = ast_rtp_instance_read(session->vrtp, 0);
  1229. }
  1230. break;
  1231. case 3:
  1232. if (session->vrtp) {
  1233. frame = ast_rtp_instance_read(session->vrtp, 1);
  1234. }
  1235. break;
  1236. default:
  1237. break;
  1238. }
  1239. if (frame && frame->frametype == AST_FRAME_VOICE &&
  1240. !ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format)) {
  1241. if (!ast_format_cap_iscompatible(session->jointcap, &frame->subclass.format)) {
  1242. ast_debug(1, "Bogus frame of format '%s' received from '%s'!\n",
  1243. ast_getformatname(&frame->subclass.format), ast_channel_name(ast));
  1244. ast_frfree(frame);
  1245. frame = &ast_null_frame;
  1246. } else {
  1247. ast_debug(1, "Oooh, format changed to %s\n",
  1248. ast_getformatname(&frame->subclass.format));
  1249. ast_format_cap_remove_bytype(ast_channel_nativeformats(ast), AST_FORMAT_TYPE_AUDIO);
  1250. ast_format_cap_add(ast_channel_nativeformats(ast), &frame->subclass.format);
  1251. ast_set_read_format(ast, ast_channel_readformat(ast));
  1252. ast_set_write_format(ast, ast_channel_writeformat(ast));
  1253. }
  1254. }
  1255. return frame;
  1256. }
  1257. /*! \brief Function called by core to write frames */
  1258. static int jingle_write(struct ast_channel *ast, struct ast_frame *frame)
  1259. {
  1260. struct jingle_session *session = ast_channel_tech_pvt(ast);
  1261. int res = 0;
  1262. char buf[256];
  1263. switch (frame->frametype) {
  1264. case AST_FRAME_VOICE:
  1265. if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) {
  1266. ast_log(LOG_WARNING,
  1267. "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
  1268. ast_getformatname(&frame->subclass.format),
  1269. ast_getformatname_multiple(buf, sizeof(buf), ast_channel_nativeformats(ast)),
  1270. ast_getformatname(ast_channel_readformat(ast)),
  1271. ast_getformatname(ast_channel_writeformat(ast)));
  1272. return 0;
  1273. }
  1274. if (session && session->rtp) {
  1275. res = ast_rtp_instance_write(session->rtp, frame);
  1276. }
  1277. break;
  1278. case AST_FRAME_VIDEO:
  1279. if (session && session->vrtp) {
  1280. res = ast_rtp_instance_write(session->vrtp, frame);
  1281. }
  1282. break;
  1283. default:
  1284. ast_log(LOG_WARNING, "Can't send %u type frames with Jingle write\n",
  1285. frame->frametype);
  1286. return 0;
  1287. }
  1288. return res;
  1289. }
  1290. /*! \brief Function called by core to change the underlying owner channel */
  1291. static int jingle_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
  1292. {
  1293. struct jingle_session *session = ast_channel_tech_pvt(newchan);
  1294. ao2_lock(session);
  1295. session->owner = newchan;
  1296. ao2_unlock(session);
  1297. return 0;
  1298. }
  1299. /*! \brief Function called by core to ask the channel to indicate some sort of condition */
  1300. static int jingle_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
  1301. {
  1302. struct jingle_session *session = ast_channel_tech_pvt(ast);
  1303. int res = 0;
  1304. switch (condition) {
  1305. case AST_CONTROL_RINGING:
  1306. if (ast_channel_state(ast) == AST_STATE_RING) {
  1307. jingle_send_session_info(session, "ringing xmlns='urn:xmpp:jingle:apps:rtp:info:1'");
  1308. } else {
  1309. res = -1;
  1310. }
  1311. break;
  1312. case AST_CONTROL_BUSY:
  1313. if (ast_channel_state(ast) != AST_STATE_UP) {
  1314. ast_channel_hangupcause_set(ast, AST_CAUSE_BUSY);
  1315. ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
  1316. } else {
  1317. res = -1;
  1318. }
  1319. break;
  1320. case AST_CONTROL_CONGESTION:
  1321. if (ast_channel_state(ast) != AST_STATE_UP) {
  1322. ast_channel_hangupcause_set(ast, AST_CAUSE_CONGESTION);
  1323. ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
  1324. } else {
  1325. res = -1;
  1326. }
  1327. break;
  1328. case AST_CONTROL_INCOMPLETE:
  1329. if (ast_channel_state(ast) != AST_STATE_UP) {
  1330. ast_channel_hangupcause_set(ast, AST_CAUSE_CONGESTION);
  1331. ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
  1332. }
  1333. break;
  1334. case AST_CONTROL_HOLD:
  1335. ast_moh_start(ast, data, NULL);
  1336. break;
  1337. case AST_CONTROL_UNHOLD:
  1338. ast_moh_stop(ast);
  1339. break;
  1340. case AST_CONTROL_SRCUPDATE:
  1341. if (session->rtp) {
  1342. ast_rtp_instance_update_source(session->rtp);
  1343. }
  1344. break;
  1345. case AST_CONTROL_SRCCHANGE:
  1346. if (session->rtp) {
  1347. ast_rtp_instance_change_source(session->rtp);
  1348. }
  1349. break;
  1350. case AST_CONTROL_VIDUPDATE:
  1351. case AST_CONTROL_UPDATE_RTP_PEER:
  1352. case AST_CONTROL_CONNECTED_LINE:
  1353. break;
  1354. case AST_CONTROL_PVT_CAUSE_CODE:
  1355. case -1:
  1356. res = -1;
  1357. break;
  1358. default:
  1359. ast_log(LOG_NOTICE, "Don't know how to indicate condition '%d'\n", condition);
  1360. res = -1;
  1361. }
  1362. return res;
  1363. }
  1364. /*! \brief Function called by core to send text to the remote party of the Jingle session */
  1365. static int jingle_sendtext(struct ast_channel *chan, const char *text)
  1366. {
  1367. struct jingle_session *session = ast_channel_tech_pvt(chan);
  1368. return ast_xmpp_client_send_message(session->connection, session->remote, text);
  1369. }
  1370. /*! \brief Function called by core to start a DTMF digit */
  1371. static int jingle_digit_begin(struct ast_channel *chan, char digit)
  1372. {
  1373. struct jingle_session *session = ast_channel_tech_pvt(chan);
  1374. if (session->rtp) {
  1375. ast_rtp_instance_dtmf_begin(session->rtp, digit);
  1376. }
  1377. return 0;
  1378. }
  1379. /*! \brief Function called by core to stop a DTMF digit */
  1380. static int jingle_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
  1381. {
  1382. struct jingle_session *session = ast_channel_tech_pvt(ast);
  1383. if (session->rtp) {
  1384. ast_rtp_instance_dtmf_end_with_duration(session->rtp, digit, duration);
  1385. }
  1386. return 0;
  1387. }
  1388. /*! \brief Function called by core to actually start calling a remote party */
  1389. static int jingle_call(struct ast_channel *ast, const char *dest, int timeout)
  1390. {
  1391. struct jingle_session *session = ast_channel_tech_pvt(ast);
  1392. ast_setstate(ast, AST_STATE_RING);
  1393. /* Since we have no idea of the remote capabilities use ours for now */
  1394. ast_format_cap_copy(session->jointcap, session->cap);
  1395. /* We set up a hook so we can know when our session-initiate message was accepted or rejected */
  1396. session->rule = iks_filter_add_rule(session->connection->filter, jingle_outgoing_hook, session,
  1397. IKS_RULE_ID, session->connection->mid, IKS_RULE_DONE);
  1398. jingle_send_session_initiate(session);
  1399. return 0;
  1400. }
  1401. /*! \brief Function called by core to hang up a Jingle session */
  1402. static int jingle_hangup(struct ast_channel *ast)
  1403. {
  1404. struct jingle_session *session = ast_channel_tech_pvt(ast);
  1405. ao2_lock(session);
  1406. if ((ast_channel_state(ast) != AST_STATE_DOWN) && !session->gone) {
  1407. int cause = (session->owner ? ast_channel_hangupcause(session->owner) : AST_CAUSE_CONGESTION);
  1408. const char *reason = "success";
  1409. int i;
  1410. /* Get the appropriate reason and send a session-terminate */
  1411. for (i = 0; i < ARRAY_LEN(jingle_reason_mappings); i++) {
  1412. if (jingle_reason_mappings[i].cause == cause) {
  1413. reason = jingle_reason_mappings[i].reason;
  1414. break;
  1415. }
  1416. }
  1417. jingle_send_session_terminate(session, reason);
  1418. }
  1419. ast_channel_tech_pvt_set(ast, NULL);
  1420. session->owner = NULL;
  1421. ao2_unlink(session->state->sessions, session);
  1422. ao2_ref(session->state, -1);
  1423. ao2_unlock(session);
  1424. ao2_ref(session, -1);
  1425. return 0;
  1426. }
  1427. /*! \brief Function called by core to create a new outgoing Jingle session */
  1428. static struct ast_channel *jingle_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
  1429. {
  1430. RAII_VAR(struct jingle_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
  1431. RAII_VAR(struct jingle_endpoint *, endpoint, NULL, ao2_cleanup);
  1432. char *dialed, target[200] = "";
  1433. struct ast_xmpp_buddy *buddy;
  1434. struct jingle_session *session;
  1435. struct ast_channel *chan;
  1436. enum jingle_transport transport = JINGLE_TRANSPORT_NONE;
  1437. struct ast_rtp_engine_ice *ice;
  1438. AST_DECLARE_APP_ARGS(args,
  1439. AST_APP_ARG(name);
  1440. AST_APP_ARG(target);
  1441. );
  1442. /* We require at a minimum one audio format to be requested */
  1443. if (!ast_format_cap_has_type(cap, AST_FORMAT_TYPE_AUDIO)) {
  1444. ast_log(LOG_ERROR, "Motif channel driver requires an audio format when dialing a destination\n");
  1445. *cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
  1446. return NULL;
  1447. }
  1448. if (ast_strlen_zero(data) || !(dialed = ast_strdupa(data))) {
  1449. ast_log(LOG_ERROR, "Unable to create channel with empty destination.\n");
  1450. *cause = AST_CAUSE_CHANNEL_UNACCEPTABLE;
  1451. return NULL;
  1452. }
  1453. /* Parse the given dial string and validate the results */
  1454. AST_NONSTANDARD_APP_ARGS(args, dialed, '/');
  1455. if (ast_strlen_zero(args.name) || ast_strlen_zero(args.target)) {
  1456. ast_log(LOG_ERROR, "Unable to determine endpoint name and target.\n");
  1457. *cause = AST_CAUSE_CHANNEL_UNACCEPTABLE;
  1458. return NULL;
  1459. }
  1460. if (!(endpoint = jingle_endpoint_find(cfg->endpoints, args.name))) {
  1461. ast_log(LOG_ERROR, "Endpoint '%s' does not exist.\n", args.name);
  1462. *cause = AST_CAUSE_CHANNEL_UNACCEPTABLE;
  1463. return NULL;
  1464. }
  1465. ao2_lock(endpoint->state);
  1466. /* If we don't have a connection for the endpoint we can't exactly start a session on it */
  1467. if (!endpoint->connection) {
  1468. ast_log(LOG_ERROR, "Unable to create Jingle session on endpoint '%s' as no valid connection exists\n", args.name);
  1469. *cause = AST_CAUSE_SWITCH_CONGESTION;
  1470. ao2_unlock(endpoint->state);
  1471. return NULL;
  1472. }
  1473. /* Find the target in the roster so we can choose a resource */
  1474. if ((buddy = ao2_find(endpoint->connection->buddies, args.target, OBJ_KEY))) {
  1475. struct ao2_iterator res;
  1476. struct ast_xmpp_resource *resource;
  1477. /* Iterate through finding the first viable Jingle capable resource */
  1478. res = ao2_iterator_init(buddy->resources, 0);
  1479. while ((resource = ao2_iterator_next(&res))) {
  1480. if (resource->caps.jingle) {
  1481. snprintf(target, sizeof(target), "%s/%s", args.target, resource->resource);
  1482. transport = JINGLE_TRANSPORT_ICE_UDP;
  1483. break;
  1484. } else if (resource->caps.google) {
  1485. snprintf(target, sizeof(target), "%s/%s", args.target, resource->resource);
  1486. transport = JINGLE_TRANSPORT_GOOGLE_V2;
  1487. break;
  1488. }
  1489. ao2_ref(resource, -1);
  1490. }
  1491. ao2_iterator_destroy(&res);
  1492. ao2_ref(buddy, -1);
  1493. } else {
  1494. /* If the target is NOT in the roster use the provided target as-is */
  1495. ast_copy_string(target, args.target, sizeof(target));
  1496. }
  1497. ao2_unlock(endpoint->state);
  1498. /* If no target was found we can't set up a session */
  1499. if (ast_strlen_zero(target)) {
  1500. ast_log(LOG_ERROR, "Unable to create Jingle session on endpoint '%s' as no capable resource for target '%s' was found\n", args.name, args.target);
  1501. *cause = AST_CAUSE_SWITCH_CONGESTION;
  1502. return NULL;
  1503. }
  1504. if (!(session = jingle_alloc(endpoint, target, NULL))) {
  1505. ast_log(LOG_ERROR, "Unable to create Jingle session on endpoint '%s'\n", args.name);
  1506. *cause = AST_CAUSE_SWITCH_CONGESTION;
  1507. return NULL;
  1508. }
  1509. /* Update the transport if we learned what we should actually use */
  1510. if (transport != JINGLE_TRANSPORT_NONE) {
  1511. session->transport = transport;
  1512. /* Note that for Google-V1 and Google-V2 we don't stop built-in ICE support, this will happen in jingle_new */
  1513. }
  1514. if (!(chan = jingle_new(endpoint, session, AST_STATE_DOWN, target, requestor ? ast_channel_linkedid(requestor) : NULL, NULL))) {
  1515. ast_log(LOG_ERROR, "Unable to create Jingle channel on endpoint '%s'\n", args.name);
  1516. *cause = AST_CAUSE_SWITCH_CONGESTION;
  1517. ao2_ref(session, -1);
  1518. return NULL;
  1519. }
  1520. /* If video was requested try to enable it on the session */
  1521. if (ast_format_cap_has_type(cap, AST_FORMAT_TYPE_VIDEO)) {
  1522. jingle_enable_video(session);
  1523. }
  1524. /* As this is outgoing set ourselves as controlling */
  1525. if (session->rtp && (ice = ast_rtp_instance_get_ice(session->rtp))) {
  1526. ice->ice_lite(session->rtp);
  1527. }
  1528. if (session->vrtp && (ice = ast_rtp_instance_get_ice(session->vrtp))) {
  1529. ice->ice_lite(session->vrtp);
  1530. }
  1531. /* We purposely don't decrement the session here as there is a reference on the channel */
  1532. ao2_link(endpoint->state->sessions, session);
  1533. return chan;
  1534. }
  1535. /*! \brief Helper function which handles content descriptions */
  1536. static int jingle_interpret_description(struct jingle_session *session, iks *description, const char *name, struct ast_rtp_instance **rtp)
  1537. {
  1538. char *media = iks_find_attrib(description, "media");
  1539. struct ast_rtp_codecs codecs;
  1540. iks *codec;
  1541. int othercapability = 0;
  1542. /* Google-V1 is always carrying audio, but just doesn't tell us so */
  1543. if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
  1544. media = "audio";
  1545. } else if (ast_strlen_zero(media)) {
  1546. jingle_queue_hangup_with_cause(session, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
  1547. ast_log(LOG_ERROR, "Received a content description on session '%s' without a name\n", session->sid);
  1548. return -1;
  1549. }
  1550. /* Determine the type of media that is being carried and update the RTP instance, as well as the name */
  1551. if (!strcasecmp(media, "audio")) {
  1552. if (!ast_strlen_zero(name)) {
  1553. ast_string_field_set(session, audio_name, name);
  1554. }
  1555. *rtp = session->rtp;
  1556. ast_format_cap_remove_bytype(session->peercap, AST_FORMAT_TYPE_AUDIO);
  1557. ast_format_cap_remove_bytype(session->jointcap, AST_FORMAT_TYPE_AUDIO);
  1558. } else if (!strcasecmp(media, "video")) {
  1559. if (!ast_strlen_zero(name)) {
  1560. ast_string_field_set(session, video_name, name);
  1561. }
  1562. jingle_enable_video(session);
  1563. *rtp = session->vrtp;
  1564. /* If video is not present cancel this session */
  1565. if (!session->vrtp) {
  1566. jingle_queue_hangup_with_cause(session, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
  1567. ast_log(LOG_ERROR, "Received a video content description on session '%s' but could not enable video\n", session->sid);
  1568. return -1;
  1569. }
  1570. ast_format_cap_remove_bytype(session->peercap, AST_FORMAT_TYPE_VIDEO);
  1571. ast_format_cap_remove_bytype(session->jointcap, AST_FORMAT_TYPE_VIDEO);
  1572. } else {
  1573. /* Unknown media type */
  1574. jingle_queue_hangup_with_cause(session, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
  1575. ast_log(LOG_ERROR, "Unsupported media type '%s' received in content description on session '%s'\n", media, session->sid);
  1576. return -1;
  1577. }
  1578. if (ast_rtp_codecs_payloads_initialize(&codecs)) {
  1579. jingle_queue_hangup_with_cause(session, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
  1580. ast_log(LOG_ERROR, "Could not initialize codecs for negotiation on session '%s'\n", session->sid);
  1581. return -1;
  1582. }
  1583. /* Iterate the codecs updating the relevant RTP instance as we go */
  1584. for (codec = iks_child(description); codec; codec = iks_next(codec)) {
  1585. char *id = iks_find_attrib(codec, "id"), *name = iks_find_attrib(codec, "name");
  1586. char *clockrate = iks_find_attrib(codec, "clockrate");
  1587. int rtp_id, rtp_clockrate;
  1588. if (!ast_strlen_zero(id) && !ast_strlen_zero(name) && (sscanf(id, "%30d", &rtp_id) == 1)) {
  1589. ast_rtp_codecs_payloads_set_m_type(&codecs, NULL, rtp_id);
  1590. if (!ast_strlen_zero(clockrate) && (sscanf(clockrate, "%30d", &rtp_clockrate) == 1)) {
  1591. ast_rtp_codecs_payloads_set_rtpmap_type_rate(&codecs, NULL, rtp_id, media, name, 0, rtp_clockrate);
  1592. } else {
  1593. ast_rtp_codecs_payloads_set_rtpmap_type(&codecs, NULL, rtp_id, media, name, 0);
  1594. }
  1595. }
  1596. }
  1597. ast_rtp_codecs_payload_formats(&codecs, session->peercap, &othercapability);
  1598. ast_format_cap_joint_append(session->cap, session->peercap, session->jointcap);
  1599. if (ast_format_cap_is_empty(session->jointcap)) {
  1600. /* We have no compatible codecs, so terminate the session appropriately */
  1601. jingle_queue_hangup_with_cause(session, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
  1602. ast_rtp_codecs_payloads_destroy(&codecs);
  1603. return -1;
  1604. }
  1605. ast_rtp_codecs_payloads_copy(&codecs, ast_rtp_instance_get_codecs(*rtp), *rtp);
  1606. ast_rtp_codecs_payloads_destroy(&codecs);
  1607. return 0;
  1608. }
  1609. /*! \brief Helper function which handles ICE-UDP transport information */
  1610. static int jingle_interpret_ice_udp_transport(struct jingle_session *session, iks *transport, struct ast_rtp_instance *rtp)
  1611. {
  1612. struct ast_rtp_engine_ice *ice = ast_rtp_instance_get_ice(rtp);
  1613. char *ufrag = iks_find_attrib(transport, "ufrag"), *pwd = iks_find_attrib(transport, "pwd");
  1614. iks *candidate;
  1615. if (!ice) {
  1616. jingle_queue_hangup_with_cause(session, AST_CAUSE_SWITCH_CONGESTION);
  1617. ast_log(LOG_ERROR, "Received ICE-UDP transport information on session '%s' but ICE support not available\n", session->sid);
  1618. return -1;
  1619. }
  1620. if (!ast_strlen_zero(ufrag) && !ast_strlen_zero(pwd)) {
  1621. ice->set_authentication(rtp, ufrag, pwd);
  1622. }
  1623. for (candidate = iks_child(transport); candidate; candidate = iks_next(candidate)) {
  1624. char *component = iks_find_attrib(candidate, "component"), *foundation = iks_find_attrib(candidate, "foundation");
  1625. char *generation = iks_find_attrib(candidate, "generation"), *id = iks_find_attrib(candidate, "id");
  1626. char *ip = iks_find_attrib(candidate, "ip"), *port = iks_find_attrib(candidate, "port");
  1627. char *priority = iks_find_attrib(candidate, "priority"), *protocol = iks_find_attrib(candidate, "protocol");
  1628. char *type = iks_find_attrib(candidate, "type");
  1629. struct ast_rtp_engine_ice_candidate local_candidate = { 0, };
  1630. int real_port;
  1631. struct ast_sockaddr remote_address = { { 0, } };
  1632. /* If this candidate is incomplete skip it */
  1633. if (ast_strlen_zero(component) || ast_strlen_zero(foundation) || ast_strlen_zero(generation) || ast_strlen_zero(id) ||
  1634. ast_strlen_zero(ip) || ast_strlen_zero(port) || ast_strlen_zero(priority) ||
  1635. ast_strlen_zero(protocol) || ast_strlen_zero(type)) {
  1636. jingle_queue_hangup_with_cause(session, AST_CAUSE_PROTOCOL_ERROR);
  1637. ast_log(LOG_ERROR, "Incomplete ICE-UDP candidate received on session '%s'\n", session->sid);
  1638. return -1;
  1639. }
  1640. if ((sscanf(component, "%30u", &local_candidate.id) != 1) ||
  1641. (sscanf(priority, "%30u", (unsigned *)&local_candidate.priority) != 1) ||
  1642. (sscanf(port, "%30d", &real_port) != 1)) {
  1643. jingle_queue_hangup_with_cause(session, AST_CAUSE_PROTOCOL_ERROR);
  1644. ast_log(LOG_ERROR, "Invalid ICE-UDP candidate information received on session '%s'\n", session->sid);
  1645. return -1;
  1646. }
  1647. local_candidate.foundation = foundation;
  1648. local_candidate.transport = protocol;
  1649. ast_sockaddr_parse(&local_candidate.address, ip, PARSE_PORT_FORBID);
  1650. /* We only support IPv4 right now */
  1651. if (!ast_sockaddr_is_ipv4(&local_candidate.address)) {
  1652. continue;
  1653. }
  1654. ast_sockaddr_set_port(&local_candidate.address, real_port);
  1655. if (!strcasecmp(type, "host")) {
  1656. local_candidate.type = AST_RTP_ICE_CANDIDATE_TYPE_HOST;
  1657. } else if (!strcasecmp(type, "srflx")) {
  1658. local_candidate.type = AST_RTP_ICE_CANDIDATE_TYPE_SRFLX;
  1659. } else if (!strcasecmp(type, "relay")) {
  1660. local_candidate.type = AST_RTP_ICE_CANDIDATE_TYPE_RELAYED;
  1661. } else {
  1662. continue;
  1663. }
  1664. /* Worst case use the first viable address */
  1665. ast_rtp_instance_get_remote_address(rtp, &remote_address);
  1666. if (ast_sockaddr_is_ipv4(&local_candidate.address) && ast_sockaddr_isnull(&remote_address)) {
  1667. ast_rtp_instance_set_remote_address(rtp, &local_candidate.address);
  1668. }
  1669. ice->add_remote_candidate(rtp, &local_candidate);
  1670. }
  1671. ice->start(rtp);
  1672. return 0;
  1673. }
  1674. /*! \brief Helper function which handles Google transport information */
  1675. static int jingle_interpret_google_transport(struct jingle_session *session, iks *transport, struct ast_rtp_instance *rtp)
  1676. {
  1677. struct ast_rtp_engine_ice *ice = ast_rtp_instance_get_ice(rtp);
  1678. iks *candidate;
  1679. if (!ice) {
  1680. jingle_queue_hangup_with_cause(session, AST_CAUSE_SWITCH_CONGESTION);
  1681. ast_log(LOG_ERROR, "Received Google transport information on session '%s' but ICE support not available\n", session->sid);
  1682. return -1;
  1683. }
  1684. /* If this session has not transitioned to the Google transport do so now */
  1685. if ((session->transport != JINGLE_TRANSPORT_GOOGLE_V2) &&
  1686. (session->transport != JINGLE_TRANSPORT_GOOGLE_V1)) {
  1687. /* Stop built-in ICE support... we need to fall back to the old old old STUN */
  1688. ice->stop(rtp);
  1689. session->transport = JINGLE_TRANSPORT_GOOGLE_V2;
  1690. }
  1691. for (candidate = iks_child(transport); candidate; candidate = iks_next(candidate)) {
  1692. char *address = iks_find_attrib(candidate, "address"), *port = iks_find_attrib(candidate, "port");
  1693. char *username = iks_find_attrib(candidate, "username"), *name = iks_find_attrib(candidate, "name");
  1694. char *protocol = iks_find_attrib(candidate, "protocol");
  1695. int real_port;
  1696. struct ast_sockaddr target = { { 0, } };
  1697. /* In Google land the combined value is 32 bytes */
  1698. char combined[33] = "";
  1699. /* If this is NOT actually a candidate just skip it */
  1700. if (strcasecmp(iks_name(candidate), "candidate") &&
  1701. strcasecmp(iks_name(candidate), "p:candidate") &&
  1702. strcasecmp(iks_name(candidate), "ses:candidate")) {
  1703. continue;
  1704. }
  1705. /* If this candidate is incomplete skip it */
  1706. if (ast_strlen_zero(address) || ast_strlen_zero(port) || ast_strlen_zero(username) ||
  1707. ast_strlen_zero(name)) {
  1708. jingle_queue_hangup_with_cause(session, AST_CAUSE_PROTOCOL_ERROR);
  1709. ast_log(LOG_ERROR, "Incomplete Google candidate received on session '%s'\n", session->sid);
  1710. return -1;
  1711. }
  1712. /* We only support UDP so skip any other protocols */
  1713. if (!ast_strlen_zero(protocol) && strcasecmp(protocol, "udp")) {
  1714. continue;
  1715. }
  1716. /* We only permit audio and video, not RTCP */
  1717. if (strcasecmp(name, "rtp") && strcasecmp(name, "video_rtp")) {
  1718. continue;
  1719. }
  1720. /* Parse the target information so we can send a STUN request to the candidate */
  1721. if (sscanf(port, "%30d", &real_port) != 1) {
  1722. jingle_queue_hangup_with_cause(session, AST_CAUSE_PROTOCOL_ERROR);
  1723. ast_log(LOG_ERROR, "Invalid Google candidate port '%s' received on session '%s'\n", port, session->sid);
  1724. return -1;
  1725. }
  1726. ast_sockaddr_parse(&target, address, PARSE_PORT_FORBID);
  1727. ast_sockaddr_set_port(&target, real_port);
  1728. /* Per the STUN support Google talk uses combine the two usernames */
  1729. snprintf(combined, sizeof(combined), "%s%s", username, ice->get_ufrag(rtp));
  1730. /* This should appease the masses... we will actually change the remote address when we get their STUN packet */
  1731. ast_rtp_instance_stun_request(rtp, &target, combined);
  1732. }
  1733. return 0;
  1734. }
  1735. /*!
  1736. * \brief Helper function which locates content stanzas and interprets them
  1737. *
  1738. * \note The session *must not* be locked before calling this
  1739. */
  1740. static int jingle_interpret_content(struct jingle_session *session, ikspak *pak)
  1741. {
  1742. iks *content;
  1743. unsigned int changed = 0;
  1744. struct ast_channel *chan;
  1745. /* Look at the content in the session initiation */
  1746. for (content = iks_child(iks_child(pak->x)); content; content = iks_next(content)) {
  1747. char *name;
  1748. struct ast_rtp_instance *rtp = NULL;
  1749. iks *description, *transport;
  1750. /* Ignore specific parts if they are known not to be useful */
  1751. if (!strcmp(iks_name(content), "conference-info")) {
  1752. continue;
  1753. }
  1754. name = iks_find_attrib(content, "name");
  1755. if (session->transport != JINGLE_TRANSPORT_GOOGLE_V1) {
  1756. /* If this content stanza has no name consider it invalid and move on */
  1757. if (ast_strlen_zero(name) && !(name = iks_find_attrib(content, "jin:name"))) {
  1758. jingle_queue_hangup_with_cause(session, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
  1759. ast_log(LOG_ERROR, "Received content without a name on session '%s'\n", session->sid);
  1760. return -1;
  1761. }
  1762. /* Try to pre-populate which RTP instance this content is relevant to */
  1763. if (!strcmp(session->audio_name, name)) {
  1764. rtp = session->rtp;
  1765. } else if (!strcmp(session->video_name, name)) {
  1766. rtp = session->vrtp;
  1767. }
  1768. } else {
  1769. /* Google-V1 has no concept of assocating things like the above does, so since we only support audio over it assume they want audio */
  1770. rtp = session->rtp;
  1771. }
  1772. /* If description information is available use it */
  1773. if ((description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_RTP_NS)) ||
  1774. (description = iks_find_with_attrib(content, "rtp:description", "xmlns:rtp", JINGLE_RTP_NS)) ||
  1775. (description = iks_find_with_attrib(content, "pho:description", "xmlns:pho", GOOGLE_PHONE_NS)) ||
  1776. (description = iks_find_with_attrib(pak->query, "description", "xmlns", GOOGLE_PHONE_NS)) ||
  1777. (description = iks_find_with_attrib(pak->query, "pho:description", "xmlns:pho", GOOGLE_PHONE_NS)) ||
  1778. (description = iks_find_with_attrib(pak->query, "vid:description", "xmlns", GOOGLE_VIDEO_NS))) {
  1779. /* If we failed to do something with the content description abort immediately */
  1780. if (jingle_interpret_description(session, description, name, &rtp)) {
  1781. return -1;
  1782. }
  1783. /* If we successfully interpret the description then the codecs need updating */
  1784. changed = 1;
  1785. }
  1786. /* If we get past the description handling and we still don't know what RTP instance this is for... it is unknown content */
  1787. if (!rtp) {
  1788. ast_log(LOG_ERROR, "Received a content stanza but have no RTP instance for it on session '%s'\n", session->sid);
  1789. jingle_queue_hangup_with_cause(session, AST_CAUSE_SWITCH_CONGESTION);
  1790. return -1;
  1791. }
  1792. /* If ICE UDP transport information is available use it */
  1793. if ((transport = iks_find_with_attrib(content, "transport", "xmlns", JINGLE_ICE_UDP_NS))) {
  1794. if (jingle_interpret_ice_udp_transport(session, transport, rtp)) {
  1795. return -1;
  1796. }
  1797. } else if ((transport = iks_find_with_attrib(content, "transport", "xmlns", GOOGLE_TRANSPORT_NS)) ||
  1798. (transport = iks_find_with_attrib(content, "p:transport", "xmlns:p", GOOGLE_TRANSPORT_NS)) ||
  1799. (transport = iks_find_with_attrib(pak->x, "session", "xmlns", GOOGLE_SESSION_NS)) ||
  1800. (transport = iks_find_with_attrib(pak->x, "ses:session", "xmlns:ses", GOOGLE_SESSION_NS))) {
  1801. /* If Google transport support is available use it */
  1802. if (jingle_interpret_google_transport(session, transport, rtp)) {
  1803. return -1;
  1804. }
  1805. } else if (iks_find(content, "transport")) {
  1806. /* If this is a transport we do not support terminate the session as it probably won't work out in the end */
  1807. jingle_queue_hangup_with_cause(session, AST_CAUSE_FACILITY_NOT_IMPLEMENTED);
  1808. ast_log(LOG_ERROR, "Unsupported transport type received on session '%s'\n", session->sid);
  1809. return -1;
  1810. }
  1811. }
  1812. if (!changed) {
  1813. return 0;
  1814. }
  1815. if ((chan = jingle_session_lock_full(session))) {
  1816. struct ast_format fmt;
  1817. ast_format_cap_copy(ast_channel_nativeformats(chan), session->jointcap);
  1818. ast_codec_choose(&session->prefs, session->jointcap, 1, &fmt);
  1819. ast_set_read_format(chan, &fmt);
  1820. ast_set_write_format(chan, &fmt);
  1821. ast_channel_unlock(chan);
  1822. ast_channel_unref(chan);
  1823. }
  1824. ao2_unlock(session);
  1825. return 0;
  1826. }
  1827. /*! \brief Handler function for the 'session-initiate' action */
  1828. static void jingle_action_session_initiate(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak)
  1829. {
  1830. char *sid;
  1831. enum jingle_transport transport = JINGLE_TRANSPORT_NONE;
  1832. struct ast_channel *chan;
  1833. int res;
  1834. if (session) {
  1835. /* This is a duplicate session setup, so respond accordingly */
  1836. jingle_send_error_response(endpoint->connection, pak, "result", "out-of-order", NULL);
  1837. return;
  1838. }
  1839. /* Retrieve the session identifier from the message, note that this may alter the transport */
  1840. if ((sid = iks_find_attrib(pak->query, "id"))) {
  1841. /* The presence of the session identifier in the 'id' attribute tells us that this is Google-V1 as everything else uses 'sid' */
  1842. transport = JINGLE_TRANSPORT_GOOGLE_V1;
  1843. } else if (!(sid = iks_find_attrib(pak->query, "sid"))) {
  1844. jingle_send_error_response(endpoint->connection, pak, "bad-request", NULL, NULL);
  1845. return;
  1846. }
  1847. /* Create a new local session */
  1848. if (!(session = jingle_alloc(endpoint, pak->from->full, sid))) {
  1849. jingle_send_error_response(endpoint->connection, pak, "cancel", "service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'", NULL);
  1850. return;
  1851. }
  1852. /* If we determined that the transport should change as a result of how we got the SID change it */
  1853. if (transport != JINGLE_TRANSPORT_NONE) {
  1854. session->transport = transport;
  1855. }
  1856. /* Create a new Asterisk channel using the above local session */
  1857. if (!(chan = jingle_new(endpoint, session, AST_STATE_DOWN, pak->from->user, NULL, pak->from->full))) {
  1858. ao2_ref(session, -1);
  1859. jingle_send_error_response(endpoint->connection, pak, "cancel", "service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'", NULL);
  1860. return;
  1861. }
  1862. ao2_link(endpoint->state->sessions, session);
  1863. ast_setstate(chan, AST_STATE_RING);
  1864. res = ast_pbx_start(chan);
  1865. switch (res) {
  1866. case AST_PBX_FAILED:
  1867. ast_log(LOG_WARNING, "Failed to start PBX :(\n");
  1868. jingle_send_error_response(endpoint->connection, pak, "cancel", "service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'", NULL);
  1869. session->gone = 1;
  1870. ast_hangup(chan);
  1871. break;
  1872. case AST_PBX_CALL_LIMIT:
  1873. ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n");
  1874. jingle_send_error_response(endpoint->connection, pak, "wait", "resource-constraint xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'", NULL);
  1875. ast_hangup(chan);
  1876. break;
  1877. case AST_PBX_SUCCESS:
  1878. jingle_send_response(endpoint->connection, pak);
  1879. /* Only send a transport-info message if we successfully interpreted the available content */
  1880. if (!jingle_interpret_content(session, pak)) {
  1881. jingle_send_transport_info(session, iks_find_attrib(pak->x, "from"));
  1882. }
  1883. break;
  1884. }
  1885. }
  1886. /*! \brief Handler function for the 'transport-info' action */
  1887. static void jingle_action_transport_info(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak)
  1888. {
  1889. if (!session) {
  1890. jingle_send_error_response(endpoint->connection, pak, "cancel", "item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
  1891. "unknown-session xmlns='urn:xmpp:jingle:errors:1'");
  1892. return;
  1893. }
  1894. jingle_interpret_content(session, pak);
  1895. jingle_send_response(endpoint->connection, pak);
  1896. }
  1897. /*! \brief Handler function for the 'session-accept' action */
  1898. static void jingle_action_session_accept(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak)
  1899. {
  1900. struct ast_channel *chan;
  1901. if (!session) {
  1902. jingle_send_error_response(endpoint->connection, pak, "cancel", "item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
  1903. "unknown-session xmlns='urn:xmpp:jingle:errors:1'");
  1904. return;
  1905. }
  1906. jingle_interpret_content(session, pak);
  1907. if ((chan = jingle_session_lock_full(session))) {
  1908. ast_queue_control(chan, AST_CONTROL_ANSWER);
  1909. ast_channel_unlock(chan);
  1910. ast_channel_unref(chan);
  1911. }
  1912. ao2_unlock(session);
  1913. jingle_send_response(endpoint->connection, pak);
  1914. }
  1915. /*! \brief Handler function for the 'session-info' action */
  1916. static void jingle_action_session_info(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak)
  1917. {
  1918. struct ast_channel *chan;
  1919. if (!session) {
  1920. jingle_send_error_response(endpoint->connection, pak, "cancel", "item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
  1921. "unknown-session xmlns='urn:xmpp:jingle:errors:1'");
  1922. return;
  1923. }
  1924. if (!(chan = jingle_session_lock_full(session))) {
  1925. ao2_unlock(session);
  1926. jingle_send_response(endpoint->connection, pak);
  1927. return;
  1928. }
  1929. if (iks_find_with_attrib(pak->query, "ringing", "xmlns", JINGLE_RTP_INFO_NS)) {
  1930. ast_queue_control(chan, AST_CONTROL_RINGING);
  1931. if (ast_channel_state(chan) != AST_STATE_UP) {
  1932. ast_setstate(chan, AST_STATE_RINGING);
  1933. }
  1934. } else if (iks_find_with_attrib(pak->query, "hold", "xmlns", JINGLE_RTP_INFO_NS)) {
  1935. ast_queue_control(chan, AST_CONTROL_HOLD);
  1936. } else if (iks_find_with_attrib(pak->query, "unhold", "xmlns", JINGLE_RTP_INFO_NS)) {
  1937. ast_queue_control(chan, AST_CONTROL_UNHOLD);
  1938. }
  1939. ast_channel_unlock(chan);
  1940. ast_channel_unref(chan);
  1941. ao2_unlock(session);
  1942. jingle_send_response(endpoint->connection, pak);
  1943. }
  1944. /*! \brief Handler function for the 'session-terminate' action */
  1945. static void jingle_action_session_terminate(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak)
  1946. {
  1947. struct ast_channel *chan;
  1948. iks *reason, *text;
  1949. int cause = AST_CAUSE_NORMAL;
  1950. struct ast_control_pvt_cause_code *cause_code;
  1951. int data_size = sizeof(*cause_code);
  1952. if (!session) {
  1953. jingle_send_error_response(endpoint->connection, pak, "cancel", "item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
  1954. "unknown-session xmlns='urn:xmpp:jingle:errors:1'");
  1955. return;
  1956. }
  1957. if (!(chan = jingle_session_lock_full(session))) {
  1958. ao2_unlock(session);
  1959. jingle_send_response(endpoint->connection, pak);
  1960. return;
  1961. }
  1962. /* Pull the reason text from the session-terminate message and translate it into a cause code */
  1963. if ((reason = iks_find(pak->query, "reason")) && (text = iks_child(reason))) {
  1964. int i;
  1965. /* Size of the string making up the cause code is "Motif " + text */
  1966. data_size += 6 + strlen(iks_name(text));
  1967. cause_code = ast_alloca(data_size);
  1968. memset(cause_code, 0, data_size);
  1969. /* Get the appropriate cause code mapping for this reason */
  1970. for (i = 0; i < ARRAY_LEN(jingle_reason_mappings); i++) {
  1971. if (!strcasecmp(jingle_reason_mappings[i].reason, iks_name(text))) {
  1972. cause = jingle_reason_mappings[i].cause;
  1973. break;
  1974. }
  1975. }
  1976. /* Store the technology specific information */
  1977. snprintf(cause_code->code, data_size - sizeof(*cause_code) + 1, "Motif %s", iks_name(text));
  1978. } else {
  1979. /* No technology specific information is available */
  1980. cause_code = ast_alloca(data_size);
  1981. memset(cause_code, 0, data_size);
  1982. }
  1983. ast_copy_string(cause_code->chan_name, ast_channel_name(chan), AST_CHANNEL_NAME);
  1984. cause_code->ast_cause = cause;
  1985. ast_queue_control_data(chan, AST_CONTROL_PVT_CAUSE_CODE, cause_code, data_size);
  1986. ast_channel_hangupcause_hash_set(chan, cause_code, data_size);
  1987. ast_debug(3, "Hanging up channel '%s' due to session terminate message with cause '%d'\n", ast_channel_name(chan), cause);
  1988. ast_queue_hangup_with_cause(chan, cause);
  1989. session->gone = 1;
  1990. ast_channel_unlock(chan);
  1991. ast_channel_unref(chan);
  1992. ao2_unlock(session);
  1993. jingle_send_response(endpoint->connection, pak);
  1994. }
  1995. /*! \brief Callback for when a Jingle action is received from an endpoint */
  1996. static int jingle_action_hook(void *data, ikspak *pak)
  1997. {
  1998. char *action;
  1999. const char *sid = NULL;
  2000. struct jingle_session *session = NULL;
  2001. struct jingle_endpoint *endpoint = data;
  2002. int i, handled = 0;
  2003. /* We accept both Jingle and Google-V1 */
  2004. if (!(action = iks_find_attrib(pak->query, "action")) &&
  2005. !(action = iks_find_attrib(pak->query, "type"))) {
  2006. /* This occurs if either receive a packet masquerading as Jingle or Google-V1 that is actually not OR we receive a response
  2007. * to a message that has no response hook. */
  2008. return IKS_FILTER_EAT;
  2009. }
  2010. /* Bump the endpoint reference count up in case a reload occurs. Unfortunately the available synchronization between iksemel and us
  2011. * does not permit us to make this completely safe. */
  2012. ao2_ref(endpoint, +1);
  2013. /* If a Jingle session identifier is present use it */
  2014. if (!(sid = iks_find_attrib(pak->query, "sid"))) {
  2015. /* If a Google-V1 session identifier is present use it */
  2016. sid = iks_find_attrib(pak->query, "id");
  2017. }
  2018. /* If a session identifier was present in the message attempt to find the session, it is up to the action handler whether
  2019. * this is required or not */
  2020. if (!ast_strlen_zero(sid)) {
  2021. session = ao2_find(endpoint->state->sessions, sid, OBJ_KEY);
  2022. }
  2023. /* If a session is present associate the callid with this thread */
  2024. if (session) {
  2025. ast_callid_threadassoc_add(session->callid);
  2026. }
  2027. /* Iterate through supported action handlers looking for one that is able to handle this */
  2028. for (i = 0; i < ARRAY_LEN(jingle_action_handlers); i++) {
  2029. if (!strcasecmp(jingle_action_handlers[i].action, action)) {
  2030. jingle_action_handlers[i].handler(endpoint, session, pak);
  2031. handled = 1;
  2032. break;
  2033. }
  2034. }
  2035. /* If no action handler is present for the action they sent us make it evident */
  2036. if (!handled) {
  2037. ast_log(LOG_NOTICE, "Received action '%s' for session '%s' that has no handler\n", action, sid);
  2038. }
  2039. /* If a session was successfully found for this message deref it now since the handler is done */
  2040. if (session) {
  2041. ast_callid_threadassoc_remove();
  2042. ao2_ref(session, -1);
  2043. }
  2044. ao2_ref(endpoint, -1);
  2045. return IKS_FILTER_EAT;
  2046. }
  2047. /*! \brief Custom handler for groups */
  2048. static int custom_group_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
  2049. {
  2050. struct jingle_endpoint *endpoint = obj;
  2051. if (!strcasecmp(var->name, "callgroup")) {
  2052. endpoint->callgroup = ast_get_group(var->value);
  2053. } else if (!strcasecmp(var->name, "pickupgroup")) {
  2054. endpoint->pickupgroup = ast_get_group(var->value);
  2055. } else {
  2056. return -1;
  2057. }
  2058. return 0;
  2059. }
  2060. /*! \brief Custom handler for connection */
  2061. static int custom_connection_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
  2062. {
  2063. struct jingle_endpoint *endpoint = obj;
  2064. /* You might think... but Josh, shouldn't you do this in a prelink callback? Well I *could* but until the original is destroyed
  2065. * this will not actually get called, so even if the config turns out to be bogus this is harmless.
  2066. */
  2067. if (!(endpoint->connection = ast_xmpp_client_find(var->value))) {
  2068. ast_log(LOG_ERROR, "Connection '%s' configured on endpoint '%s' could not be found\n", var->value, endpoint->name);
  2069. return -1;
  2070. }
  2071. if (!(endpoint->rule = iks_filter_add_rule(endpoint->connection->filter, jingle_action_hook, endpoint,
  2072. IKS_RULE_TYPE, IKS_PAK_IQ,
  2073. IKS_RULE_NS, JINGLE_NS,
  2074. IKS_RULE_NS, GOOGLE_SESSION_NS,
  2075. IKS_RULE_DONE))) {
  2076. ast_log(LOG_ERROR, "Action hook could not be added to connection '%s' on endpoint '%s'\n", var->value, endpoint->name);
  2077. return -1;
  2078. }
  2079. return 0;
  2080. }
  2081. /*! \brief Custom handler for transport */
  2082. static int custom_transport_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
  2083. {
  2084. struct jingle_endpoint *endpoint = obj;
  2085. if (!strcasecmp(var->value, "ice-udp")) {
  2086. endpoint->transport = JINGLE_TRANSPORT_ICE_UDP;
  2087. } else if (!strcasecmp(var->value, "google")) {
  2088. endpoint->transport = JINGLE_TRANSPORT_GOOGLE_V2;
  2089. } else if (!strcasecmp(var->value, "google-v1")) {
  2090. endpoint->transport = JINGLE_TRANSPORT_GOOGLE_V1;
  2091. } else {
  2092. ast_log(LOG_WARNING, "Unknown transport type '%s' on endpoint '%s', defaulting to 'ice-udp'\n", var->value, endpoint->name);
  2093. endpoint->transport = JINGLE_TRANSPORT_ICE_UDP;
  2094. }
  2095. return 0;
  2096. }
  2097. /*! \brief Load module into PBX, register channel */
  2098. static int load_module(void)
  2099. {
  2100. if (!(jingle_tech.capabilities = ast_format_cap_alloc())) {
  2101. return AST_MODULE_LOAD_DECLINE;
  2102. }
  2103. if (aco_info_init(&cfg_info)) {
  2104. ast_log(LOG_ERROR, "Unable to intialize configuration for chan_motif.\n");
  2105. goto end;
  2106. }
  2107. aco_option_register(&cfg_info, "context", ACO_EXACT, endpoint_options, "default", OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, context));
  2108. aco_option_register_custom(&cfg_info, "callgroup", ACO_EXACT, endpoint_options, NULL, custom_group_handler, 0);
  2109. aco_option_register_custom(&cfg_info, "pickupgroup", ACO_EXACT, endpoint_options, NULL, custom_group_handler, 0);
  2110. aco_option_register(&cfg_info, "language", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, language));
  2111. aco_option_register(&cfg_info, "musicclass", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, musicclass));
  2112. aco_option_register(&cfg_info, "parkinglot", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, parkinglot));
  2113. aco_option_register(&cfg_info, "accountcode", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, accountcode));
  2114. aco_option_register(&cfg_info, "allow", ACO_EXACT, endpoint_options, "ulaw,alaw", OPT_CODEC_T, 1, FLDSET(struct jingle_endpoint, prefs, cap));
  2115. aco_option_register(&cfg_info, "disallow", ACO_EXACT, endpoint_options, "all", OPT_CODEC_T, 0, FLDSET(struct jingle_endpoint, prefs, cap));
  2116. aco_option_register_custom(&cfg_info, "connection", ACO_EXACT, endpoint_options, NULL, custom_connection_handler, 0);
  2117. aco_option_register_custom(&cfg_info, "transport", ACO_EXACT, endpoint_options, NULL, custom_transport_handler, 0);
  2118. aco_option_register(&cfg_info, "maxicecandidates", ACO_EXACT, endpoint_options, DEFAULT_MAX_ICE_CANDIDATES, OPT_UINT_T, PARSE_DEFAULT,
  2119. FLDSET(struct jingle_endpoint, maxicecandidates), DEFAULT_MAX_ICE_CANDIDATES);
  2120. aco_option_register(&cfg_info, "maxpayloads", ACO_EXACT, endpoint_options, DEFAULT_MAX_PAYLOADS, OPT_UINT_T, PARSE_DEFAULT,
  2121. FLDSET(struct jingle_endpoint, maxpayloads), DEFAULT_MAX_PAYLOADS);
  2122. ast_format_cap_add_all_by_type(jingle_tech.capabilities, AST_FORMAT_TYPE_AUDIO);
  2123. if (aco_process_config(&cfg_info, 0)) {
  2124. ast_log(LOG_ERROR, "Unable to read config file motif.conf. Not loading module.\n");
  2125. aco_info_destroy(&cfg_info);
  2126. ast_format_cap_destroy(jingle_tech.capabilities);
  2127. jingle_tech.capabilities = NULL;
  2128. return AST_MODULE_LOAD_DECLINE;
  2129. }
  2130. if (!(sched = ast_sched_context_create())) {
  2131. ast_log(LOG_ERROR, "Unable to create scheduler context.\n");
  2132. goto end;
  2133. }
  2134. if (ast_sched_start_thread(sched)) {
  2135. ast_log(LOG_ERROR, "Unable to create scheduler context thread.\n");
  2136. goto end;
  2137. }
  2138. ast_rtp_glue_register(&jingle_rtp_glue);
  2139. if (ast_channel_register(&jingle_tech)) {
  2140. ast_log(LOG_ERROR, "Unable to register channel class %s\n", channel_type);
  2141. goto end;
  2142. }
  2143. return 0;
  2144. end:
  2145. ast_rtp_glue_unregister(&jingle_rtp_glue);
  2146. if (sched) {
  2147. ast_sched_context_destroy(sched);
  2148. }
  2149. aco_info_destroy(&cfg_info);
  2150. ao2_global_obj_release(globals);
  2151. ast_format_cap_destroy(jingle_tech.capabilities);
  2152. jingle_tech.capabilities = NULL;
  2153. return AST_MODULE_LOAD_FAILURE;
  2154. }
  2155. /*! \brief Reload module */
  2156. static int reload(void)
  2157. {
  2158. return aco_process_config(&cfg_info, 1);
  2159. }
  2160. /*! \brief Unload the jingle channel from Asterisk */
  2161. static int unload_module(void)
  2162. {
  2163. ast_channel_unregister(&jingle_tech);
  2164. ast_format_cap_destroy(jingle_tech.capabilities);
  2165. jingle_tech.capabilities = NULL;
  2166. ast_rtp_glue_unregister(&jingle_rtp_glue);
  2167. ast_sched_context_destroy(sched);
  2168. aco_info_destroy(&cfg_info);
  2169. ao2_global_obj_release(globals);
  2170. return 0;
  2171. }
  2172. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Motif Jingle Channel Driver",
  2173. .load = load_module,
  2174. .unload = unload_module,
  2175. .reload = reload,
  2176. .load_pri = AST_MODPRI_CHANNEL_DRIVER,
  2177. );