phone connector module basically done
Stefan Schuermans

Stefan Schuermans commited on 2011-12-22 17:40:48
Showing 2 changed files, with 159 additions and 6 deletions.

... ...
@@ -15,6 +15,8 @@
15 15
 #include "ListTracker.h"
16 16
 #include "Mgrs.h"
17 17
 #include "Module.h"
18
+#include "OpConn.h"
19
+#include "OpConnIf.h"
18 20
 #include "SettingFile.h"
19 21
 #include "Time.h"
20 22
 #include "TimeCallee.h"
... ...
@@ -23,7 +25,7 @@ namespace Blinker {
23 25
 
24 26
 /// phone connector (using EBIP)
25 27
 template<typename ADDR, typename SOCK>
26
-class Phone: public IoCallee, public Module, public TimeCallee
28
+class Phone: public IoCallee, public Module, public OpConnIf, public TimeCallee
27 29
 {
28 30
 protected:
29 31
   /// type for address setting file
... ...
@@ -38,6 +40,12 @@ protected:
38 40
   /// map of extensions to call (extension name  -> module name)
39 41
   typedef std::map<std::string, std::string> ExtMap;
40 42
 
43
+  /// map from line number to connection
44
+  typedef std::map<unsigned int, OpConn *> LineConnMap;
45
+
46
+  /// map from connection to line number
47
+  typedef std::map<OpConn *, unsigned int> ConnLineMap;
48
+
41 49
 public:
42 50
   /**
43 51
    * @brief constructor
... ...
@@ -75,6 +83,12 @@ public:
75 83
    */
76 84
   virtual void ioWriteCall(Io *io);
77 85
 
86
+  /**
87
+   * @brief operator connection is closed
88
+   * @param[in] pConn operator connection object
89
+   */
90
+  virtual void opConnClose(OpConn *pConn);
91
+
78 92
 protected:
79 93
   /// (re-)read server address
80 94
   void readServer();
... ...
@@ -91,6 +105,12 @@ protected:
91 105
   /// send heartbeat to server
92 106
   void sendHeartbeat();
93 107
 
108
+  /**
109
+   * @brief send hangup message
110
+   * @param[in] line number of line to hangup
111
+   */
112
+  void sendHangup(unsigned int line);
113
+
94 114
   /**
95 115
    * @brief send message to server
96 116
    * @param[in] msg message to send
... ...
@@ -106,6 +126,26 @@ protected:
106 126
    */
107 127
   void serverMsg(const std::string &msg);
108 128
 
129
+  /**
130
+   * @brief process incoming call
131
+   * @param[in] line number of phone line
132
+   * @param[in] extension extenstion called (i.e. phone number)
133
+   */
134
+  void incomingCall(unsigned int line, const std::string &extension);
135
+
136
+  /**
137
+   * @brief hangup on phone line
138
+   * @param[in] line number of phone line
139
+   */
140
+  void hangup(unsigned int line);
141
+
142
+  /**
143
+   * @brief key pressed on phone line
144
+   * @param[in] line number of phone line
145
+   * @param[in] key key that has been pressed
146
+   */
147
+  void keyPressed(unsigned int line, char key);
148
+
109 149
   /// update time callback
110 150
   void updateTimeCallback();
111 151
 
... ...
@@ -121,6 +161,8 @@ protected:
121 161
   Time           m_timeRegister;   ///< time to re-register
122 162
   Time           m_timeHeartbeat;  ///< time to send next heartbeat
123 163
   ExtMap         m_extMap;         ///< map of extensions to call
164
+  LineConnMap    m_lineConnMap;    ///< map from line number to connection
165
+  ConnLineMap    m_connLineMap;    ///< map from connection to line number
124 166
 }; // class Phone
125 167
 
126 168
 } // namespace Blinker
... ...
@@ -6,6 +6,7 @@
6 6
 #ifndef BLINKER_PHONE_IMPL_H
7 7
 #define BLINKER_PHONE_IMPL_H
8 8
 
9
+#include <sstream>
9 10
 #include <string>
10 11
 
11 12
 #include "Directory.h"
... ...
@@ -15,6 +16,9 @@
15 16
 #include "ListTracker_impl.h"
16 17
 #include "Mgrs.h"
17 18
 #include "Module.h"
19
+#include "OpConn.h"
20
+#include "OpConnIf.h"
21
+#include "OpMgr.h"
18 22
 #include "Phone.h"
19 23
 #include "PhoneExtension.h"
20 24
 #include "PhoneExtension_impl.h"
... ...
@@ -55,6 +59,14 @@ Phone<ADDR, SOCK>::~Phone()
55 59
   // unload extensions
56 60
   m_extListTracker.clear();
57 61
 
62
+  // close all connections
63
+  while (!m_connLineMap.empty()) {
64
+    ConnLineMap::iterator it = m_connLineMap.begin();
65
+    it->first->close();
66
+    sendHangup(it->second);
67
+    m_connLineMap.erase(it);
68
+  }
69
+
58 70
   // destroy socket
59 71
   destroySock();
60 72
 
... ...
@@ -117,6 +129,27 @@ void Phone<ADDR, SOCK>::ioWriteCall(Io *io)
117 129
   (void)io; // unused
118 130
 }
119 131
 
132
+/**
133
+ * @brief operator connection is closed
134
+ * @param[in] pConn operator connection object
135
+ */
136
+template<typename ADDR, typename SOCK>
137
+void Phone<ADDR, SOCK>::opConnClose(OpConn *pConn)
138
+{
139
+  // get phone line of connection
140
+  ConnLineMap::iterator itConn = m_connLineMap.find(pConn);
141
+  if (itConn == m_connLineMap.end())
142
+    return;
143
+  unsigned int line = itConn->second;
144
+
145
+  // send hangup message
146
+  sendHangup(line);
147
+
148
+  // remove connection from maps
149
+  m_connLineMap.erase(itConn);
150
+  m_lineConnMap.erase(line);
151
+}
152
+
120 153
 /// (re-)read server address
121 154
 template<typename ADDR, typename SOCK>
122 155
 void Phone<ADDR, SOCK>::readServer()
... ...
@@ -197,6 +230,18 @@ void Phone<ADDR, SOCK>::sendHeartbeat()
197 230
   updateTimeCallback();
198 231
 }
199 232
 
233
+/**
234
+ * @brief send hangup message
235
+ * @param[in] line number of line to hangup
236
+ */
237
+template<typename ADDR, typename SOCK>
238
+void Phone<ADDR, SOCK>::sendHangup(unsigned int line)
239
+{
240
+  std::stringstream strm;
241
+  strm << line << ":hangup";
242
+  send(strm.str());
243
+}
244
+
200 245
 /**
201 246
  * @brief send message to server
202 247
  * @param[in] msg message to send
... ...
@@ -246,9 +291,8 @@ void Phone<ADDR, SOCK>::receiveFromSock()
246 291
 template<typename ADDR, typename SOCK>
247 292
 void Phone<ADDR, SOCK>::serverMsg(const std::string &msg)
248 293
 {
249
-  StringParser parser(msg);
250
-
251 294
   // get line number and command
295
+  StringParser parser(msg);
252 296
   unsigned int line;
253 297
   std::string cmd;
254 298
   if (!parser.uintNo(line) || !parser.fixChr(':') ||
... ...
@@ -261,12 +305,12 @@ void Phone<ADDR, SOCK>::serverMsg(const std::string &msg)
261 305
     if (!parser.fixChr(':') || !parser.untilDelim(":", true, caller) ||
262 306
         !parser.fixChr(':') || !parser.untilDelim(":", false, extension))
263 307
       return;
264
-    // TODO incomingCall(line, extension);
308
+    incomingCall(line, extension);
265 309
   }
266 310
 
267 311
   // hangup
268 312
   else if (cmd == "onhook") {
269
-    // TODO hangup(line);
313
+    hangup(line);
270 314
   }
271 315
 
272 316
   // DTMF symbol (i.e. key pressed)
... ...
@@ -274,8 +318,75 @@ void Phone<ADDR, SOCK>::serverMsg(const std::string &msg)
274 318
     char key;
275 319
     if (!parser.fixChr(':') || !parser.oneChrOf("0123456789*#", key))
276 320
       return;
277
-    // TODO keyPressed(line, key);
321
+    keyPressed(line, key);
322
+  }
323
+}
324
+
325
+/**
326
+ * @brief process incoming call
327
+ * @param[in] line number of phone line
328
+ * @param[in] extension extenstion called (i.e. phone number)
329
+ */
330
+template<typename ADDR, typename SOCK>
331
+void Phone<ADDR, SOCK>::incomingCall(unsigned int line,
332
+                                     const std::string &extension)
333
+{
334
+  // hangup old call on this line (to be on the safe side)
335
+  hangup(line);
336
+
337
+  // lookup extension
338
+  ExtMap::iterator itExt = m_extMap.find(extension);
339
+  if (itExt == m_extMap.end())
340
+    return; // unknown extension -> ignore
341
+
342
+  // try to open operator connection to module
343
+  OpConn *pConn = m_mgrs.m_opMgr.connect(itExt->second, this);
344
+  if (!pConn) // module is not ready for connection
345
+    return;
346
+
347
+  // add connection to maps
348
+  m_lineConnMap[line] = pConn;
349
+  m_connLineMap[pConn] = line;
278 350
 }
351
+
352
+/**
353
+ * @brief hangup on phone line
354
+ * @param[in] line number of phone line
355
+ */
356
+template<typename ADDR, typename SOCK>
357
+void Phone<ADDR, SOCK>::hangup(unsigned int line)
358
+{
359
+  // get connection
360
+  LineConnMap::iterator itLine = m_lineConnMap.find(line);
361
+  if (itLine == m_lineConnMap.end())
362
+    return; // no connection on this line
363
+  OpConn *pConn = itLine->second;
364
+
365
+  // close connection
366
+  pConn->close();
367
+
368
+  // remove connection from maps
369
+  m_lineConnMap.erase(itLine);
370
+  m_connLineMap.erase(pConn);
371
+}
372
+
373
+/**
374
+ * @brief key pressed on phone line
375
+ * @param[in] line number of phone line
376
+ * @param[in] key key that has been pressed
377
+ */
378
+template<typename ADDR, typename SOCK>
379
+void Phone<ADDR, SOCK>::keyPressed(unsigned int line, char key)
380
+{
381
+  // get connection
382
+  LineConnMap::iterator itLine = m_lineConnMap.find(line);
383
+  if (itLine == m_lineConnMap.end())
384
+    return; // no connection on this line
385
+  OpConn *pConn = itLine->second;
386
+
387
+  // TODO
388
+  (void)pConn;
389
+  (void)key;
279 390
 }
280 391
 
281 392
 /// update time callback
282 393