New upstream version 2.1.0
Bastian Germann
3 years ago
5 | 5 | # - INCLUDEDIR (default "CMAKE_INSTALL_PREFIX/include") - set to directory where header files should be installed |
6 | 6 | # - BIBLESYNC_SOVERSION (defaults to BIBLESYNC_VERSION) - Manually set the SOVERSION of the installed file |
7 | 7 | PROJECT(libbiblesync CXX) |
8 | SET(BIBLESYNC_VERSION 1.2.0) | |
8 | SET(BIBLESYNC_VERSION 2.1.0) | |
9 | 9 | # A required CMake line |
10 | 10 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) |
11 | 11 | # Where our custom Find* files are located |
8 | 8 | @SHAREDLIB_TRUE@Libs: -L${libdir} -lbiblesync |
9 | 9 | @SHAREDLIB_FALSE@Libs: -L${libdir} -lbiblesync @LIBS@ |
10 | 10 | Libs.private: -L${libdir} -lbiblesync @LIBS@ |
11 | Cflags: -I${includedir}/bibleysnc | |
11 | Cflags: -I${includedir} |
70 | 70 | // bible, ref, alt, group, domain as arrived. |
71 | 71 | // info + dump available. |
72 | 72 | // 3. 'M' (mismatch) against passphrase or mode or listen status. |
73 | // info == "announce" or "sync" or "beacon" (+ user @ [ipaddr]) | |
73 | // info == "announce"/"sync"/"beacon"/"chat" (+ user @ [ipaddr]) | |
74 | 74 | // sync: bible, ref, alt, group, domain as arrived. |
75 | 75 | // announce: presence message in alt. |
76 | 76 | // also, individual elements are also available: |
77 | 77 | // overload: bible ref group domain |
78 | 78 | // user [ipaddr] app+ver device |
79 | // chat: message in alt. | |
79 | 80 | // dump available. |
80 | 81 | // 4. 'S' (new speaker) |
81 | 82 | // param overload as above. alt unused. see listenToSpeaker(). |
82 | 83 | // 5. 'D' (dead speaker) |
83 | 84 | // opposite of new speaker. only param is speakerkey. |
84 | // 6. 'E' (error) for network errors & malformed packets. | |
85 | // 6. 'C' (chat) | |
86 | // human chat message to be displayed to user. | |
87 | // message in alt. | |
88 | // 7. 'E' (error) for network errors & malformed packets. | |
85 | 89 | // only info + dump are useful. |
86 | 90 | // |
87 | 91 | // - get current mode. |
120 | 124 | // - allow another speaker to drive us |
121 | 125 | // void listenToSpeaker(bool listen, string speakerkey) |
122 | 126 | // say yes/no to listening. |
127 | // | |
128 | // - send a human chat message to others listening. | |
129 | // BibleSync_xmit_status retval = Chat("your message for others here"); | |
130 | // sends your message to all other listeners. not restricted to Speakers. | |
123 | 131 | // |
124 | 132 | // Receive() USAGE NOTE: |
125 | 133 | // the application must call BibleSync::Receive(YourBibleSyncObjPtr) |
220 | 228 | #define BSP_MAX_PAYLOAD (BSP_MAX_SIZE - BSP_HEADER_SIZE) |
221 | 229 | |
222 | 230 | // message indications |
223 | #define BSP_MAGIC htonl(0x409CAF11) | |
224 | #define BSP_PROTOCOL 2 | |
231 | #define BSP_MAGIC htonl(0x409CAF11) | |
232 | #define BSP_PROTOCOL 3 | |
233 | #define BSP_OLD_PROTOCOL 2 | |
225 | 234 | |
226 | 235 | // message types |
227 | 236 | #define BSP_ANNOUNCE 1 // presence announcement. |
228 | 237 | #define BSP_SYNC 2 // navigation synchronization. |
229 | 238 | #define BSP_BEACON 3 // speaker availability beacon. |
239 | #define BSP_CHAT 4 // human chat message. | |
230 | 240 | // beacon packet is identical to presence announcement except for type. |
231 | 241 | |
232 | 242 | // beacon constants |
246 | 256 | #define BSP_MSG_SYNC_BIBLEABBREV "msg.sync.bibleAbbrev" // req'd |
247 | 257 | #define BSP_MSG_SYNC_GROUP "msg.sync.group" // req'd |
248 | 258 | #define BSP_MSG_PASSPHRASE "msg.sync.passPhrase" // req'd |
259 | #define BSP_MSG_CHAT "msg.chat" // req'd for BSP_CHAT | |
249 | 260 | |
250 | 261 | // required number of fields to send (out) or verify (in). |
251 | 262 | #define BSP_FIELDS_RECV_ANNOUNCE 4 |
263 | #define BSP_FIELDS_RECV_CHAT 5 | |
252 | 264 | #define BSP_FIELDS_RECV_SYNC 8 |
265 | ||
253 | 266 | #define BSP_FIELDS_XMIT_ANNOUNCE 7 |
267 | #define BSP_FIELDS_XMIT_CHAT 8 | |
254 | 268 | #define BSP_FIELDS_XMIT_SYNC 12 |
255 | 269 | |
256 | 270 | #ifdef linux |
365 | 379 | |
366 | 380 | #ifdef linux |
367 | 381 | // network self-analysis, borrowed from the net. |
368 | int get_default_if_name(char *name, socklen_t size); | |
369 | int parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo); | |
370 | int readNlSock(int sockFd, char *bufPtr, size_t buf_size, | |
371 | unsigned int seqNum, unsigned int pId); | |
382 | int get_default_if_name(char *name); | |
372 | 383 | #else |
373 | 384 | // no other support routines needed for Windows/Solaris/BSD. |
374 | 385 | #endif /* linux */ |
402 | 413 | string domain = "BIBLE-VERSE") |
403 | 414 | { |
404 | 415 | return TransmitInternal(BSP_SYNC, bible, ref, alt, group, domain); |
416 | } | |
417 | ||
418 | // simple chat interface | |
419 | inline BibleSync_xmit_status Chat(string message) | |
420 | { | |
421 | return TransmitInternal(BSP_CHAT, message); | |
405 | 422 | } |
406 | 423 | |
407 | 424 | // set privacy using TTL 0 in personal mode. |
7 | 7 | .\" make back to the origin repository. These obligations are non- |
8 | 8 | .\" binding for public domain software, but they are to be seriously |
9 | 9 | .\" handled nonetheless. |
10 | .TH BIBLESYNC 7 2014-10-31 "Linux" "Linux Programmer's Manual" | |
10 | .TH BIBLESYNC 7 2018-04-27 "Linux" "Linux Programmer's Manual" | |
11 | 11 | .SH NAME |
12 | 12 | biblesync \- multicast navigation synchronization in Bible programs |
13 | 13 | .SH SYNOPSIS |
46 | 46 | .br |
47 | 47 | .BI "} BibleSync_xmit_status;" |
48 | 48 | .sp |
49 | .BI "#define BSP_ANNOUNCE 1" | |
50 | .br | |
51 | .BI "#define BSP_SYNC 2" | |
52 | .br | |
53 | .BI "#define BSP_BEACON 3" | |
54 | .sp | |
55 | 49 | .BI "typedef void (*BibleSync_navigate)(char " cmd ", string " speakerkey "," |
56 | 50 | .br |
57 | 51 | .BI " string " bible ", string " ref ", string " alt "," |
84 | 78 | .br |
85 | 79 | .BI " string " group ", string " domain ");" |
86 | 80 | .br |
81 | .BI "BibleSync_xmit_status BibleSync::Chat(string " message ");" | |
82 | .br | |
87 | 83 | .BI "static int BibleSync::Receive(void *" object ");" |
88 | 84 | .br |
89 | 85 | .BI "bool BibleSync::setPrivate(bool " privacy ");" |
90 | 86 | .br |
91 | 87 | .BI "void BibleSync::setBeaconCount(uint8_t " count ");" |
88 | .br | |
89 | .BI "void BibleSync::setUser(string " user ");" | |
92 | 90 | .br |
93 | 91 | .BI "void BibleSync::listenToSpeaker(bool " listen ", string " speakerkey ");" |
94 | 92 | .fi |
107 | 105 | all of which he wishes to follow along together. |
108 | 106 | |
109 | 107 | Similarly, a group of people working closely together, such as |
110 | translators, can stay together as they work. | |
108 | translators or a group Bible study, can stay together as they work. | |
111 | 109 | |
112 | 110 | In an instructional motif, |
113 | 111 | .I BibleSync |
147 | 145 | |
148 | 146 | Transmitters (Personal and Speaker modes) issue availability beacons every |
149 | 147 | 10 seconds. Received beacons for previously-unknown Speakers are handed |
150 | up to the application. These beacons provide for receivers (Personal and | |
151 | Audience modes) to maintain a managed list of available Speakers. | |
152 | Furthermore, when a transmitter ceases to issue beacons, its presence in | |
153 | the list of available Speakers is aged out until being removed after 30 | |
154 | seconds of beacon silence. The application is again informed when a | |
155 | Speaker goes dead. | |
148 | up to the application as "new Speaker" events. These beacons provide for | |
149 | receivers (Personal and Audience modes) to maintain a managed list of | |
150 | available Speakers. Furthermore, when a transmitter ceases to issue | |
151 | beacons, its presence in the list of available Speakers is aged out until | |
152 | being removed after 30 seconds of beacon silence. The application is | |
153 | again informed as a Speaker ages out with a "dead Speaker" event. | |
156 | 154 | |
157 | 155 | Default listening behavior is that the first Speaker heard via beacon is |
158 | 156 | marked for listening. Other transmitters claiming Speaker status via |
188 | 186 | |
189 | 187 | .I BibleSync |
190 | 188 | transmits no packet when the application leaves the conversation. |
191 | ||
192 | Only the 3 packet types BSP_ANNOUNCE, BSP_SYNC, and BSP_BEACON are defined | |
193 | in the protocol. | |
194 | 189 | .SH PUBLIC INTERFACE |
195 | 190 | .SS Object creation |
196 | 191 | The application must create a single BibleSync object, identifying the |
219 | 214 | in |
220 | 215 | .BI Transmit: |
221 | 216 | KJV, Gen.1.1, empty alternate, 1, and BIBLE-VERSE. |
217 | .SS Chat | |
218 | This is a method for transmission of casual text messages to all others in | |
219 | the conversation. It is expected to be received by applications who will | |
220 | display them in a suitable manner to the user. | |
222 | 221 | .SS Receive |
223 | 222 | This is a static method accessible from either C or C++. It must be |
224 | 223 | called with the object pointer so as to re-enter object context for the |
240 | 239 | second. If the application will call Receive() less frequently, divide |
241 | 240 | that time (say, 2 seconds) into 10 to get a value (5) to use with this |
242 | 241 | call. Use setBeaconCount() prior to enabling Personal or Speaker mode. |
242 | .SS setUser | |
243 | If the application allows the user to set a name via settings dialog, | |
244 | setUser() is available to re-assign the associated user name as seen by | |
245 | others. | |
243 | 246 | .SS listenToSpeaker |
244 | 247 | Aside from default listen behavior detailed above, the application |
245 | 248 | specifically asks to listen or not to listen to specific Speakers. The |
246 | 249 | key is as provided during the notification of a new Speaker. |
247 | 250 | .SH RECEIVE USE CASES |
248 | There are 6 values for the | |
251 | There are 7 values for the | |
249 | 252 | .I cmd |
250 | 253 | parameter of the |
251 | 254 | .I nav_func. |
283 | 286 | .I speakerkey |
284 | 287 | holds the UUID key of a previously-identified application which is no |
285 | 288 | longer a candidate for listening. |
289 | .SS 'C' | |
290 | Chat. | |
291 | Message text is in | |
292 | .I alt | |
293 | and other parameters are overloaded as per announce, above. | |
286 | 294 | .SS 'M' |
287 | 295 | Mismatch. The incoming event packet is mismatched, either against the |
288 | 296 | current passphrase or for a navigation synchronization packet when |
323 | 331 | mode, Receive is again scheduled for polled use. |
324 | 332 | |
325 | 333 | A 1-second poll interval is expected. Brief experience during development |
326 | has shown that longer intervals lead to a perception of lag. | |
334 | has shown that longer intervals lead to a perception of lag. If the | |
335 | application designer nonetheless expects to call | |
336 | .BI Receive() | |
337 | less frequently, it is necessary to use | |
338 | .BI setBeaconCount() | |
339 | to change the number of calls to it between beacon transmissions. | |
327 | 340 | |
328 | 341 | During every |
329 | 342 | .BI Receive() |
0 | 0 | BIBLESYNC(7) Linux Programmer's Manual BIBLESYNC(7) |
1 | ||
2 | ||
3 | 1 | |
4 | 2 | NAME |
5 | 3 | biblesync - multicast navigation synchronization in Bible programs |
25 | 23 | N_BSP_XMIT |
26 | 24 | } BibleSync_xmit_status; |
27 | 25 | |
28 | #define BSP_ANNOUNCE 1 | |
29 | #define BSP_SYNC 2 | |
30 | #define BSP_BEACON 3 | |
31 | ||
32 | 26 | typedef void (*BibleSync_navigate)(char cmd, string speakerkey, |
33 | 27 | string bible, string ref, string alt, |
34 | 28 | string group, string domain, |
48 | 42 | string BibleSync::getPassphrase(void); |
49 | 43 | BibleSync_xmit_status BibleSync::Transmit(string bible, string ref, string alt, |
50 | 44 | string group, string domain); |
45 | BibleSync_xmit_status BibleSync::Chat(string message); | |
51 | 46 | static int BibleSync::Receive(void *object); |
52 | 47 | bool BibleSync::setPrivate(bool privacy); |
48 | void BibleSync::setBeaconCount(uint8_t count); | |
49 | void BibleSync::setUser(string user); | |
53 | 50 | void BibleSync::listenToSpeaker(bool listen, string speakerkey); |
54 | 51 | |
55 | 52 | DESCRIPTION |
64 | 61 | ers/devices, all of which he wishes to follow along together. |
65 | 62 | |
66 | 63 | Similarly, a group of people working closely together, such as transla- |
67 | tors, can stay together as they work. | |
64 | tors or a group Bible study, can stay together as they work. | |
68 | 65 | |
69 | 66 | In an instructional motif, BibleSync takes either the active or passive |
70 | 67 | mode, providing for a unidirectional navigation control. |
100 | 97 | |
101 | 98 | Transmitters (Personal and Speaker modes) issue availability beacons |
102 | 99 | every 10 seconds. Received beacons for previously-unknown Speakers are |
103 | handed up to the application. These beacons provide for receivers | |
104 | (Personal and Audience modes) to maintain a managed list of available | |
105 | Speakers. Furthermore, when a transmitter ceases to issue beacons, its | |
106 | presence in the list of available Speakers is aged out until being | |
107 | removed after 30 seconds of beacon silence. The application is again | |
108 | informed when a Speaker goes dead. | |
109 | ||
110 | Default listening behavior is that the first Speaker heard via beacon | |
111 | is marked for listening. Other transmitters claiming Speaker status | |
112 | via beacon are initially ignored, but their presence is made known to | |
113 | the application. This provides for the application to maintain a list | |
114 | from which the user can select Speakers he wishes to synchronize his | |
100 | handed up to the application as "new Speaker" events. These beacons | |
101 | provide for receivers (Personal and Audience modes) to maintain a man- | |
102 | aged list of available Speakers. Furthermore, when a transmitter | |
103 | ceases to issue beacons, its presence in the list of available Speakers | |
104 | is aged out until being removed after 30 seconds of beacon silence. | |
105 | The application is again informed as a Speaker ages out with a "dead | |
106 | Speaker" event. | |
107 | ||
108 | Default listening behavior is that the first Speaker heard via beacon | |
109 | is marked for listening. Other transmitters claiming Speaker status | |
110 | via beacon are initially ignored, but their presence is made known to | |
111 | the application. This provides for the application to maintain a list | |
112 | from which the user can select Speakers he wishes to synchronize his | |
115 | 113 | application. It is useful for the application to provide blanket "lis- |
116 | ten to all" and "listen to none" functions, as well as per-Speaker | |
117 | selections, informing BibleSync of these choices. In any case, this | |
118 | default "first Speaker only" policy can be overridden by the applica- | |
119 | tion with any other policy desired, through the use of listenToS- | |
114 | ten to all" and "listen to none" functions, as well as per-Speaker | |
115 | selections, informing BibleSync of these choices. In any case, this | |
116 | default "first Speaker only" policy can be overridden by the applica- | |
117 | tion with any other policy desired, through the use of listenToS- | |
120 | 118 | peaker() as the application designer requires. |
121 | 119 | |
122 | 120 | Synchronization events include 5 data elements: The Bible abbreviation; |
123 | the verse reference; an alternate reference (if desired; not required) | |
124 | which may allow the application to interpret better based on variant | |
121 | the verse reference; an alternate reference (if desired; not required) | |
122 | which may allow the application to interpret better based on variant | |
125 | 123 | versification; a synchronization group identifier; and the domain. |
126 | 124 | |
127 | 125 | The group identifier is a single digit between 1 and 9. The specifica- |
128 | tion is imprecise as to this parameter's use. The initial implementa- | |
129 | tion of BibleSync in Xiphos uses the synchronization group as an indi- | |
130 | cator of the tab number in its tabbed interface: Not only is the Bible | |
126 | tion is imprecise as to this parameter's use. The initial implementa- | |
127 | tion of BibleSync in Xiphos uses the synchronization group as an indi- | |
128 | cator of the tab number in its tabbed interface: Not only is the Bible | |
131 | 129 | navigated, but the tab in which to navigate is selected. |
132 | 130 | |
133 | 131 | The domain parameter is currently fixed as "BIBLE-VERSE". This will be |
135 | 133 | |
136 | 134 | BibleSync transmits no packet when the application leaves the conversa- |
137 | 135 | tion. |
138 | ||
139 | Only the 3 packet types BSP_ANNOUNCE, BSP_SYNC, and BSP_BEACON are | |
140 | defined in the protocol. | |
141 | 136 | |
142 | 137 | PUBLIC INTERFACE |
143 | 138 | Object creation |
165 | 160 | tion may request the current passphrase, so as to provide a default. |
166 | 161 | |
167 | 162 | Transmit |
168 | The protocol requires all the indicated parameters, but all have | |
169 | defaults in Transmit: KJV, Gen.1.1, empty alternate, 1, and BIBLE-VERSE. | |
163 | The protocol requires all the indicated parameters, but all have | |
164 | defaults in Transmit: KJV, Gen.1.1, empty alternate, 1, and BIBLE- | |
165 | VERSE. | |
166 | ||
167 | Chat | |
168 | This is a method for transmission of casual text messages to all others | |
169 | in the conversation. It is expected to be received by applications who | |
170 | will display them in a suitable manner to the user. | |
170 | 171 | |
171 | 172 | Receive |
172 | This is a static method accessible from either C or C++. It must be | |
173 | This is a static method accessible from either C or C++. It must be | |
173 | 174 | called with the object pointer so as to re-enter object context for the |
174 | private internal receiver. Receive() must be called regularly (i.e. | |
175 | private internal receiver. Receive() must be called regularly (i.e. | |
175 | 176 | polled) as long as it continues to return TRUE. When it returns FALSE, |
176 | it means that the mode has changed to BSP_MODE_DISABLE, and the sched- | |
177 | it means that the mode has changed to BSP_MODE_DISABLE, and the sched- | |
177 | 178 | uled polling should stop. See also the note below on polled reception. |
178 | 179 | |
179 | 180 | setPrivate |
180 | In the circumstance where the user has multiple programs running on a | |
181 | In the circumstance where the user has multiple programs running on a | |
181 | 182 | single computer and does not want his navigation broadcast outside that |
182 | single system, when in Personal mode, the application may also request | |
183 | privacy. The effect is to set multicast TTL to zero, meaning that | |
183 | single system, when in Personal mode, the application may also request | |
184 | privacy. The effect is to set multicast TTL to zero, meaning that | |
184 | 185 | packets will not go out on the wire. |
185 | 186 | |
186 | 187 | setBeaconCount |
187 | Beacon transmission occurs during every Nth call to Receive(); the | |
188 | default value is 10. This presumes the application will call Receive() | |
189 | once per second. If the application will call Receive() less | |
190 | frequently, divide that time (say, 2 seconds) into 10 to get a value | |
191 | (5) to use with this call. Use setBeaconCount() prior to enabling | |
192 | Personal or Speaker mode. | |
188 | Beacon transmission occurs during every Nth call to Receive(); the | |
189 | default value is 10. This presumes the application will call Receive() | |
190 | once per second. If the application will call Receive() less fre- | |
191 | quently, divide that time (say, 2 seconds) into 10 to get a value (5) | |
192 | to use with this call. Use setBeaconCount() prior to enabling Personal | |
193 | or Speaker mode. | |
194 | ||
195 | setUser | |
196 | If the application allows the user to set a name via settings dialog, | |
197 | setUser() is available to re-assign the associated user name as seen by | |
198 | others. | |
193 | 199 | |
194 | 200 | listenToSpeaker |
195 | 201 | Aside from default listen behavior detailed above, the application |
197 | 203 | key is as provided during the notification of a new Speaker. |
198 | 204 | |
199 | 205 | RECEIVE USE CASES |
200 | There are 6 values for the cmd parameter of the nav_func. In all | |
206 | There are 7 values for the cmd parameter of the nav_func. In all | |
201 | 207 | cases, the dump parameter provides the raw content of an arriving |
202 | 208 | packet. |
203 | 209 | |
220 | 226 | Dead Speaker. speakerkey holds the UUID key of a previously-identified |
221 | 227 | application which is no longer a candidate for listening. |
222 | 228 | |
229 | 'C' | |
230 | Chat. Message text is in alt and other parameters are overloaded as | |
231 | per announce, above. | |
232 | ||
223 | 233 | 'M' |
224 | Mismatch. The incoming event packet is mismatched, either against the | |
225 | current passphrase or for a navigation synchronization packet when | |
226 | BibleSync is in Speaker mode. The info parameter begins with either | |
234 | Mismatch. The incoming event packet is mismatched, either against the | |
235 | current passphrase or for a navigation synchronization packet when | |
236 | BibleSync is in Speaker mode. The info parameter begins with either | |
227 | 237 | "announce" or "sync", plus the user and IP address from whom the packet |
228 | came. As well, in the sync case, the regular bible, ref, alt, group, | |
229 | and domain parameters are available. In the announce case, the pres- | |
238 | came. As well, in the sync case, the regular bible, ref, alt, group, | |
239 | and domain parameters are available. In the announce case, the pres- | |
230 | 240 | ence message is in alt, with overloaded individual parameters as previ- |
231 | 241 | ously described. |
232 | 242 | |
233 | 243 | 'E' |
234 | Error. This indicates network errors and malformed packets. The | |
244 | Error. This indicates network errors and malformed packets. The | |
235 | 245 | application's nav_func is provided only the info and dump parameters. |
236 | 246 | |
237 | 247 | NOTES |
238 | 248 | Polled reception |
239 | The application must provide a means by which to poll regularly for | |
240 | incoming packets. In Xiphos, which is built on GTK and GLib, this is | |
249 | The application must provide a means by which to poll regularly for | |
250 | incoming packets. In Xiphos, which is built on GTK and GLib, this is | |
241 | 251 | readily provided by mechanisms like g_timeout_add(), which sets a regu- |
242 | 252 | lar interval call of the indicated function. GLib will re-schedule the |
243 | call as long as the called function returns TRUE. When it returns | |
253 | call as long as the called function returns TRUE. When it returns | |
244 | 254 | FALSE, GLib un-schedules the call. Receive() adheres to this straight- |
245 | forward convention. Therefore, it is imperative that every time the | |
246 | application moves from disabled to any non-disabled mode, Receive is | |
255 | forward convention. Therefore, it is imperative that every time the | |
256 | application moves from disabled to any non-disabled mode, Receive is | |
247 | 257 | again scheduled for polled use. |
248 | 258 | |
249 | 259 | A 1-second poll interval is expected. Brief experience during develop- |
250 | ment has shown that longer intervals lead to a perception of lag. | |
260 | ment has shown that longer intervals lead to a perception of lag. If | |
261 | the application designer nonetheless expects to call Receive() less | |
262 | frequently, it is necessary to use setBeaconCount() to change the num- | |
263 | ber of calls to it between beacon transmissions. | |
251 | 264 | |
252 | 265 | During every Receive() call, all waiting packets are processed. |
253 | 266 | |
299 | 312 | and ip(7), especially sections on IP_ADD_MEMBERSHIP, IP_MULTICAST_IF, |
300 | 313 | IP_MULTICAST_LOOP, and IP_MULTICAST_TTL. |
301 | 314 | |
302 | ||
303 | ||
304 | Linux 2018-04-10 BIBLESYNC(7) | |
315 | Linux 2018-04-27 BIBLESYNC(7) |
63 | 63 | 0, so the user's entirely internal navigation is not also heard over the |
64 | 64 | wire. |
65 | 65 | |
66 | ||
67 | ||
68 | 66 | .ti 0 |
69 | 67 | Packet Structure |
70 | 68 | |
89 | 87 | The magic value is 0x409CAF11, by which to determine that a packet is |
90 | 88 | intended for BibleSync. |
91 | 89 | |
92 | The protocol version is 2. | |
93 | ||
94 | Three message types are defined: 1 = presence announcement, 2 = navigation | |
95 | synchronization, 3 = speaker availability beacon. | |
90 | The protocol version is 3. The protocol interoperates with the previous | |
91 | version 2, though lacking the distinguishing feature of chat messages. | |
92 | ||
93 | Four message types are defined: 1 = presence announcement, 2 = navigation | |
94 | synchronization, 3 = speaker availability beacon, 4 = chat message. | |
96 | 95 | |
97 | 96 | Currently BibleSync is specified as a single packet protocol, but the |
98 | 97 | number of packets and packet index fields are included for possible future |
126 | 125 | |
127 | 126 | The speaker beacon packet is identical to the presence announcement except |
128 | 127 | for having message type 3, and is sent by transmitting applications every |
129 | 10 seconds. | |
128 | 10 seconds. Beacon silence for 30 seconds indicates a dead Speaker. | |
129 | ||
130 | The chat message packet contains only 1 field, the message content, beyond | |
131 | those found in announce and beacon. | |
130 | 132 | |
131 | 133 | .ti 0 |
132 | 134 | Speaker Beacons |
180 | 182 | |
181 | 183 | Continuation lines are not supported. |
182 | 184 | |
183 | There are 12 names defined for use in the body. The application may | |
185 | There are 13 names defined for use in the body. The application may | |
184 | 186 | provide any others its designer finds useful, but these names define the |
185 | 187 | protocol's interoperability. |
186 | 188 | |
275 | 277 | .in 7 |
276 | 278 | Required in navigation. This field has a fixed value of "BIBLE-VERSE" but |
277 | 279 | its use will be expanded in future revisions. |
280 | ||
281 | .in 3 | |
282 | 13. msg.chat | |
283 | ||
284 | .in 7 | |
285 | Required for chat and useful only there. A free-from, newline-less text | |
286 | string to be shared in the conversation, intended to be displayed to all | |
287 | users. | |
278 | 288 | |
279 | 289 | |
280 | 290 | .in 3 |
308 | 318 | Presence announcement: |
309 | 319 | |
310 | 320 | magic: 0x409caf11 |
311 | version: 0x02 | |
321 | version: 0x03 | |
312 | 322 | type: 0x01 |
313 | 323 | uuid: 00112233-4455-6677-8899-aabbccddeeff |
314 | 324 | #pkt: 1 |
318 | 328 | app.user=John Doe (jdoe) |
319 | 329 | msg.sync.passPhrase=qwerty |
320 | 330 | |
321 | Beacon is identical to presence announcement except for being type 3. | |
331 | Beacon is identical to presence announcement except for being type 0x03. | |
322 | 332 | |
323 | 333 | Navigation: |
324 | 334 | |
325 | 335 | magic: 0x409caf11 |
326 | version: 0x02 | |
336 | version: 0x03 | |
327 | 337 | type: 0x02 |
328 | 338 | uuid: 00112233-4455-6677-8899-aabbccddeeff |
329 | 339 | #pkt: 1 |
337 | 347 | msg.sync.bibleAbbrev=NET |
338 | 348 | msg.sync.verse=Rom.14.4 |
339 | 349 | |
350 | Chat: | |
351 | ||
352 | magic: 0x409caf11 | |
353 | version: 0x03 | |
354 | type: 0x04 | |
355 | uuid: 00112233-4455-6677-8899-aabbccddeeff | |
356 | #pkt: 1 | |
357 | pkt index: 0 | |
358 | app.name=TestBibleApp | |
359 | app.inst.uuid=00112233-4455-6677-8899-aabbccddeeff | |
360 | app.user=John Doe (jdoe) | |
361 | msg.sync.passPhrase=qwerty | |
362 | msg.chat=This is just a test message. No newlines permitted. | |
363 | ||
340 | 364 | Additional name/value examples, optional use: |
341 | 365 | |
342 | 366 | app.version=2.7a |
344 | 368 | app.device=i686 |
345 | 369 | msg.sync.altVerse=1Mac.1.2 |
346 | 370 | |
347 | Real-world example, using all defined names: | |
371 | Real-world example, navigation synchronization, using all defined names: | |
348 | 372 | |
349 | 373 | magic: 0x409caf11 |
350 | version: 0x02 | |
374 | version: 0x03 | |
351 | 375 | type: 0x02 (sync) |
352 | 376 | uuid: 49b387bd-6324-4a2e-871a-4b24e065bff7 |
353 | 377 | #pkt: 1 |
354 | 378 | pkt index: 0 |
355 | 379 | app.name=Xiphos |
356 | app.version=3.2.1 | |
380 | app.version=4.1.1 | |
357 | 381 | app.inst.uuid=49b387bd-6324-4a2e-871a-4b24e065bff7 |
358 | 382 | app.os=Linux |
359 | 383 | app.device=x86_64: Linux @ awol.kleinpaste.org |
49 | 49 | available by setting multicast TTL to 0, so the user’s entirely |
50 | 50 | internal navigation is not also heard over the wire. |
51 | 51 | |
52 | ||
52 | Packet Structure | |
53 | 53 | |
54 | 54 | |
55 | 55 | |
62 | 62 | |
63 | 63 | RFC -BSP- BibleSync Protocol - DRAFT 15 June 2014 |
64 | 64 | |
65 | ||
66 | Packet Structure | |
67 | 65 | |
68 | 66 | Payload maximum length is 1280 bytes. Within this, the first 32 |
69 | 67 | bytes are a header identifying the sender’s protocol version, message |
86 | 84 | The magic value is 0x409CAF11, by which to determine that a packet is |
87 | 85 | intended for BibleSync. |
88 | 86 | |
89 | The protocol version is 2. | |
90 | ||
91 | Three message types are defined: 1 = presence announcement, 2 = | |
92 | navigation synchronization, 3 = speaker availability beacon. | |
87 | The protocol version is 3. The protocol interoperates with the | |
88 | previous version 2, though lacking the distinguishing feature of chat | |
89 | messages. | |
90 | ||
91 | Four message types are defined: 1 = presence announcement, 2 = | |
92 | navigation synchronization, 3 = speaker availability beacon, 4 = chat | |
93 | message. | |
93 | 94 | |
94 | 95 | Currently BibleSync is specified as a single packet protocol, but the |
95 | 96 | number of packets and packet index fields are included for possible |
110 | 111 | |
111 | 112 | The presence packet announces the application’s participation in the |
112 | 113 | conversation. It is non-essential, but useful if the application |
114 | ||
115 | ||
116 | ||
117 | Stergiou et al [Page 2] | |
118 | ||
119 | ||
120 | ||
121 | ||
122 | ||
123 | RFC -BSP- BibleSync Protocol - DRAFT 15 June 2014 | |
124 | ||
125 | ||
113 | 126 | designer chooses to make it visible to the user. |
114 | ||
115 | ||
116 | ||
117 | Stergiou et al [Page 2] | |
118 | ||
119 | ||
120 | ||
121 | ||
122 | ||
123 | RFC -BSP- BibleSync Protocol - DRAFT 15 June 2014 | |
124 | ||
125 | 127 | |
126 | 128 | The navigation packet specifies a Bible name and a reference. It may |
127 | 129 | also contain an alternate reference to provide a second means of |
133 | 135 | |
134 | 136 | The speaker beacon packet is identical to the presence announcement |
135 | 137 | except for having message type 3, and is sent by transmitting |
136 | applications every 10 seconds. | |
138 | applications every 10 seconds. Beacon silence for 30 seconds | |
139 | indicates a dead Speaker. | |
140 | ||
141 | The chat message packet contains only 1 field, the message content, | |
142 | beyond those found in announce and beacon. | |
137 | 143 | |
138 | 144 | Speaker Beacons |
139 | 145 | |
165 | 171 | claiming speaker status by sending beacons, and a newly-started |
166 | 172 | application begins to listen, it may first hear the interloper’s |
167 | 173 | beacon and begin listening to it. The user must be able to consult a |
174 | ||
175 | ||
176 | ||
177 | Stergiou et al [Page 3] | |
178 | ||
179 | ||
180 | ||
181 | ||
182 | ||
183 | RFC -BSP- BibleSync Protocol - DRAFT 15 June 2014 | |
184 | ||
185 | ||
168 | 186 | list of potential speakers and pick the one(s) actually needed. |
169 | 187 | |
170 | 188 | Beacons must be sent at least every 10 seconds. Receivers must track |
171 | 189 | speaker beacons, aging speakers toward removal. Each new beacon for |
172 | 190 | a speaker restarts its aging countdown. A potential speaker that has |
173 | 191 | gone beacon-silent for 30 seconds is considered a dead speaker and is |
174 | ||
175 | ||
176 | ||
177 | Stergiou et al [Page 3] | |
178 | ||
179 | ||
180 | ||
181 | ||
182 | ||
183 | RFC -BSP- BibleSync Protocol - DRAFT 15 June 2014 | |
184 | ||
185 | ||
186 | 192 | removed from the list of available speakers. |
187 | 193 | |
188 | 194 | Navigation synchronization received without beacon support is |
199 | 205 | |
200 | 206 | Continuation lines are not supported. |
201 | 207 | |
202 | There are 12 names defined for use in the body. The application may | |
208 | There are 13 names defined for use in the body. The application may | |
203 | 209 | provide any others its designer finds useful, but these names define |
204 | 210 | the protocol’s interoperability. |
205 | 211 | |
226 | 232 | |
227 | 233 | Optional; recommended. The application’s version stamp. |
228 | 234 | |
235 | ||
236 | ||
237 | Stergiou et al [Page 4] | |
238 | ||
239 | ||
240 | ||
241 | ||
242 | ||
243 | RFC -BSP- BibleSync Protocol - DRAFT 15 June 2014 | |
244 | ||
245 | ||
229 | 246 | 6. app.os |
230 | 247 | |
231 | 248 | Optional. Identification of the OS under which the application |
232 | 249 | runs. |
233 | ||
234 | ||
235 | ||
236 | ||
237 | Stergiou et al [Page 4] | |
238 | ||
239 | ||
240 | ||
241 | ||
242 | ||
243 | RFC -BSP- BibleSync Protocol - DRAFT 15 June 2014 | |
244 | ||
245 | 250 | |
246 | 251 | 7. app.device |
247 | 252 | |
287 | 292 | |
288 | 293 | 12. msg.sync.domain |
289 | 294 | |
295 | ||
296 | ||
297 | Stergiou et al [Page 5] | |
298 | ||
299 | ||
300 | ||
301 | ||
302 | ||
303 | RFC -BSP- BibleSync Protocol - DRAFT 15 June 2014 | |
304 | ||
305 | ||
290 | 306 | Required in navigation. This field has a fixed value of "BIBLE- |
291 | 307 | VERSE" but its use will be expanded in future revisions. |
292 | 308 | |
293 | ||
294 | ||
295 | ||
296 | ||
297 | Stergiou et al [Page 5] | |
298 | ||
299 | ||
300 | ||
301 | ||
302 | ||
303 | RFC -BSP- BibleSync Protocol - DRAFT 15 June 2014 | |
309 | 13. msg.chat | |
310 | ||
311 | Required for chat and useful only there. A free-from, newline- | |
312 | less text string to be shared in the conversation, intended to be | |
313 | displayed to all users. | |
304 | 314 | |
305 | 315 | |
306 | 316 | Security Considerations |
331 | 341 | Presence announcement: |
332 | 342 | |
333 | 343 | magic: 0x409caf11 |
334 | version: 0x02 | |
344 | version: 0x03 | |
335 | 345 | type: 0x01 |
336 | 346 | uuid: 00112233-4455-6677-8899-aabbccddeeff |
337 | 347 | #pkt: 1 |
341 | 351 | app.user=John Doe (jdoe) |
342 | 352 | msg.sync.passPhrase=qwerty |
343 | 353 | |
344 | Beacon is identical to presence announcement except for being type 3. | |
354 | ||
355 | ||
356 | ||
357 | Stergiou et al [Page 6] | |
358 | ||
359 | ||
360 | ||
361 | ||
362 | ||
363 | RFC -BSP- BibleSync Protocol - DRAFT 15 June 2014 | |
364 | ||
365 | ||
366 | Beacon is identical to presence announcement except for being type 0x03. | |
345 | 367 | |
346 | 368 | Navigation: |
347 | 369 | |
348 | 370 | magic: 0x409caf11 |
349 | version: 0x02 | |
371 | version: 0x03 | |
350 | 372 | type: 0x02 |
351 | 373 | uuid: 00112233-4455-6677-8899-aabbccddeeff |
352 | 374 | #pkt: 1 |
353 | 375 | pkt index: 0 |
354 | ||
355 | ||
356 | ||
357 | Stergiou et al [Page 6] | |
358 | ||
359 | ||
360 | ||
361 | ||
362 | ||
363 | RFC -BSP- BibleSync Protocol - DRAFT 15 June 2014 | |
364 | ||
365 | ||
366 | 376 | app.name=TestBibleApp |
367 | 377 | app.inst.uuid=00112233-4455-6677-8899-aabbccddeeff |
368 | 378 | app.user=John Doe (jdoe) |
372 | 382 | msg.sync.bibleAbbrev=NET |
373 | 383 | msg.sync.verse=Rom.14.4 |
374 | 384 | |
385 | Chat: | |
386 | ||
387 | magic: 0x409caf11 | |
388 | version: 0x03 | |
389 | type: 0x04 | |
390 | uuid: 00112233-4455-6677-8899-aabbccddeeff | |
391 | #pkt: 1 | |
392 | pkt index: 0 | |
393 | app.name=TestBibleApp | |
394 | app.inst.uuid=00112233-4455-6677-8899-aabbccddeeff | |
395 | app.user=John Doe (jdoe) | |
396 | msg.sync.passPhrase=qwerty | |
397 | msg.chat=This is just a test message. No newlines permitted. | |
398 | ||
375 | 399 | Additional name/value examples, optional use: |
376 | 400 | |
377 | 401 | app.version=2.7a |
379 | 403 | app.device=i686 |
380 | 404 | msg.sync.altVerse=1Mac.1.2 |
381 | 405 | |
382 | Real-world example, using all defined names: | |
406 | Real-world example, navigation synchronization, using all defined names: | |
383 | 407 | |
384 | 408 | magic: 0x409caf11 |
385 | version: 0x02 | |
409 | version: 0x03 | |
386 | 410 | type: 0x02 (sync) |
387 | 411 | uuid: 49b387bd-6324-4a2e-871a-4b24e065bff7 |
388 | 412 | #pkt: 1 |
389 | 413 | pkt index: 0 |
414 | ||
415 | ||
416 | ||
417 | Stergiou et al [Page 7] | |
418 | ||
419 | ||
420 | ||
421 | ||
422 | ||
423 | RFC -BSP- BibleSync Protocol - DRAFT 15 June 2014 | |
424 | ||
425 | ||
390 | 426 | app.name=Xiphos |
391 | app.version=3.2.1 | |
427 | app.version=4.1.1 | |
392 | 428 | app.inst.uuid=49b387bd-6324-4a2e-871a-4b24e065bff7 |
393 | 429 | app.os=Linux |
394 | 430 | app.device=x86_64: Linux @ awol.kleinpaste.org |
411 | 447 | UUID: |
412 | 448 | RFC 4122 |
413 | 449 | |
414 | ||
415 | ||
416 | ||
417 | Stergiou et al [Page 7] | |
418 | ||
419 | ||
420 | ||
421 | ||
422 | ||
423 | RFC -BSP- BibleSync Protocol - DRAFT 15 June 2014 | |
424 | ||
425 | ||
426 | 450 | This specification alters and extends technical aspects of the original |
427 | 451 | specification (cf. wikispaces, above), notably max packet size, size and |
428 | 452 | alignment of header, speaker beacons, use of app.user, and stipulations |
450 | 474 | |
451 | 475 | |
452 | 476 | |
453 | ||
454 | ||
455 | ||
456 | ||
457 | ||
458 | ||
459 | ||
460 | ||
461 | ||
462 | ||
463 | ||
464 | ||
465 | ||
466 | ||
467 | ||
468 | ||
469 | ||
470 | ||
471 | ||
472 | ||
473 | ||
474 | ||
475 | ||
476 | ||
477 | 477 | Stergiou et al [Page 8] |
478 | 478 | |
479 | 479 |
20 | 20 | |
21 | 21 | using namespace std; |
22 | 22 | |
23 | // sync is a proper superset of announce & beacon, | |
23 | // chat is a proper superset of announce/beacon, | |
24 | // sync is a proper superset of chat, | |
24 | 25 | // both inbound as well as outbound. |
25 | // in these 2 arrays of strings, sync-specific | |
26 | // fields are placed after announce fields. | |
26 | // in these 2 arrays of strings, chat-specific fields follow | |
27 | // announce fields, and sync-specific follow chat fields. | |
28 | // (chat overloads bible for this purpose.) | |
27 | 29 | // see field_count in ReceiveInternal + TransmitInternal. |
28 | 30 | static string inbound_required[] = { |
29 | 31 | BSP_APP_NAME, |
30 | 32 | BSP_APP_INSTANCE_UUID, |
31 | 33 | BSP_APP_USER, |
32 | 34 | BSP_MSG_PASSPHRASE, |
35 | BSP_MSG_SYNC_BIBLEABBREV, | |
33 | 36 | BSP_MSG_SYNC_DOMAIN, |
34 | 37 | BSP_MSG_SYNC_VERSE, |
35 | BSP_MSG_SYNC_BIBLEABBREV, | |
36 | 38 | BSP_MSG_SYNC_GROUP |
39 | }; | |
40 | #define CHAT_INBOUND_INDEX 4 // index in list above. | |
41 | ||
42 | static int inbound_required_count[5] = | |
43 | { | |
44 | 0, // unused | |
45 | BSP_FIELDS_RECV_ANNOUNCE, | |
46 | BSP_FIELDS_RECV_SYNC, | |
47 | BSP_FIELDS_RECV_ANNOUNCE, // beacon identical to announce | |
48 | BSP_FIELDS_RECV_CHAT | |
37 | 49 | }; |
38 | 50 | |
39 | 51 | static string outbound_fill[] = { |
44 | 56 | BSP_APP_DEVICE, |
45 | 57 | BSP_APP_USER, |
46 | 58 | BSP_MSG_PASSPHRASE, |
59 | BSP_MSG_SYNC_BIBLEABBREV, | |
47 | 60 | BSP_MSG_SYNC_DOMAIN, |
48 | 61 | BSP_MSG_SYNC_GROUP, |
49 | BSP_MSG_SYNC_BIBLEABBREV, | |
50 | 62 | BSP_MSG_SYNC_ALTVERSE, |
51 | 63 | BSP_MSG_SYNC_VERSE // last: could go overly long, risk cutoff. |
52 | 64 | }; |
65 | #define CHAT_OUTBOUND_INDEX 7 // index in list above. | |
66 | ||
67 | static int outbound_fill_count[5] = | |
68 | { | |
69 | 0, // unused | |
70 | BSP_FIELDS_XMIT_ANNOUNCE, | |
71 | BSP_FIELDS_XMIT_SYNC, | |
72 | BSP_FIELDS_XMIT_ANNOUNCE, // beacon identical to announce | |
73 | BSP_FIELDS_XMIT_CHAT | |
74 | }; | |
75 | ||
76 | static string chat_field = BSP_MSG_CHAT; // for referential substitution. | |
53 | 77 | |
54 | 78 | // BibleSync class constructor. |
55 | 79 | // args identify the user of the class, by application, version, and user. |
367 | 391 | ? "sync" |
368 | 392 | : ((bsp.msg_type == BSP_BEACON) |
369 | 393 | ? "beacon" |
370 | : "*???*"))), | |
394 | : ((bsp.msg_type == BSP_CHAT) | |
395 | ? "chat" | |
396 | : "*???*")))), | |
371 | 397 | uuid_dump_string, |
372 | 398 | bsp.num_packets, bsp.index_packet, |
373 | 399 | bsp.body); |
377 | 403 | (*nav_func)('E', EMPTY, |
378 | 404 | EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, |
379 | 405 | BSP + _("bad magic"), dump); |
380 | else if (bsp.version != BSP_PROTOCOL) | |
406 | else if ((bsp.version != BSP_PROTOCOL) && (bsp.version != BSP_OLD_PROTOCOL)) | |
407 | // we are fine with previous v2 protocol that lacks chat messages. | |
381 | 408 | (*nav_func)('E', EMPTY, |
382 | 409 | EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, |
383 | 410 | BSP + _("bad protocol version"), dump); |
384 | 411 | else if ((bsp.msg_type != BSP_ANNOUNCE) && |
385 | 412 | (bsp.msg_type != BSP_SYNC) && |
386 | (bsp.msg_type != BSP_BEACON)) | |
413 | (bsp.msg_type != BSP_BEACON) && | |
414 | (bsp.msg_type != BSP_CHAT)) | |
387 | 415 | (*nav_func)('E', EMPTY, |
388 | 416 | EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, |
389 | 417 | BSP + _("bad msg type"), dump); |
443 | 471 | else |
444 | 472 | { |
445 | 473 | // verify minimum body content. |
446 | int field_count = ((bsp.msg_type == BSP_SYNC) | |
447 | ? BSP_FIELDS_RECV_SYNC | |
448 | : BSP_FIELDS_RECV_ANNOUNCE); // or beacon. | |
474 | int field_count = inbound_required_count[bsp.msg_type]; | |
449 | 475 | |
450 | 476 | for (int i = 0; i < field_count; ++i) |
451 | 477 | { |
452 | if (content.find(inbound_required[i]) == content.end()) | |
478 | string &locator = (((bsp.msg_type == BSP_CHAT) && | |
479 | (i == CHAT_INBOUND_INDEX)) | |
480 | ? chat_field | |
481 | : inbound_required[i]); | |
482 | ||
483 | if (content.find(locator) == content.end()) | |
453 | 484 | { |
454 | 485 | ok_so_far = false; |
455 | 486 | string info = BSP + _("missing required header ") |
526 | 557 | version = (string)"(version?)"; |
527 | 558 | |
528 | 559 | // generally good, so extract interesting content. |
529 | if (bsp.msg_type == BSP_SYNC) | |
560 | if (bsp.msg_type == BSP_CHAT) | |
561 | { | |
562 | bible = content.find(BSP_APP_USER)->second; | |
563 | ref = source_addr; | |
564 | group = content.find(BSP_APP_NAME)->second | |
565 | + " " + version; | |
566 | domain = content.find(BSP_APP_DEVICE)->second; | |
567 | alt = content.find(BSP_MSG_CHAT)->second; | |
568 | ||
569 | info = (string)"chat: " | |
570 | + content.find(BSP_APP_USER)->second | |
571 | + " @ " + source_addr; | |
572 | ||
573 | cmd = ((passphrase == | |
574 | content.find(BSP_MSG_PASSPHRASE)->second) | |
575 | ? 'C' // chat message | |
576 | : 'M'); // mismatch | |
577 | } | |
578 | else if (bsp.msg_type == BSP_SYNC) | |
530 | 579 | { |
531 | 580 | // regular synchronized navigation |
532 | 581 | bible = content.find(BSP_MSG_SYNC_BIBLEABBREV)->second; |
744 | 793 | |
745 | 794 | if ((message_type != BSP_ANNOUNCE) && |
746 | 795 | (message_type != BSP_SYNC) && |
747 | (message_type != BSP_BEACON)) | |
796 | (message_type != BSP_BEACON) && | |
797 | (message_type != BSP_CHAT)) | |
748 | 798 | return BSP_XMIT_BAD_TYPE; |
749 | 799 | |
750 | 800 | if ((mode == BSP_MODE_AUDIENCE) && |
756 | 806 | string body = ""; |
757 | 807 | |
758 | 808 | // all name/value pairs. |
759 | content[BSP_APP_NAME] = application; | |
760 | content[BSP_APP_VERSION] = version; | |
761 | content[BSP_APP_USER] = user; | |
762 | content[BSP_APP_DEVICE] = device; | |
763 | content[BSP_APP_OS] = BSP_OS; | |
764 | content[BSP_APP_INSTANCE_UUID] = uuid_string; | |
765 | content[BSP_MSG_SYNC_BIBLEABBREV] = bible; | |
766 | content[BSP_MSG_SYNC_VERSE] = ref; | |
767 | content[BSP_MSG_SYNC_ALTVERSE] = alt; | |
768 | content[BSP_MSG_SYNC_GROUP] = group; | |
769 | content[BSP_MSG_SYNC_DOMAIN] = domain; | |
770 | content[BSP_MSG_PASSPHRASE] = passphrase; | |
809 | content[BSP_APP_NAME] = application; | |
810 | content[BSP_APP_VERSION] = version; | |
811 | content[BSP_APP_USER] = user; | |
812 | content[BSP_APP_DEVICE] = device; | |
813 | content[BSP_APP_OS] = BSP_OS; | |
814 | content[BSP_APP_INSTANCE_UUID] = uuid_string; | |
815 | if (message_type != BSP_CHAT) | |
816 | content[BSP_MSG_SYNC_BIBLEABBREV] = bible; | |
817 | else { | |
818 | content[BSP_MSG_CHAT] = bible; // overload. | |
819 | // innoculate chat content against internal \n. | |
820 | for (char *chase = (char *)bible.c_str(); chase = strchr(chase, '\n'); ++chase) | |
821 | *chase = '\t'; | |
822 | } | |
823 | content[BSP_MSG_SYNC_VERSE] = ref; | |
824 | content[BSP_MSG_SYNC_ALTVERSE] = alt; | |
825 | content[BSP_MSG_SYNC_GROUP] = group; | |
826 | content[BSP_MSG_SYNC_DOMAIN] = domain; | |
827 | content[BSP_MSG_PASSPHRASE] = passphrase; | |
771 | 828 | |
772 | 829 | // header. |
773 | 830 | bsp.magic = BSP_MAGIC; |
779 | 836 | memset((void *)&bsp.reserved, 0, BSP_RES_SIZE); |
780 | 837 | |
781 | 838 | // body prep. |
782 | int field_count = ((message_type == BSP_SYNC) | |
783 | ? BSP_FIELDS_XMIT_SYNC | |
784 | : BSP_FIELDS_XMIT_ANNOUNCE); // or beacon. | |
839 | int field_count = outbound_fill_count[message_type]; | |
785 | 840 | |
786 | 841 | for (int i = 0; i < field_count; ++i) |
787 | 842 | { |
788 | body += outbound_fill[i] + "=" + content[outbound_fill[i]] + "\n"; | |
843 | string &filler = (((message_type == BSP_CHAT) && | |
844 | (i == CHAT_OUTBOUND_INDEX)) | |
845 | ? chat_field | |
846 | : outbound_fill[i]); | |
847 | body += filler + "=" + content[filler] + "\n"; | |
789 | 848 | } |
790 | 849 | |
791 | 850 | // ship it. |
794 | 853 | BSP_HEADER_SIZE + body.length()); |
795 | 854 | |
796 | 855 | // force last == newline: attempt to preserve body format when long. |
856 | // (cuts off excessively long verse references and chat messages.) | |
797 | 857 | ((unsigned char*)&bsp)[BSP_MAX_SIZE-1] = '\n'; |
798 | 858 | |
799 | 859 | BibleSync_xmit_status retval; |
895 | 955 | |
896 | 956 | #ifdef linux |
897 | 957 | |
898 | // routines below imported from the net as workable examples. | |
899 | 958 | // in order to do multicast setup, we require the address |
900 | // of the interface that has our default route. code below | |
901 | // finds the name of that interface. then getifaddrs(3) | |
902 | // code (taken from its man page) lets us match that name | |
903 | // against an entry that has the address we need. | |
904 | ||
905 | // extra includes needed only for the | |
906 | // route & gateway discovery code below. | |
959 | // of the interface that has our default route. | |
960 | // get_default_if_name() reads /proc/net/route to find that interface. | |
961 | // then getifaddrs(3) code (taken from its man page) lets us | |
962 | // match that name against an entry that has the address we need. | |
963 | // this entire methodology is 100 times simpler than the former | |
964 | // rtnetlink-driven nightmare | |
965 | ||
966 | // lines in /proc/net/route consist of | |
967 | // IFACE \t DESTINATION \t GATEWAY \t FLAGS \t ... | |
968 | // DESTINATION is an 8-byte hex value (string), so look for \t00000000\t. | |
969 | ||
970 | #define PROC_ROUTE "/proc/net/route" | |
907 | 971 | |
908 | 972 | #include <net/if.h> |
909 | #include <linux/rtnetlink.h> | |
910 | ||
911 | struct route_info | |
912 | { | |
913 | struct in_addr dstAddr; | |
914 | struct in_addr srcAddr; | |
915 | struct in_addr gateWay; | |
916 | char ifName[IF_NAMESIZE]; | |
917 | }; | |
918 | ||
919 | int BibleSync::readNlSock(int sockFd, | |
920 | char *bufPtr, | |
921 | size_t buf_size, | |
922 | unsigned int seqNum, | |
923 | unsigned int pId) | |
924 | { | |
925 | struct nlmsghdr *nlHdr; | |
926 | int readLen = 0, msgLen = 0; | |
927 | ||
928 | do | |
929 | { | |
930 | if((readLen = recv(sockFd, bufPtr, buf_size - msgLen, 0)) < 0) | |
931 | { | |
932 | return -1; | |
933 | } | |
934 | ||
935 | nlHdr = (struct nlmsghdr *)bufPtr; | |
936 | ||
937 | if((NLMSG_OK(nlHdr, readLen) == 0) || (nlHdr->nlmsg_type == NLMSG_ERROR)) | |
938 | { | |
939 | return -1; | |
940 | } | |
941 | ||
942 | /* check if last message */ | |
943 | if(nlHdr->nlmsg_type == NLMSG_DONE) | |
944 | { | |
945 | break; | |
946 | } | |
947 | else | |
948 | { | |
949 | /* else move pointer to buffer appropriately */ | |
950 | bufPtr += readLen; | |
951 | msgLen += readLen; | |
952 | } | |
953 | ||
954 | /* check if multi part message */ | |
955 | if((nlHdr->nlmsg_flags & NLM_F_MULTI) == 0) | |
956 | { | |
957 | /* return if its not */ | |
958 | break; | |
959 | } | |
960 | } | |
961 | while((nlHdr->nlmsg_seq != seqNum) || (nlHdr->nlmsg_pid != pId)); | |
962 | ||
963 | return msgLen; | |
964 | } | |
965 | ||
966 | int BibleSync::parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo) | |
967 | { | |
968 | struct rtmsg *rtMsg; | |
969 | struct rtattr *rtAttr; | |
970 | int rtLen; | |
971 | ||
972 | rtMsg = (struct rtmsg *)NLMSG_DATA(nlHdr); | |
973 | ||
974 | /* if route is not AF_INET or not in main table, return. */ | |
975 | if((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN)) | |
976 | return -1; | |
977 | ||
978 | rtAttr = (struct rtattr *)RTM_RTA(rtMsg); | |
979 | rtLen = RTM_PAYLOAD(nlHdr); | |
980 | ||
981 | for(; RTA_OK(rtAttr,rtLen); rtAttr = RTA_NEXT(rtAttr,rtLen)) | |
982 | { | |
983 | switch(rtAttr->rta_type) | |
984 | { | |
985 | case RTA_OIF: | |
986 | if_indextoname(*(int *)RTA_DATA(rtAttr), rtInfo->ifName); | |
987 | break; | |
988 | ||
989 | case RTA_GATEWAY: | |
990 | memcpy(&rtInfo->gateWay, RTA_DATA(rtAttr), sizeof(rtInfo->gateWay)); | |
991 | break; | |
992 | ||
993 | case RTA_PREFSRC: | |
994 | memcpy(&rtInfo->srcAddr, RTA_DATA(rtAttr), sizeof(rtInfo->srcAddr)); | |
995 | break; | |
996 | ||
997 | case RTA_DST: | |
998 | memcpy(&rtInfo->dstAddr, RTA_DATA(rtAttr), sizeof(rtInfo->dstAddr)); | |
999 | break; | |
1000 | } | |
1001 | } | |
1002 | ||
1003 | return 0; | |
1004 | } | |
1005 | ||
1006 | int BibleSync::get_default_if_name(char *name, socklen_t size) | |
1007 | { | |
1008 | int found_default = 0; | |
1009 | ||
1010 | struct nlmsghdr *nlMsg; | |
1011 | //struct rtmsg *rtMsg; | |
1012 | struct route_info route_info; | |
1013 | char msgBuf[4096]; | |
1014 | ||
1015 | int sock, len, msgSeq = 0; | |
1016 | ||
1017 | name[1] = '\0'; // pre-set, in case of error. | |
1018 | ||
1019 | if((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) | |
973 | #include <netdb.h> | |
974 | #include <ifaddrs.h> | |
975 | ||
976 | int BibleSync::get_default_if_name(char *name) | |
977 | { | |
978 | int found = 0; | |
979 | char line[256], *field; | |
980 | FILE *proc_route; | |
981 | ||
982 | if ((proc_route = fopen(PROC_ROUTE, "r")) == NULL) | |
1020 | 983 | { |
1021 | 984 | name[0] = 'x'; |
1022 | 985 | return -1; |
1023 | 986 | } |
1024 | 987 | |
1025 | memset(msgBuf, 0, sizeof(msgBuf)); | |
1026 | ||
1027 | nlMsg = (struct nlmsghdr *)msgBuf; | |
1028 | //rtMsg = (struct rtmsg *)NLMSG_DATA(nlMsg); | |
1029 | ||
1030 | nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); | |
1031 | nlMsg->nlmsg_type = RTM_GETROUTE; | |
1032 | ||
1033 | nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; | |
1034 | nlMsg->nlmsg_seq = msgSeq++; | |
1035 | nlMsg->nlmsg_pid = getpid(); | |
1036 | ||
1037 | if(send(sock, nlMsg, nlMsg->nlmsg_len, 0) < 0) | |
1038 | { | |
1039 | name[0] = 'y'; | |
1040 | return -1; | |
1041 | } | |
1042 | ||
1043 | if((len = readNlSock(sock, msgBuf, sizeof(msgBuf), msgSeq, getpid())) < 0) | |
1044 | { | |
1045 | name[0] = 'z'; | |
1046 | return -1; | |
1047 | } | |
1048 | ||
1049 | for(; NLMSG_OK(nlMsg,len); nlMsg = NLMSG_NEXT(nlMsg,len)) | |
1050 | { | |
1051 | memset(&route_info, 0, sizeof(route_info)); | |
1052 | if ( parseRoutes(nlMsg, &route_info) < 0 ) | |
1053 | continue; // don't check: not set up | |
1054 | ||
1055 | if (strstr((char *)inet_ntoa(route_info.dstAddr), "0.0.0.0")) | |
988 | while (fgets(line, 255, proc_route) != NULL) | |
989 | { | |
990 | if ((field = strchr(line, '\t')) == NULL) | |
991 | continue; // invalid line? | |
992 | ||
993 | if (strncmp(field, "\t00000000\t", 10) == 0) | |
1056 | 994 | { |
1057 | // copy it over | |
1058 | strcpy(name, route_info.ifName); | |
1059 | found_default = 1; | |
995 | found = 1; | |
996 | *field = '\0'; | |
997 | strcpy(name, line); | |
1060 | 998 | break; |
1061 | 999 | } |
1062 | 1000 | } |
1063 | ||
1064 | close(sock); | |
1065 | return found_default; | |
1066 | } | |
1067 | ||
1068 | #include <netdb.h> | |
1069 | #include <ifaddrs.h> | |
1001 | fclose(proc_route); | |
1002 | ||
1003 | if (!found) | |
1004 | { | |
1005 | // no default route? fallback: we're holding a valid last line. | |
1006 | // so we arbitrarily choose whatever was found there. | |
1007 | *field = '\0'; | |
1008 | strcpy(name, line); | |
1009 | } | |
1010 | ||
1011 | return 0; | |
1012 | } | |
1070 | 1013 | |
1071 | 1014 | void BibleSync::InterfaceAddress() |
1072 | 1015 | { |
1076 | 1019 | |
1077 | 1020 | char gw_if[IF_NAMESIZE]; // default gateway interface. |
1078 | 1021 | |
1079 | (void)get_default_if_name(gw_if, 100); | |
1022 | (void)get_default_if_name(gw_if); | |
1080 | 1023 | |
1081 | 1024 | // if no error, search the interface list for that address. |
1082 | 1025 | if (gw_if[0] != '\0') |
1108 | 1051 | |
1109 | 1052 | // Solaris & BSD. |
1110 | 1053 | |
1111 | // | |
1112 | 1054 | // this seeming grotesqueness is in fact the most general command |
1113 | 1055 | // that could be found which finds the interface holding the default |
1114 | 1056 | // route and then collects that interface's address. handles both |
1115 | // solaris and bsd. in fact, it suffices for linux as well, but | |
1116 | // we're leaving the existing code above in place for linux, if for | |
1117 | // no other reason than that it's more likely that someone will | |
1118 | // foolishly screw up ifconfig output format in the linux world. | |
1119 | // | |
1120 | #define ADDRESS "PATH=/sbin:/usr/sbin:/bin:/usr/bin " \ | |
1121 | "ifconfig \"`netstat -rn | egrep '^0\\.0\\.0\\.0|^default' | " \ | |
1122 | "tr ' ' '\\n' | sed -e '/^$/d' | tail -1`\" | grep 'inet ' | " \ | |
1057 | // solaris and bsd. also an instance for linux using "ip", in case | |
1058 | // whoever builds this doesn't like depending on /proc/net/route. | |
1059 | ||
1060 | #ifdef linux | |
1061 | #define ADDRESS "PATH=/sbin:/usr/sbin:/bin:/usr/bin " \ | |
1062 | "ip address show dev `ip route | egrep '^(default|0\\.0\\.0\\.0)' | " \ | |
1063 | "head -1 | sed 's/dev /DEV-/' | tr ' ' '\\n' | grep DEV | sed s/DEV-//` | " \ | |
1064 | "grep 'inet ' | tr '/ ' '\\n\\n' | grep '^[0-9.][0-9.]*' | head -1 | tr -d '\\n'" | |
1065 | #else | |
1066 | #define ADDRESS "PATH=/sbin:/usr/sbin:/bin:/usr/bin " \ | |
1067 | "ifconfig \"`netstat -rn | egrep '^0\\.0\\.0\\.0|^default' | " \ | |
1068 | "tr ' ' '\\n' | sed -e '/^$/d' | tail -1`\" | grep 'inet ' | " \ | |
1123 | 1069 | "tr ' ' '\\n' | grep '^[0-9.][0-9.]*$' | head -1 | tr -d '\\n'" |
1070 | #endif | |
1124 | 1071 | |
1125 | 1072 | void BibleSync::InterfaceAddress() |
1126 | 1073 | { |