chan_skinny.c 101 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 1999 - 2005, Digium, Inc.
  5. *
  6. * chan_skinny was developed by Jeremy McNamara & Florian Overkamp
  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. * \brief Implementation of the Skinny protocol
  21. *
  22. * \author Jeremy McNamara & Florian Overkamp
  23. * \ingroup channel_drivers
  24. */
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <unistd.h>
  29. #include <sys/socket.h>
  30. #include <netinet/in.h>
  31. #include <netinet/tcp.h>
  32. #include <sys/ioctl.h>
  33. #include <net/if.h>
  34. #include <errno.h>
  35. #include <fcntl.h>
  36. #include <netdb.h>
  37. #include <arpa/inet.h>
  38. #include <sys/signal.h>
  39. #include <signal.h>
  40. #include <ctype.h>
  41. #include "asterisk.h"
  42. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  43. #include "asterisk/lock.h"
  44. #include "asterisk/channel.h"
  45. #include "asterisk/config.h"
  46. #include "asterisk/logger.h"
  47. #include "asterisk/module.h"
  48. #include "asterisk/pbx.h"
  49. #include "asterisk/options.h"
  50. #include "asterisk/lock.h"
  51. #include "asterisk/sched.h"
  52. #include "asterisk/io.h"
  53. #include "asterisk/rtp.h"
  54. #include "asterisk/acl.h"
  55. #include "asterisk/callerid.h"
  56. #include "asterisk/cli.h"
  57. #include "asterisk/say.h"
  58. #include "asterisk/cdr.h"
  59. #include "asterisk/astdb.h"
  60. #include "asterisk/features.h"
  61. #include "asterisk/app.h"
  62. #include "asterisk/musiconhold.h"
  63. #include "asterisk/utils.h"
  64. #include "asterisk/dsp.h"
  65. /************************************************************************************/
  66. /* Skinny/Asterisk Protocol Settings */
  67. /************************************************************************************/
  68. static const char desc[] = "Skinny Client Control Protocol (Skinny)";
  69. static const char tdesc[] = "Skinny Client Control Protocol (Skinny)";
  70. static const char type[] = "Skinny";
  71. static const char config[] = "skinny.conf";
  72. /* Just about everybody seems to support ulaw, so make it a nice default */
  73. static int capability = AST_FORMAT_ULAW;
  74. #define DEFAULT_SKINNY_PORT 2000
  75. #define DEFAULT_SKINNY_BACKLOG 2
  76. #define SKINNY_MAX_PACKET 1000
  77. static int keep_alive = 120;
  78. static char date_format[6] = "D-M-Y";
  79. static char version_id[16] = "P002F202";
  80. /* these should be in an include file, but dunno what to include */
  81. typedef unsigned char UINT8;
  82. typedef unsigned short UINT16;
  83. typedef unsigned int UINT32;
  84. #if __BYTE_ORDER == __LITTLE_ENDIAN
  85. #define letohl(x) (x)
  86. #define letohs(x) (x)
  87. #define htolel(x) (x)
  88. #define htoles(x) (x)
  89. #else
  90. #if defined(SOLARIS) || defined(__Darwin__) || defined(__NetBSD__)
  91. #define __bswap_16(x) \
  92. ((((x) & 0xff00) >> 8) | \
  93. (((x) & 0x00ff) << 8))
  94. #define __bswap_32(x) \
  95. ((((x) & 0xff000000) >> 24) | \
  96. (((x) & 0x00ff0000) >> 8) | \
  97. (((x) & 0x0000ff00) << 8) | \
  98. (((x) & 0x000000ff) << 24))
  99. #else
  100. #include <bits/byteswap.h>
  101. #endif
  102. #define letohl(x) __bswap_32(x)
  103. #define letohs(x) __bswap_16(x)
  104. #define htolel(x) __bswap_32(x)
  105. #define htoles(x) __bswap_16(x)
  106. #endif
  107. /************************************************************************************/
  108. /* Protocol Messages */
  109. /************************************************************************************/
  110. /* message types */
  111. #define KEEP_ALIVE_MESSAGE 0x0000
  112. /* no additional struct */
  113. #define REGISTER_MESSAGE 0x0001
  114. typedef struct register_message {
  115. char name[16];
  116. int userId;
  117. int instance;
  118. char ip[4];
  119. int type;
  120. int maxStreams;
  121. } register_message;
  122. #define IP_PORT_MESSAGE 0x0002
  123. #define KEYPAD_BUTTON_MESSAGE 0x0003
  124. typedef struct keypad_button_message {
  125. int button;
  126. } keypad_button_message;
  127. #define STIMULUS_MESSAGE 0x0005
  128. typedef struct stimulus_message {
  129. int stimulus;
  130. int stimulusInstance;
  131. } stimulus_message;
  132. #define OFFHOOK_MESSAGE 0x0006
  133. #define ONHOOK_MESSAGE 0x0007
  134. #define CAPABILITIES_RES_MESSAGE 0x0010
  135. typedef struct station_capabilities {
  136. int codec;
  137. int frames;
  138. union {
  139. char res[8];
  140. long rate;
  141. } payloads;
  142. } station_capabilities;
  143. typedef struct capabilities_res_message {
  144. int count;
  145. struct station_capabilities caps[18];
  146. } capabilities_res_message;
  147. #define SPEED_DIAL_STAT_REQ_MESSAGE 0x000A
  148. typedef struct speed_dial_stat_req_message {
  149. int speedDialNumber;
  150. } speed_dial_stat_req_message;
  151. #define LINE_STATE_REQ_MESSAGE 0x000B
  152. typedef struct line_state_req_message {
  153. int lineNumber;
  154. } line_state_req_message;
  155. #define TIME_DATE_REQ_MESSAGE 0x000D
  156. #define VERSION_REQ_MESSAGE 0x000F
  157. #define BUTTON_TEMPLATE_REQ_MESSAGE 0x000E
  158. #define SERVER_REQUEST_MESSAGE 0x0012
  159. #define ALARM_MESSAGE 0x0020
  160. #define OPEN_RECIEVE_CHANNEL_ACK_MESSAGE 0x0022
  161. typedef struct open_recieve_channel_ack_message {
  162. int status;
  163. char ipAddr[4];
  164. int port;
  165. int passThruId;
  166. } open_recieve_channel_ack_message;
  167. #define SOFT_KEY_SET_REQ_MESSAGE 0x0025
  168. #define UNREGISTER_MESSAGE 0x0027
  169. #define SOFT_KEY_TEMPLATE_REQ_MESSAGE 0x0028
  170. #define REGISTER_ACK_MESSAGE 0x0081
  171. typedef struct register_ack_message {
  172. int keepAlive;
  173. char dateTemplate[6];
  174. char res[2];
  175. int secondaryKeepAlive;
  176. char res2[4];
  177. } register_ack_message;
  178. #define START_TONE_MESSAGE 0x0082
  179. typedef struct start_tone_message {
  180. int tone;
  181. } start_tone_message;
  182. #define STOP_TONE_MESSAGE 0x0083
  183. #define SET_RINGER_MESSAGE 0x0085
  184. typedef struct set_ringer_message {
  185. int ringerMode;
  186. } set_ringer_message;
  187. #define SET_LAMP_MESSAGE 0x0086
  188. typedef struct set_lamp_message {
  189. int stimulus;
  190. int stimulusInstance;
  191. int deviceStimulus;
  192. } set_lamp_message;
  193. #define SET_SPEAKER_MESSAGE 0x0088
  194. typedef struct set_speaker_message {
  195. int mode;
  196. } set_speaker_message;
  197. #define START_MEDIA_TRANSMISSION_MESSAGE 0x008A
  198. typedef struct media_qualifier {
  199. int precedence;
  200. int vad;
  201. int packets;
  202. int bitRate;
  203. } media_qualifier;
  204. typedef struct start_media_transmission_message {
  205. int conferenceId;
  206. int passThruPartyId;
  207. char remoteIp[4];
  208. int remotePort;
  209. int packetSize;
  210. int payloadType;
  211. media_qualifier qualifier;
  212. } start_media_transmission_message;
  213. #define STOP_MEDIA_TRANSMISSION_MESSAGE 0x008B
  214. typedef struct stop_media_transmission_message {
  215. int conferenceId;
  216. int passThruPartyId;
  217. } stop_media_transmission_message;
  218. #define CALL_INFO_MESSAGE 0x008F
  219. typedef struct call_info_message {
  220. char callingPartyName[40];
  221. char callingParty[24];
  222. char calledPartyName[40];
  223. char calledParty[24];
  224. int instance;
  225. int reference;
  226. int type;
  227. char originalCalledPartyName[40];
  228. char originalCalledParty[24];
  229. } call_info_message;
  230. #define SPEED_DIAL_STAT_RES_MESSAGE 0x0091
  231. typedef struct speed_dial_stat_res_message {
  232. int speedDialNumber;
  233. char speedDialDirNumber[24];
  234. char speedDialDisplayName[40];
  235. } speed_dial_stat_res_message;
  236. #define LINE_STAT_RES_MESSAGE 0x0092
  237. typedef struct line_stat_res_message {
  238. int linenumber;
  239. char lineDirNumber[24];
  240. char lineDisplayName[42];
  241. int space;
  242. } line_stat_res_message;
  243. #define DEFINETIMEDATE_MESSAGE 0x0094
  244. typedef struct definetimedate_message {
  245. int year; /* since 1900 */
  246. int month;
  247. int dayofweek; /* monday = 1 */
  248. int day;
  249. int hour;
  250. int minute;
  251. int seconds;
  252. int milliseconds;
  253. int timestamp;
  254. } definetimedate_message;
  255. #define DISPLAYTEXT_MESSAGE 0x0099
  256. typedef struct displaytext_message {
  257. char text[40];
  258. } displaytext_message;
  259. #define CLEAR_DISPLAY_MESSAGE 0x009A
  260. #define REGISTER_REJ_MESSAGE 0x009D
  261. typedef struct register_rej_message {
  262. char errMsg[33];
  263. } register_rej_message;
  264. #define CAPABILITIES_REQ_MESSAGE 0x009B
  265. #define SERVER_RES_MESSAGE 0x009E
  266. typedef struct server_identifier {
  267. char serverName[48];
  268. } server_identifier;
  269. typedef struct server_res_message {
  270. server_identifier server[5];
  271. int serverListenPort[5];
  272. int serverIpAddr[5];
  273. } server_res_message;
  274. #define BUTTON_TEMPLATE_RES_MESSAGE 0x0097
  275. typedef struct buttondefinition {
  276. UINT8 instanceNumber;
  277. UINT8 buttonDefinition;
  278. } button_definition;
  279. #define STIMULUS_REDIAL 0x01
  280. #define STIMULUS_SPEEDDIAL 0x02
  281. #define STIMULUS_HOLD 0x03
  282. #define STIMULUS_TRANSFER 0x04
  283. #define STIMULUS_FORWARDALL 0x05
  284. #define STIMULUS_FORWARDBUSY 0x06
  285. #define STIMULUS_FORWARDNOANSWER 0x07
  286. #define STIMULUS_DISPLAY 0x08
  287. #define STIMULUS_LINE 0x09
  288. #define STIMULUS_VOICEMAIL 0x0F
  289. #define STIMULUS_AUTOANSWER 0x11
  290. #define STIMULUS_CONFERENCE 0x7D
  291. #define STIMULUS_CALLPARK 0x7E
  292. #define STIMULUS_CALLPICKUP 0x7F
  293. #define STIMULUS_NONE 0xFF
  294. button_definition button_def_30vip[] = {
  295. { 1, STIMULUS_LINE }, /* Line 1 */
  296. { 2, STIMULUS_LINE }, /* Line 2 */
  297. { 3, STIMULUS_LINE }, /* Line 3 */
  298. { 4, STIMULUS_LINE }, /* Line 4 */
  299. { 1, STIMULUS_CALLPARK }, /* Call Park */
  300. { 0, STIMULUS_NONE },
  301. { 1, STIMULUS_SPEEDDIAL }, /* Speeddial 1 */
  302. { 2, STIMULUS_SPEEDDIAL }, /* Speeddial 2 */
  303. { 3, STIMULUS_SPEEDDIAL }, /* Speeddial 3 */
  304. { 4, STIMULUS_SPEEDDIAL }, /* Speeddial 4 */
  305. { 5, STIMULUS_SPEEDDIAL }, /* Speeddial 5 */
  306. { 6, STIMULUS_SPEEDDIAL }, /* Speeddial 6 */
  307. { 1, STIMULUS_VOICEMAIL }, /* Voicemail */
  308. { 1, STIMULUS_FORWARDALL }, /* Forward All */
  309. { 1, STIMULUS_CONFERENCE }, /* Conference */
  310. { 0, STIMULUS_NONE },
  311. { 0, STIMULUS_NONE },
  312. { 0, STIMULUS_NONE },
  313. { 0, STIMULUS_NONE },
  314. { 0, STIMULUS_NONE },
  315. { 7, STIMULUS_SPEEDDIAL }, /* Speeddial 7 */
  316. { 8, STIMULUS_SPEEDDIAL }, /* Speeddial 8 */
  317. { 9, STIMULUS_SPEEDDIAL }, /* Speeddial 9 */
  318. { 10, STIMULUS_SPEEDDIAL } /* Speeddial 10 */
  319. };
  320. button_definition button_def_12sp[] = {
  321. { 1, STIMULUS_LINE }, /* Line 1 */
  322. { 1, STIMULUS_LINE }, /* Line 1 */
  323. { 1, STIMULUS_SPEEDDIAL }, /* Speeddial 1 */
  324. { 2, STIMULUS_SPEEDDIAL }, /* Speeddial 2 */
  325. { 3, STIMULUS_SPEEDDIAL }, /* Speeddial 3 */
  326. { 4, STIMULUS_SPEEDDIAL }, /* Speeddial 4 */
  327. { 1, STIMULUS_VOICEMAIL }, /* Voicemail */
  328. { 5, STIMULUS_SPEEDDIAL }, /* Speeddial 5 */
  329. { 6, STIMULUS_SPEEDDIAL }, /* Speeddial 6 */
  330. { 7, STIMULUS_SPEEDDIAL }, /* Speeddial 7 */
  331. { 8, STIMULUS_SPEEDDIAL }, /* Speeddial 8 */
  332. { 9, STIMULUS_SPEEDDIAL } /* Speeddial 9 */
  333. };
  334. button_definition button_def_7902[] = {
  335. { 1, STIMULUS_LINE }, /* Line 1 */
  336. { 1, STIMULUS_HOLD }, /* Hold */
  337. { 1, STIMULUS_TRANSFER },
  338. { 1, STIMULUS_DISPLAY },
  339. { 1, STIMULUS_VOICEMAIL },
  340. { 1, STIMULUS_CONFERENCE },
  341. { 1, STIMULUS_FORWARDALL },
  342. { 1, STIMULUS_SPEEDDIAL }, /* Speeddial 1 */
  343. { 2, STIMULUS_SPEEDDIAL }, /* Speeddial 2 */
  344. { 3, STIMULUS_SPEEDDIAL }, /* Speeddial 3 */
  345. { 4, STIMULUS_SPEEDDIAL }, /* Speeddial 4 */
  346. { 1, STIMULUS_REDIAL }
  347. };
  348. button_definition button_def_7910[] = {
  349. { 1, STIMULUS_LINE }, /* Line 1 */
  350. { 1, STIMULUS_HOLD }, /* Hold */
  351. { 1, STIMULUS_TRANSFER },
  352. { 1, STIMULUS_DISPLAY },
  353. { 1, STIMULUS_VOICEMAIL },
  354. { 1, STIMULUS_CONFERENCE },
  355. { 1, STIMULUS_FORWARDALL },
  356. { 1, STIMULUS_SPEEDDIAL }, /* Speeddial 1 */
  357. { 2, STIMULUS_SPEEDDIAL }, /* Speeddial 2 */
  358. { 1, STIMULUS_REDIAL }
  359. };
  360. button_definition button_def_7920[] = {
  361. { 1, STIMULUS_LINE }, /* Line 1 */
  362. { 2, STIMULUS_LINE }, /* Line 2 */
  363. { 1, STIMULUS_SPEEDDIAL }, /* Speeddial 1 */
  364. { 2, STIMULUS_SPEEDDIAL }, /* Speeddial 2 */
  365. { 3, STIMULUS_SPEEDDIAL }, /* Speeddial 3 */
  366. { 4, STIMULUS_SPEEDDIAL } /* Speeddial 4 */
  367. };
  368. button_definition button_def_7935[] = {
  369. { 1, STIMULUS_LINE }, /* Line 1 */
  370. { 2, STIMULUS_LINE } /* Line 2 */
  371. };
  372. button_definition button_def_7940[] = {
  373. { 1, STIMULUS_LINE }, /* Line 1 */
  374. { 2, STIMULUS_LINE } /* Line 2 */
  375. };
  376. button_definition button_def_7960[] = {
  377. { 1, STIMULUS_LINE }, /* Line 1 */
  378. { 2, STIMULUS_LINE }, /* Line 2 */
  379. { 3, STIMULUS_LINE }, /* Line 3 */
  380. { 1, STIMULUS_SPEEDDIAL }, /* Speeddial 1 */
  381. { 2, STIMULUS_SPEEDDIAL }, /* Speeddial 2 */
  382. { 3, STIMULUS_SPEEDDIAL } /* Speeddial 3 */
  383. };
  384. button_definition button_def_7970[] = {
  385. { 1, STIMULUS_LINE }, /* Line 1 */
  386. { 2, STIMULUS_LINE }, /* Line 2 */
  387. { 3, STIMULUS_LINE }, /* Line 3 */
  388. { 1, STIMULUS_SPEEDDIAL }, /* Speeddial 1 */
  389. { 2, STIMULUS_SPEEDDIAL }, /* Speeddial 2 */
  390. { 3, STIMULUS_SPEEDDIAL }, /* Speeddial 3 */
  391. { 4, STIMULUS_SPEEDDIAL }, /* Speeddial 4 */
  392. { 5, STIMULUS_SPEEDDIAL } /* Speeddial 5 */
  393. };
  394. button_definition button_def_none = { 0, STIMULUS_NONE };
  395. typedef struct button_defs {
  396. char *type;
  397. int num_buttons;
  398. button_definition *button_def;
  399. } button_defs_t;
  400. button_defs_t button_defs[] = {
  401. { "12SP", 12, button_def_12sp }, /* First one is used if
  402. there's no match */
  403. { "30VIP", 26, button_def_30vip },
  404. { "7902", 12, button_def_7902 },
  405. { "7910", 10, button_def_7910 },
  406. { "7920", 6, button_def_7920 },
  407. { "7935", 2, button_def_7935 },
  408. { "7940", 2, button_def_7940 },
  409. { "7960", 6, button_def_7960 },
  410. { "7970", 8, button_def_7970 },
  411. { NULL, 0, NULL }
  412. };
  413. typedef struct button_template_res_message {
  414. UINT32 buttonOffset;
  415. UINT32 buttonCount;
  416. UINT32 totalButtonCount;
  417. button_definition definition[42];
  418. } button_template_res_message;
  419. #define VERSION_RES_MESSAGE 0x0098
  420. typedef struct version_res_message {
  421. char version[16];
  422. } version_res_message;
  423. #define KEEP_ALIVE_ACK_MESSAGE 0x0100
  424. #define OPEN_RECIEVE_CHANNEL_MESSAGE 0x0105
  425. typedef struct open_recieve_channel_message {
  426. int conferenceId;
  427. int partyId;
  428. int packets;
  429. int capability;
  430. int echo;
  431. int bitrate;
  432. } open_recieve_channel_message;
  433. #define CLOSE_RECIEVE_CHANNEL_MESSAGE 0x0106
  434. typedef struct close_recieve_channel_message {
  435. int conferenceId;
  436. int partyId;
  437. } close_recieve_channel_message;
  438. #define SOFT_KEY_TEMPLATE_RES_MESSAGE 0x0108
  439. typedef struct soft_key_template_definition {
  440. char softKeyLabel[16];
  441. int softKeyEvent;
  442. } soft_key_template_definition;
  443. soft_key_template_definition soft_key_template_default[] = {
  444. { "Redial", 1 },
  445. { "NewCall", 2 },
  446. { "Hold", 3 },
  447. { "Trnsfer", 4 },
  448. { "CFwdAll", 5 },
  449. { "CFwdBusy", 6 },
  450. { "CFwdNoAnswer", 7 },
  451. { "<<", 8 },
  452. { "EndCall", 9 },
  453. { "Resume", 10 },
  454. { "Answer", 11 },
  455. { "Info", 12 },
  456. { "Confrn", 13 },
  457. { "Park", 14 },
  458. { "Join", 15 },
  459. { "MeetMe", 16 },
  460. { "PickUp", 17 },
  461. { "GPickUp", 18 },
  462. };
  463. typedef struct soft_key_template {
  464. int softKeyOffset;
  465. int softKeyCount;
  466. int totalSoftKeyCount;
  467. soft_key_template_definition softKeyTemplateDefinition[32];
  468. } soft_key_template;
  469. #define SOFT_KEY_SET_RES_MESSAGE 0x0109
  470. static const char *soft_key_set_hack = {
  471. "\x01\x02\x05\x03\x09\x0a\x0b\x10\x11\x12\x04\x0e\x0d\x00\x00\x00"
  472. "\x2d\x01\x2e\x01\x31\x01\x2f\x01\x35\x01\x36\x01\x37\x01\x3c\x01"
  473. "\x3d\x01\x3e\x01\x30\x01\x3a\x01\x39\x01\x00\x00\x00\x00\x00\x00"
  474. "\x03\x09\x04\x0e\x0d\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  475. "\x2f\x01\x35\x01\x30\x01\x3a\x01\x39\x01\x3f\x01\x00\x00\x00\x00"
  476. "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  477. "\x0a\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  478. "\x36\x01\x2e\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  479. "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  480. "\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  481. "\x37\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  482. "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  483. "\x01\x09\x05\x10\x11\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  484. "\x2d\x01\x35\x01\x31\x01\x3c\x01\x3d\x01\x3e\x01\x00\x00\x00\x00"
  485. "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  486. "\x00\x09\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  487. "\x00\x00\x35\x01\x30\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  488. "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  489. "\x08\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  490. "\x34\x01\x35\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  491. "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  492. "\x00\x09\x0d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  493. "\x00\x00\x35\x01\x39\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  494. "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  495. "\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  496. "\x00\x00\x35\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  497. "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  498. "\x01\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  499. "\x2d\x01\x35\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  500. "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  501. "\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  502. "\x41\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  503. "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  504. };
  505. typedef struct soft_key_set_definition {
  506. UINT8 softKeyTemplateIndex[16];
  507. UINT16 softKeyInfoIndex[16];
  508. } soft_key_set_definition;
  509. typedef struct soft_key_sets {
  510. UINT32 softKeySetOffset;
  511. UINT32 softKeySetCount;
  512. UINT32 totalSoftKeySetCount;
  513. soft_key_set_definition softKeySetDefinition[16];
  514. UINT32 res;
  515. } soft_key_sets;
  516. #define SELECT_SOFT_KEYS_MESSAGE 0x0110
  517. typedef struct select_soft_keys_message {
  518. int instance;
  519. int reference;
  520. int softKeySetIndex;
  521. int validKeyMask;
  522. } select_soft_keys_message;
  523. #define CALL_STATE_MESSAGE 0x0111
  524. typedef struct call_state_message {
  525. int callState;
  526. int lineInstance;
  527. int callReference;
  528. } call_state_message;
  529. #define DISPLAY_PROMPT_STATUS_MESSAGE 0x0112
  530. typedef struct display_prompt_status_message {
  531. int messageTimeout;
  532. char promptMessage[32];
  533. int lineInstance;
  534. int callReference;
  535. } display_prompt_status_message;
  536. #define DISPLAY_NOTIFY_MESSAGE 0x0114
  537. typedef struct display_notify_message {
  538. int displayTimeout;
  539. char displayMessage[100];
  540. } display_notify_message;
  541. #define ACTIVATE_CALL_PLANE_MESSAGE 0x0116
  542. typedef struct activate_call_plane_message {
  543. int lineInstance;
  544. } activate_call_plane_message;
  545. #define DIALLED_NUMBER_MESSAGE 0x011D
  546. typedef struct dialled_number_message {
  547. char dialledNumber[24];
  548. int lineInstance;
  549. int callReference;
  550. } dialled_number_message;
  551. /* packet composition */
  552. typedef struct {
  553. int len;
  554. int res;
  555. int e;
  556. union {
  557. speed_dial_stat_req_message speeddialreq;
  558. register_message reg;
  559. register_ack_message regack;
  560. register_rej_message regrej;
  561. capabilities_res_message caps;
  562. version_res_message version;
  563. button_template_res_message buttontemplate;
  564. displaytext_message displaytext;
  565. display_prompt_status_message displaypromptstatus;
  566. definetimedate_message definetimedate;
  567. start_tone_message starttone;
  568. speed_dial_stat_res_message speeddial;
  569. line_state_req_message line;
  570. line_stat_res_message linestat;
  571. soft_key_sets softkeysets;
  572. soft_key_template softkeytemplate;
  573. server_res_message serverres;
  574. set_lamp_message setlamp;
  575. set_ringer_message setringer;
  576. call_state_message callstate;
  577. keypad_button_message keypad;
  578. select_soft_keys_message selectsoftkey;
  579. activate_call_plane_message activatecallplane;
  580. stimulus_message stimulus;
  581. set_speaker_message setspeaker;
  582. call_info_message callinfo;
  583. start_media_transmission_message startmedia;
  584. stop_media_transmission_message stopmedia;
  585. open_recieve_channel_message openrecievechannel;
  586. open_recieve_channel_ack_message openrecievechannelack;
  587. close_recieve_channel_message closerecievechannel;
  588. display_notify_message displaynotify;
  589. dialled_number_message diallednumber;
  590. } data;
  591. } skinny_req;
  592. /************************************************************************************/
  593. /* Asterisk specific globals */
  594. /************************************************************************************/
  595. static int skinnydebug = 1; /* XXX for now, enable debugging default */
  596. /* a hostname, portnumber, socket and such is usefull for VoIP protocols */
  597. static struct sockaddr_in bindaddr;
  598. static char ourhost[256];
  599. static int ourport;
  600. static struct in_addr __ourip;
  601. struct ast_hostent ahp; struct hostent *hp;
  602. static int skinnysock = -1;
  603. static pthread_t tcp_thread;
  604. static pthread_t accept_t;
  605. static char context[AST_MAX_CONTEXT] = "default";
  606. static char language[MAX_LANGUAGE] = "";
  607. static char musicclass[MAX_MUSICCLASS] = "";
  608. static char cid_num[AST_MAX_EXTENSION] = "";
  609. static char cid_name[AST_MAX_EXTENSION] = "";
  610. static char linelabel[AST_MAX_EXTENSION] ="";
  611. static int nat = 0;
  612. static ast_group_t cur_callergroup = 0;
  613. static ast_group_t cur_pickupgroup = 0;
  614. static int immediate = 0;
  615. static int callwaiting = 0;
  616. static int callreturn = 0;
  617. static int threewaycalling = 0;
  618. static int mwiblink = 0;
  619. /* This is for flashhook transfers */
  620. static int transfer = 0;
  621. static int cancallforward = 0;
  622. /* static int busycount = 3;*/
  623. static char accountcode[AST_MAX_ACCOUNT_CODE] = "";
  624. static char mailbox[AST_MAX_EXTENSION];
  625. static int amaflags = 0;
  626. static int callnums = 1;
  627. #define SUB_REAL 0
  628. #define SUB_ALT 1
  629. #define MAX_SUBS 2
  630. #define SKINNY_SPEAKERON 1
  631. #define SKINNY_SPEAKEROFF 2
  632. #define SKINNY_OFFHOOK 1
  633. #define SKINNY_ONHOOK 2
  634. #define SKINNY_RINGOUT 3
  635. #define SKINNY_RINGIN 4
  636. #define SKINNY_CONNECTED 5
  637. #define SKINNY_BUSY 6
  638. #define SKINNY_CONGESTION 7
  639. #define SKINNY_HOLD 8
  640. #define SKINNY_CALLWAIT 9
  641. #define SKINNY_TRANSFER 10
  642. #define SKINNY_PARK 11
  643. #define SKINNY_PROGRESS 12
  644. #define SKINNY_INVALID 14
  645. #define SKINNY_SILENCE 0x00
  646. #define SKINNY_DIALTONE 0x21
  647. #define SKINNY_BUSYTONE 0x23
  648. #define SKINNY_ALERT 0x24
  649. #define SKINNY_REORDER 0x25
  650. #define SKINNY_CALLWAITTONE 0x2D
  651. #define SKINNY_NOTONE 0x7F
  652. #define SKINNY_LAMP_OFF 1
  653. #define SKINNY_LAMP_ON 2
  654. #define SKINNY_LAMP_WINK 3
  655. #define SKINNY_LAMP_FLASH 4
  656. #define SKINNY_LAMP_BLINK 5
  657. #define SKINNY_RING_OFF 1
  658. #define SKINNY_RING_INSIDE 2
  659. #define SKINNY_RING_OUTSIDE 3
  660. #define SKINNY_RING_FEATURE 4
  661. #define TYPE_TRUNK 1
  662. #define TYPE_LINE 2
  663. /* Skinny rtp stream modes. Do we really need this? */
  664. #define SKINNY_CX_SENDONLY 0
  665. #define SKINNY_CX_RECVONLY 1
  666. #define SKINNY_CX_SENDRECV 2
  667. #define SKINNY_CX_CONF 3
  668. #define SKINNY_CX_CONFERENCE 3
  669. #define SKINNY_CX_MUTE 4
  670. #define SKINNY_CX_INACTIVE 4
  671. #if 0
  672. static char *skinny_cxmodes[] = {
  673. "sendonly",
  674. "recvonly",
  675. "sendrecv",
  676. "confrnce",
  677. "inactive"
  678. };
  679. #endif
  680. /* driver scheduler */
  681. static struct sched_context *sched;
  682. static struct io_context *io;
  683. /* usage count and locking */
  684. static int usecnt = 0;
  685. AST_MUTEX_DEFINE_STATIC(usecnt_lock);
  686. /* Protect the monitoring thread, so only one process can kill or start it, and not
  687. when it's doing something critical. */
  688. AST_MUTEX_DEFINE_STATIC(monlock);
  689. /* Protect the network socket */
  690. AST_MUTEX_DEFINE_STATIC(netlock);
  691. /* Protect the session list */
  692. AST_MUTEX_DEFINE_STATIC(sessionlock);
  693. /* Protect the device list */
  694. AST_MUTEX_DEFINE_STATIC(devicelock);
  695. #if 0
  696. /* Protect the paging device list */
  697. AST_MUTEX_DEFINE_STATIC(pagingdevicelock);
  698. #endif
  699. /* This is the thread for the monitor which checks for input on the channels
  700. which are not currently in use. */
  701. static pthread_t monitor_thread = AST_PTHREADT_NULL;
  702. /* Wait up to 16 seconds for first digit */
  703. static int firstdigittimeout = 16000;
  704. /* How long to wait for following digits */
  705. static int gendigittimeout = 8000;
  706. /* How long to wait for an extra digit, if there is an ambiguous match */
  707. static int matchdigittimeout = 3000;
  708. struct skinny_subchannel {
  709. ast_mutex_t lock;
  710. unsigned int callid;
  711. struct ast_channel *owner;
  712. struct skinny_line *parent;
  713. struct ast_rtp *rtp;
  714. time_t lastouttime;
  715. int progress;
  716. int ringing;
  717. int lastout;
  718. int cxmode;
  719. int nat;
  720. int outgoing;
  721. int alreadygone;
  722. struct skinny_subchannel *next;
  723. };
  724. struct skinny_line {
  725. ast_mutex_t lock;
  726. char name[80];
  727. char label[42]; /* Label that shows next to the line buttons */
  728. struct skinny_subchannel *sub; /* pointer to our current connection, channel and stuff */
  729. char accountcode[AST_MAX_ACCOUNT_CODE];
  730. char exten[AST_MAX_EXTENSION]; /* Extention where to start */
  731. char context[AST_MAX_CONTEXT];
  732. char language[MAX_LANGUAGE];
  733. char cid_num[AST_MAX_EXTENSION]; /* Caller*ID */
  734. char cid_name[AST_MAX_EXTENSION]; /* Caller*ID */
  735. char lastcallerid[AST_MAX_EXTENSION]; /* Last Caller*ID */
  736. char call_forward[AST_MAX_EXTENSION];
  737. char mailbox[AST_MAX_EXTENSION];
  738. char musicclass[MAX_MUSICCLASS];
  739. int curtone; /* Current tone being played */
  740. ast_group_t callgroup;
  741. ast_group_t pickupgroup;
  742. int callwaiting;
  743. int transfer;
  744. int threewaycalling;
  745. int mwiblink;
  746. int cancallforward;
  747. int callreturn;
  748. int dnd; /* How does this affect callwait? Do we just deny a skinny_request if we're dnd? */
  749. int hascallerid;
  750. int hidecallerid;
  751. int amaflags;
  752. int type;
  753. int instance;
  754. int group;
  755. int needdestroy;
  756. int capability;
  757. int nonCodecCapability;
  758. int onhooktime;
  759. int msgstate; /* voicemail message state */
  760. int immediate;
  761. int hookstate;
  762. int progress;
  763. struct skinny_line *next;
  764. struct skinny_device *parent;
  765. };
  766. static struct skinny_device {
  767. /* A device containing one or more lines */
  768. char name[80];
  769. char id[16];
  770. char version_id[16];
  771. int type;
  772. int registered;
  773. char model[6];
  774. struct sockaddr_in addr;
  775. struct in_addr ourip;
  776. struct skinny_line *lines;
  777. struct ast_ha *ha;
  778. struct skinnysession *session;
  779. struct skinny_device *next;
  780. } *devices = NULL;
  781. struct skinny_paging_device {
  782. char name[80];
  783. char id[16];
  784. struct skinny_device ** devices;
  785. struct skinny_paging_device *next;
  786. };
  787. static struct skinnysession {
  788. pthread_t t;
  789. ast_mutex_t lock;
  790. struct sockaddr_in sin;
  791. int fd;
  792. char inbuf[SKINNY_MAX_PACKET];
  793. struct skinny_device *device;
  794. struct skinnysession *next;
  795. } *sessions = NULL;
  796. static struct ast_channel *skinny_request(const char *type, int format, void *data, int *cause);
  797. static int skinny_call(struct ast_channel *ast, char *dest, int timeout);
  798. static int skinny_hangup(struct ast_channel *ast);
  799. static int skinny_answer(struct ast_channel *ast);
  800. static struct ast_frame *skinny_read(struct ast_channel *ast);
  801. static int skinny_write(struct ast_channel *ast, struct ast_frame *frame);
  802. static int skinny_indicate(struct ast_channel *ast, int ind);
  803. static int skinny_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
  804. static int skinny_senddigit(struct ast_channel *ast, char digit);
  805. static const struct ast_channel_tech skinny_tech = {
  806. .type = type,
  807. .description = tdesc,
  808. .capabilities = AST_FORMAT_ULAW,
  809. .properties = AST_CHAN_TP_WANTSJITTER,
  810. .requester = skinny_request,
  811. .call = skinny_call,
  812. .hangup = skinny_hangup,
  813. .answer = skinny_answer,
  814. .read = skinny_read,
  815. .write = skinny_write,
  816. .indicate = skinny_indicate,
  817. .fixup = skinny_fixup,
  818. .send_digit = skinny_senddigit,
  819. /* .bridge = ast_rtp_bridge, */
  820. };
  821. static skinny_req *req_alloc(size_t size)
  822. {
  823. skinny_req *req;
  824. req = malloc(size+12);
  825. if (!req) {
  826. return NULL;
  827. }
  828. memset(req, 0, size+12);
  829. return req;
  830. }
  831. static struct skinny_subchannel *find_subchannel_by_line(struct skinny_line *l)
  832. {
  833. /* XXX Need to figure out how to determine which sub we want */
  834. struct skinny_subchannel *sub = l->sub;
  835. return sub;
  836. }
  837. static struct skinny_subchannel *find_subchannel_by_name(char *dest)
  838. {
  839. struct skinny_line *l;
  840. struct skinny_device *d;
  841. char line[256];
  842. char *at;
  843. char *device;
  844. strncpy(line, dest, sizeof(line) - 1);
  845. at = strchr(line, '@');
  846. if (!at) {
  847. ast_log(LOG_NOTICE, "Device '%s' has no @ (at) sign!\n", dest);
  848. return NULL;
  849. }
  850. *at = '\0';
  851. at++;
  852. device = at;
  853. ast_mutex_lock(&devicelock);
  854. d = devices;
  855. while(d) {
  856. if (!strcasecmp(d->name, device)) {
  857. if (skinnydebug) {
  858. ast_verbose("Found device: %s\n", d->name);
  859. }
  860. /* Found the device */
  861. l = d->lines;
  862. while (l) {
  863. /* Search for the right line */
  864. if (!strcasecmp(l->name, line)) {
  865. ast_mutex_unlock(&devicelock);
  866. return l->sub;
  867. }
  868. l = l->next;
  869. }
  870. }
  871. d = d->next;
  872. }
  873. /* Device not found*/
  874. ast_mutex_unlock(&devicelock);
  875. return NULL;
  876. }
  877. static int transmit_response(struct skinnysession *s, skinny_req *req)
  878. {
  879. int res = 0;
  880. ast_mutex_lock(&s->lock);
  881. #if 0
  882. if (skinnydebug) {
  883. ast_verbose("writing packet type %04X (%d bytes) to socket %d\n", letohl(req->e), letohl(req->len)+8, s->fd);
  884. }
  885. #endif
  886. res = write(s->fd, req, letohl(req->len)+8);
  887. if (res != letohl(req->len)+8) {
  888. ast_log(LOG_WARNING, "Transmit: write only sent %d out of %d bytes: %s\n", res, letohl(req->len)+8, strerror(errno));
  889. }
  890. ast_mutex_unlock(&s->lock);
  891. return 1;
  892. }
  893. /* XXX Do this right */
  894. static int convert_cap(int capability)
  895. {
  896. return 4; /* ulaw (this is not the same as asterisk's '4' */
  897. }
  898. static void transmit_speaker_mode(struct skinnysession *s, int mode)
  899. {
  900. skinny_req *req;
  901. req = req_alloc(sizeof(struct set_speaker_message));
  902. if (!req) {
  903. ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
  904. return;
  905. }
  906. req->len = htolel(sizeof(set_speaker_message)+4);
  907. req->e = htolel(SET_SPEAKER_MESSAGE);
  908. req->data.setspeaker.mode = htolel(mode);
  909. transmit_response(s, req);
  910. }
  911. static void transmit_callstate(struct skinnysession *s, int instance, int state, unsigned callid)
  912. {
  913. skinny_req *req;
  914. int memsize = sizeof(struct call_state_message);
  915. req = req_alloc(memsize);
  916. if (!req) {
  917. ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
  918. return;
  919. }
  920. if (state == SKINNY_ONHOOK) {
  921. transmit_speaker_mode(s, SKINNY_SPEAKEROFF);
  922. }
  923. req->len = htolel(sizeof(call_state_message)+4);
  924. req->e = htolel(CALL_STATE_MESSAGE);
  925. req->data.callstate.callState = htolel(state);
  926. req->data.callstate.lineInstance = htolel(instance);
  927. req->data.callstate.callReference = htolel(callid);
  928. transmit_response(s, req);
  929. if (state == SKINNY_OFFHOOK) {
  930. memset(req, 0, memsize);
  931. req->len = htolel(sizeof(activate_call_plane_message)+4);
  932. req->e = htolel(ACTIVATE_CALL_PLANE_MESSAGE);
  933. req->data.activatecallplane.lineInstance = htolel(instance);
  934. transmit_response(s, req);
  935. } else if (state == SKINNY_ONHOOK) {
  936. memset(req, 0, memsize);
  937. req->len = htolel(sizeof(activate_call_plane_message)+4);
  938. req->e = htolel(ACTIVATE_CALL_PLANE_MESSAGE);
  939. req->data.activatecallplane.lineInstance = 0;
  940. transmit_response(s, req);
  941. memset(req, 0, memsize);
  942. req->len = htolel(sizeof(close_recieve_channel_message)+4);
  943. req->e = htolel(CLOSE_RECIEVE_CHANNEL_MESSAGE);
  944. req->data.closerecievechannel.conferenceId = 0;
  945. req->data.closerecievechannel.partyId = 0;
  946. transmit_response(s, req);
  947. memset(req, 0, memsize);
  948. req->len = htolel(sizeof(stop_media_transmission_message)+4);
  949. req->e = htolel(STOP_MEDIA_TRANSMISSION_MESSAGE);
  950. req->data.stopmedia.conferenceId = 0;
  951. req->data.stopmedia.passThruPartyId = 0;
  952. transmit_response(s, req);
  953. }
  954. }
  955. static void transmit_callinfo(struct skinnysession *s, char *fromname, char *fromnum, char *toname, char *tonum, int instance, int callid, int calltype)
  956. {
  957. skinny_req *req;
  958. req = req_alloc(sizeof(struct call_info_message));
  959. if (!req) {
  960. ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
  961. return;
  962. }
  963. req->len = htolel(sizeof(struct call_info_message));
  964. req->e = htolel(CALL_INFO_MESSAGE);
  965. if (fromname) {
  966. ast_copy_string(req->data.callinfo.callingPartyName, fromname, sizeof(req->data.callinfo.callingPartyName));
  967. }
  968. if (fromnum) {
  969. ast_copy_string(req->data.callinfo.callingParty, fromnum, sizeof(req->data.callinfo.callingParty));
  970. }
  971. if (toname) {
  972. ast_copy_string(req->data.callinfo.calledPartyName, toname, sizeof(req->data.callinfo.calledPartyName));
  973. }
  974. if (tonum) {
  975. ast_copy_string(req->data.callinfo.calledParty, tonum, sizeof(req->data.callinfo.calledParty));
  976. }
  977. req->data.callinfo.instance = htolel(instance);
  978. req->data.callinfo.reference = htolel(callid);
  979. req->data.callinfo.type = htolel(calltype);
  980. transmit_response(s, req);
  981. }
  982. static void transmit_connect(struct skinnysession *s)
  983. {
  984. skinny_req *req;
  985. struct skinny_line *l = s->device->lines;
  986. req = req_alloc(sizeof(struct open_recieve_channel_message));
  987. if (!req) {
  988. ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
  989. return;
  990. }
  991. req->len = htolel(sizeof(struct open_recieve_channel_message));
  992. req->e = htolel(OPEN_RECIEVE_CHANNEL_MESSAGE);
  993. req->data.openrecievechannel.conferenceId = 0;
  994. req->data.openrecievechannel.partyId = 0;
  995. req->data.openrecievechannel.packets = htolel(20);
  996. req->data.openrecievechannel.capability = htolel(convert_cap(l->capability));
  997. req->data.openrecievechannel.echo = 0;
  998. req->data.openrecievechannel.bitrate = 0;
  999. transmit_response(s, req);
  1000. }
  1001. static void transmit_tone(struct skinnysession *s, int tone)
  1002. {
  1003. skinny_req *req;
  1004. if (tone > 0) {
  1005. req = req_alloc(sizeof(struct start_tone_message));
  1006. } else {
  1007. req = req_alloc(4);
  1008. }
  1009. if (!req) {
  1010. ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
  1011. return;
  1012. }
  1013. if (tone > 0) {
  1014. req->len = htolel(sizeof(start_tone_message)+4);
  1015. req->e = htolel(START_TONE_MESSAGE);
  1016. req->data.starttone.tone = htolel(tone);
  1017. } else {
  1018. req->len = htolel(4);
  1019. req->e = htolel(STOP_TONE_MESSAGE);
  1020. }
  1021. transmit_response(s, req);
  1022. }
  1023. #if 0
  1024. /* XXX need to properly deal with softkeys */
  1025. static void transmit_selectsoftkeys(struct skinnysession *s, int instance, int callid, int softkey)
  1026. {
  1027. skinny_req *req;
  1028. int memsize = sizeof(struct select_soft_keys_message);
  1029. req = req_alloc(memsize);
  1030. if (!req) {
  1031. ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
  1032. return;
  1033. }
  1034. memset(req, 0, memsize);
  1035. req->len = htolel(sizeof(select_soft_keys_message)+4);
  1036. req->e = htolel(SELECT_SOFT_KEYS_MESSAGE);
  1037. req->data.selectsoftkey.instance = htolel(instance);
  1038. req->data.selectsoftkey.reference = htolel(callid);
  1039. req->data.selectsoftkey.softKeySetIndex = htolel(softkey);
  1040. transmit_response(s, req);
  1041. }
  1042. #endif
  1043. static void transmit_lamp_indication(struct skinnysession *s, int stimulus, int instance, int indication)
  1044. {
  1045. skinny_req *req;
  1046. req = req_alloc(sizeof(struct set_lamp_message));
  1047. if (!req) {
  1048. ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
  1049. return;
  1050. }
  1051. req->len = htolel(sizeof(set_lamp_message)+4);
  1052. req->e = htolel(SET_LAMP_MESSAGE);
  1053. req->data.setlamp.stimulus = htolel(stimulus);
  1054. req->data.setlamp.stimulusInstance = htolel(instance);
  1055. req->data.setlamp.deviceStimulus = htolel(indication);
  1056. transmit_response(s, req);
  1057. }
  1058. static void transmit_ringer_mode(struct skinnysession *s, int mode)
  1059. {
  1060. skinny_req *req;
  1061. req = req_alloc(sizeof(struct set_ringer_message));
  1062. if (!req) {
  1063. ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
  1064. return;
  1065. }
  1066. req->len = htolel(sizeof(set_ringer_message)+4);
  1067. req->e = htolel(SET_RINGER_MESSAGE);
  1068. req->data.setringer.ringerMode = htolel(mode);
  1069. transmit_response(s, req);
  1070. }
  1071. static void transmit_displaymessage(struct skinnysession *s, char *text)
  1072. {
  1073. skinny_req *req;
  1074. if (text == 0) {
  1075. req = req_alloc(4);
  1076. req->len = htolel(4);
  1077. req->e = htolel(CLEAR_DISPLAY_MESSAGE);
  1078. } else {
  1079. req = req_alloc(sizeof(struct displaytext_message));
  1080. strncpy(req->data.displaytext.text, text, sizeof(req->data.displaytext.text)-1);
  1081. req->len = htolel(sizeof(displaytext_message) + 4);
  1082. req->e = htolel(DISPLAYTEXT_MESSAGE);
  1083. if (skinnydebug) {
  1084. ast_verbose("Displaying message '%s'\n", req->data.displaytext.text);
  1085. }
  1086. }
  1087. if (!req) {
  1088. ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
  1089. return;
  1090. }
  1091. transmit_response(s, req);
  1092. }
  1093. static void transmit_displaynotify(struct skinnysession *s, char *text, int t)
  1094. {
  1095. skinny_req *req;
  1096. req = req_alloc(sizeof(struct display_notify_message));
  1097. if (!req) {
  1098. ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
  1099. return;
  1100. }
  1101. req->e = htolel(DISPLAY_NOTIFY_MESSAGE);
  1102. req->len = htolel(sizeof(display_notify_message) + 4);
  1103. strncpy(req->data.displaynotify.displayMessage, text, sizeof(req->data.displaynotify.displayMessage)-1);
  1104. req->data.displaynotify.displayTimeout = htolel(t);
  1105. if (skinnydebug) {
  1106. ast_verbose("Displaying notify '%s'\n", text);
  1107. }
  1108. transmit_response(s, req);
  1109. }
  1110. static void transmit_displaypromptstatus(struct skinnysession *s, char *text, int t, int instance, int callid)
  1111. {
  1112. skinny_req *req;
  1113. req = req_alloc(sizeof(struct display_prompt_status_message));
  1114. if (!req) {
  1115. ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
  1116. return;
  1117. }
  1118. req->e = htolel(DISPLAY_PROMPT_STATUS_MESSAGE);
  1119. req->len = htolel(sizeof(display_prompt_status_message) + 4);
  1120. strncpy(req->data.displaypromptstatus.promptMessage, text, sizeof(req->data.displaypromptstatus.promptMessage)-1);
  1121. req->data.displaypromptstatus.messageTimeout = htolel(t);
  1122. req->data.displaypromptstatus.lineInstance = htolel(instance);
  1123. req->data.displaypromptstatus.callReference = htolel(callid);
  1124. if (skinnydebug) {
  1125. ast_verbose("Displaying Prompt Status '%s'\n", text);
  1126. }
  1127. transmit_response(s, req);
  1128. }
  1129. static void transmit_diallednumber(struct skinnysession *s, char *text, int instance, int callid)
  1130. {
  1131. skinny_req *req;
  1132. req = req_alloc(sizeof(struct dialled_number_message));
  1133. if (!req) {
  1134. ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
  1135. return;
  1136. }
  1137. req->e = htolel(DIALLED_NUMBER_MESSAGE);
  1138. req->len = htolel(sizeof(dialled_number_message) + 4);
  1139. strncpy(req->data.diallednumber.dialledNumber, text, sizeof(req->data.diallednumber.dialledNumber)-1);
  1140. req->data.diallednumber.lineInstance = htolel(instance);
  1141. req->data.diallednumber.callReference = htolel(callid);
  1142. transmit_response(s, req);
  1143. }
  1144. static int has_voicemail(struct skinny_line *l)
  1145. {
  1146. return ast_app_has_voicemail(l->mailbox, NULL);
  1147. }
  1148. static void do_housekeeping(struct skinnysession *s)
  1149. {
  1150. int new;
  1151. int old;
  1152. struct skinny_subchannel *sub;
  1153. struct skinny_line *l = s->device->lines;
  1154. sub = find_subchannel_by_line(l);
  1155. transmit_displaymessage(s, NULL);
  1156. if (has_voicemail(sub->parent)) {
  1157. if (skinnydebug) {
  1158. ast_verbose("Checking for voicemail Skinny %s@%s\n", sub->parent->name, sub->parent->parent->name);
  1159. }
  1160. ast_app_messagecount(sub->parent->mailbox, &new, &old);
  1161. if (skinnydebug) {
  1162. ast_verbose("Skinny %s@%s has voicemail!\n", sub->parent->name, sub->parent->parent->name);
  1163. }
  1164. transmit_lamp_indication(s, STIMULUS_VOICEMAIL, l->instance, l->mwiblink?SKINNY_LAMP_BLINK:SKINNY_LAMP_ON);
  1165. } else {
  1166. transmit_lamp_indication(s, STIMULUS_VOICEMAIL, l->instance, SKINNY_LAMP_OFF);
  1167. }
  1168. }
  1169. /* I do not believe skinny can deal with video.
  1170. Anyone know differently? */
  1171. static struct ast_rtp *skinny_get_vrtp_peer(struct ast_channel *chan)
  1172. {
  1173. return NULL;
  1174. }
  1175. static struct ast_rtp *skinny_get_rtp_peer(struct ast_channel *chan)
  1176. {
  1177. struct skinny_subchannel *sub;
  1178. sub = chan->tech_pvt;
  1179. if (sub && sub->rtp) {
  1180. return sub->rtp;
  1181. }
  1182. return NULL;
  1183. }
  1184. static int skinny_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active)
  1185. {
  1186. struct skinny_subchannel *sub;
  1187. sub = chan->tech_pvt;
  1188. if (sub) {
  1189. /* transmit_modify_with_sdp(sub, rtp); @@FIXME@@ if needed */
  1190. return 0;
  1191. }
  1192. return -1;
  1193. }
  1194. static struct ast_rtp_protocol skinny_rtp = {
  1195. .type = type,
  1196. .get_rtp_info = skinny_get_rtp_peer,
  1197. .get_vrtp_info = skinny_get_vrtp_peer,
  1198. .set_rtp_peer = skinny_set_rtp_peer,
  1199. };
  1200. static int skinny_do_debug(int fd, int argc, char *argv[])
  1201. {
  1202. if (argc != 2) {
  1203. return RESULT_SHOWUSAGE;
  1204. }
  1205. skinnydebug = 1;
  1206. ast_cli(fd, "Skinny Debugging Enabled\n");
  1207. return RESULT_SUCCESS;
  1208. }
  1209. static int skinny_no_debug(int fd, int argc, char *argv[])
  1210. {
  1211. if (argc != 3) {
  1212. return RESULT_SHOWUSAGE;
  1213. }
  1214. skinnydebug = 0;
  1215. ast_cli(fd, "Skinny Debugging Disabled\n");
  1216. return RESULT_SUCCESS;
  1217. }
  1218. static int skinny_show_devices(int fd, int argc, char *argv[])
  1219. {
  1220. struct skinny_device *d;
  1221. struct skinny_line *l;
  1222. int numlines = 0;
  1223. char iabuf[INET_ADDRSTRLEN];
  1224. if (argc != 3) {
  1225. return RESULT_SHOWUSAGE;
  1226. }
  1227. ast_mutex_lock(&devicelock);
  1228. d = devices;
  1229. ast_cli(fd, "Name DeviceId IP TypeId R Model NL\n");
  1230. ast_cli(fd, "-------------------- ---------------- --------------- ------ - ------ --\n");
  1231. while(d) {
  1232. l = d->lines;
  1233. numlines = 0;
  1234. while(l) { numlines++; l = l->next; }
  1235. ast_cli(fd, "%-20s %-16s %-16s %6X %c %-6s %2d\n",
  1236. d->name,
  1237. d->id,
  1238. ast_inet_ntoa(iabuf, sizeof(iabuf), d->addr.sin_addr),
  1239. d->type,
  1240. d->registered?'Y':'N',
  1241. d->model,
  1242. numlines);
  1243. d = d->next;
  1244. }
  1245. ast_mutex_unlock(&devicelock);
  1246. return RESULT_SUCCESS;
  1247. }
  1248. static int skinny_show_lines(int fd, int argc, char *argv[])
  1249. {
  1250. struct skinny_device *d;
  1251. struct skinny_line *l;
  1252. if (argc != 3) {
  1253. return RESULT_SHOWUSAGE;
  1254. }
  1255. ast_mutex_lock(&devicelock);
  1256. d = devices;
  1257. while(d) {
  1258. l = d->lines;
  1259. while (l) {
  1260. ast_cli(fd, "%-20s %2d %-20s %-20s %c %c\n",
  1261. l->parent->name,
  1262. l->instance,
  1263. l->name,
  1264. l->label,
  1265. l->sub->owner?'Y':'N',
  1266. l->sub->rtp?'Y':'N');
  1267. l = l->next;
  1268. }
  1269. d = d->next;
  1270. }
  1271. ast_mutex_unlock(&devicelock);
  1272. return RESULT_SUCCESS;
  1273. }
  1274. static char show_devices_usage[] =
  1275. "Usage: skinny show devices\n"
  1276. " Lists all devices known to the Skinny subsystem.\n";
  1277. static char show_lines_usage[] =
  1278. "Usage: skinny show lines\n"
  1279. " Lists all lines known to the Skinny subsystem.\n";
  1280. static char debug_usage[] =
  1281. "Usage: skinny debug\n"
  1282. " Enables dumping of Skinny packets for debugging purposes\n";
  1283. static char no_debug_usage[] =
  1284. "Usage: skinny no debug\n"
  1285. " Disables dumping of Skinny packets for debugging purposes\n";
  1286. static struct ast_cli_entry cli_show_devices =
  1287. { { "skinny", "show", "devices", NULL }, skinny_show_devices, "Show defined Skinny devices", show_devices_usage };
  1288. static struct ast_cli_entry cli_show_lines =
  1289. { { "skinny", "show", "lines", NULL }, skinny_show_lines, "Show defined Skinny lines per device", show_lines_usage };
  1290. static struct ast_cli_entry cli_debug =
  1291. { { "skinny", "debug", NULL }, skinny_do_debug, "Enable Skinny debugging", debug_usage };
  1292. static struct ast_cli_entry cli_no_debug =
  1293. { { "skinny", "no", "debug", NULL }, skinny_no_debug, "Disable Skinny debugging", no_debug_usage };
  1294. #if 0
  1295. static struct skinny_paging_device *build_paging_device(char *cat, struct ast_variable *v)
  1296. {
  1297. return NULL;
  1298. }
  1299. #endif
  1300. static struct skinny_device *build_device(char *cat, struct ast_variable *v)
  1301. {
  1302. struct skinny_device *d;
  1303. struct skinny_line *l;
  1304. struct skinny_subchannel *sub;
  1305. int i=0, y=0;
  1306. d = malloc(sizeof(struct skinny_device));
  1307. if (d) {
  1308. memset(d, 0, sizeof(struct skinny_device));
  1309. strncpy(d->name, cat, sizeof(d->name) - 1);
  1310. while(v) {
  1311. if (!strcasecmp(v->name, "host")) {
  1312. if (ast_get_ip(&d->addr, v->value)) {
  1313. free(d);
  1314. return NULL;
  1315. }
  1316. } else if (!strcasecmp(v->name, "port")) {
  1317. d->addr.sin_port = htons(atoi(v->value));
  1318. } else if (!strcasecmp(v->name, "device")) {
  1319. strncpy(d->id, v->value, sizeof(d->id)-1);
  1320. } else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) {
  1321. d->ha = ast_append_ha(v->name, v->value, d->ha);
  1322. } else if (!strcasecmp(v->name, "context")) {
  1323. strncpy(context, v->value, sizeof(context) - 1);
  1324. } else if (!strcasecmp(v->name, "version")) {
  1325. strncpy(d->version_id, v->value, sizeof(d->version_id) -1);
  1326. } else if (!strcasecmp(v->name, "nat")) {
  1327. nat = ast_true(v->value);
  1328. } else if (!strcasecmp(v->name, "model")) {
  1329. strncpy(d->model, v->value, sizeof(d->model) - 1);
  1330. } else if (!strcasecmp(v->name, "callerid")) {
  1331. if (!strcasecmp(v->value, "asreceived")) {
  1332. cid_num[0] = '\0';
  1333. cid_name[0] = '\0';
  1334. } else {
  1335. ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
  1336. }
  1337. } else if (!strcasecmp(v->name, "language")) {
  1338. strncpy(language, v->value, sizeof(language)-1);
  1339. } else if (!strcasecmp(v->name, "accountcode")) {
  1340. strncpy(accountcode, v->value, sizeof(accountcode)-1);
  1341. } else if (!strcasecmp(v->name, "amaflags")) {
  1342. y = ast_cdr_amaflags2int(v->value);
  1343. if (y < 0) {
  1344. ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
  1345. } else {
  1346. amaflags = y;
  1347. }
  1348. } else if (!strcasecmp(v->name, "musiconhold")) {
  1349. strncpy(musicclass, v->value, sizeof(musicclass)-1);
  1350. } else if (!strcasecmp(v->name, "callgroup")) {
  1351. cur_callergroup = ast_get_group(v->value);
  1352. } else if (!strcasecmp(v->name, "pickupgroup")) {
  1353. cur_pickupgroup = ast_get_group(v->value);
  1354. } else if (!strcasecmp(v->name, "immediate")) {
  1355. immediate = ast_true(v->value);
  1356. } else if (!strcasecmp(v->name, "cancallforward")) {
  1357. cancallforward = ast_true(v->value);
  1358. } else if (!strcasecmp(v->name, "mailbox")) {
  1359. strncpy(mailbox, v->value, sizeof(mailbox) -1);
  1360. } else if (!strcasecmp(v->name, "callreturn")) {
  1361. callreturn = ast_true(v->value);
  1362. } else if (!strcasecmp(v->name, "callwaiting")) {
  1363. callwaiting = ast_true(v->value);
  1364. } else if (!strcasecmp(v->name, "transfer")) {
  1365. transfer = ast_true(v->value);
  1366. } else if (!strcasecmp(v->name, "threewaycalling")) {
  1367. threewaycalling = ast_true(v->value);
  1368. } else if (!strcasecmp(v->name, "mwiblink")) {
  1369. mwiblink = ast_true(v->value);
  1370. } else if (!strcasecmp(v->name, "linelabel")) {
  1371. strncpy(linelabel, v->value, sizeof(linelabel)-1);
  1372. } else if (!strcasecmp(v->name, "trunk") || !strcasecmp(v->name, "line")) {
  1373. l = malloc(sizeof(struct skinny_line));;
  1374. if (l) {
  1375. memset(l, 0, sizeof(struct skinny_line));
  1376. ast_mutex_init(&l->lock);
  1377. strncpy(l->name, v->value, sizeof(l->name) - 1);
  1378. /* XXX Should we check for uniqueness?? XXX */
  1379. strncpy(l->context, context, sizeof(l->context) - 1);
  1380. strncpy(l->cid_num, cid_num, sizeof(l->cid_num) - 1);
  1381. strncpy(l->cid_name, cid_name, sizeof(l->cid_name) - 1);
  1382. strncpy(l->label, linelabel, sizeof(l->label) - 1);
  1383. strncpy(l->language, language, sizeof(l->language) - 1);
  1384. strncpy(l->musicclass, musicclass, sizeof(l->musicclass)-1);
  1385. strncpy(l->mailbox, mailbox, sizeof(l->mailbox)-1);
  1386. strncpy(l->mailbox, mailbox, sizeof(l->mailbox)-1);
  1387. if (!ast_strlen_zero(mailbox)) {
  1388. ast_verbose(VERBOSE_PREFIX_3 "Setting mailbox '%s' on %s@%s\n", mailbox, d->name, l->name);
  1389. }
  1390. l->msgstate = -1;
  1391. l->capability = capability;
  1392. l->parent = d;
  1393. if (!strcasecmp(v->name, "trunk")) {
  1394. l->type = TYPE_TRUNK;
  1395. } else {
  1396. l->type = TYPE_LINE;
  1397. }
  1398. l->immediate = immediate;
  1399. l->callgroup = cur_callergroup;
  1400. l->pickupgroup = cur_pickupgroup;
  1401. l->callreturn = callreturn;
  1402. l->cancallforward = cancallforward;
  1403. l->callwaiting = callwaiting;
  1404. l->transfer = transfer;
  1405. l->threewaycalling = threewaycalling;
  1406. l->mwiblink = mwiblink;
  1407. l->onhooktime = time(NULL);
  1408. l->instance = 1;
  1409. /* ASSUME we're onhook at this point*/
  1410. l->hookstate = SKINNY_ONHOOK;
  1411. for (i = 0; i < MAX_SUBS; i++) {
  1412. sub = malloc(sizeof(struct skinny_subchannel));
  1413. if (sub) {
  1414. ast_verbose(VERBOSE_PREFIX_3 "Allocating Skinny subchannel '%d' on %s@%s\n", i, l->name, d->name);
  1415. memset(sub, 0, sizeof(struct skinny_subchannel));
  1416. ast_mutex_init(&sub->lock);
  1417. sub->parent = l;
  1418. /* Make a call*ID */
  1419. sub->callid = callnums;
  1420. callnums++;
  1421. sub->cxmode = SKINNY_CX_INACTIVE;
  1422. sub->nat = nat;
  1423. sub->next = l->sub;
  1424. l->sub = sub;
  1425. } else {
  1426. /* XXX Should find a way to clean up our memory */
  1427. ast_log(LOG_WARNING, "Out of memory allocating subchannel");
  1428. return NULL;
  1429. }
  1430. }
  1431. l->next = d->lines;
  1432. d->lines = l;
  1433. } else {
  1434. /* XXX Should find a way to clean up our memory */
  1435. ast_log(LOG_WARNING, "Out of memory allocating line");
  1436. return NULL;
  1437. }
  1438. } else {
  1439. ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
  1440. }
  1441. v = v->next;
  1442. }
  1443. if (!d->lines) {
  1444. ast_log(LOG_ERROR, "A Skinny device must have at least one line!\n");
  1445. return NULL;
  1446. }
  1447. if (d->addr.sin_addr.s_addr && !ntohs(d->addr.sin_port)) {
  1448. d->addr.sin_port = htons(DEFAULT_SKINNY_PORT);
  1449. }
  1450. if (d->addr.sin_addr.s_addr) {
  1451. if (ast_ouraddrfor(&d->addr.sin_addr, &d->ourip)) {
  1452. memcpy(&d->ourip, &__ourip, sizeof(d->ourip));
  1453. }
  1454. } else {
  1455. memcpy(&d->ourip, &__ourip, sizeof(d->ourip));
  1456. }
  1457. }
  1458. return d;
  1459. }
  1460. static int skinny_register(skinny_req *req, struct skinnysession *s)
  1461. {
  1462. struct skinny_device *d;
  1463. ast_mutex_lock(&devicelock);
  1464. d = devices;
  1465. while (d) {
  1466. if (!strcasecmp(req->data.reg.name, d->id)
  1467. && ast_apply_ha(d->ha, &(s->sin))) {
  1468. s->device = d;
  1469. d->type = letohl(req->data.reg.type);
  1470. if (ast_strlen_zero(d->version_id)) {
  1471. strncpy(d->version_id, version_id, sizeof(d->version_id) - 1);
  1472. }
  1473. d->registered = 1;
  1474. d->session = s;
  1475. break;
  1476. }
  1477. d = d->next;
  1478. }
  1479. ast_mutex_unlock(&devicelock);
  1480. if (!d) {
  1481. return 0;
  1482. }
  1483. return 1;
  1484. }
  1485. static void start_rtp(struct skinny_subchannel *sub)
  1486. {
  1487. ast_mutex_lock(&sub->lock);
  1488. /* Allocate the RTP */
  1489. sub->rtp = ast_rtp_new(sched, io, 1, 0);
  1490. if (sub->rtp && sub->owner) {
  1491. sub->owner->fds[0] = ast_rtp_fd(sub->rtp);
  1492. }
  1493. if (sub->rtp) {
  1494. ast_rtp_setnat(sub->rtp, sub->nat);
  1495. }
  1496. /* Create the RTP connection */
  1497. transmit_connect(sub->parent->parent->session);
  1498. ast_mutex_unlock(&sub->lock);
  1499. }
  1500. static void *skinny_ss(void *data)
  1501. {
  1502. struct ast_channel *chan = data;
  1503. struct skinny_subchannel *sub = chan->tech_pvt;
  1504. struct skinny_line *l = sub->parent;
  1505. struct skinnysession *s = l->parent->session;
  1506. char exten[AST_MAX_EXTENSION] = "";
  1507. int len = 0;
  1508. int timeout = firstdigittimeout;
  1509. int res;
  1510. int getforward=0;
  1511. if (option_verbose > 2) {
  1512. ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s@%s'\n", l->name, l->parent->name);
  1513. }
  1514. while(len < AST_MAX_EXTENSION-1) {
  1515. res = ast_waitfordigit(chan, timeout);
  1516. timeout = 0;
  1517. if (res < 0) {
  1518. if (skinnydebug) {
  1519. ast_verbose("Skinny(%s@%s): waitfordigit returned < 0\n", l->name, l->parent->name);
  1520. }
  1521. ast_indicate(chan, -1);
  1522. ast_hangup(chan);
  1523. return NULL;
  1524. } else if (res) {
  1525. exten[len++]=res;
  1526. exten[len] = '\0';
  1527. }
  1528. if (!ast_ignore_pattern(chan->context, exten)) {
  1529. transmit_tone(s, SKINNY_SILENCE);
  1530. }
  1531. if (ast_exists_extension(chan, chan->context, exten, 1, l->cid_num)) {
  1532. if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, l->cid_num)) {
  1533. if (getforward) {
  1534. /* Record this as the forwarding extension */
  1535. strncpy(l->call_forward, exten, sizeof(l->call_forward) - 1);
  1536. if (option_verbose > 2) {
  1537. ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %s\n",
  1538. l->call_forward, chan->name);
  1539. }
  1540. transmit_tone(s, SKINNY_DIALTONE);
  1541. if (res) {
  1542. break;
  1543. }
  1544. ast_safe_sleep(chan, 500);
  1545. ast_indicate(chan, -1);
  1546. ast_safe_sleep(chan, 1000);
  1547. memset(exten, 0, sizeof(exten));
  1548. transmit_tone(s, SKINNY_DIALTONE);
  1549. len = 0;
  1550. getforward = 0;
  1551. } else {
  1552. strncpy(chan->exten, exten, sizeof(chan->exten)-1);
  1553. if (!ast_strlen_zero(l->cid_num)) {
  1554. if (!l->hidecallerid) {
  1555. chan->cid.cid_num = strdup(l->cid_num);
  1556. chan->cid.cid_ani = strdup(l->cid_num);
  1557. }
  1558. ast_setstate(chan, AST_STATE_RING);
  1559. res = ast_pbx_run(chan);
  1560. if (res) {
  1561. ast_log(LOG_WARNING, "PBX exited non-zero\n");
  1562. transmit_tone(s, SKINNY_REORDER);
  1563. }
  1564. return NULL;
  1565. }
  1566. }
  1567. } else {
  1568. /* It's a match, but they just typed a digit, and there is an ambiguous match,
  1569. so just set the timeout to matchdigittimeout and wait some more */
  1570. timeout = matchdigittimeout;
  1571. }
  1572. } else if (res == 0) {
  1573. ast_log(LOG_DEBUG, "Not enough digits (and no ambiguous match)...\n");
  1574. transmit_tone(s, SKINNY_REORDER);
  1575. ast_hangup(chan);
  1576. return NULL;
  1577. } else if (l->callwaiting && !strcmp(exten, "*70")) {
  1578. if (option_verbose > 2) {
  1579. ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
  1580. }
  1581. /* Disable call waiting if enabled */
  1582. l->callwaiting = 0;
  1583. transmit_tone(s, SKINNY_DIALTONE);
  1584. len = 0;
  1585. memset(exten, 0, sizeof(exten));\
  1586. timeout = firstdigittimeout;
  1587. } else if (!strcmp(exten,ast_pickup_ext())) {
  1588. /* Scan all channels and see if any there
  1589. * ringing channqels with that have call groups
  1590. * that equal this channels pickup group
  1591. */
  1592. if (ast_pickup_call(chan)) {
  1593. ast_log(LOG_WARNING, "No call pickup possible...\n");
  1594. transmit_tone(s, SKINNY_REORDER);
  1595. }
  1596. ast_hangup(chan);
  1597. return NULL;
  1598. } else if (!l->hidecallerid && !strcmp(exten, "*67")) {
  1599. if (option_verbose > 2) {
  1600. ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
  1601. }
  1602. /* Disable Caller*ID if enabled */
  1603. l->hidecallerid = 1;
  1604. if (chan->cid.cid_num) {
  1605. free(chan->cid.cid_num);
  1606. }
  1607. chan->cid.cid_num = NULL;
  1608. if (chan->cid.cid_name) {
  1609. free(chan->cid.cid_name);
  1610. }
  1611. chan->cid.cid_name = NULL;
  1612. transmit_tone(s, SKINNY_DIALTONE);
  1613. len = 0;
  1614. memset(exten, 0, sizeof(exten));
  1615. timeout = firstdigittimeout;
  1616. } else if (l->callreturn && !strcmp(exten, "*69")) {
  1617. res = 0;
  1618. if (!ast_strlen_zero(l->lastcallerid)) {
  1619. res = ast_say_digit_str(chan, l->lastcallerid, "", chan->language);
  1620. }
  1621. if (!res) {
  1622. transmit_tone(s, SKINNY_DIALTONE);
  1623. }
  1624. break;
  1625. } else if (!strcmp(exten, "*78")) {
  1626. /* Do not disturb */
  1627. if (option_verbose > 2) {
  1628. ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %s\n", chan->name);
  1629. }
  1630. transmit_tone(s, SKINNY_DIALTONE);
  1631. l->dnd = 1;
  1632. getforward = 0;
  1633. memset(exten, 0, sizeof(exten));
  1634. len = 0;
  1635. } else if (!strcmp(exten, "*79")) {
  1636. /* Do not disturb */
  1637. if (option_verbose > 2) {
  1638. ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %s\n", chan->name);
  1639. }
  1640. transmit_tone(s, SKINNY_DIALTONE);
  1641. l->dnd = 0;
  1642. getforward = 0;
  1643. memset(exten, 0, sizeof(exten));
  1644. len = 0;
  1645. } else if (l->cancallforward && !strcmp(exten, "*72")) {
  1646. transmit_tone(s, SKINNY_DIALTONE);
  1647. getforward = 1;
  1648. memset(exten, 0, sizeof(exten));
  1649. len = 0;
  1650. } else if (l->cancallforward && !strcmp(exten, "*73")) {
  1651. if (option_verbose > 2) {
  1652. ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %s\n", chan->name);
  1653. }
  1654. transmit_tone(s, SKINNY_DIALTONE);
  1655. memset(l->call_forward, 0, sizeof(l->call_forward));
  1656. getforward = 0;
  1657. memset(exten, 0, sizeof(exten));
  1658. len = 0;
  1659. } else if (!strcmp(exten, ast_parking_ext()) &&
  1660. sub->next->owner &&
  1661. ast_bridged_channel(sub->next->owner)) {
  1662. /* This is a three way call, the main call being a real channel,
  1663. and we're parking the first call. */
  1664. ast_masq_park_call(ast_bridged_channel(sub->next->owner), chan, 0, NULL);
  1665. if (option_verbose > 2) {
  1666. ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
  1667. }
  1668. break;
  1669. } else if (!ast_strlen_zero(l->lastcallerid) && !strcmp(exten, "*60")) {
  1670. if (option_verbose > 2) {
  1671. ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", l->lastcallerid);
  1672. }
  1673. res = ast_db_put("blacklist", l->lastcallerid, "1");
  1674. if (!res) {
  1675. transmit_tone(s, SKINNY_DIALTONE);
  1676. memset(exten, 0, sizeof(exten));
  1677. len = 0;
  1678. }
  1679. } else if (l->hidecallerid && !strcmp(exten, "*82")) {
  1680. if (option_verbose > 2) {
  1681. ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
  1682. }
  1683. /* Enable Caller*ID if enabled */
  1684. l->hidecallerid = 0;
  1685. if (chan->cid.cid_num) {
  1686. free(chan->cid.cid_num);
  1687. }
  1688. if (!ast_strlen_zero(l->cid_num)) {
  1689. chan->cid.cid_num = strdup(l->cid_num);
  1690. }
  1691. if (chan->cid.cid_name) {
  1692. free(chan->cid.cid_name);
  1693. }
  1694. if (!ast_strlen_zero(l->cid_name)) {
  1695. chan->cid.cid_name = strdup(l->cid_name);
  1696. }
  1697. transmit_tone(s, SKINNY_DIALTONE);
  1698. len = 0;
  1699. memset(exten, 0, sizeof(exten));
  1700. timeout = firstdigittimeout;
  1701. } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
  1702. ((exten[0] != '*') || (!ast_strlen_zero(exten) > 2))) {
  1703. ast_log(LOG_WARNING, "Can't match [%s] from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
  1704. transmit_tone(s, SKINNY_REORDER);
  1705. /* hang out for 3 seconds to let congestion play */
  1706. ast_safe_sleep(chan, 3000);
  1707. break;
  1708. }
  1709. if (!timeout) {
  1710. timeout = gendigittimeout;
  1711. }
  1712. if (len && !ast_ignore_pattern(chan->context, exten)) {
  1713. ast_indicate(chan, -1);
  1714. }
  1715. }
  1716. ast_hangup(chan);
  1717. return NULL;
  1718. }
  1719. static int skinny_call(struct ast_channel *ast, char *dest, int timeout)
  1720. {
  1721. int res = 0;
  1722. int tone = 0;
  1723. struct skinny_line *l;
  1724. struct skinny_subchannel *sub;
  1725. struct skinnysession *session;
  1726. sub = ast->tech_pvt;
  1727. l = sub->parent;
  1728. session = l->parent->session;
  1729. if (!l->parent->registered) {
  1730. ast_log(LOG_ERROR, "Device not registered, cannot call %s\n", dest);
  1731. return -1;
  1732. }
  1733. if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
  1734. ast_log(LOG_WARNING, "skinny_call called on %s, neither down nor reserved\n", ast->name);
  1735. return -1;
  1736. }
  1737. if (skinnydebug) {
  1738. ast_verbose(VERBOSE_PREFIX_3 "skinny_call(%s)\n", ast->name);
  1739. }
  1740. if (l->dnd) {
  1741. ast_queue_control(ast, AST_CONTROL_BUSY);
  1742. return -1;
  1743. }
  1744. switch (l->hookstate) {
  1745. case SKINNY_OFFHOOK:
  1746. tone = SKINNY_CALLWAITTONE;
  1747. break;
  1748. case SKINNY_ONHOOK:
  1749. tone = SKINNY_ALERT;
  1750. break;
  1751. default:
  1752. ast_log(LOG_ERROR, "Don't know how to deal with hookstate %d\n", l->hookstate);
  1753. break;
  1754. }
  1755. transmit_lamp_indication(session, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
  1756. transmit_ringer_mode(session, SKINNY_RING_INSIDE);
  1757. if (ast->cid.cid_num) {
  1758. char ciddisplay[41];
  1759. char *work;
  1760. size_t size = sizeof(ciddisplay);
  1761. /* For now, we'll assume that if it is 10 numbers, it is a standard NANPA number */
  1762. if (strlen(ast->cid.cid_num) == 10) {
  1763. ast_build_string(&work, &size, "(xxx)xxx-xxxx %s",
  1764. ast->cid.cid_name ? ast->cid.cid_name : "");
  1765. memcpy(&ciddisplay[1], ast->cid.cid_num, 3);
  1766. memcpy(&ciddisplay[5], &ast->cid.cid_num[3], 3);
  1767. memcpy(&ciddisplay[9], &ast->cid.cid_num[6], 4);
  1768. } else {
  1769. if (strlen(ast->cid.cid_num) < 41) {
  1770. ast_build_string(&work, &size, "%s -- %s", ast->cid.cid_num,
  1771. ast->cid.cid_name ? ast->cid.cid_name : "");
  1772. } else {
  1773. strncpy(ciddisplay, "Number too long!", 15);
  1774. }
  1775. }
  1776. if (skinnydebug) {
  1777. ast_verbose("Trying to send: '%s'\n",ciddisplay);
  1778. }
  1779. transmit_displaymessage(session, ciddisplay);
  1780. } else {
  1781. transmit_displaymessage(session, "Unknown Name");
  1782. }
  1783. transmit_tone(session, tone);
  1784. transmit_callstate(session, l->instance, SKINNY_RINGIN, sub->callid);
  1785. transmit_displaypromptstatus(session, "Ring-In", 0, l->instance, sub->callid);
  1786. transmit_callinfo(session, ast->cid.cid_name, ast->cid.cid_num, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
  1787. /* XXX need to deal with softkeys */
  1788. ast_setstate(ast, AST_STATE_RINGING);
  1789. ast_queue_control(ast, AST_CONTROL_RINGING);
  1790. sub->outgoing = 1;
  1791. return res;
  1792. }
  1793. static int skinny_hangup(struct ast_channel *ast)
  1794. {
  1795. struct skinny_subchannel *sub = ast->tech_pvt;
  1796. struct skinny_line *l = sub->parent;
  1797. struct skinnysession *s = l->parent->session;
  1798. if (skinnydebug) {
  1799. ast_verbose("skinny_hangup(%s) on %s@%s\n", ast->name, l->name, l->parent->name);
  1800. }
  1801. if (!ast->tech_pvt) {
  1802. ast_log(LOG_DEBUG, "Asked to hangup channel not connected\n");
  1803. return 0;
  1804. }
  1805. if (l->parent->registered) {
  1806. if ((sub->parent->type = TYPE_LINE) && (sub->parent->hookstate == SKINNY_OFFHOOK)) {
  1807. sub->parent->hookstate = SKINNY_ONHOOK;
  1808. transmit_callstate(s, l->instance, SKINNY_ONHOOK, sub->callid);
  1809. transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF);
  1810. transmit_speaker_mode(s, SKINNY_SPEAKEROFF);
  1811. } else if ((sub->parent->type = TYPE_LINE) && (sub->parent->hookstate == SKINNY_ONHOOK)) {
  1812. transmit_callstate(s, l->instance, SKINNY_ONHOOK, sub->callid);
  1813. transmit_speaker_mode(s, SKINNY_SPEAKEROFF);
  1814. transmit_ringer_mode(s, SKINNY_RING_OFF);
  1815. transmit_tone(s, SKINNY_SILENCE);
  1816. transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF);
  1817. do_housekeeping(s);
  1818. }
  1819. }
  1820. ast_mutex_lock(&sub->lock);
  1821. sub->owner = NULL;
  1822. ast->tech_pvt = NULL;
  1823. sub->alreadygone = 0;
  1824. sub->outgoing = 0;
  1825. if (sub->rtp) {
  1826. ast_rtp_destroy(sub->rtp);
  1827. sub->rtp = NULL;
  1828. }
  1829. ast_mutex_unlock(&sub->lock);
  1830. return 0;
  1831. }
  1832. static int skinny_answer(struct ast_channel *ast)
  1833. {
  1834. int res = 0;
  1835. struct skinny_subchannel *sub = ast->tech_pvt;
  1836. struct skinny_line *l = sub->parent;
  1837. struct skinnysession *s = l->parent->session;
  1838. sub->cxmode = SKINNY_CX_SENDRECV;
  1839. if (!sub->rtp) {
  1840. start_rtp(sub);
  1841. }
  1842. ast_verbose("skinny_answer(%s) on %s@%s-%d\n", ast->name, l->name, l->parent->name, sub->callid);
  1843. if (ast->_state != AST_STATE_UP) {
  1844. ast_setstate(ast, AST_STATE_UP);
  1845. }
  1846. transmit_tone(s, SKINNY_NOTONE);
  1847. transmit_callstate(s, l->instance, SKINNY_CONNECTED, sub->callid);
  1848. transmit_displaypromptstatus(s, "Connected", 0, l->instance, sub->callid);
  1849. return res;
  1850. }
  1851. static struct ast_frame *skinny_rtp_read(struct skinny_subchannel *sub)
  1852. {
  1853. /* Retrieve audio/etc from channel. Assumes sub->lock is already held. */
  1854. struct ast_frame *f;
  1855. f = ast_rtp_read(sub->rtp);
  1856. if (sub->owner) {
  1857. /* We already hold the channel lock */
  1858. if (f->frametype == AST_FRAME_VOICE) {
  1859. if (f->subclass != sub->owner->nativeformats) {
  1860. ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
  1861. sub->owner->nativeformats = f->subclass;
  1862. ast_set_read_format(sub->owner, sub->owner->readformat);
  1863. ast_set_write_format(sub->owner, sub->owner->writeformat);
  1864. }
  1865. }
  1866. }
  1867. return f;
  1868. }
  1869. static struct ast_frame *skinny_read(struct ast_channel *ast)
  1870. {
  1871. struct ast_frame *fr;
  1872. struct skinny_subchannel *sub = ast->tech_pvt;
  1873. ast_mutex_lock(&sub->lock);
  1874. fr = skinny_rtp_read(sub);
  1875. ast_mutex_unlock(&sub->lock);
  1876. return fr;
  1877. }
  1878. static int skinny_write(struct ast_channel *ast, struct ast_frame *frame)
  1879. {
  1880. struct skinny_subchannel *sub = ast->tech_pvt;
  1881. int res = 0;
  1882. if (frame->frametype != AST_FRAME_VOICE) {
  1883. if (frame->frametype == AST_FRAME_IMAGE) {
  1884. return 0;
  1885. } else {
  1886. ast_log(LOG_WARNING, "Can't send %d type frames with skinny_write\n", frame->frametype);
  1887. return 0;
  1888. }
  1889. } else {
  1890. if (!(frame->subclass & ast->nativeformats)) {
  1891. ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
  1892. frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat);
  1893. return -1;
  1894. }
  1895. }
  1896. if (sub) {
  1897. ast_mutex_lock(&sub->lock);
  1898. if (sub->rtp) {
  1899. res = ast_rtp_write(sub->rtp, frame);
  1900. }
  1901. ast_mutex_unlock(&sub->lock);
  1902. }
  1903. return res;
  1904. }
  1905. static int skinny_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
  1906. {
  1907. struct skinny_subchannel *sub = newchan->tech_pvt;
  1908. ast_log(LOG_NOTICE, "skinny_fixup(%s, %s)\n", oldchan->name, newchan->name);
  1909. if (sub->owner != oldchan) {
  1910. ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
  1911. return -1;
  1912. }
  1913. sub->owner = newchan;
  1914. return 0;
  1915. }
  1916. static int skinny_senddigit(struct ast_channel *ast, char digit)
  1917. {
  1918. #if 0
  1919. struct skinny_subchannel *sub = ast->tech_pvt;
  1920. int tmp;
  1921. /* not right */
  1922. sprintf(tmp, "%d", digit);
  1923. transmit_tone(sub->parent->parent->session, digit);
  1924. #endif
  1925. return -1;
  1926. }
  1927. static char *control2str(int ind) {
  1928. static char tmp[100];
  1929. switch (ind) {
  1930. case AST_CONTROL_HANGUP:
  1931. return "Other end has hungup";
  1932. case AST_CONTROL_RING:
  1933. return "Local ring";
  1934. case AST_CONTROL_RINGING:
  1935. return "Remote end is ringing";
  1936. case AST_CONTROL_ANSWER:
  1937. return "Remote end has answered";
  1938. case AST_CONTROL_BUSY:
  1939. return "Remote end is busy";
  1940. case AST_CONTROL_TAKEOFFHOOK:
  1941. return "Make it go off hook";
  1942. case AST_CONTROL_OFFHOOK:
  1943. return "Line is off hook";
  1944. case AST_CONTROL_CONGESTION:
  1945. return "Congestion (circuits busy)";
  1946. case AST_CONTROL_FLASH:
  1947. return "Flash hook";
  1948. case AST_CONTROL_WINK:
  1949. return "Wink";
  1950. case AST_CONTROL_OPTION:
  1951. return "Set a low-level option";
  1952. case AST_CONTROL_RADIO_KEY:
  1953. return "Key Radio";
  1954. case AST_CONTROL_RADIO_UNKEY:
  1955. return "Un-Key Radio";
  1956. case AST_CONTROL_PROGRESS:
  1957. return "Remote end is making Progress";
  1958. case AST_CONTROL_PROCEEDING:
  1959. return "Remote end is proceeding";
  1960. case AST_CONTROL_HOLD:
  1961. return "Hold";
  1962. case AST_CONTROL_UNHOLD:
  1963. return "Unhold";
  1964. case -1:
  1965. return "Stop tone";
  1966. }
  1967. snprintf(tmp, 100, "UNKNOWN-%d", ind);
  1968. return tmp;
  1969. }
  1970. static int skinny_indicate(struct ast_channel *ast, int ind)
  1971. {
  1972. struct skinny_subchannel *sub = ast->tech_pvt;
  1973. struct skinny_line *l = sub->parent;
  1974. struct skinnysession *s = l->parent->session;
  1975. if (skinnydebug) {
  1976. ast_verbose(VERBOSE_PREFIX_3 "Asked to indicate '%s' condition on channel %s\n", control2str(ind), ast->name);
  1977. }
  1978. switch(ind) {
  1979. case AST_CONTROL_RINGING:
  1980. if (ast->_state != AST_STATE_UP) {
  1981. if (!sub->progress) {
  1982. transmit_tone(s, SKINNY_ALERT);
  1983. transmit_callstate(s, l->instance, SKINNY_RINGOUT, sub->callid);
  1984. transmit_diallednumber(s, ast->exten, l->instance, sub->callid);
  1985. transmit_displaypromptstatus(s, "Ring Out", 0, l->instance, sub->callid);
  1986. transmit_callinfo(s, ast->cid.cid_name, ast->cid.cid_num, ast->exten, ast->exten, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
  1987. sub->ringing = 1;
  1988. break;
  1989. }
  1990. }
  1991. return -1;
  1992. case AST_CONTROL_BUSY:
  1993. if (ast->_state != AST_STATE_UP) {
  1994. transmit_tone(s, SKINNY_BUSYTONE);
  1995. transmit_callstate(s, l->instance, SKINNY_BUSY, sub->callid);
  1996. sub->alreadygone = 1;
  1997. ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
  1998. break;
  1999. }
  2000. return -1;
  2001. case AST_CONTROL_CONGESTION:
  2002. if (ast->_state != AST_STATE_UP) {
  2003. transmit_tone(s, SKINNY_REORDER);
  2004. transmit_callstate(s, l->instance, SKINNY_CONGESTION, sub->callid);
  2005. sub->alreadygone = 1;
  2006. ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
  2007. break;
  2008. }
  2009. return -1;
  2010. case AST_CONTROL_PROGRESS:
  2011. if ((ast->_state != AST_STATE_UP) && !sub->progress && !sub->outgoing) {
  2012. transmit_tone(s, SKINNY_ALERT);
  2013. transmit_callstate(s, l->instance, SKINNY_PROGRESS, sub->callid);
  2014. transmit_displaypromptstatus(s, "Call Progress", 0, l->instance, sub->callid);
  2015. transmit_callinfo(s, ast->cid.cid_name, ast->cid.cid_num, ast->exten, ast->exten, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
  2016. sub->progress = 1;
  2017. break;
  2018. }
  2019. return -1;
  2020. case -1:
  2021. transmit_tone(s, SKINNY_SILENCE);
  2022. break;
  2023. case AST_CONTROL_PROCEEDING:
  2024. break;
  2025. default:
  2026. ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
  2027. return -1;
  2028. }
  2029. return 0;
  2030. }
  2031. static struct ast_channel *skinny_new(struct skinny_subchannel *sub, int state)
  2032. {
  2033. struct ast_channel *tmp;
  2034. struct skinny_line *l = sub->parent;
  2035. int fmt;
  2036. l = sub->parent;
  2037. tmp = ast_channel_alloc(1);
  2038. if (tmp) {
  2039. tmp->tech = &skinny_tech;
  2040. tmp->nativeformats = l->capability;
  2041. if (!tmp->nativeformats)
  2042. tmp->nativeformats = capability;
  2043. fmt = ast_best_codec(tmp->nativeformats);
  2044. ast_verbose("skinny_new: tmp->nativeformats=%d fmt=%d\n", tmp->nativeformats, fmt);
  2045. snprintf(tmp->name, sizeof(tmp->name), "Skinny/%s@%s-%d", l->name, l->parent->name, sub->callid);
  2046. if (sub->rtp) {
  2047. tmp->fds[0] = ast_rtp_fd(sub->rtp);
  2048. }
  2049. tmp->type = type;
  2050. ast_setstate(tmp, state);
  2051. if (state == AST_STATE_RING) {
  2052. tmp->rings = 1;
  2053. }
  2054. tmp->writeformat = fmt;
  2055. tmp->rawwriteformat = fmt;
  2056. tmp->readformat = fmt;
  2057. tmp->rawreadformat = fmt;
  2058. tmp->tech_pvt = sub;
  2059. if (!ast_strlen_zero(l->language)) {
  2060. strncpy(tmp->language, l->language, sizeof(tmp->language)-1);
  2061. }
  2062. if (!ast_strlen_zero(l->accountcode)) {
  2063. strncpy(tmp->accountcode, l->accountcode, sizeof(tmp->accountcode)-1);
  2064. }
  2065. if (l->amaflags) {
  2066. tmp->amaflags = l->amaflags;
  2067. }
  2068. sub->owner = tmp;
  2069. ast_mutex_lock(&usecnt_lock);
  2070. usecnt++;
  2071. ast_mutex_unlock(&usecnt_lock);
  2072. ast_update_use_count();
  2073. tmp->callgroup = l->callgroup;
  2074. tmp->pickupgroup = l->pickupgroup;
  2075. strncpy(tmp->call_forward, l->call_forward, sizeof(tmp->call_forward) - 1);
  2076. strncpy(tmp->context, l->context, sizeof(tmp->context)-1);
  2077. strncpy(tmp->exten,l->exten, sizeof(tmp->exten)-1);
  2078. if (!ast_strlen_zero(l->cid_num)) {
  2079. tmp->cid.cid_num = strdup(l->cid_num);
  2080. }
  2081. if (!ast_strlen_zero(l->cid_name)) {
  2082. tmp->cid.cid_name = strdup(l->cid_name);
  2083. }
  2084. tmp->priority = 1;
  2085. tmp->adsicpe = AST_ADSI_UNAVAILABLE;
  2086. if (state != AST_STATE_DOWN) {
  2087. if (ast_pbx_start(tmp)) {
  2088. ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
  2089. ast_hangup(tmp);
  2090. tmp = NULL;
  2091. }
  2092. }
  2093. } else {
  2094. ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
  2095. }
  2096. return tmp;
  2097. }
  2098. static int handle_message(skinny_req *req, struct skinnysession *s)
  2099. {
  2100. struct skinny_subchannel *sub;
  2101. struct ast_channel *c;
  2102. struct ast_frame f = { 0, };
  2103. struct sockaddr_in sin;
  2104. struct sockaddr_in us;
  2105. struct skinny_line *lines;
  2106. char name[16];
  2107. char addr[4];
  2108. char d;
  2109. char iabuf[INET_ADDRSTRLEN];
  2110. int digit;
  2111. int res=0;
  2112. int speedDialNum;
  2113. int lineNumber;
  2114. int stimulus;
  2115. int stimulusInstance;
  2116. int status;
  2117. int port;
  2118. int i;
  2119. time_t timer;
  2120. struct tm *cmtime;
  2121. pthread_t t;
  2122. button_defs_t *b, *buse;
  2123. if ((!s->device) && (letohl(req->e) != REGISTER_MESSAGE && letohl(req->e) != ALARM_MESSAGE)) {
  2124. ast_log(LOG_WARNING, "Client sent message #%d without first registering.\n", req->e);
  2125. free(req);
  2126. return 0;
  2127. }
  2128. switch(letohl(req->e)) {
  2129. case ALARM_MESSAGE:
  2130. /* no response necessary */
  2131. break;
  2132. case REGISTER_MESSAGE:
  2133. if (skinnydebug) {
  2134. ast_verbose("Device %s is attempting to register\n", req->data.reg.name);
  2135. }
  2136. res = skinny_register(req, s);
  2137. if (!res) {
  2138. ast_log(LOG_ERROR, "Rejecting Device %s: Device not found\n", req->data.reg.name);
  2139. memcpy(&name, req->data.reg.name, sizeof(req->data.reg.name));
  2140. memset(req, 0, sizeof(skinny_req));
  2141. req->len = htolel(sizeof(register_rej_message)+4);
  2142. req->e = htolel(REGISTER_REJ_MESSAGE);
  2143. snprintf(req->data.regrej.errMsg, sizeof(req->data.regrej.errMsg), "No Authority: %s", name);
  2144. transmit_response(s, req);
  2145. break;
  2146. }
  2147. if (option_verbose > 2) {
  2148. ast_verbose(VERBOSE_PREFIX_3 "Device '%s' successfuly registered\n", s->device->name);
  2149. }
  2150. memset(req, 0, SKINNY_MAX_PACKET);
  2151. req->len = htolel(sizeof(register_ack_message)+4);
  2152. req->e = htolel(REGISTER_ACK_MESSAGE);
  2153. req->data.regack.res[0] = '0';
  2154. req->data.regack.res[1] = '\0';
  2155. req->data.regack.keepAlive = htolel(keep_alive);
  2156. strncpy(req->data.regack.dateTemplate, date_format, sizeof(req->data.regack.dateTemplate) - 1);
  2157. req->data.regack.res2[0] = '0';
  2158. req->data.regack.res2[1] = '\0';
  2159. req->data.regack.secondaryKeepAlive = htolel(keep_alive);
  2160. transmit_response(s, req);
  2161. if (skinnydebug) {
  2162. ast_verbose("Requesting capabilities\n");
  2163. }
  2164. memset(req, 0, SKINNY_MAX_PACKET);
  2165. req->len = htolel(4);
  2166. req->e = htolel(CAPABILITIES_REQ_MESSAGE);
  2167. transmit_response(s, req);
  2168. break;
  2169. case UNREGISTER_MESSAGE:
  2170. /* XXX Acutally unregister the device */
  2171. break;
  2172. case IP_PORT_MESSAGE:
  2173. /* no response necessary */
  2174. break;
  2175. case STIMULUS_MESSAGE:
  2176. stimulus = letohl(req->data.stimulus.stimulus);
  2177. stimulusInstance = letohl(req->data.stimulus.stimulusInstance);
  2178. switch(stimulus) {
  2179. case STIMULUS_REDIAL:
  2180. /* If we can keep an array of dialed frames we can implement a quick
  2181. and dirty redial, feeding the frames we last got into the queue
  2182. function */
  2183. if (skinnydebug) {
  2184. ast_verbose("Recieved Stimulus: Redial(%d)\n", stimulusInstance);
  2185. }
  2186. break;
  2187. case STIMULUS_SPEEDDIAL:
  2188. if (skinnydebug) {
  2189. ast_verbose("Recieved Stimulus: SpeedDial(%d)\n", stimulusInstance);
  2190. }
  2191. break;
  2192. case STIMULUS_HOLD:
  2193. /* start moh? set RTP to 0.0.0.0? */
  2194. if (skinnydebug) {
  2195. ast_verbose("Recieved Stimulus: Hold(%d)\n", stimulusInstance);
  2196. }
  2197. break;
  2198. case STIMULUS_TRANSFER:
  2199. if (skinnydebug) {
  2200. ast_verbose("Recieved Stimulus: Transfer(%d)\n", stimulusInstance);
  2201. }
  2202. transmit_tone(s, SKINNY_DIALTONE);
  2203. /* XXX figure out how to transfer */
  2204. break;
  2205. case STIMULUS_CONFERENCE:
  2206. if (skinnydebug) {
  2207. ast_verbose("Recieved Stimulus: Transfer(%d)\n", stimulusInstance);
  2208. }
  2209. transmit_tone(s, SKINNY_DIALTONE);
  2210. /* XXX determine the best way to pull off a conference. Meetme? */
  2211. break;
  2212. case STIMULUS_VOICEMAIL:
  2213. if (skinnydebug) {
  2214. ast_verbose("Recieved Stimulus: Voicemail(%d)\n", stimulusInstance);
  2215. }
  2216. /* XXX Find and dial voicemail extension */
  2217. break;
  2218. case STIMULUS_CALLPARK:
  2219. if (skinnydebug) {
  2220. ast_verbose("Recieved Stimulus: Park Call(%d)\n", stimulusInstance);
  2221. }
  2222. /* XXX Park the call */
  2223. break;
  2224. case STIMULUS_FORWARDALL:
  2225. /* Why is DND under FORWARDALL ? */
  2226. /* Do not disturb */
  2227. transmit_tone(s, SKINNY_DIALTONE);
  2228. if (s->device->lines->dnd != 0){
  2229. if (option_verbose > 2) {
  2230. ast_verbose(VERBOSE_PREFIX_3 "Disabling DND on %s@%s\n",find_subchannel_by_line(s->device->lines)->parent->name,find_subchannel_by_line(s->device->lines)->parent->name);
  2231. }
  2232. s->device->lines->dnd = 0;
  2233. transmit_lamp_indication(s, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_ON);
  2234. transmit_displaynotify(s, "DnD disabled",10);
  2235. } else {
  2236. if (option_verbose > 2) {
  2237. ast_verbose(VERBOSE_PREFIX_3 "Enabling DND on %s@%s\n",find_subchannel_by_line(s->device->lines)->parent->name,find_subchannel_by_line(s->device->lines)->parent->name);
  2238. }
  2239. s->device->lines->dnd = 1;
  2240. transmit_lamp_indication(s, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_OFF);
  2241. transmit_displaynotify(s, "DnD enabled",10);
  2242. }
  2243. break;
  2244. case STIMULUS_FORWARDBUSY:
  2245. case STIMULUS_FORWARDNOANSWER:
  2246. /* Gonna be fun, not */
  2247. if (skinnydebug) {
  2248. ast_verbose("Recieved Stimulus: Forward (%d)\n", stimulusInstance);
  2249. }
  2250. break;
  2251. case STIMULUS_DISPLAY:
  2252. /* Not sure what this is */
  2253. if (skinnydebug) {
  2254. ast_verbose("Recieved Stimulus: Display(%d)\n", stimulusInstance);
  2255. }
  2256. break;
  2257. case STIMULUS_LINE:
  2258. if (skinnydebug) {
  2259. ast_verbose("Recieved Stimulus: Line(%d)\n", stimulusInstance);
  2260. }
  2261. sub = find_subchannel_by_line(s->device->lines);
  2262. /* turn the speaker on */
  2263. transmit_speaker_mode(s, 1);
  2264. break;
  2265. default:
  2266. ast_verbose("RECEIVED UNKNOWN STIMULUS: %d(%d)\n", stimulus, stimulusInstance);
  2267. break;
  2268. }
  2269. break;
  2270. case VERSION_REQ_MESSAGE:
  2271. if (skinnydebug) {
  2272. ast_verbose("Version Request\n");
  2273. }
  2274. memset(req, 0, SKINNY_MAX_PACKET);
  2275. req->len = htolel(sizeof(version_res_message)+4);
  2276. req->e = htolel(VERSION_RES_MESSAGE);
  2277. snprintf(req->data.version.version, sizeof(req->data.version.version), s->device->version_id);
  2278. transmit_response(s, req);
  2279. break;
  2280. case SERVER_REQUEST_MESSAGE:
  2281. if (skinnydebug) {
  2282. ast_verbose("Recieved Server Request\n");
  2283. }
  2284. memset(req, 0, SKINNY_MAX_PACKET);
  2285. req->len = htolel(sizeof(server_res_message)+4);
  2286. req->e = htolel(SERVER_RES_MESSAGE);
  2287. memcpy(req->data.serverres.server[0].serverName, ourhost,
  2288. sizeof(req->data.serverres.server[0].serverName));
  2289. req->data.serverres.serverListenPort[0] = htolel(ourport);
  2290. req->data.serverres.serverIpAddr[0] = htolel(__ourip.s_addr);
  2291. transmit_response(s, req);
  2292. break;
  2293. case BUTTON_TEMPLATE_REQ_MESSAGE:
  2294. if (skinnydebug) {
  2295. ast_verbose("Buttontemplate requested\n");
  2296. }
  2297. sub = find_subchannel_by_line(s->device->lines);
  2298. memset(req, 0, SKINNY_MAX_PACKET);
  2299. req->e = htolel(BUTTON_TEMPLATE_RES_MESSAGE);
  2300. req->len = htolel(sizeof(button_template_res_message)+4);
  2301. /* Find a matching button definition, default to first in the
  2302. list */
  2303. buse = button_defs;
  2304. for(b=button_defs; b->type; b++) {
  2305. if (!strcmp(s->device->model, b->type)) {
  2306. buse = b;
  2307. }
  2308. }
  2309. req->data.buttontemplate.buttonOffset = 0;
  2310. req->data.buttontemplate.buttonCount = htolel(buse->num_buttons);
  2311. req->data.buttontemplate.totalButtonCount = htolel(buse->num_buttons);
  2312. for (i=0; i<42; i++) {
  2313. if (i < buse->num_buttons) {
  2314. memcpy(&(req->data.buttontemplate.definition[i]),
  2315. &(buse->button_def[i]),
  2316. sizeof(button_definition));
  2317. } else {
  2318. memcpy(&(req->data.buttontemplate.definition[i]),
  2319. &(button_def_none),
  2320. sizeof(button_definition));
  2321. }
  2322. }
  2323. if (skinnydebug) {
  2324. ast_verbose("Sending %s template to %s@%s (%s)\n",
  2325. buse->type,
  2326. sub->parent->name,
  2327. sub->parent->parent->name,
  2328. s->device->model);
  2329. }
  2330. transmit_response(s, req);
  2331. break;
  2332. case SOFT_KEY_SET_REQ_MESSAGE:
  2333. if (skinnydebug) {
  2334. ast_verbose("Received SoftKeySetReq\n");
  2335. }
  2336. memset(req, 0, SKINNY_MAX_PACKET);
  2337. req->len = htolel(sizeof(soft_key_sets)+4);
  2338. req->e = htolel(SOFT_KEY_SET_RES_MESSAGE);
  2339. req->data.softkeysets.softKeySetOffset = 0;
  2340. req->data.softkeysets.softKeySetCount = htolel(11);
  2341. req->data.softkeysets.totalSoftKeySetCount = htolel(11);
  2342. /* XXX Wicked hack XXX */
  2343. memcpy(req->data.softkeysets.softKeySetDefinition,
  2344. soft_key_set_hack,
  2345. sizeof(req->data.softkeysets.softKeySetDefinition));
  2346. transmit_response(s,req);
  2347. break;
  2348. case SOFT_KEY_TEMPLATE_REQ_MESSAGE:
  2349. if (skinnydebug) {
  2350. ast_verbose("Recieved SoftKey Template Request\n");
  2351. }
  2352. memset(req, 0, SKINNY_MAX_PACKET);
  2353. req->len = htolel(sizeof(soft_key_template)+4);
  2354. req->e = htolel(SOFT_KEY_TEMPLATE_RES_MESSAGE);
  2355. req->data.softkeytemplate.softKeyOffset = 0;
  2356. req->data.softkeytemplate.softKeyCount = htolel(sizeof(soft_key_template_default) / sizeof(soft_key_template_definition));
  2357. req->data.softkeytemplate.totalSoftKeyCount = htolel(sizeof(soft_key_template_default) / sizeof(soft_key_template_definition));
  2358. memcpy(req->data.softkeytemplate.softKeyTemplateDefinition,
  2359. soft_key_template_default,
  2360. sizeof(soft_key_template_default));
  2361. transmit_response(s,req);
  2362. break;
  2363. case TIME_DATE_REQ_MESSAGE:
  2364. if (skinnydebug) {
  2365. ast_verbose("Received Time/Date Request\n");
  2366. }
  2367. memset(req, 0, SKINNY_MAX_PACKET);
  2368. req->len = htolel(sizeof(definetimedate_message)+4);
  2369. req->e = htolel(DEFINETIMEDATE_MESSAGE);
  2370. timer=time(NULL);
  2371. cmtime = localtime(&timer);
  2372. req->data.definetimedate.year = htolel(cmtime->tm_year+1900);
  2373. req->data.definetimedate.month = htolel(cmtime->tm_mon+1);
  2374. req->data.definetimedate.dayofweek = htolel(cmtime->tm_wday);
  2375. req->data.definetimedate.day = htolel(cmtime->tm_mday);
  2376. req->data.definetimedate.hour = htolel(cmtime->tm_hour);
  2377. req->data.definetimedate.minute = htolel(cmtime->tm_min);
  2378. req->data.definetimedate.seconds = htolel(cmtime->tm_sec);
  2379. transmit_response(s, req);
  2380. break;
  2381. case SPEED_DIAL_STAT_REQ_MESSAGE:
  2382. /* Not really sure how Speed Dial's are different than the
  2383. Softkey templates */
  2384. speedDialNum = letohl(req->data.speeddialreq.speedDialNumber);
  2385. memset(req, 0, SKINNY_MAX_PACKET);
  2386. req->len = htolel(sizeof(speed_dial_stat_res_message)+4);
  2387. req->e = htolel(SPEED_DIAL_STAT_RES_MESSAGE);
  2388. #if 0
  2389. /* XXX Do this right XXX */
  2390. /* If the redial function works the way I think it will, a modification of it
  2391. can work here was well. Yikes. */
  2392. req->data.speeddialreq.speedDialNumber = speedDialNum;
  2393. snprintf(req->data.speeddial.speedDialDirNumber, sizeof(req->data.speeddial.speedDialDirNumber), "31337");
  2394. snprintf(req->data.speeddial.speedDialDisplayName, sizeof(req->data.speeddial.speedDialDisplayName),"Asterisk Rules!");
  2395. #endif
  2396. transmit_response(s, req);
  2397. break;
  2398. case LINE_STATE_REQ_MESSAGE:
  2399. lineNumber = letohl(req->data.line.lineNumber);
  2400. if (skinnydebug) {
  2401. ast_verbose("Received LineStateReq\n");
  2402. }
  2403. memset(req, 0, SKINNY_MAX_PACKET);
  2404. req->len = htolel(sizeof(line_stat_res_message)+4);
  2405. req->e = htolel(LINE_STAT_RES_MESSAGE);
  2406. sub = find_subchannel_by_line(s->device->lines);
  2407. if (!sub) {
  2408. ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
  2409. return 0;
  2410. }
  2411. lines = sub->parent;
  2412. ast_mutex_lock(&devicelock);
  2413. for (i=1; i < lineNumber; i++) {
  2414. lines = lines->next;
  2415. }
  2416. ast_mutex_unlock(&devicelock);
  2417. req->data.linestat.linenumber = letohl(lineNumber);
  2418. memcpy(req->data.linestat.lineDirNumber, lines->name,
  2419. sizeof(req->data.linestat.lineDirNumber));
  2420. memcpy(req->data.linestat.lineDisplayName, lines->label,
  2421. sizeof(req->data.linestat.lineDisplayName));
  2422. transmit_response(s,req);
  2423. break;
  2424. case CAPABILITIES_RES_MESSAGE:
  2425. if (skinnydebug) {
  2426. ast_verbose("Received CapabilitiesRes\n");
  2427. }
  2428. /* XXX process the capabilites */
  2429. break;
  2430. case KEEP_ALIVE_MESSAGE:
  2431. memset(req, 0, SKINNY_MAX_PACKET);
  2432. req->len = htolel(4);
  2433. req->e = htolel(KEEP_ALIVE_ACK_MESSAGE);
  2434. transmit_response(s, req);
  2435. do_housekeeping(s);
  2436. break;
  2437. case OFFHOOK_MESSAGE:
  2438. transmit_ringer_mode(s,SKINNY_RING_OFF);
  2439. transmit_lamp_indication(s, STIMULUS_LINE, s->device->lines->instance, SKINNY_LAMP_ON);
  2440. sub = find_subchannel_by_line(s->device->lines);
  2441. if (!sub) {
  2442. ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
  2443. return 0;
  2444. }
  2445. sub->parent->hookstate = SKINNY_OFFHOOK;
  2446. if (sub->outgoing) {
  2447. /* We're answering a ringing call */
  2448. ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
  2449. transmit_callstate(s, s->device->lines->instance, SKINNY_OFFHOOK, sub->callid);
  2450. transmit_tone(s, SKINNY_SILENCE);
  2451. transmit_callstate(s, s->device->lines->instance, SKINNY_CONNECTED, sub->callid);
  2452. start_rtp(sub);
  2453. ast_setstate(sub->owner, AST_STATE_UP);
  2454. /* XXX select the appropriate soft key here */
  2455. } else {
  2456. if (!sub->owner) {
  2457. transmit_callstate(s, s->device->lines->instance, SKINNY_OFFHOOK, sub->callid);
  2458. if (skinnydebug) {
  2459. ast_verbose("Attempting to Clear display on Skinny %s@%s\n",sub->parent->name, sub->parent->parent->name);
  2460. }
  2461. transmit_displaymessage(s, NULL); /* clear display */
  2462. transmit_tone(s, SKINNY_DIALTONE);
  2463. c = skinny_new(sub, AST_STATE_DOWN);
  2464. if(c) {
  2465. /* start the switch thread */
  2466. if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
  2467. ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
  2468. ast_hangup(c);
  2469. }
  2470. } else {
  2471. ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", sub->parent->name, s->device->name);
  2472. }
  2473. } else {
  2474. ast_log(LOG_DEBUG, "Current sub [%s] already has owner\n", sub->owner->name);
  2475. }
  2476. }
  2477. break;
  2478. case ONHOOK_MESSAGE:
  2479. sub = find_subchannel_by_line(s->device->lines);
  2480. if (sub->parent->hookstate == SKINNY_ONHOOK) {
  2481. /* Somthing else already put us back on hook */
  2482. break;
  2483. }
  2484. sub->cxmode = SKINNY_CX_RECVONLY;
  2485. sub->parent->hookstate = SKINNY_ONHOOK;
  2486. transmit_callstate(s, s->device->lines->instance, sub->parent->hookstate,sub->callid);
  2487. if (skinnydebug) {
  2488. ast_verbose("Skinny %s@%s went on hook\n",sub->parent->name, sub->parent->parent->name);
  2489. }
  2490. if (sub->parent->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) {
  2491. /* We're allowed to transfer, we have two active calls and */
  2492. /* we made at least one of the calls. Let's try and transfer */
  2493. #if 0
  2494. if ((res = attempt_transfer(p)) < 0) {
  2495. if (p->sub->next->owner) {
  2496. sub->next->alreadygone = 1;
  2497. ast_queue_hangup(sub->next->owner,1);
  2498. }
  2499. } else if (res) {
  2500. ast_log(LOG_WARNING, "Transfer attempt failed\n");
  2501. return -1;
  2502. }
  2503. #endif
  2504. } else {
  2505. /* Hangup the current call */
  2506. /* If there is another active call, skinny_hangup will ring the phone with the other call */
  2507. if (sub->owner) {
  2508. sub->alreadygone = 1;
  2509. ast_queue_hangup(sub->owner);
  2510. } else {
  2511. ast_log(LOG_WARNING, "Skinny(%s@%s-%d) channel already destroyed\n",
  2512. sub->parent->name, sub->parent->parent->name, sub->callid);
  2513. }
  2514. }
  2515. if ((sub->parent->hookstate == SKINNY_ONHOOK) && (!sub->next->rtp)) {
  2516. do_housekeeping(s);
  2517. }
  2518. break;
  2519. case KEYPAD_BUTTON_MESSAGE:
  2520. digit = letohl(req->data.keypad.button);
  2521. if (skinnydebug) {
  2522. ast_verbose("Collected digit: [%d]\n", digit);
  2523. }
  2524. f.frametype = AST_FRAME_DTMF;
  2525. if (digit == 14) {
  2526. d = '*';
  2527. } else if (digit == 15) {
  2528. d = '#';
  2529. } else if (digit >=0 && digit <= 9) {
  2530. d = '0' + digit;
  2531. } else {
  2532. /* digit=10-13 (A,B,C,D ?), or
  2533. * digit is bad value
  2534. *
  2535. * probably should not end up here, but set
  2536. * value for backward compatibility, and log
  2537. * a warning.
  2538. */
  2539. d = '0' + digit;
  2540. ast_log(LOG_WARNING, "Unsupported digit %d\n", digit);
  2541. }
  2542. f.subclass = d;
  2543. f.src = "skinny";
  2544. sub = find_subchannel_by_line(s->device->lines);
  2545. if (sub->owner) {
  2546. /* XXX MUST queue this frame to all subs in threeway call if threeway call is active */
  2547. ast_queue_frame(sub->owner, &f);
  2548. if (sub->next->owner) {
  2549. ast_queue_frame(sub->next->owner, &f);
  2550. }
  2551. } else {
  2552. ast_verbose("No owner: %s\n", s->device->lines->name);
  2553. }
  2554. break;
  2555. case OPEN_RECIEVE_CHANNEL_ACK_MESSAGE:
  2556. ast_verbose("Recieved Open Recieve Channel Ack\n");
  2557. status = letohl(req->data.openrecievechannelack.status);
  2558. if (status) {
  2559. ast_log(LOG_ERROR, "Open Recieve Channel Failure\n");
  2560. break;
  2561. }
  2562. /* ENDIAN */
  2563. memcpy(addr, req->data.openrecievechannelack.ipAddr, sizeof(addr));
  2564. port = htolel(req->data.openrecievechannelack.port);
  2565. sin.sin_family = AF_INET;
  2566. /* I smell endian problems */
  2567. memcpy(&sin.sin_addr, addr, sizeof(sin.sin_addr));
  2568. sin.sin_port = htons(port);
  2569. if (skinnydebug) {
  2570. ast_verbose("ipaddr = %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port));
  2571. }
  2572. sub = find_subchannel_by_line(s->device->lines);
  2573. if (sub->rtp) {
  2574. ast_rtp_set_peer(sub->rtp, &sin);
  2575. ast_rtp_get_us(sub->rtp, &us);
  2576. } else {
  2577. ast_log(LOG_ERROR, "No RTP structure, this is very bad\n");
  2578. break;
  2579. }
  2580. memset(req, 0, SKINNY_MAX_PACKET);
  2581. req->len = htolel(sizeof(start_media_transmission_message)+4);
  2582. req->e = htolel(START_MEDIA_TRANSMISSION_MESSAGE);
  2583. req->data.startmedia.conferenceId = 0;
  2584. req->data.startmedia.passThruPartyId = 0;
  2585. memcpy(req->data.startmedia.remoteIp, &s->device->ourip, 4); /* Endian? */
  2586. req->data.startmedia.remotePort = htolel(ntohs(us.sin_port));
  2587. req->data.startmedia.packetSize = htolel(20);
  2588. req->data.startmedia.payloadType = htolel(convert_cap(s->device->lines->capability));
  2589. req->data.startmedia.qualifier.precedence = htolel(127);
  2590. req->data.startmedia.qualifier.vad = 0;
  2591. req->data.startmedia.qualifier.packets = 0;
  2592. req->data.startmedia.qualifier.bitRate = 0;
  2593. transmit_response(s, req);
  2594. break;
  2595. default:
  2596. ast_verbose("RECEIVED UNKNOWN MESSAGE TYPE: %x\n", letohl(req->e));
  2597. break;
  2598. }
  2599. free(req);
  2600. return 1;
  2601. }
  2602. static void destroy_session(struct skinnysession *s)
  2603. {
  2604. struct skinnysession *cur, *prev = NULL;
  2605. ast_mutex_lock(&sessionlock);
  2606. cur = sessions;
  2607. while(cur) {
  2608. if (cur == s) {
  2609. break;
  2610. }
  2611. prev = cur;
  2612. cur = cur->next;
  2613. }
  2614. if (cur) {
  2615. if (prev) {
  2616. prev->next = cur->next;
  2617. } else {
  2618. sessions = cur->next;
  2619. }
  2620. if (s->fd > -1) {
  2621. close(s->fd);
  2622. }
  2623. ast_mutex_destroy(&s->lock);
  2624. free(s);
  2625. } else {
  2626. ast_log(LOG_WARNING, "Trying to delete nonexistent session %p?\n", s);
  2627. }
  2628. ast_mutex_unlock(&sessionlock);
  2629. }
  2630. static int get_input(struct skinnysession *s)
  2631. {
  2632. int res;
  2633. int dlen = 0;
  2634. struct pollfd fds[1];
  2635. fds[0].fd = s->fd;
  2636. fds[0].events = POLLIN;
  2637. res = poll(fds, 1, -1);
  2638. if (res < 0) {
  2639. ast_log(LOG_WARNING, "Select returned error: %s\n", strerror(errno));
  2640. } else if (res > 0) {
  2641. memset(s->inbuf,0,sizeof(s->inbuf));
  2642. res = read(s->fd, s->inbuf, 4);
  2643. if (res != 4) {
  2644. ast_log(LOG_WARNING, "Skinny Client sent less data than expected.\n");
  2645. return -1;
  2646. }
  2647. dlen = letohl(*(int *)s->inbuf);
  2648. if (dlen+8 > sizeof(s->inbuf)) {
  2649. dlen = sizeof(s->inbuf) - 8;
  2650. }
  2651. *(int *)s->inbuf = htolel(dlen);
  2652. res = read(s->fd, s->inbuf+4, dlen+4);
  2653. ast_mutex_unlock(&s->lock);
  2654. if (res != (dlen+4)) {
  2655. ast_log(LOG_WARNING, "Skinny Client sent less data than expected.\n");
  2656. return -1;
  2657. }
  2658. }
  2659. return res;
  2660. }
  2661. static skinny_req *skinny_req_parse(struct skinnysession *s)
  2662. {
  2663. skinny_req *req;
  2664. req = malloc(SKINNY_MAX_PACKET);
  2665. if (!req) {
  2666. ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
  2667. return NULL;
  2668. }
  2669. memset(req, 0, sizeof(skinny_req));
  2670. /* +8 to account for reserved and length fields */
  2671. memcpy(req, s->inbuf, letohl(*(int*)(s->inbuf))+8);
  2672. if (letohl(req->e) < 0) {
  2673. ast_log(LOG_ERROR, "Event Message is NULL from socket %d, This is bad\n", s->fd);
  2674. free(req);
  2675. return NULL;
  2676. }
  2677. return req;
  2678. }
  2679. static void *skinny_session(void *data)
  2680. {
  2681. int res;
  2682. skinny_req *req;
  2683. struct skinnysession *s = data;
  2684. char iabuf[INET_ADDRSTRLEN];
  2685. ast_verbose(VERBOSE_PREFIX_3 "Starting Skinny session from %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr));
  2686. for (;;) {
  2687. res = 0;
  2688. res = get_input(s);
  2689. if (res < 0) {
  2690. break;
  2691. }
  2692. req = skinny_req_parse(s);
  2693. if (!req) {
  2694. return NULL;
  2695. }
  2696. res = handle_message(req, s);
  2697. if (res < 0) {
  2698. destroy_session(s);
  2699. return NULL;
  2700. }
  2701. }
  2702. ast_log(LOG_NOTICE, "Skinny Session returned: %s\n", strerror(errno));
  2703. destroy_session(s);
  2704. return 0;
  2705. }
  2706. static void *accept_thread(void *ignore)
  2707. {
  2708. int as;
  2709. struct sockaddr_in sin;
  2710. socklen_t sinlen;
  2711. struct skinnysession *s;
  2712. struct protoent *p;
  2713. int arg = 1;
  2714. pthread_attr_t attr;
  2715. pthread_attr_init(&attr);
  2716. pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  2717. for (;;) {
  2718. sinlen = sizeof(sin);
  2719. as = accept(skinnysock, (struct sockaddr *)&sin, &sinlen);
  2720. if (as < 0) {
  2721. ast_log(LOG_NOTICE, "Accept returned -1: %s\n", strerror(errno));
  2722. continue;
  2723. }
  2724. p = getprotobyname("tcp");
  2725. if(p) {
  2726. if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
  2727. ast_log(LOG_WARNING, "Failed to set Skinny tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
  2728. }
  2729. }
  2730. s = malloc(sizeof(struct skinnysession));
  2731. if (!s) {
  2732. ast_log(LOG_WARNING, "Failed to allocate Skinny session: %s\n", strerror(errno));
  2733. continue;
  2734. }
  2735. memset(s, 0, sizeof(struct skinnysession));
  2736. memcpy(&s->sin, &sin, sizeof(sin));
  2737. ast_mutex_init(&s->lock);
  2738. s->fd = as;
  2739. ast_mutex_lock(&sessionlock);
  2740. s->next = sessions;
  2741. sessions = s;
  2742. ast_mutex_unlock(&sessionlock);
  2743. if (ast_pthread_create(&tcp_thread, NULL, skinny_session, s)) {
  2744. destroy_session(s);
  2745. }
  2746. }
  2747. if (skinnydebug) {
  2748. ast_verbose("killing accept thread\n");
  2749. }
  2750. close(as);
  2751. return 0;
  2752. }
  2753. static void *do_monitor(void *data)
  2754. {
  2755. int res;
  2756. /* This thread monitors all the interfaces which are not yet in use
  2757. (and thus do not have a separate thread) indefinitely */
  2758. /* From here on out, we die whenever asked */
  2759. for(;;) {
  2760. pthread_testcancel();
  2761. /* Wait for sched or io */
  2762. res = ast_sched_wait(sched);
  2763. if ((res < 0) || (res > 1000)) {
  2764. res = 1000;
  2765. }
  2766. res = ast_io_wait(io, res);
  2767. ast_mutex_lock(&monlock);
  2768. if (res >= 0) {
  2769. ast_sched_runq(sched);
  2770. }
  2771. ast_mutex_unlock(&monlock);
  2772. }
  2773. /* Never reached */
  2774. return NULL;
  2775. }
  2776. static int restart_monitor(void)
  2777. {
  2778. /* If we're supposed to be stopped -- stay stopped */
  2779. if (monitor_thread == AST_PTHREADT_STOP)
  2780. return 0;
  2781. if (ast_mutex_lock(&monlock)) {
  2782. ast_log(LOG_WARNING, "Unable to lock monitor\n");
  2783. return -1;
  2784. }
  2785. if (monitor_thread == pthread_self()) {
  2786. ast_mutex_unlock(&monlock);
  2787. ast_log(LOG_WARNING, "Cannot kill myself\n");
  2788. return -1;
  2789. }
  2790. if (monitor_thread != AST_PTHREADT_NULL) {
  2791. /* Wake up the thread */
  2792. pthread_kill(monitor_thread, SIGURG);
  2793. } else {
  2794. /* Start a new monitor */
  2795. if (ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
  2796. ast_mutex_unlock(&monlock);
  2797. ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
  2798. return -1;
  2799. }
  2800. }
  2801. ast_mutex_unlock(&monlock);
  2802. return 0;
  2803. }
  2804. static struct ast_channel *skinny_request(const char *type, int format, void *data, int *cause)
  2805. {
  2806. int oldformat;
  2807. struct skinny_subchannel *sub;
  2808. struct ast_channel *tmpc = NULL;
  2809. char tmp[256];
  2810. char *dest = data;
  2811. oldformat = format;
  2812. format &= capability;
  2813. if (!format) {
  2814. ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
  2815. return NULL;
  2816. }
  2817. strncpy(tmp, dest, sizeof(tmp) - 1);
  2818. if (ast_strlen_zero(tmp)) {
  2819. ast_log(LOG_NOTICE, "Skinny channels require a device\n");
  2820. return NULL;
  2821. }
  2822. sub = find_subchannel_by_name(tmp);
  2823. if (!sub) {
  2824. ast_log(LOG_NOTICE, "No available lines on: %s\n", dest);
  2825. return NULL;
  2826. }
  2827. if (option_verbose > 2) {
  2828. ast_verbose(VERBOSE_PREFIX_3 "skinny_request(%s)\n", tmp);
  2829. ast_verbose(VERBOSE_PREFIX_3 "Skinny cw: %d, dnd: %d, so: %d, sno: %d\n",
  2830. sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0);
  2831. }
  2832. tmpc = skinny_new(sub->owner ? sub->next : sub, AST_STATE_DOWN);
  2833. if (!tmpc) {
  2834. ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
  2835. }
  2836. restart_monitor();
  2837. return tmpc;
  2838. }
  2839. static int reload_config(void)
  2840. {
  2841. int on = 1;
  2842. struct ast_config *cfg;
  2843. struct ast_variable *v;
  2844. int format;
  2845. char *cat;
  2846. char iabuf[INET_ADDRSTRLEN];
  2847. struct skinny_device *d;
  2848. int oldport = ntohs(bindaddr.sin_port);
  2849. if (gethostname(ourhost, sizeof(ourhost))) {
  2850. ast_log(LOG_WARNING, "Unable to get hostname, Skinny disabled\n");
  2851. return 0;
  2852. }
  2853. cfg = ast_config_load(config);
  2854. /* We *must* have a config file otherwise stop immediately */
  2855. if (!cfg) {
  2856. ast_log(LOG_NOTICE, "Unable to load config %s, Skinny disabled\n", config);
  2857. return 0;
  2858. }
  2859. /* load the general section */
  2860. memset(&bindaddr, 0, sizeof(bindaddr));
  2861. v = ast_variable_browse(cfg, "general");
  2862. while(v) {
  2863. /* Create the interface list */
  2864. if (!strcasecmp(v->name, "bindaddr")) {
  2865. if (!(hp = ast_gethostbyname(v->value, &ahp))) {
  2866. ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
  2867. } else {
  2868. memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
  2869. }
  2870. } else if (!strcasecmp(v->name, "keepAlive")) {
  2871. keep_alive = atoi(v->value);
  2872. } else if (!strcasecmp(v->name, "dateFormat")) {
  2873. strncpy(date_format, v->value, sizeof(date_format) - 1);
  2874. } else if (!strcasecmp(v->name, "allow")) {
  2875. format = ast_getformatbyname(v->value);
  2876. if (format < 1) {
  2877. ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
  2878. } else {
  2879. capability |= format;
  2880. }
  2881. } else if (!strcasecmp(v->name, "disallow")) {
  2882. format = ast_getformatbyname(v->value);
  2883. if (format < 1) {
  2884. ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value);
  2885. } else {
  2886. capability &= ~format;
  2887. }
  2888. } else if (!strcasecmp(v->name, "port")) {
  2889. if (sscanf(v->value, "%d", &ourport) == 1) {
  2890. bindaddr.sin_port = htons(ourport);
  2891. } else {
  2892. ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config);
  2893. }
  2894. }
  2895. v = v->next;
  2896. }
  2897. if (ntohl(bindaddr.sin_addr.s_addr)) {
  2898. memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip));
  2899. } else {
  2900. hp = ast_gethostbyname(ourhost, &ahp);
  2901. if (!hp) {
  2902. ast_log(LOG_WARNING, "Unable to get our IP address, Skinny disabled\n");
  2903. ast_config_destroy(cfg);
  2904. return 0;
  2905. }
  2906. memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
  2907. }
  2908. if (!ntohs(bindaddr.sin_port)) {
  2909. bindaddr.sin_port = ntohs(DEFAULT_SKINNY_PORT);
  2910. }
  2911. bindaddr.sin_family = AF_INET;
  2912. /* load the device sections */
  2913. cat = ast_category_browse(cfg, NULL);
  2914. while(cat) {
  2915. if (!strcasecmp(cat, "general")) {
  2916. /* Nothing to do */
  2917. #if 0
  2918. } else if (!strncasecmp(cat, "paging-", 7)) {
  2919. p = build_paging_device(cat, ast_variable_browse(cfg, cat));
  2920. if (p) {
  2921. }
  2922. #endif
  2923. } else {
  2924. d = build_device(cat, ast_variable_browse(cfg, cat));
  2925. if (d) {
  2926. if (option_verbose > 2) {
  2927. ast_verbose(VERBOSE_PREFIX_3 "Added device '%s'\n", d->name);
  2928. }
  2929. ast_mutex_lock(&devicelock);
  2930. d->next = devices;
  2931. devices = d;
  2932. ast_mutex_unlock(&devicelock);
  2933. }
  2934. }
  2935. cat = ast_category_browse(cfg, cat);
  2936. }
  2937. ast_mutex_lock(&netlock);
  2938. if ((skinnysock > -1) && (ntohs(bindaddr.sin_port) != oldport)) {
  2939. close(skinnysock);
  2940. skinnysock = -1;
  2941. }
  2942. if (skinnysock < 0) {
  2943. skinnysock = socket(AF_INET, SOCK_STREAM, 0);
  2944. if(setsockopt(skinnysock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
  2945. ast_log(LOG_ERROR, "Set Socket Options failed: errno %d, %s", errno, strerror(errno));
  2946. ast_config_destroy(cfg);
  2947. return 0;
  2948. }
  2949. if (skinnysock < 0) {
  2950. ast_log(LOG_WARNING, "Unable to create Skinny socket: %s\n", strerror(errno));
  2951. } else {
  2952. if (bind(skinnysock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
  2953. ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
  2954. ast_inet_ntoa(iabuf, sizeof(iabuf), bindaddr.sin_addr), ntohs(bindaddr.sin_port),
  2955. strerror(errno));
  2956. close(skinnysock);
  2957. skinnysock = -1;
  2958. ast_config_destroy(cfg);
  2959. return 0;
  2960. }
  2961. if (listen(skinnysock,DEFAULT_SKINNY_BACKLOG)) {
  2962. ast_log(LOG_WARNING, "Failed to start listening to %s:%d: %s\n",
  2963. ast_inet_ntoa(iabuf, sizeof(iabuf), bindaddr.sin_addr), ntohs(bindaddr.sin_port),
  2964. strerror(errno));
  2965. close(skinnysock);
  2966. skinnysock = -1;
  2967. ast_config_destroy(cfg);
  2968. return 0;
  2969. }
  2970. if (option_verbose > 1) {
  2971. ast_verbose(VERBOSE_PREFIX_2 "Skinny listening on %s:%d\n",
  2972. ast_inet_ntoa(iabuf, sizeof(iabuf), bindaddr.sin_addr), ntohs(bindaddr.sin_port));
  2973. }
  2974. ast_pthread_create(&accept_t,NULL, accept_thread, NULL);
  2975. }
  2976. }
  2977. ast_mutex_unlock(&netlock);
  2978. ast_config_destroy(cfg);
  2979. return 0;
  2980. }
  2981. void delete_devices(void)
  2982. {
  2983. struct skinny_device *d, *dlast;
  2984. struct skinny_line *l, *llast;
  2985. struct skinny_subchannel *sub, *slast;
  2986. ast_mutex_lock(&devicelock);
  2987. /* Delete all devices */
  2988. for (d=devices;d;) {
  2989. /* Delete all lines for this device */
  2990. for (l=d->lines;l;) {
  2991. /* Delete all subchannels for this line */
  2992. for (sub=l->sub;sub;) {
  2993. slast = sub;
  2994. sub = sub->next;
  2995. ast_mutex_destroy(&slast->lock);
  2996. free(slast);
  2997. }
  2998. llast = l;
  2999. l = l->next;
  3000. ast_mutex_destroy(&llast->lock);
  3001. free(llast);
  3002. }
  3003. dlast = d;
  3004. d = d->next;
  3005. free(dlast);
  3006. }
  3007. devices=NULL;
  3008. ast_mutex_unlock(&devicelock);
  3009. }
  3010. int reload(void)
  3011. {
  3012. delete_devices();
  3013. reload_config();
  3014. restart_monitor();
  3015. return 0;
  3016. }
  3017. int load_module()
  3018. {
  3019. int res = 0;
  3020. for (; res < (sizeof(soft_key_template_default) / sizeof(soft_key_template_default[0])); res++) {
  3021. soft_key_template_default[res].softKeyEvent = htolel(soft_key_template_default[res].softKeyEvent);
  3022. }
  3023. /* load and parse config */
  3024. res = reload_config();
  3025. ast_rtp_proto_register(&skinny_rtp);
  3026. ast_cli_register(&cli_show_devices);
  3027. ast_cli_register(&cli_show_lines);
  3028. ast_cli_register(&cli_debug);
  3029. ast_cli_register(&cli_no_debug);
  3030. sched = sched_context_create();
  3031. if (!sched) {
  3032. ast_log(LOG_WARNING, "Unable to create schedule context\n");
  3033. }
  3034. io = io_context_create();
  3035. if (!io) {
  3036. ast_log(LOG_WARNING, "Unable to create I/O context\n");
  3037. }
  3038. /* And start the monitor for the first time */
  3039. restart_monitor();
  3040. /* Announce our presence to Asterisk */
  3041. if (!res) {
  3042. /* Make sure we can register our skinny channel type */
  3043. if (ast_channel_register(&skinny_tech)) {
  3044. ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
  3045. return -1;
  3046. }
  3047. }
  3048. return res;
  3049. }
  3050. int unload_module()
  3051. {
  3052. #if 0
  3053. struct skinny_session *session, s;
  3054. struct skinny_subchannel *sub;
  3055. struct skinny_line *line = session;
  3056. /* close all IP connections */
  3057. if (!ast_mutex_lock(&devicelock)) {
  3058. /* Terminate tcp listener thread */
  3059. } else {
  3060. ast_log(LOG_WARNING, "Unable to lock the monitor\n");
  3061. return -1;
  3062. }
  3063. if (!ast_mutex_lock(&monlock)) {
  3064. if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
  3065. pthread_cancel(monitor_thread);
  3066. pthread_kill(monitor_thread, SIGURG);
  3067. pthread_join(monitor_thread, NULL);
  3068. }
  3069. monitor_thread = AST_PTHREADT_STOP;
  3070. ast_mutex_unlock(&monlock);
  3071. } else {
  3072. ast_log(LOG_WARNING, "Unable to lock the monitor\n");
  3073. return -1;
  3074. }
  3075. if (!ast_mutex_lock(&iflock)) {
  3076. /* Destroy all the interfaces and free their memory */
  3077. p = iflist;
  3078. while(p) {
  3079. pl = p;
  3080. p = p->next;
  3081. /* Free associated memory */
  3082. ast_mutex_destroy(&pl->lock);
  3083. free(pl);
  3084. }
  3085. iflist = NULL;
  3086. ast_mutex_unlock(&iflock);
  3087. } else {
  3088. ast_log(LOG_WARNING, "Unable to lock the monitor\n");
  3089. return -1;
  3090. }
  3091. ast_rtp_proto_register(&skinny_rtp);
  3092. ast_channel_unregister(&skinny_tech);
  3093. ast_cli_register(&cli_show_devices);
  3094. ast_cli_register(&cli_show_lines);
  3095. ast_cli_register(&cli_debug);
  3096. ast_cli_register(&cli_no_debug);
  3097. return 0;
  3098. #endif
  3099. return -1;
  3100. }
  3101. int usecount()
  3102. {
  3103. return usecnt;
  3104. }
  3105. char *key()
  3106. {
  3107. return ASTERISK_GPL_KEY;
  3108. }
  3109. char *description()
  3110. {
  3111. return (char *) desc;
  3112. }