f544b7eb4775000b6c9efc50cf4bc6014f0da3a5
Stefan Schuermans implement UDP synchronizati...

Stefan Schuermans authored 10 years ago

1) /* Blinker
2)    Copyright 2011-2014 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_SYNCRECEIVER_IMPL_H
7) #define BLINKER_SYNCRECEIVER_IMPL_H
8) 
9) #include <stdint.h>
10) #include <string>
11) #include <string.h>
12) 
13) #include "Directory.h"
14) #include "File.h"
15) #include "IoCallee.h"
16) #include "Mgrs.h"
17) #include "Module.h"
18) #include "NetHost.h"
19) #include "OutSyncFile.h"
20) #include "Protocol.h"
21) #include "ProtocolFile.h"
22) #include "SettingFile.h"
23) #include "SyncRecv.h"
24) #include "SyncReceiver.h"
25) 
26) namespace Blinker {
27) 
28) /**
29)  * @brief constructor
30)  * @param[in] name module name
31)  * @param[in] mgrs managers
32)  * @param[in] dirBase base directory
33)  */
34) template<typename ADDR, typename SOCK>
35) SyncReceiver<ADDR, SOCK>::SyncReceiver(const std::string &name, Mgrs &mgrs,
36)                                        const Directory &dirBase):
37)   Module(name, mgrs, dirBase),
38)   m_fileOutSync(dirBase.getFile("outsync"), mgrs.m_syncMgr),
39)   m_fileBind(dirBase.getFile("bind")),
40)   m_fileSrc(dirBase.getFile("source")),
41)   m_pSock(NULL)
42) {
43)   // read source address
44)   m_fileSrc.update();
45) 
46)   // create and bind socket
47)   createSock();
48) }
49) 
50) /// virtual destructor
51) template<typename ADDR, typename SOCK>
52) SyncReceiver<ADDR, SOCK>::~SyncReceiver()
53) {
54)   // destroy socket
55)   destroySock();
56) }
57) 
58) /// check for update of configuration
59) template<typename ADDR, typename SOCK>
60) void SyncReceiver<ADDR, SOCK>::updateConfig()
61) {
62)   // output sync stream name file was modified -> re-get output sync stream
63)   if (m_fileOutSync.checkModified())
64)     m_fileOutSync.update();
65) 
66)   // bind address file was modified -> re-create socket
67)   if (m_fileBind.checkModified()) {
68)     destroySock();
69)     createSock();
70)   }
71) 
72)   // source address file was modified -> re-read source address
73)   if (m_fileSrc.checkModified())
74)     m_fileSrc.update();
75) }
76) 
77) /**
78)  * @brief callback when I/O object is readable
79)  * @param[in] io I/O object that is readable
80)  */
81) template<typename ADDR, typename SOCK>
82) void SyncReceiver<ADDR, SOCK>::ioReadCall(Io *io)
83) {
84)   // reception on socket
85)   if (io == m_pSock)
86)     receiveFromSock();
87) }
88) 
89) /**
90)  * @brief callback when I/O object is writable
91)  * @param[in] io I/O object that is writable
92)  */
93) template<typename ADDR, typename SOCK>
94) void SyncReceiver<ADDR, SOCK>::ioWriteCall(Io *io)
95) {
96)   (void)io; // unused
97) }
98) 
99) /// create socket and bind it
100) template<typename ADDR, typename SOCK>
101) void SyncReceiver<ADDR, SOCK>::createSock()
102) {
103)   // create socket
104)   if (!m_pSock) {
105)     m_pSock = new SOCK();
106)     if (!m_pSock)
107)       return;
108)   }
109) 
110)   // get bind address from bind address setting file
111)   m_fileBind.update();
112)   if (!m_fileBind.m_valid) {
113)     delete m_pSock;
114)     m_pSock = NULL;
115)     return;
116)   }
117) 
118)   // bind socket
119)   if (!m_pSock->bind(m_fileBind.m_obj)) {
120)     delete m_pSock;
121)     m_pSock = NULL;
122)     return;
123)   }
124) 
125)   // request callback on recepetion
126)   m_mgrs.m_callMgr.requestIoReadCall(this, m_pSock);
127) }
128) 
129) /// destroy socket
130) template<typename ADDR, typename SOCK>
131) void SyncReceiver<ADDR, SOCK>::destroySock()
132) {
133)   // cancel callback request
134)   m_mgrs.m_callMgr.cancelIoReadCall(this, m_pSock);
135) 
136)   // destroy socket
137)   if (m_pSock) {
138)     delete m_pSock;
139)     m_pSock = NULL;
140)   }
141) }
142) 
143) /// receive data from socket
144) template<typename ADDR, typename SOCK>
145) void SyncReceiver<ADDR, SOCK>::receiveFromSock()
146) {
147)   std::string data;
148)   ADDR addr;
149) 
150)   // make sure socket exists
151)   if (!m_pSock)
152)     return;
153) 
154)   // receive (leave if no reception)
155)   if (!m_pSock->recv(data, addr))
156)     return;
157) 
158)   // check source address (if configured)
159)   if (m_fileSrc.m_valid && addr != m_fileSrc.m_obj)
160)     return; // mismatch
161) 
162)   // process received synchronization information
163)   procInfo(data);
164) }
165) 
166) /**
167)  * @brief process synchronization information
168)  * @param[in] data received synchronization data
169)  */
170) template<typename ADDR, typename SOCK>
171) void SyncReceiver<ADDR, SOCK>::procInfo(const std::string &data)
172) {
173)   /// Po.W.E.R. (stage play by BBM) synchronization protocol
174)   struct PoSyPacket {
175)     char     magic[4]; ///< fixed magic, always "PoSy"
176)     uint32_t flags;    ///< flags, see PosSyFlags below
177)     char     name[64]; ///< name of current piece in playlist
178)     uint32_t pos_ms;   ///< position within current piece in milliseconds
179)   };
180) 
181)   /// flags for PoSyPacket
182)   enum PoSyFlags {
183)     PoSyPause = 0x00000001, ///< pause mode active
184)   };
185) 
186)   PoSyPacket     packet;
187)   SyncRecv::Info info;
188) 
189)   // parse frame, leave if invalid
190)   if (data.size() < sizeof(packet))
191)     return;
192)   memcpy(&packet, data.c_str(), sizeof(packet));
193)   if (memcmp(packet.magic, "PoSy", sizeof(packet.magic)) != 0)
194)     return;
195)   info.pause = (Net2Host32(packet.flags) & PoSyPause) != 0;
196)   info.name = packet.name;
Stefan Schuermans implement synchronization f...

Stefan Schuermans authored 10 years ago

197)   info.pos.fromMs(Net2Host32(packet.pos_ms));