sender static destination now own class
Stefan Schuermans

Stefan Schuermans commited on 2011-11-22 22:13:20
Showing 8 changed files, with 846 additions and 632 deletions.

... ...
@@ -33,16 +33,17 @@ class Sender: public IoCallee, public Module, public StreamRecv,
33 33
 {
34 34
 protected:
35 35
   /// static destination
36
-  struct Dest {
36
+  class Dest;
37
+
38
+  /// static destination list entry
39
+  struct DestEntry {
37 40
     std::string m_name;   ///< name of static destination
38
-    SettingFile m_file; ///< setting file object
39
-    ADDR        m_addr; ///< parsed address
40
-    Dest(const std::string &name, const File &file); ///< constructor
41
-    bool parse();       ///< parse address from current file
41
+    Dest        *m_pDest; ///< static destination object
42
+    DestEntry(const std::string &name); ///< constructor
42 43
   };
43 44
 
44 45
   /// static destinations
45
-  typedef std::list<Dest> Dests;
46
+  typedef std::list<DestEntry> DestList;
46 47
 
47 48
   /// dynamic destinations: address -> time of last request
48 49
   typedef std::map<ADDR, Time> DynDests;
... ...
@@ -99,6 +100,12 @@ public:
99 100
   virtual void ioWriteCall(Io *io);
100 101
 
101 102
 protected:
103
+  /**
104
+   * @brief free static destiation list
105
+   * @param[in] destList static destination list to free
106
+   */
107
+  void freeDestList(DestList &destList);
108
+
102 109
   /// get input stream and attach to it
103 110
   void getInStream();
104 111
 
... ...
@@ -114,20 +121,19 @@ protected:
114 121
   /**
115 122
    * @brief light update of static destinations,
116 123
    *        i.e. stat all files in current static destination directory
117
-   * @param[in] dests static destinations for protocol
118
-   * @param[in] proto Blinken protocol identifier
124
+   * @param[in] destList static destinations for protocol
119 125
    */
120
-  void updateDestsLight(Dests &dests, etBlinkenProto proto);
126
+  void updateDestsLight(DestList &destList);
121 127
 
122 128
   /**
123 129
    * @brief full update of static destinations,
124 130
    *        i.e. scan files in playlist directory
125 131
    * @param[in] dirDests static destinations directory for protocol
126
-   * @param[in] dests static destinations for protocol
127
-   * @param[in] proto Blinken protocol identifier
132
+   * @param[in] destList static destinations for protocol
133
+   * @param[in] pNoFrameData "no frame" protocaol data
128 134
    */
129
-  void updateDestsFull(Directory &dirDests, Dests &dests,
130
-                       etBlinkenProto proto);
135
+  void updateDestsFull(Directory &dirDests, DestList &destList,
136
+                       const std::string *pNoFrameData);
131 137
 
132 138
   /// remove timed-out dynamic destinations
133 139
   void removeTimedOutDynDests();
... ...
@@ -143,17 +149,18 @@ protected:
143 149
 
144 150
   /**
145 151
    * @brief send data to static/dynamic destinations
146
-   * @param[in] data data to send
147
-   * @param[in] dests static destinations
152
+   * @param[in] data *pData protocol data to send
153
+   * @param[in] destList static destinations
148 154
    * @param[in] dynDests dynamic destinations
149 155
    */
150
-  void sendDests(const std::string &data, const Dests dests,
156
+  void sendDests(const std::string *pData, const DestList destList,
151 157
                  const DynDests dynDests);
152 158
 
153 159
   /**
154 160
    * @brief send current frame to address
155 161
    * @param[in] addr address to send to
156 162
    * @param[in] proto Blinken protocol identifier
163
+   TODO: still needed?
157 164
    */
158 165
   void sendCurFrame(const ADDR &addr, etBlinkenProto proto) const;
159 166
 
... ...
@@ -161,6 +168,7 @@ protected:
161 168
    * @brief send "no frame" to address
162 169
    * @param[in] addr address to send to
163 170
    * @param[in] proto Blinken protocol identifier
171
+   TODO: still needed?
164 172
    */
165 173
   void sendNoFrame(const ADDR &addr, etBlinkenProto proto) const;
166 174
 
... ...
@@ -199,626 +207,20 @@ protected:
199 207
   std::string m_nameInStream;    ///< name of input stream
200 208
   Stream      *m_pInStream;      ///< input stream
201 209
   SOCK        *m_pSock;          ///< socket to use for sending streams
202
-  Dests       m_destsBlp;     ///< static BLP destinations
203
-  Dests       m_destsEblp;    ///< static EBLP destinations
204
-  Dests       m_destsMcuf;    ///< static MCUF destinations
210
+  DestList    m_destListBlp;     ///< static BLP destinations
211
+  DestList    m_destListEblp;    ///< static EBLP destinations
212
+  DestList    m_destListMcuf;    ///< static MCUF destinations
205 213
   DynDests    m_dynDestsBlp;     ///< dynamic BLP destinations
206 214
   DynDests    m_dynDestsEblp;    ///< dynamic EBLP destinations
207 215
   DynDests    m_dynDestsMcuf;    ///< dynamic MCUF destinations
216
+  std::string m_noFrameDataBlp;  ///< "no frame" BLP protocol data
217
+  std::string m_noFrameDataEblp; ///< "no frame" EBLP protocol data
218
+  std::string m_noFrameDataMcuf; ///< "no frame" MCUF protocol data
219
+  std::string m_dataBlp;         ///< current BLP protocol data
220
+  std::string m_dataEblp;        ///< current BLP protocol data
221
+  std::string m_dataMcuf;        ///< current BLP protocol data
208 222
 }; // class Sender
209 223
 
210
-/* ##########
211
-   # Sender #
212
-   ########## */
213
-
214
-/**
215
- * @brief constructor
216
- * @param[in] callMgr callback manager
217
- * @param[in] streamMgr stream manager
218
- * @param[in] dirBase base directory
219
- */
220
-template<typename ADDR, typename SOCK>
221
-Sender<ADDR, SOCK>::Sender(CallMgr &callMgr, StreamMgr &streamMgr,
222
-                           const Directory &dirBase):
223
-  Module(callMgr, streamMgr, dirBase),
224
-  m_fileInStream(dirBase.getFile("instream")),
225
-  m_fileBind(dirBase.getFile("bind")),
226
-  m_dirDestsBlp(dirBase.getSubdir("blp")),
227
-  m_dirDestsEblp(dirBase.getSubdir("eblp")),
228
-  m_dirDestsMcuf(dirBase.getSubdir("mcuf")),
229
-  m_pInStream(NULL),
230
-  m_pSock(NULL)
231
-{
232
-  // get input stream and attach to it
233
-  getInStream();
234
-  // create and bind socket
235
-  createSock();
236
-
237
-  // load static destinations
238
-  updateDestsFull(m_dirDestsBlp, m_destsBlp, BlinkenProtoBlp);
239
-  updateDestsFull(m_dirDestsEblp, m_destsEblp, BlinkenProtoEblp);
240
-  updateDestsFull(m_dirDestsMcuf, m_destsMcuf, BlinkenProtoMcuf);
241
-}
242
-
243
-/// virtual destructor
244
-template<typename ADDR, typename SOCK>
245
-Sender<ADDR, SOCK>::~Sender()
246
-{
247
-  // send "no frame" to all destinations
248
-  sendAllNoFrame();
249
-
250
-  // destroy socket
251
-  destroySock();
252
-  // detach from input stream and release it
253
-  releaseInStream();
254
-  // cancel time callback
255
-  m_callMgr.cancelTimeCall(this);
256
-}
257
-
258
-/// check for update of configuration
259
-template<typename ADDR, typename SOCK>
260
-void Sender<ADDR, SOCK>::updateConfig()
261
-{
262
-  // input stream name file was modified -> re-get input stream
263
-  if (m_fileInStream.checkModified()) {
264
-    releaseInStream();
265
-    getInStream();
266
-  }
267
-
268
-  // bind address file was modified -> re-create socket
269
-  if (m_fileBind.checkModified()) {
270
-    destroySock();
271
-    createSock();
272
-  }
273
-
274
-  // static destinations update
275
-  // (directory modified -> full, otherwise -> light)
276
-  if (m_dirDestsBlp.checkModified())
277
-    updateDestsFull(m_dirDestsBlp, m_destsBlp, BlinkenProtoBlp);
278
-  else
279
-    updateDestsLight(m_destsBlp, BlinkenProtoBlp);
280
-  if (m_dirDestsEblp.checkModified())
281
-    updateDestsFull(m_dirDestsEblp, m_destsEblp, BlinkenProtoEblp);
282
-  else
283
-    updateDestsLight(m_destsEblp, BlinkenProtoEblp);
284
-  if (m_dirDestsMcuf.checkModified())
285
-    updateDestsFull(m_dirDestsMcuf, m_destsMcuf, BlinkenProtoMcuf);
286
-  else
287
-    updateDestsLight(m_destsMcuf, BlinkenProtoMcuf);
288
-}
289
-
290
-/**
291
- * @brief set current frame
292
- * @param[in] stream stream name
293
- * @param[in] pFrame current frame
294
- */
295
-template<typename ADDR, typename SOCK>
296
-void Sender<ADDR, SOCK>::setFrame(const std::string &stream,
297
-                                  stBlinkenFrame *pFrame)
298
-{
299
-  // send frame to all destinations
300
-  sendAllFrame(pFrame);
301
-
302
-  (void)stream; // unused
303
-}
304
-
305
-/**
306
- * @brief set current frame to none
307
- * @param[in] stream stream name
308
- */
309
-template<typename ADDR, typename SOCK>
310
-void Sender<ADDR, SOCK>::setNoFrame(const std::string &stream)
311
-{
312
-  // send "no frame" to all destinations
313
-  sendAllNoFrame();
314
-
315
-  (void)stream; // unused
316
-}
317
-
318
-/// callback when requsted time reached
319
-template<typename ADDR, typename SOCK>
320
-void Sender<ADDR, SOCK>::timeCall()
321
-{
322
-  stBlinkenFrame *pFrame;
323
-  std::string data;
324
-
325
-  // get current frame from stream
326
-  if (m_pInStream && m_pInStream->getCurFrame(pFrame))
327
-    // repeat frame to all destinations
328
-    sendAllFrame(pFrame);
329
-
330
-  // no stream of no current frame
331
-  else
332
-    // repeat "no frame" to all destinations
333
-    sendAllNoFrame();
334
-}
335
-
336
-/**
337
- * @brief callback when I/O object is readable
338
- * @param[in] io I/O object that is readable
339
- */
340
-template<typename ADDR, typename SOCK>
341
-void Sender<ADDR, SOCK>::ioReadCall(Io *io)
342
-{
343
-  // reception on socket
344
-  if (io == m_pSock)
345
-    receiveFromSock();
346
-}
347
-
348
-/**
349
- * @brief callback when I/O object is writable
350
- * @param[in] io I/O object that is writable
351
- */
352
-template<typename ADDR, typename SOCK>
353
-void Sender<ADDR, SOCK>::ioWriteCall(Io *io)
354
-{
355
-  (void)io; // unused
356
-}
357
-
358
-/// get input stream and attach to it
359
-template<typename ADDR, typename SOCK>
360
-void Sender<ADDR, SOCK>::getInStream()
361
-{
362
-  // get input stream
363
-  m_fileInStream.getStr(m_nameInStream);
364
-  m_pInStream = &m_streamMgr.refStream(m_nameInStream);
365
-
366
-  // attach to input stream
367
-  if (m_pInStream)
368
-    m_pInStream->attach(this);
369
-}
370
-
371
-/// detach from input stream and release it
372
-template<typename ADDR, typename SOCK>
373
-void Sender<ADDR, SOCK>::releaseInStream()
374
-{
375
-  // detach from input stream
376
-  if (m_pInStream)
377
-    m_pInStream->detach(this);
378
-
379
-  // unreference stream
380
-  m_pInStream = NULL;
381
-  m_streamMgr.unrefStream(m_nameInStream);
382
-}
383
-
384
-/// create socket and bind it
385
-template<typename ADDR, typename SOCK>
386
-void Sender<ADDR, SOCK>::createSock()
387
-{
388
-  std::string strAddr;
389
-  ADDR addr;
390
-
391
-  // create socket
392
-  if (!m_pSock) {
393
-    m_pSock = new SOCK();
394
-    if (!m_pSock)
395
-      return;
396
-  }
397
-
398
-  // get bind address from bind address setting file
399
-  if (!m_fileBind.getStr(strAddr) || !addr.fromStr(strAddr)) {
400
-    delete m_pSock;
401
-    m_pSock = NULL;
402
-    return;
403
-  }
404
-
405
-  // bind socket
406
-  if (!m_pSock->bind(addr)) {
407
-    delete m_pSock;
408
-    m_pSock = NULL;
409
-    return;
410
-  }
411
-
412
-  // request callback on recpetion
413
-  m_callMgr.requestIoReadCall(this, m_pSock);
414
-}
415
-
416
-/// destroy socket
417
-template<typename ADDR, typename SOCK>
418
-void Sender<ADDR, SOCK>::destroySock()
419
-{
420
-  // send "no frame" to all destinations
421
-  // (stream from this socket will stop now)
422
-  sendAllNoFrame();
423
-
424
-  // clear dynamic destinations
425
-  // (they registered with this socket adn this socket is gone)
426
-  m_dynDestsBlp.clear();
427
-  m_dynDestsEblp.clear();
428
-  m_dynDestsMcuf.clear();
429
-
430
-  // cancel callback request
431
-  m_callMgr.cancelIoReadCall(this, m_pSock);
432
-
433
-  // destroy socket
434
-  if (m_pSock) {
435
-    delete m_pSock;
436
-    m_pSock = NULL;
437
-  }
438
-}
439
-
440
-/**
441
- * @brief light update of static destinations,
442
- *        i.e. stat all files in current static destination directory
443
- * @param[in] dests static destinations for one protocol
444
- * @param[in] proto Blinken protocol identifier
445
- */
446
-template<typename ADDR, typename SOCK>
447
-void Sender<ADDR, SOCK>::updateDestsLight(Dests &dests, etBlinkenProto proto)
448
-{
449
-  // walk through all files in static dest dir and check for modification
450
-  typename Dests::iterator itDest = dests.begin();
451
-  while (itDest != dests.end()) {
452
-
453
-    // address changed
454
-    if (itDest->m_file.checkModified()) {
455
-      // send "no frame" to old address
456
-      sendNoFrame(itDest->m_addr, proto);
457
-      // re-load address
458
-      if (!itDest->parse()) {
459
-        // parsing address failed -> remove destination
460
-        itDest = dests.erase(itDest);
461
-        // do not advance to next destination
462
-        continue;
463
-      }
464
-      // send current frame to new address
465
-      sendCurFrame(itDest->m_addr, proto);
466
-    }
467
-
468
-    // advance to next destination
469
-    ++itDest;
470
-
471
-  } // while itDest
472
-}
473
-
474
-/**
475
- * @brief full update of static destinations,
476
- *        i.e. scan files in playlist directory
477
- * @param[in] dirDests static destinations directory for protocol
478
- * @param[in] dests static destinations for protocol
479
- * @param[in] proto Blinken protocol identifier
480
- */
481
-template<typename ADDR, typename SOCK>
482
-void Sender<ADDR, SOCK>::updateDestsFull(Directory &dirDests, Dests &dests,
483
-                                         etBlinkenProto proto)
484
-{
485
-  // get list of files in static destinations directory
486
-  typedef std::list<std::string> Filelist;
487
-  Filelist curFiles;
488
-  dirDests.getEntries(Directory::TypeFile, curFiles);
489
-
490
-  // walk through current static destinations and file list simultaneously
491
-  Filelist::const_iterator itFile = curFiles.begin();
492
-  typename Dests::iterator itDest = dests.begin();
493
-  while (itFile != curFiles.end() || itDest != dests.end()) {
494
-
495
-    // new static destination inserted
496
-    if (itDest == dests.end() ||
497
-        (itFile != curFiles.end() && *itFile < itDest->m_name)) {
498
-      // parse new address
499
-      Dest dest(*itFile, dirDests.getFile(*itFile));
500
-      if (dest.parse()) {
501
-        // insert new static destination
502
-        dests.insert(itDest, dest);
503
-        // send current frame to new static destination
504
-        sendCurFrame(itDest->m_addr, proto);
505
-      }
506
-      // advance to next file
507
-      ++itFile;
508
-    }
509
-
510
-    // static destination removed
511
-    // static destination changed (=> remove and re-insert in next iteration)
512
-    else if (itFile == curFiles.end() || *itFile > itDest->m_name ||
513
-             itDest->m_file.checkModified()) {
514
-      // send "no frame" to old static destination
515
-      sendNoFrame(itDest->m_addr, proto);
516
-      // remove static destination
517
-      itDest = dests.erase(itDest);
518
-      // do not advance to next file
519
-    }
520
-
521
-    // static destination stayed in playlist and did not change
522
-    else {
523
-      // advance to next file and next static destination
524
-      ++itFile;
525
-      ++itDest;
526
-    }
527
-
528
-  } // while itFile itDest
529
-}
530
-
531
-/// remove timed-out dynamic destinations
532
-template<typename ADDR, typename SOCK>
533
-void Sender<ADDR, SOCK>::removeTimedOutDynDests()
534
-{
535
-  Time now, timeout;
536
-  typename DynDests::iterator itDyn;
537
-
538
-  now = Time::now();
539
-  timeout = Time(30);
540
-
541
-  for (itDyn = m_dynDestsBlp.begin(); itDyn != m_dynDestsBlp.end(); )
542
-    if (itDyn->second + timeout < now)
543
-      m_dynDestsBlp.erase(itDyn++);
544
-    else
545
-      ++itDyn;
546
-  for (itDyn = m_dynDestsEblp.begin(); itDyn != m_dynDestsEblp.end(); )
547
-    if (itDyn->second + timeout < now)
548
-      m_dynDestsEblp.erase(itDyn++);
549
-    else
550
-      ++itDyn;
551
-  for (itDyn = m_dynDestsMcuf.begin(); itDyn != m_dynDestsMcuf.end(); )
552
-    if (itDyn->second + timeout < now)
553
-      m_dynDestsMcuf.erase(itDyn++);
554
-    else
555
-      ++itDyn;
556
-}
557
-
558
-/**
559
- * @brief send frame to all destinations
560
- * @param[in] pFrame frame to send
561
- */
562
-template<typename ADDR, typename SOCK>
563
-void Sender<ADDR, SOCK>::sendAllFrame(stBlinkenFrame *pFrame)
564
-{
565
-  std::string data;
566
-
567
-  // remove timed-out dynamic destinations
568
-  removeTimedOutDynDests();
569
-
570
-  // convert frame to protocol data and send to all static/dynamic destinations
571
-  if (!m_destsBlp.empty() || !m_dynDestsBlp.empty()) {
572
-    frame2data(pFrame, BlinkenProtoBlp, data);
573
-    sendDests(data, m_destsBlp, m_dynDestsBlp);
574
-  }
575
-  if (!m_destsEblp.empty() || !m_dynDestsEblp.empty()) {
576
-    frame2data(pFrame, BlinkenProtoEblp, data);
577
-    sendDests(data, m_destsEblp, m_dynDestsEblp);
578
-  }
579
-  if (!m_destsMcuf.empty() || !m_dynDestsMcuf.empty()) {
580
-    frame2data(pFrame, BlinkenProtoMcuf, data);
581
-    sendDests(data, m_destsMcuf, m_dynDestsMcuf);
582
-  }
583
-
584
-  // request time callback in one second
585
-  m_callMgr.requestTimeCall(this, Time::now() + Time(1));
586
-}
587
-
588
-/// send "no frame" to all destinations
589
-template<typename ADDR, typename SOCK>
590
-void Sender<ADDR, SOCK>::sendAllNoFrame()
591
-{
592
-  std::string data;
593
-
594
-  // remove timed-out dynamic destinations
595
-  removeTimedOutDynDests();
596
-
597
-  // get "no frame" protocol data and send to all static/dynamic destinations
598
-  if (!m_destsBlp.empty() || !m_dynDestsBlp.empty()) {
599
-    noFrame2data(BlinkenProtoBlp, data);
600
-    sendDests(data, m_destsBlp, m_dynDestsBlp);
601
-  }
602
-  if (!m_destsEblp.empty() || !m_dynDestsEblp.empty()) {
603
-    noFrame2data(BlinkenProtoEblp, data);
604
-    sendDests(data, m_destsEblp, m_dynDestsEblp);
605
-  }
606
-  if (!m_destsMcuf.empty() || !m_dynDestsMcuf.empty()) {
607
-    noFrame2data(BlinkenProtoMcuf, data);
608
-    sendDests(data, m_destsMcuf, m_dynDestsMcuf);
609
-  }
610
-
611
-  // request time callback in one second
612
-  m_callMgr.requestTimeCall(this, Time::now() + Time(1));
613
-}
614
-
615
-/**
616
- * @brief send data to static/dynamic destinations
617
- * @param[in] data data to send
618
- * @param[in] dests static destinations
619
- * @param[in] dynDests dynamic destinations
620
- */
621
-template<typename ADDR, typename SOCK>
622
-void Sender<ADDR, SOCK>::sendDests(const std::string &data, const Dests dests,
623
-                                   const DynDests dynDests)
624
-{
625
-  // send data to static destinations
626
-  typename Dests::const_iterator itDest;
627
-  for (itDest = dests.begin(); itDest != dests.end(); ++itDest)
628
-    sendFrame(data, itDest->m_addr);
629
-
630
-  // send data to all dynamic destinations
631
-  typename DynDests::const_iterator itDyn;
632
-  for (itDyn = dynDests.begin(); itDyn != dynDests.end(); ++itDyn)
633
-    sendFrame(data, itDyn->first);
634
-}
635
-
636
-/**
637
- * @brief send current frame to address
638
- * @param[in] addr address to send to
639
- * @param[in] proto Blinken protocol identifier
640
- */
641
-template<typename ADDR, typename SOCK>
642
-void Sender<ADDR, SOCK>::sendCurFrame(const ADDR &addr,
643
-                                      etBlinkenProto proto) const
644
-{
645
-  stBlinkenFrame *pFrame;
646
-  std::string data;
647
-
648
-  // get current frame from stream
649
-  if (m_pInStream && m_pInStream->getCurFrame(pFrame)) {
650
-    // convert frame to protocal data
651
-    frame2data(pFrame, proto, data);
652
-    // send frame to address
653
-    sendFrame(data, addr);
654
-  }
655
-
656
-  // no stream of no current frame
657
-  else {
658
-    // get "no frame" ad protocal data
659
-    noFrame2data(proto, data);
660
-    // send "no frame" to address
661
-    sendFrame(data, addr);
662
-  }
663
-}
664
-
665
-/**
666
- * @brief send "no frame" to address
667
- * @param[in] addr address to send to
668
- * @param[in] proto Blinken protocol identifier
669
- */
670
-template<typename ADDR, typename SOCK>
671
-void Sender<ADDR, SOCK>::sendNoFrame(const ADDR &addr,
672
-                                     etBlinkenProto proto) const
673
-{
674
-  std::string data;
675
-
676
-  // get "no frame" ad protocal data
677
-  noFrame2data(proto, data);
678
-
679
-  // send "no frame" to address
680
-  sendFrame(data, addr);
681
-}
682
-
683
-/**
684
- * @brief send frame to address
685
- * @param[in] data protocol data of frame
686
- * @param[in] addr address to send to
687
- */
688
-template<typename ADDR, typename SOCK>
689
-void Sender<ADDR, SOCK>::sendFrame(const std::string &data,
690
-                                   const ADDR &addr) const
691
-{
692
-  if (m_pSock) {
693
-    m_pSock->send(data, addr);
694
-  }
695
-}
696
-
697
-/**
698
- * @brief convert frame to protocol data
699
- * @param[in] pFrame frame
700
- * @param[in] proto Blinken protocol identifier
701
- * @param[out] data protocol data
702
- */
703
-template<typename ADDR, typename SOCK>
704
-void Sender<ADDR, SOCK>::frame2data(stBlinkenFrame *pFrame,
705
-                                    etBlinkenProto proto, std::string &data)
706
-{
707
-  char buf[65536];
708
-  int len;
709
-
710
-  // convert frame to protcol data
711
-  len = BlinkenFrameToNetwork(pFrame, proto, buf, sizeof(buf));
712
-  if (len < 0)
713
-    len = 0;
714
-  data.assign(buf, len);
715
-}
716
-
717
-/**
718
- * @brief get "no frame" protocol data
719
- * @param[in] proto Blinken protocol identifier
720
- * @param[out] data protcol data
721
- */
722
-template<typename ADDR, typename SOCK>
723
-void Sender<ADDR, SOCK>::noFrame2data(etBlinkenProto proto, std::string &data)
724
-{
725
-  char buf[16];
726
-  int len;
727
-
728
-  // obtain "no frame" protcol data
729
-  len = BlinkenProtoMakePacket(proto, BlinkenPacketStreamEnd,
730
-        buf, sizeof(buf));
731
-  if (len < 0)
732
-    len = 0;
733
-  data.assign(buf, len);
734
-}
735
-
736
-/// receive data from socket
737
-template<typename ADDR, typename SOCK>
738
-void Sender<ADDR, SOCK>::receiveFromSock()
739
-{
740
-  etBlinkenProto proto;
741
-  etBlinkenPacket packet;
742
-  std::string data;
743
-  ADDR addr;
744
-
745
-  // make sure socket exists
746
-  if (!m_pSock)
747
-    return;
748
-
749
-  // receive (leave if no reception)
750
-  if (!m_pSock->recv(data, addr))
751
-    return;
752
-
753
-  // detect packet type and protocol
754
-  BlinkenProtoDetectPacket(data.c_str(), data.size(), &proto, &packet);
755
-
756
-  switch (packet) {
757
-
758
-    // request -> add to dynamic destinations and send current frame
759
-    case BlinkenPacketRequest:
760
-      switch (proto) {
761
-        case BlinkenProtoBlp:
762
-          m_dynDestsBlp[addr] = Time::now();
763
-          sendCurFrame(addr, BlinkenProtoBlp);
764
-          break;
765
-        case BlinkenProtoEblp:
766
-          m_dynDestsEblp[addr] = Time::now();
767
-          sendCurFrame(addr, BlinkenProtoEblp);
768
-          break;
769
-        case BlinkenProtoMcuf:
770
-          m_dynDestsMcuf[addr] = Time::now();
771
-          sendCurFrame(addr, BlinkenProtoMcuf);
772
-          break;
773
-        default:
774
-          break;
775
-      }
776
-      break;
777
-
778
-    // end request -> remove from dynamic destinations
779
-    case BlinkenPacketEndRequest:
780
-      switch (proto) {
781
-        case BlinkenProtoBlp:
782
-          m_dynDestsBlp.erase(addr);
783
-          break;
784
-        case BlinkenProtoEblp:
785
-          m_dynDestsEblp.erase(addr);
786
-          break;
787
-        case BlinkenProtoMcuf:
788
-          m_dynDestsMcuf.erase(addr);
789
-          break;
790
-        default:
791
-          break;
792
-      }
793
-      break;
794
-
795
-    default:
796
-      break;
797
-
798
-  } // switch (packet)
799
-
800
-}
801
-
802
-/* ################
803
-   # Sender::Dest #
804
-   ################ */
805
-
806
-/// constructor
807
-template<typename ADDR, typename SOCK>
808
-Sender<ADDR, SOCK>::Dest::Dest(const std::string &name, const File &file):
809
-  m_name(name),
810
-  m_file(file)
811
-{
812
-}
813
-
814
-/// parse address from current file
815
-template<typename ADDR, typename SOCK>
816
-bool Sender<ADDR, SOCK>::Dest::parse()
817
-{
818
-  std::string strAddr;
819
-  return m_file.getStr(strAddr) && m_addr.fromStr(strAddr);
820
-}
821
-
822 224
 } // namespace Blinker
823 225
 
824 226
 #endif // #ifndef SENDER_H
... ...
@@ -0,0 +1,75 @@
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 SENDERDEST_H
7
+#define SENDERDEST_H
8
+
9
+#include <string>
10
+
11
+#include "Directory.h"
12
+#include "File.h"
13
+#include "Module.h"
14
+#include "Sender.h"
15
+#include "SettingFile.h"
16
+
17
+namespace Blinker {
18
+
19
+/// static destination of a stream sender
20
+template<typename ADDR, typename SOCK>
21
+class Sender<ADDR, SOCK>::Dest
22
+{
23
+public:
24
+  /**
25
+   * @brief constructor
26
+   * @param[in] sender owning sender object
27
+   * @param[in] dirBase base directory
28
+   * @param[in] pNoFrameData protocol data for "no frame" packet
29
+   */
30
+  Dest(Sender &sender, const Directory &dirBase,
31
+       const std::string *pNoFrameData);
32
+
33
+  /// destructor
34
+  ~Dest();
35
+
36
+private:
37
+  /// copy constructor disabled
38
+  Dest(const Dest &that);
39
+
40
+  /// assignment operator disabled
41
+  const Dest & operator=(const Dest &that);
42
+
43
+public:
44
+  /// check for update of configuration
45
+  void updateConfig();
46
+
47
+  /**
48
+   * @brief set current protocol data
49
+   * @param[in] pData protocol data to send to address
50
+   */
51
+  void setProtoData(const std::string *pData);
52
+
53
+protected:
54
+  /// (re-)get address
55
+  void getAddr();
56
+
57
+  /**
58
+   * @brief send protocol data to address
59
+   * @param[in] pData protocol data to send to address
60
+   */
61
+  void send(const std::string *pData);
62
+
63
+protected:
64
+  Sender            &m_sender;       ///< owning sender object
65
+  SettingFile       m_fileAddr;      ///< address file
66
+  ADDR              m_addr;          ///< address
67
+  bool              m_haveAddr;      ///< if address is available
68
+  const std::string *m_pNoFrameData; ///< protocol data for "no frame" packet
69
+  const std::string *m_pData;        ///< protocol data to send to address
70
+}; // class Sender<ADDr, SOCK>::Dest
71
+
72
+} // namespace Blinker
73
+
74
+#endif // #ifndef SENDERDEST_H
75
+
... ...
@@ -0,0 +1,100 @@
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 SENDERDEST_IMPL_H
7
+#define SENDERDEST_IMPL_H
8
+
9
+#include <string>
10
+
11
+#include "Directory.h"
12
+#include "File.h"
13
+#include "Module.h"
14
+#include "Sender.h"
15
+#include "SenderDest.h"
16
+#include "SettingFile.h"
17
+
18
+namespace Blinker {
19
+
20
+/**
21
+ * @brief constructor
22
+ * @param[in] sender owning sender object
23
+ * @param[in] dirBase base directory
24
+ * @param[in] pNoFrameData protocol data for "no frame" packet
25
+ */
26
+template<typename ADDR, typename SOCK>
27
+Sender<ADDR, SOCK>::Dest::Dest(Sender &sender, const Directory &dirBase,
28
+                               const std::string *pNoFrameData):
29
+  m_sender(sender),
30
+  m_fileAddr(dirBase.getFile("addr")),
31
+  m_haveAddr(false),
32
+  m_pNoFrameData(pNoFrameData),
33
+  m_pData(pNoFrameData)
34
+{
35
+  // set up
36
+  getAddr();
37
+}
38
+
39
+/// destructor
40
+template<typename ADDR, typename SOCK>
41
+Sender<ADDR, SOCK>::Dest::~Dest()
42
+{
43
+  // send "no frame" protocol data to old address
44
+  send(m_pNoFrameData);
45
+}
46
+
47
+/// check for update of configuration
48
+template<typename ADDR, typename SOCK>
49
+void Sender<ADDR, SOCK>::Dest::updateConfig()
50
+{
51
+  // address file was modified -> re-get address
52
+  if (m_fileAddr.checkModified())
53
+    getAddr();
54
+}
55
+
56
+/**
57
+ * @brief set current protocol data
58
+ * @param[in] pData protocol data to send to address
59
+ */
60
+template<typename ADDR, typename SOCK>
61
+void Sender<ADDR, SOCK>::Dest::setProtoData(const std::string *pData)
62
+{
63
+  // remember new data
64
+  m_pData = pData;
65
+
66
+  // send new protocol data to current address
67
+  send(m_pData);
68
+}
69
+
70
+/// (re-)get address
71
+template<typename ADDR, typename SOCK>
72
+void Sender<ADDR, SOCK>::Dest::getAddr()
73
+{
74
+  std::string strAddr;
75
+
76
+  // send "no frame" protocol data to old address
77
+  send(m_pNoFrameData);
78
+
79
+  // parse new address from file
80
+  m_haveAddr = m_fileAddr.getStr(strAddr) && m_addr.fromStr(strAddr);
81
+
82
+  // send current protocol data to new address
83
+  send(m_pData);
84
+}
85
+
86
+/**
87
+ * @brief send protocol data to address
88
+ * @param[in] pData protocol data to send to address
89
+ */
90
+template<typename ADDR, typename SOCK>
91
+void Sender<ADDR, SOCK>::Dest::send(const std::string *pData)
92
+{
93
+  if (m_sender.m_pSock && m_haveAddr && pData)
94
+    m_sender.m_pSock->send(*pData, m_addr);
95
+}
96
+
97
+} // namespace Blinker
98
+
99
+#endif // #ifndef SENDERDEST_IMPL_H
100
+
... ...
@@ -0,0 +1,637 @@
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 SENDER_IMPL_H
7
+#define SENDER_IMPL_H
8
+
9
+#include <list>
10
+#include <map>
11
+#include <string>
12
+
13
+#include <BlinkenLib/BlinkenProto.h>
14
+#include <BlinkenLib/BlinkenFrame.h>
15
+
16
+#include "CallMgr.h"
17
+#include "Directory.h"
18
+#include "File.h"
19
+#include "IoCallee.h"
20
+#include "Module.h"
21
+#include "Sender.h"
22
+#include "SenderDest.h"
23
+#include "SenderDest_impl.h"
24
+#include "SettingFile.h"
25
+#include "StreamMgr.h"
26
+#include "StreamRecv.h"
27
+#include "Time.h"
28
+#include "TimeCallee.h"
29
+
30
+namespace Blinker {
31
+
32
+/**
33
+ * @brief constructor
34
+ * @param[in] callMgr callback manager
35
+ * @param[in] streamMgr stream manager
36
+ * @param[in] dirBase base directory
37
+ */
38
+template<typename ADDR, typename SOCK>
39
+Sender<ADDR, SOCK>::Sender(CallMgr &callMgr, StreamMgr &streamMgr,
40
+                           const Directory &dirBase):
41
+  Module(callMgr, streamMgr, dirBase),
42
+  m_fileInStream(dirBase.getFile("instream")),
43
+  m_fileBind(dirBase.getFile("bind")),
44
+  m_dirDestsBlp(dirBase.getSubdir("blp")),
45
+  m_dirDestsEblp(dirBase.getSubdir("eblp")),
46
+  m_dirDestsMcuf(dirBase.getSubdir("mcuf")),
47
+  m_pInStream(NULL),
48
+  m_pSock(NULL)
49
+{
50
+  // initialize protocol data buffers
51
+  noFrame2data(BlinkenProtoBlp, m_noFrameDataBlp);
52
+  noFrame2data(BlinkenProtoEblp, m_noFrameDataEblp);
53
+  noFrame2data(BlinkenProtoMcuf, m_noFrameDataMcuf);
54
+  m_dataBlp = m_noFrameDataBlp;
55
+  m_dataEblp = m_noFrameDataEblp;
56
+  m_dataMcuf = m_noFrameDataMcuf;
57
+
58
+  // get input stream and attach to it
59
+  getInStream();
60
+  // create and bind socket
61
+  createSock();
62
+
63
+  // load static destinations
64
+  updateDestsFull(m_dirDestsBlp, m_destListBlp, &m_noFrameDataBlp);
65
+  updateDestsFull(m_dirDestsEblp, m_destListEblp, &m_noFrameDataEblp);
66
+  updateDestsFull(m_dirDestsMcuf, m_destListMcuf, &m_noFrameDataMcuf);
67
+}
68
+
69
+/// virtual destructor
70
+template<typename ADDR, typename SOCK>
71
+Sender<ADDR, SOCK>::~Sender()
72
+{
73
+  // send "no frame" to all destinations
74
+  sendAllNoFrame();
75
+
76
+  // free static destination lists
77
+  freeDestList(m_destListBlp);
78
+  freeDestList(m_destListEblp);
79
+  freeDestList(m_destListMcuf);
80
+
81
+  // destroy socket
82
+  destroySock();
83
+  // detach from input stream and release it
84
+  releaseInStream();
85
+  // cancel time callback
86
+  m_callMgr.cancelTimeCall(this);
87
+}
88
+
89
+/// check for update of configuration
90
+template<typename ADDR, typename SOCK>
91
+void Sender<ADDR, SOCK>::updateConfig()
92
+{
93
+  // input stream name file was modified -> re-get input stream
94
+  if (m_fileInStream.checkModified()) {
95
+    releaseInStream();
96
+    getInStream();
97
+  }
98
+
99
+  // bind address file was modified -> re-create socket
100
+  if (m_fileBind.checkModified()) {
101
+    destroySock();
102
+    createSock();
103
+  }
104
+
105
+  // static destinations update
106
+  // (directory modified -> full, otherwise -> light)
107
+  if (m_dirDestsBlp.checkModified())
108
+    updateDestsFull(m_dirDestsBlp, m_destListBlp, &m_noFrameDataBlp);
109
+  else
110
+    updateDestsLight(m_destListBlp);
111
+  if (m_dirDestsEblp.checkModified())
112
+    updateDestsFull(m_dirDestsEblp, m_destListEblp, &m_noFrameDataEblp);
113
+  else
114
+    updateDestsLight(m_destListEblp);
115
+  if (m_dirDestsMcuf.checkModified())
116
+    updateDestsFull(m_dirDestsMcuf, m_destListMcuf, &m_noFrameDataMcuf);
117
+  else
118
+    updateDestsLight(m_destListMcuf);
119
+}
120
+
121
+/**
122
+ * @brief set current frame
123
+ * @param[in] stream stream name
124
+ * @param[in] pFrame current frame
125
+ */
126
+template<typename ADDR, typename SOCK>
127
+void Sender<ADDR, SOCK>::setFrame(const std::string &stream,
128
+                                  stBlinkenFrame *pFrame)
129
+{
130
+  // send frame to all destinations
131
+  sendAllFrame(pFrame);
132
+
133
+  (void)stream; // unused
134
+}
135
+
136
+/**
137
+ * @brief set current frame to none
138
+ * @param[in] stream stream name
139
+ */
140
+template<typename ADDR, typename SOCK>
141
+void Sender<ADDR, SOCK>::setNoFrame(const std::string &stream)
142
+{
143
+  // send "no frame" to all destinations
144
+  sendAllNoFrame();
145
+
146
+  (void)stream; // unused
147
+}
148
+
149
+/// callback when requsted time reached
150
+template<typename ADDR, typename SOCK>
151
+void Sender<ADDR, SOCK>::timeCall()
152
+{
153
+  stBlinkenFrame *pFrame;
154
+  std::string data;
155
+
156
+  // get current frame from stream
157
+  if (m_pInStream && m_pInStream->getCurFrame(pFrame))
158
+    // repeat frame to all destinations
159
+    sendAllFrame(pFrame);
160
+
161
+  // no stream of no current frame
162
+  else
163
+    // repeat "no frame" to all destinations
164
+    sendAllNoFrame();
165
+}
166
+
167
+/**
168
+ * @brief callback when I/O object is readable
169
+ * @param[in] io I/O object that is readable
170
+ */
171
+template<typename ADDR, typename SOCK>
172
+void Sender<ADDR, SOCK>::ioReadCall(Io *io)
173
+{
174
+  // reception on socket
175
+  if (io == m_pSock)
176
+    receiveFromSock();
177
+}
178
+
179
+/**
180
+ * @brief callback when I/O object is writable
181
+ * @param[in] io I/O object that is writable
182
+ */
183
+template<typename ADDR, typename SOCK>
184
+void Sender<ADDR, SOCK>::ioWriteCall(Io *io)
185
+{
186
+  (void)io; // unused
187
+}
188
+
189
+/**
190
+ * @brief free static destiation list
191
+ * @param[in] destList static destination list to free
192
+ */
193
+template<typename ADDR, typename SOCK>
194
+void Sender<ADDR, SOCK>::freeDestList(DestList &destList)
195
+{
196
+  while (!destList.empty()) {
197
+    delete destList.back().m_pDest;
198
+    destList.pop_back();
199
+  }
200
+}
201
+
202
+/// get input stream and attach to it
203
+template<typename ADDR, typename SOCK>
204
+void Sender<ADDR, SOCK>::getInStream()
205
+{
206
+  // get input stream
207
+  m_fileInStream.getStr(m_nameInStream);
208
+  m_pInStream = &m_streamMgr.refStream(m_nameInStream);
209
+
210
+  // attach to input stream
211
+  if (m_pInStream)
212
+    m_pInStream->attach(this);
213
+}
214
+
215
+/// detach from input stream and release it
216
+template<typename ADDR, typename SOCK>
217
+void Sender<ADDR, SOCK>::releaseInStream()
218
+{
219
+  // detach from input stream
220
+  if (m_pInStream)
221
+    m_pInStream->detach(this);
222
+
223
+  // unreference stream
224
+  m_pInStream = NULL;
225
+  m_streamMgr.unrefStream(m_nameInStream);
226
+}
227
+
228
+/// create socket and bind it
229
+template<typename ADDR, typename SOCK>
230
+void Sender<ADDR, SOCK>::createSock()
231
+{
232
+  std::string strAddr;
233
+  ADDR addr;
234
+
235
+  // create socket
236
+  if (!m_pSock) {
237
+    m_pSock = new SOCK();
238
+    if (!m_pSock)
239
+      return;
240
+  }
241
+
242
+  // get bind address from bind address setting file
243
+  if (!m_fileBind.getStr(strAddr) || !addr.fromStr(strAddr)) {
244
+    delete m_pSock;
245
+    m_pSock = NULL;
246
+    return;
247
+  }
248
+
249
+  // bind socket
250
+  if (!m_pSock->bind(addr)) {
251
+    delete m_pSock;
252
+    m_pSock = NULL;
253
+    return;
254
+  }
255
+
256
+  // request callback on recpetion
257
+  m_callMgr.requestIoReadCall(this, m_pSock);
258
+}
259
+
260
+/// destroy socket
261
+template<typename ADDR, typename SOCK>
262
+void Sender<ADDR, SOCK>::destroySock()
263
+{
264
+  // send "no frame" to all destinations
265
+  // (stream from this socket will stop now)
266
+  sendAllNoFrame();
267
+
268
+  // clear dynamic destinations
269
+  // (they registered with this socket adn this socket is gone)
270
+  m_dynDestsBlp.clear();
271
+  m_dynDestsEblp.clear();
272
+  m_dynDestsMcuf.clear();
273
+
274
+  // cancel callback request
275
+  m_callMgr.cancelIoReadCall(this, m_pSock);
276
+
277
+  // destroy socket
278
+  if (m_pSock) {
279
+    delete m_pSock;
280
+    m_pSock = NULL;
281
+  }
282
+}
283
+
284
+/**
285
+ * @brief light update of static destinations,
286
+ *        i.e. stat all files in current static destination directory
287
+ * @param[in] destList static destinations for one protocol
288
+ */
289
+template<typename ADDR, typename SOCK>
290
+void Sender<ADDR, SOCK>::updateDestsLight(DestList &destList)
291
+{
292
+  // walk through all files in static dest dir and check for modification
293
+  typename DestList::iterator itDest;
294
+  for (itDest = destList.begin(); itDest != destList.end(); ++itDest)
295
+    itDest->m_pDest->updateConfig();
296
+}
297
+
298
+/**
299
+ * @brief full update of static destinations,
300
+ *        i.e. scan files in playlist directory
301
+ * @param[in] dirDests static destinations directory for protocol
302
+ * @param[in] destList static destinations for protocol
303
+ * @param[in] pNoFrameData "no frame" protocaol data
304
+ */
305
+template<typename ADDR, typename SOCK>
306
+void Sender<ADDR, SOCK>::updateDestsFull(Directory &dirDests,
307
+                                         DestList &destList,
308
+                                         const std::string *pNoFrameData)
309
+{
310
+  // get list of subdirs in input directory
311
+  typedef std::list<std::string> Subdirlist;
312
+  Subdirlist curSubdirs;
313
+  dirDests.getEntries(Directory::TypeSubdir, curSubdirs);
314
+
315
+  // walk through current static destinations and subdir list simultaneously
316
+  Subdirlist::const_iterator  itSubdir = curSubdirs.begin();
317
+  typename DestList::iterator itDest   = destList.begin();
318
+  while (itSubdir != curSubdirs.end() || itDest != destList.end()) {
319
+
320
+    // new static destination inserted
321
+    if (itDest == destList.end() ||
322
+        (itSubdir != curSubdirs.end() && *itSubdir < itDest->m_name)) {
323
+      // create static destination object
324
+      DestEntry destEntry(*itSubdir);
325
+      destEntry.m_pDest = new Dest(*this, dirDests.getSubdir(*itSubdir),
326
+                                   pNoFrameData);
327
+      if (destEntry.m_pDest)
328
+        // insert static destination entry
329
+        destList.insert(itDest, destEntry);
330
+      // advance to next subdir
331
+      ++itSubdir;
332
+    }
333
+
334
+    // static destination removed
335
+    else if (itSubdir == curSubdirs.end() || *itSubdir > itDest->m_name) {
336
+      // remove static destination
337
+      delete itDest->m_pDest;
338
+      itDest = destList.erase(itDest);
339
+      // do not advance to next subdir
340
+    }
341
+
342
+    // static sestination stayed in input list
343
+    else {
344
+      // check for update
345
+      itDest->m_pDest->updateConfig();
346
+      // advance to next file and next entry
347
+      ++itSubdir;
348
+      ++itDest;
349
+    }
350
+
351
+  } // while itSubdir itDest
352
+}
353
+
354
+/// remove timed-out dynamic destinations
355
+template<typename ADDR, typename SOCK>
356
+void Sender<ADDR, SOCK>::removeTimedOutDynDests()
357
+{
358
+  Time now, timeout;
359
+  typename DynDests::iterator itDyn;
360
+
361
+  now = Time::now();
362
+  timeout = Time(30);
363
+
364
+  for (itDyn = m_dynDestsBlp.begin(); itDyn != m_dynDestsBlp.end(); )
365
+    if (itDyn->second + timeout < now)
366
+      m_dynDestsBlp.erase(itDyn++);
367
+    else
368
+      ++itDyn;
369
+  for (itDyn = m_dynDestsEblp.begin(); itDyn != m_dynDestsEblp.end(); )
370
+    if (itDyn->second + timeout < now)
371
+      m_dynDestsEblp.erase(itDyn++);
372
+    else
373
+      ++itDyn;
374
+  for (itDyn = m_dynDestsMcuf.begin(); itDyn != m_dynDestsMcuf.end(); )
375
+    if (itDyn->second + timeout < now)
376
+      m_dynDestsMcuf.erase(itDyn++);
377
+    else
378
+      ++itDyn;
379
+}
380
+
381
+/**
382
+ * @brief send frame to all destinations
383
+ * @param[in] pFrame frame to send
384
+ */
385
+template<typename ADDR, typename SOCK>
386
+void Sender<ADDR, SOCK>::sendAllFrame(stBlinkenFrame *pFrame)
387
+{
388
+  // remove timed-out dynamic destinations
389
+  removeTimedOutDynDests();
390
+
391
+  // convert frame to protocol data and send to all static/dynamic destinations
392
+  if (!m_destListBlp.empty() || !m_dynDestsBlp.empty()) {
393
+    frame2data(pFrame, BlinkenProtoBlp, m_dataBlp);
394
+    sendDests(&m_dataBlp, m_destListBlp, m_dynDestsBlp);
395
+  }
396
+  if (!m_destListEblp.empty() || !m_dynDestsEblp.empty()) {
397
+    frame2data(pFrame, BlinkenProtoEblp, m_dataEblp);
398
+    sendDests(&m_dataEblp, m_destListEblp, m_dynDestsEblp);
399
+  }
400
+  if (!m_destListMcuf.empty() || !m_dynDestsMcuf.empty()) {
401
+    frame2data(pFrame, BlinkenProtoMcuf, m_dataMcuf);
402
+    sendDests(&m_dataMcuf, m_destListMcuf, m_dynDestsMcuf);
403
+  }
404
+
405
+  // request time callback in one second
406
+  m_callMgr.requestTimeCall(this, Time::now() + Time(1));
407
+}
408
+
409
+/// send "no frame" to all destinations
410
+template<typename ADDR, typename SOCK>
411
+void Sender<ADDR, SOCK>::sendAllNoFrame()
412
+{
413
+  // remove timed-out dynamic destinations
414
+  removeTimedOutDynDests();
415
+
416
+  // get "no frame" protocol data and send to all static/dynamic destinations
417
+  if (!m_destListBlp.empty() || !m_dynDestsBlp.empty()) {
418
+    noFrame2data(BlinkenProtoBlp, m_dataBlp);
419
+    sendDests(&m_dataBlp, m_destListBlp, m_dynDestsBlp);
420
+  }
421
+  if (!m_destListEblp.empty() || !m_dynDestsEblp.empty()) {
422
+    noFrame2data(BlinkenProtoEblp, m_dataEblp);
423
+    sendDests(&m_dataEblp, m_destListEblp, m_dynDestsEblp);
424
+  }
425
+  if (!m_destListMcuf.empty() || !m_dynDestsMcuf.empty()) {
426
+    noFrame2data(BlinkenProtoMcuf, m_dataMcuf);
427
+    sendDests(&m_dataMcuf, m_destListMcuf, m_dynDestsMcuf);
428
+  }
429
+
430
+  // request time callback in one second
431
+  m_callMgr.requestTimeCall(this, Time::now() + Time(1));
432
+}
433
+
434
+/**
435
+ * @brief send data to static/dynamic destinations
436
+ * @param[in] data *pData protocol data to send
437
+ * @param[in] destList static destinations
438
+ * @param[in] dynDests dynamic destinations
439
+ */
440
+template<typename ADDR, typename SOCK>
441
+void Sender<ADDR, SOCK>::sendDests(const std::string *pData,
442
+                                   const DestList destList,
443
+                                   const DynDests dynDests)
444
+{
445
+  // send data to static destinations
446
+  typename DestList::const_iterator itDest;
447
+  for (itDest = destList.begin(); itDest != destList.end(); ++itDest)
448
+    itDest->m_pDest->setProtoData(pData);
449
+
450
+  // send data to all dynamic destinations
451
+  typename DynDests::const_iterator itDyn;
452
+  for (itDyn = dynDests.begin(); itDyn != dynDests.end(); ++itDyn)
453
+    sendFrame(*pData, itDyn->first);
454
+}
455
+
456
+/**
457
+ * @brief send current frame to address
458
+ * @param[in] addr address to send to
459
+ * @param[in] proto Blinken protocol identifier
460
+ */
461
+template<typename ADDR, typename SOCK>
462
+void Sender<ADDR, SOCK>::sendCurFrame(const ADDR &addr,
463
+                                      etBlinkenProto proto) const
464
+{
465
+  stBlinkenFrame *pFrame;
466
+  std::string data;
467
+
468
+  // get current frame from stream
469
+  if (m_pInStream && m_pInStream->getCurFrame(pFrame)) {
470
+    // convert frame to protocal data
471
+    frame2data(pFrame, proto, data);
472
+    // send frame to address
473
+    sendFrame(data, addr);
474
+  }
475
+
476
+  // no stream of no current frame
477
+  else {
478
+    // get "no frame" ad protocal data
479
+    noFrame2data(proto, data);
480
+    // send "no frame" to address
481
+    sendFrame(data, addr);
482
+  }
483
+}
484
+
485
+/**
486
+ * @brief send "no frame" to address
487
+ * @param[in] addr address to send to
488
+ * @param[in] proto Blinken protocol identifier
489
+ */
490
+template<typename ADDR, typename SOCK>
491
+void Sender<ADDR, SOCK>::sendNoFrame(const ADDR &addr,
492
+                                     etBlinkenProto proto) const
493
+{
494
+  std::string data;
495
+
496
+  // get "no frame" ad protocal data
497
+  noFrame2data(proto, data);
498
+
499
+  // send "no frame" to address
500
+  sendFrame(data, addr);
501
+}
502
+
503
+/**
504
+ * @brief send frame to address
505
+ * @param[in] data protocol data of frame
506
+ * @param[in] addr address to send to
507
+ */
508
+template<typename ADDR, typename SOCK>
509
+void Sender<ADDR, SOCK>::sendFrame(const std::string &data,
510
+                                   const ADDR &addr) const
511
+{
512
+  if (m_pSock) {
513
+    m_pSock->send(data, addr);
514
+  }
515
+}
516
+
517
+/**
518
+ * @brief convert frame to protocol data
519
+ * @param[in] pFrame frame
520
+ * @param[in] proto Blinken protocol identifier
521
+ * @param[out] data protocol data
522
+ */
523
+template<typename ADDR, typename SOCK>
524
+void Sender<ADDR, SOCK>::frame2data(stBlinkenFrame *pFrame,
525
+                                    etBlinkenProto proto, std::string &data)
526
+{
527
+  char buf[65536];
528
+  int len;
529
+
530
+  // convert frame to protcol data
531
+  len = BlinkenFrameToNetwork(pFrame, proto, buf, sizeof(buf));
532
+  if (len < 0)
533
+    len = 0;
534
+  data.assign(buf, len);
535
+}
536
+
537
+/**
538
+ * @brief get "no frame" protocol data
539
+ * @param[in] proto Blinken protocol identifier
540
+ * @param[out] data protcol data
541
+ */
542
+template<typename ADDR, typename SOCK>
543
+void Sender<ADDR, SOCK>::noFrame2data(etBlinkenProto proto, std::string &data)
544
+{
545
+  char buf[16];
546
+  int len;
547
+
548
+  // obtain "no frame" protcol data
549
+  len = BlinkenProtoMakePacket(proto, BlinkenPacketStreamEnd,
550
+        buf, sizeof(buf));
551
+  if (len < 0)
552
+    len = 0;
553
+  data.assign(buf, len);
554
+}
555
+
556
+/// receive data from socket
557
+template<typename ADDR, typename SOCK>
558
+void Sender<ADDR, SOCK>::receiveFromSock()
559
+{
560
+  etBlinkenProto proto;
561
+  etBlinkenPacket packet;
562
+  std::string data;
563
+  ADDR addr;
564
+
565
+  // make sure socket exists
566
+  if (!m_pSock)
567
+    return;
568
+
569
+  // receive (leave if no reception)
570
+  if (!m_pSock->recv(data, addr))
571
+    return;
572
+
573
+  // detect packet type and protocol
574
+  BlinkenProtoDetectPacket(data.c_str(), data.size(), &proto, &packet);
575
+
576
+  switch (packet) {
577
+
578
+    // request -> add to dynamic destinations and send current frame
579
+    case BlinkenPacketRequest:
580
+      switch (proto) {
581
+        case BlinkenProtoBlp:
582
+          m_dynDestsBlp[addr] = Time::now();
583
+          sendCurFrame(addr, BlinkenProtoBlp);
584
+          break;
585
+        case BlinkenProtoEblp:
586
+          m_dynDestsEblp[addr] = Time::now();
587
+          sendCurFrame(addr, BlinkenProtoEblp);
588
+          break;
589
+        case BlinkenProtoMcuf:
590
+          m_dynDestsMcuf[addr] = Time::now();
591
+          sendCurFrame(addr, BlinkenProtoMcuf);
592
+          break;
593
+        default:
594
+          break;
595
+      }
596
+      break;
597
+
598
+    // end request -> remove from dynamic destinations
599
+    case BlinkenPacketEndRequest:
600
+      switch (proto) {
601
+        case BlinkenProtoBlp:
602
+          m_dynDestsBlp.erase(addr);
603
+          break;
604
+        case BlinkenProtoEblp:
605
+          m_dynDestsEblp.erase(addr);
606
+          break;
607
+        case BlinkenProtoMcuf:
608
+          m_dynDestsMcuf.erase(addr);
609
+          break;
610
+        default:
611
+          break;
612
+      }
613
+      break;
614
+
615
+    default:
616
+      break;
617
+
618
+  } // switch (packet)
619
+
620
+}
621
+
622
+/* #####################
623
+   # Sender::DestEntry #
624
+   ##################### */
625
+
626
+/// constructor
627
+template<typename ADDR, typename SOCK>
628
+Sender<ADDR, SOCK>::DestEntry::DestEntry(const std::string &name):
629
+  m_name(name),
630
+  m_pDest(NULL)
631
+{
632
+}
633
+
634
+} // namespace Blinker
635
+
636
+#endif // #ifndef SENDER_H
637
+
... ...
@@ -6,7 +6,7 @@
6 6
 #ifndef UDP4SENDER_H
7 7
 #define UDP4SENDER_H
8 8
 
9
-#include "Sender.h"
9
+#include "Sender_impl.h"
10 10
 #include "Udp4Addr.h"
11 11
 #include "Udp4Sock.h"
12 12
 
13 13