75c7e0f89e242837e16f0b004c3a9a343028a844
Stefan Schuermans begin of phone connector

Stefan Schuermans authored 12 years ago

1) /* Blinker
2)    Copyright 2011 Stefan Schuermans <stefan@blinkenarea.org>
3)    Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4)    a blinkenarea.org project */
5) 
6) #ifndef BLINKER_PHONE_IMPL_H
7) #define BLINKER_PHONE_IMPL_H
8) 
9) #include <string>
10) 
11) #include "Directory.h"
12) #include "File.h"
13) #include "IoCallee.h"
Stefan Schuermans implemented extension confi...

Stefan Schuermans authored 12 years ago

14) #include "ListTracker.h"
15) #include "ListTracker_impl.h"
Stefan Schuermans begin of phone connector

Stefan Schuermans authored 12 years ago

16) #include "Mgrs.h"
17) #include "Module.h"
18) #include "Phone.h"
Stefan Schuermans implemented extension confi...

Stefan Schuermans authored 12 years ago

19) #include "PhoneExtension.h"
20) #include "PhoneExtension_impl.h"
Stefan Schuermans begin of phone connector

Stefan Schuermans authored 12 years ago

21) #include "SettingFile.h"
Stefan Schuermans implemented extension confi...

Stefan Schuermans authored 12 years ago

22) #include "StringParser.h"
Stefan Schuermans begin of phone connector

Stefan Schuermans authored 12 years ago

23) #include "Time.h"
24) #include "TimeCallee.h"
25) 
26) namespace Blinker {
27) 
28) /**
29)  * @brief constructor
30)  * @param[in] mgrs managers
31)  * @param[in] dirBase base directory
32)  */
33) template<typename ADDR, typename SOCK>
34) Phone<ADDR, SOCK>::Phone(Mgrs &mgrs, const Directory &dirBase):
35)   Module(mgrs, dirBase),
36)   m_fileBind(dirBase.getFile("bind")),
37)   m_fileServer(dirBase.getFile("server")),
Stefan Schuermans implemented extension confi...

Stefan Schuermans authored 12 years ago

38)   m_extListTracker(*this, dirBase.getSubdir("extensions")),
Stefan Schuermans begin of phone connector

Stefan Schuermans authored 12 years ago

39)   m_pSock(NULL)
40) {
41)   // read server address
42)   readServer();
43) 
44)   // create and bind socket
45)   createSock();
Stefan Schuermans implemented extension confi...

Stefan Schuermans authored 12 years ago

46) 
47)   // load extensions
48)   m_extListTracker.init();
Stefan Schuermans begin of phone connector

Stefan Schuermans authored 12 years ago

49) }
50) 
51) /// virtual destructor
52) template<typename ADDR, typename SOCK>
53) Phone<ADDR, SOCK>::~Phone()
54) {
Stefan Schuermans implemented extension confi...

Stefan Schuermans authored 12 years ago

55)   // unload extensions
56)   m_extListTracker.clear();
57) 
Stefan Schuermans begin of phone connector

Stefan Schuermans authored 12 years ago

58)   // destroy socket
59)   destroySock();
60) 
61)   // cancel time callback
62)   m_mgrs.m_callMgr.cancelTimeCall(this);
63) }
64) 
65) /// check for update of configuration
66) template<typename ADDR, typename SOCK>
67) void Phone<ADDR, SOCK>::updateConfig()
68) {
69)   // bind address file was modified -> re-create socket
70)   if (m_fileBind.checkModified()) {
71)     destroySock();
72)     createSock();
73)   }
74) 
75)   // server address file was modified -> re-read server address
76)   if (m_fileServer.checkModified())
77)     readServer();
Stefan Schuermans implemented extension confi...

Stefan Schuermans authored 12 years ago

78) 
79)   // extensions update
80)   m_extListTracker.updateConfig();
Stefan Schuermans begin of phone connector

Stefan Schuermans authored 12 years ago

81) }
82) 
83) /// callback when requested time reached
84) template<typename ADDR, typename SOCK>
85) void Phone<ADDR, SOCK>::timeCall()
86) {
87)   Time now = Time::now();
88) 
89)   // server timeout -> re-register
90)   if (m_timeRegister <= now)
91)     sendRegister();
92) 
93)   // send heartbeat
94)   if (m_timeHeartbeat <= now)
95)     sendHeartbeat();
96) }
97) 
98) /**
99)  * @brief callback when I/O object is readable
100)  * @param[in] io I/O object that is readable
101)  */
102) template<typename ADDR, typename SOCK>
103) void Phone<ADDR, SOCK>::ioReadCall(Io *io)
104) {
105)   // reception on socket
106)   if (io == m_pSock)
107)     receiveFromSock();
108) }
109) 
110) /**
111)  * @brief callback when I/O object is writable
112)  * @param[in] io I/O object that is writable
113)  */
114) template<typename ADDR, typename SOCK>
115) void Phone<ADDR, SOCK>::ioWriteCall(Io *io)
116) {
117)   (void)io; // unused
118) }
119) 
120) /// (re-)read server address
121) template<typename ADDR, typename SOCK>
122) void Phone<ADDR, SOCK>::readServer()
123) {
124)   m_fileServer.update();
125) 
126)   // register with new server
127)   sendRegister();
128) }
129) 
130) /// create socket and bind it
131) template<typename ADDR, typename SOCK>
132) void Phone<ADDR, SOCK>::createSock()
133) {
134)   // create socket
135)   if (!m_pSock) {
136)     m_pSock = new SOCK();
137)     if (!m_pSock)
138)       return;
139)   }
140) 
141)   // get bind address from bind address setting file
142)   m_fileBind.update();
143)   if (!m_fileBind.m_valid) {
144)     delete m_pSock;
145)     m_pSock = NULL;
146)     return;
147)   }
148) 
149)   // bind socket
150)   if (!m_pSock->bind(m_fileBind.m_obj)) {
151)     delete m_pSock;
152)     m_pSock = NULL;
153)     return;
154)   }
155) 
156)   // request callback on recepetion
157)   m_mgrs.m_callMgr.requestIoReadCall(this, m_pSock);
158) 
159)   // register with server
160)   sendRegister();
161) }
162) 
163) /// destroy socket
164) template<typename ADDR, typename SOCK>
165) void Phone<ADDR, SOCK>::destroySock()
166) {
167)   // cancel callback request
168)   m_mgrs.m_callMgr.cancelIoReadCall(this, m_pSock);
169) 
170)   // destroy socket
171)   if (m_pSock) {
172)     delete m_pSock;
173)     m_pSock = NULL;
174)   }
175) }
176) 
177) /// register with server
178) template<typename ADDR, typename SOCK>
179) void Phone<ADDR, SOCK>::sendRegister()
180) {
181)   send("0:register");
182) 
183)   // set time for next register message and next heartbeat
184)   m_timeRegister = Time::now() + m_serverTimeout;
185)   m_timeHeartbeat = m_timeRegister + m_heartbeatInterval;
186)   updateTimeCallback();
187) }
188) 
189) /// send heartbeat to server
190) template<typename ADDR, typename SOCK>
191) void Phone<ADDR, SOCK>::sendHeartbeat()
192) {
193)   send("0:heartbeat");
194) 
195)   // set time for next heartbeat
196)   m_timeHeartbeat = Time::now() + m_heartbeatInterval;
197)   updateTimeCallback();
198) }
199) 
200) /**
201)  * @brief send message to server
202)  * @param[in] msg message to send
203)  */
204) template<typename ADDR, typename SOCK>
205) void Phone<ADDR, SOCK>::send(const std::string &msg)
206) {
207)   // check that there is a socket and a server address
208)   if (!m_pSock || !m_fileServer.m_valid)
209)     return;
210) 
211)   // send message
212)   m_pSock->send(msg, m_fileServer.m_obj);
213) }
214) 
215) /// receive data from socket
216) template<typename ADDR, typename SOCK>
217) void Phone<ADDR, SOCK>::receiveFromSock()
218) {
219)   std::string msg;
220)   ADDR addr;
221) 
222)   // make sure socket exists
223)   if (!m_pSock)
224)     return;
225) 
226)   // receive (leave if no reception)
227)   if (!m_pSock->recv(msg, addr))
228)     return;
229) 
230)   // check that packet came from server address
231)   if (!m_fileServer.m_valid || addr != m_fileServer.m_obj)
232)     return; // mismatch
233) 
234)   // reset server timeout
235)   m_timeRegister = Time::now() + m_serverTimeout;
236)   updateTimeCallback();
237) 
Stefan Schuermans implemented extension confi...

Stefan Schuermans authored 12 years ago

238)   // process message
239)   serverMsg(msg);
240) }
241) 
242) /**
243)  * @brief process message from server
244)  * @param[in] msg message from server
245)  */
246) template<typename ADDR, typename SOCK>
247) void Phone<ADDR, SOCK>::serverMsg(const std::string &msg)
248) {
249)   StringParser parser(msg);
250) 
251)   // get line number and command
252)   unsigned int line;
253)   std::string cmd;
254)   if (!parser.uintNo(line) || !parser.fixChr(':') ||
255)       !parser.untilDelim(":", false, cmd))
256)     return;
257) 
258)   // incoming call
259)   if (cmd == "setup") {
260)     std::string caller, extension;
261)     if (!parser.fixChr(':') || !parser.untilDelim(":", true, caller) ||
262)         !parser.fixChr(':') || !parser.untilDelim(":", false, extension))
263)       return;
264)     // TODO incomingCall(line, extension);
265)   }
266) 
267)   // hangup
268)   else if (cmd == "onhook") {
269)     // TODO hangup(line);
270)   }
271) 
272)   // DTMF symbol (i.e. key pressed)
273)   else if (cmd == "dtmf") {
274)     char key;
275)     if (!parser.fixChr(':') || !parser.oneChrOf("0123456789*#", key))
276)       return;
277)     // TODO keyPressed(line, key);
278)   }