implement UDP synchronizati...
Stefan Schuermans authored 10 years ago
|
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;
|