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"
|
implemented extension confi...
Stefan Schuermans authored 12 years ago
|
14) #include "ListTracker.h"
15) #include "ListTracker_impl.h"
|
begin of phone connector
Stefan Schuermans authored 12 years ago
|
16) #include "Mgrs.h"
17) #include "Module.h"
18) #include "Phone.h"
|
implemented extension confi...
Stefan Schuermans authored 12 years ago
|
19) #include "PhoneExtension.h"
20) #include "PhoneExtension_impl.h"
|
begin of phone connector
Stefan Schuermans authored 12 years ago
|
21) #include "SettingFile.h"
|
implemented extension confi...
Stefan Schuermans authored 12 years ago
|
22) #include "StringParser.h"
|
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")),
|
implemented extension confi...
Stefan Schuermans authored 12 years ago
|
38) m_extListTracker(*this, dirBase.getSubdir("extensions")),
|
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();
|
implemented extension confi...
Stefan Schuermans authored 12 years ago
|
46)
47) // load extensions
48) m_extListTracker.init();
|
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) {
|
implemented extension confi...
Stefan Schuermans authored 12 years ago
|
55) // unload extensions
56) m_extListTracker.clear();
57)
|
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();
|
implemented extension confi...
Stefan Schuermans authored 12 years ago
|
78)
79) // extensions update
80) m_extListTracker.updateConfig();
|
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)
|
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) }
|