begin of phone connector
Stefan Schuermans

Stefan Schuermans commited on 2011-12-22 14:11:23
Showing 6 changed files, with 378 additions and 0 deletions.

... ...
@@ -0,0 +1 @@
1
+127.0.0.1:12340
... ...
@@ -0,0 +1,110 @@
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_H
7
+#define BLINKER_PHONE_H
8
+
9
+#include <string>
10
+
11
+#include "Directory.h"
12
+#include "File.h"
13
+#include "IoCallee.h"
14
+#include "Mgrs.h"
15
+#include "Module.h"
16
+#include "SettingFile.h"
17
+#include "Time.h"
18
+#include "TimeCallee.h"
19
+
20
+namespace Blinker {
21
+
22
+/// phone connector (using EBIP)
23
+template<typename ADDR, typename SOCK>
24
+class Phone: public IoCallee, public Module, public TimeCallee
25
+{
26
+protected:
27
+  /// type for address setting file
28
+  typedef SettingFile<ADDR> AddrFile;
29
+
30
+public:
31
+  /**
32
+   * @brief constructor
33
+   * @param[in] mgrs managers
34
+   * @param[in] dirBase base directory
35
+   */
36
+  Phone(Mgrs &mgrs, const Directory &dirBase);
37
+
38
+  /// virtual destructor
39
+  virtual ~Phone();
40
+
41
+private:
42
+  /// copy constructor disabled
43
+  Phone(const Phone &that);
44
+
45
+  /// assignment operator disabled
46
+  const Phone & operator=(const Phone &that);
47
+
48
+public:
49
+  /// check for update of configuration
50
+  virtual void updateConfig();
51
+
52
+  /// callback when requested time reached
53
+  virtual void timeCall();
54
+
55
+  /**
56
+   * @brief callback when I/O object is readable
57
+   * @param[in] io I/O object that is readable
58
+   */
59
+  virtual void ioReadCall(Io *io);
60
+
61
+  /**
62
+   * @brief callback when I/O object is writable
63
+   * @param[in] io I/O object that is writable
64
+   */
65
+  virtual void ioWriteCall(Io *io);
66
+
67
+protected:
68
+  /// (re-)read server address
69
+  void readServer();
70
+
71
+  /// create socket and bind it
72
+  void createSock();
73
+
74
+  /// destroy socket
75
+  void destroySock();
76
+
77
+  /// register with server
78
+  void sendRegister();
79
+
80
+  /// send heartbeat to server
81
+  void sendHeartbeat();
82
+
83
+  /**
84
+   * @brief send message to server
85
+   * @param[in] msg message to send
86
+   */
87
+  void send(const std::string &msg);
88
+
89
+  /// receive data from socket
90
+  void receiveFromSock();
91
+
92
+  /// update time callback
93
+  void updateTimeCallback();
94
+
95
+protected:
96
+  static const Time m_serverTimeout;
97
+  static const Time m_heartbeatInterval;
98
+
99
+protected:
100
+  AddrFile m_fileBind;      ///< bind address file
101
+  AddrFile m_fileServer;    ///< server address file
102
+  SOCK     *m_pSock;        ///< socket to use for sending messages
103
+  Time     m_timeRegister;  ///< time to re-register
104
+  Time     m_timeHeartbeat; ///< time to send next heartbeat
105
+}; // class Phone
106
+
107
+} // namespace Blinker
108
+
109
+#endif // #ifndef BLINKER_PHONE_H
110
+
... ...
@@ -0,0 +1,243 @@
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"
14
+#include "Mgrs.h"
15
+#include "Module.h"
16
+#include "Phone.h"
17
+#include "SettingFile.h"
18
+#include "Time.h"
19
+#include "TimeCallee.h"
20
+
21
+namespace Blinker {
22
+
23
+/**
24
+ * @brief constructor
25
+ * @param[in] mgrs managers
26
+ * @param[in] dirBase base directory
27
+ */
28
+template<typename ADDR, typename SOCK>
29
+Phone<ADDR, SOCK>::Phone(Mgrs &mgrs, const Directory &dirBase):
30
+  Module(mgrs, dirBase),
31
+  m_fileBind(dirBase.getFile("bind")),
32
+  m_fileServer(dirBase.getFile("server")),
33
+  m_pSock(NULL)
34
+{
35
+  // read server address
36
+  readServer();
37
+
38
+  // create and bind socket
39
+  createSock();
40
+}
41
+
42
+/// virtual destructor
43
+template<typename ADDR, typename SOCK>
44
+Phone<ADDR, SOCK>::~Phone()
45
+{
46
+  // destroy socket
47
+  destroySock();
48
+
49
+  // cancel time callback
50
+  m_mgrs.m_callMgr.cancelTimeCall(this);
51
+}
52
+
53
+/// check for update of configuration
54
+template<typename ADDR, typename SOCK>
55
+void Phone<ADDR, SOCK>::updateConfig()
56
+{
57
+  // bind address file was modified -> re-create socket
58
+  if (m_fileBind.checkModified()) {
59
+    destroySock();
60
+    createSock();
61
+  }
62
+
63
+  // server address file was modified -> re-read server address
64
+  if (m_fileServer.checkModified())
65
+    readServer();
66
+}
67
+
68
+/// callback when requested time reached
69
+template<typename ADDR, typename SOCK>
70
+void Phone<ADDR, SOCK>::timeCall()
71
+{
72
+  Time now = Time::now();
73
+
74
+  // server timeout -> re-register
75
+  if (m_timeRegister <= now)
76
+    sendRegister();
77
+
78
+  // send heartbeat
79
+  if (m_timeHeartbeat <= now)
80
+    sendHeartbeat();
81
+}
82
+
83
+/**
84
+ * @brief callback when I/O object is readable
85
+ * @param[in] io I/O object that is readable
86
+ */
87
+template<typename ADDR, typename SOCK>
88
+void Phone<ADDR, SOCK>::ioReadCall(Io *io)
89
+{
90
+  // reception on socket
91
+  if (io == m_pSock)
92
+    receiveFromSock();
93
+}
94
+
95
+/**
96
+ * @brief callback when I/O object is writable
97
+ * @param[in] io I/O object that is writable
98
+ */
99
+template<typename ADDR, typename SOCK>
100
+void Phone<ADDR, SOCK>::ioWriteCall(Io *io)
101
+{
102
+  (void)io; // unused
103
+}
104
+
105
+/// (re-)read server address
106
+template<typename ADDR, typename SOCK>
107
+void Phone<ADDR, SOCK>::readServer()
108
+{
109
+  m_fileServer.update();
110
+
111
+  // register with new server
112
+  sendRegister();
113
+}
114
+
115
+/// create socket and bind it
116
+template<typename ADDR, typename SOCK>
117
+void Phone<ADDR, SOCK>::createSock()
118
+{
119
+  // create socket
120
+  if (!m_pSock) {
121
+    m_pSock = new SOCK();
122
+    if (!m_pSock)
123
+      return;
124
+  }
125
+
126
+  // get bind address from bind address setting file
127
+  m_fileBind.update();
128
+  if (!m_fileBind.m_valid) {
129
+    delete m_pSock;
130
+    m_pSock = NULL;
131
+    return;
132
+  }
133
+
134
+  // bind socket
135
+  if (!m_pSock->bind(m_fileBind.m_obj)) {
136
+    delete m_pSock;
137
+    m_pSock = NULL;
138
+    return;
139
+  }
140
+
141
+  // request callback on recepetion
142
+  m_mgrs.m_callMgr.requestIoReadCall(this, m_pSock);
143
+
144
+  // register with server
145
+  sendRegister();
146
+}
147
+
148
+/// destroy socket
149
+template<typename ADDR, typename SOCK>
150
+void Phone<ADDR, SOCK>::destroySock()
151
+{
152
+  // cancel callback request
153
+  m_mgrs.m_callMgr.cancelIoReadCall(this, m_pSock);
154
+
155
+  // destroy socket
156
+  if (m_pSock) {
157
+    delete m_pSock;
158
+    m_pSock = NULL;
159
+  }
160
+}
161
+
162
+/// register with server
163
+template<typename ADDR, typename SOCK>
164
+void Phone<ADDR, SOCK>::sendRegister()
165
+{
166
+  send("0:register");
167
+
168
+  // set time for next register message and next heartbeat
169
+  m_timeRegister = Time::now() + m_serverTimeout;
170
+  m_timeHeartbeat = m_timeRegister + m_heartbeatInterval;
171
+  updateTimeCallback();
172
+}
173
+
174
+/// send heartbeat to server
175
+template<typename ADDR, typename SOCK>
176
+void Phone<ADDR, SOCK>::sendHeartbeat()
177
+{
178
+  send("0:heartbeat");
179
+
180
+  // set time for next heartbeat
181
+  m_timeHeartbeat = Time::now() + m_heartbeatInterval;
182
+  updateTimeCallback();
183
+}
184
+
185
+/**
186
+ * @brief send message to server
187
+ * @param[in] msg message to send
188
+ */
189
+template<typename ADDR, typename SOCK>
190
+void Phone<ADDR, SOCK>::send(const std::string &msg)
191
+{
192
+  // check that there is a socket and a server address
193
+  if (!m_pSock || !m_fileServer.m_valid)
194
+    return;
195
+
196
+  // send message
197
+  m_pSock->send(msg, m_fileServer.m_obj);
198
+}
199
+
200
+/// receive data from socket
201
+template<typename ADDR, typename SOCK>
202
+void Phone<ADDR, SOCK>::receiveFromSock()
203
+{
204
+  std::string msg;
205
+  ADDR addr;
206
+
207
+  // make sure socket exists
208
+  if (!m_pSock)
209
+    return;
210
+
211
+  // receive (leave if no reception)
212
+  if (!m_pSock->recv(msg, addr))
213
+    return;
214
+
215
+  // check that packet came from server address
216
+  if (!m_fileServer.m_valid || addr != m_fileServer.m_obj)
217
+    return; // mismatch
218
+
219
+  // reset server timeout
220
+  m_timeRegister = Time::now() + m_serverTimeout;
221
+  updateTimeCallback();
222
+
223
+  // TODO
224
+}
225
+
226
+/// update time callback
227
+template<typename ADDR, typename SOCK>
228
+void Phone<ADDR, SOCK>::updateTimeCallback()
229
+{
230
+  m_mgrs.m_callMgr.requestTimeCall(this, m_timeRegister < m_timeHeartbeat
231
+                                         ? m_timeRegister : m_timeHeartbeat);
232
+}
233
+
234
+template<typename ADDR, typename SOCK>
235
+const Time Phone<ADDR, SOCK>::m_serverTimeout(5);
236
+
237
+template<typename ADDR, typename SOCK>
238
+const Time Phone<ADDR, SOCK>::m_heartbeatInterval(20);
239
+
240
+} // namespace Blinker
241
+
242
+#endif // #ifndef BLINKER_PHONE_IMPL_H
243
+
... ...
@@ -0,0 +1,21 @@
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 UDP4PHONE_H
7
+#define UDP4PHONE_H
8
+
9
+#include "Phone_impl.h"
10
+#include "Udp4Addr.h"
11
+#include "Udp4Sock.h"
12
+
13
+namespace Blinker {
14
+
15
+/// UDP v4 phone connector
16
+typedef Phone<Udp4Addr, Udp4Sock> Udp4Phone;
17
+
18
+} // namespace Blinker
19
+
20
+#endif // #ifndef UDP4PHONE_H
21
+
... ...
@@ -18,6 +18,7 @@
18 18
 #include "Priority.h"
19 19
 #include "Resizer.h"
20 20
 #include "Scaler.h"
21
+#include "Udp4Phone.h"
21 22
 #include "Udp4Receiver.h"
22 23
 #include "Udp4Sender.h"
23 24
 
... ...
@@ -37,6 +38,7 @@ void run(const std::string &dirConfig)
37 38
   ModuleMgr<Priority>     priorities(mgrs,    cfg.getSubdir("priorities"));
38 39
   ModuleMgr<Resizer>      resizers(mgrs,      cfg.getSubdir("resizers"));
39 40
   ModuleMgr<Scaler>       scalers(mgrs,       cfg.getSubdir("scalers"));
41
+  ModuleMgr<Udp4Phone>    udp4Phone(mgrs,     cfg.getSubdir("udp4phones"));
40 42
   ModuleMgr<Udp4Receiver> udp4Receivers(mgrs, cfg.getSubdir("udp4receivers"));
41 43
   ModuleMgr<Udp4Sender>   udp4Senders(mgrs,   cfg.getSubdir("udp4senders"));
42 44
 
43 45