~ubuntu-branches/debian/sid/xiphos/sid

« back to all changes in this revision

Viewing changes to src/biblesync/biblesync.hh

  • Committer: Package Import Robot
  • Author(s): Dimitri John Ledkov
  • Date: 2014-07-12 17:08:46 UTC
  • mfrom: (1.3.3)
  • Revision ID: package-import@ubuntu.com-20140712170846-ja9jzhgt51d3fkrd
Tags: 3.2.2+dfsg1-1
* New upstream release.
* Bump standards version.
* Switch uscan to sf.net redirector.
* Unpack waf in get-orig-source target.
* Bump to debhelper 9.
* Add uuid-dev build-dep.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * BibleSync library
 
3
 * biblesync.hh
 
4
 *
 
5
 * Karl Kleinpaste, May 2014
 
6
 *
 
7
 * All files related to implementation of BibleSync, including program
 
8
 * source, READMEs, manual pages, and related similar documents, are in
 
9
 * the public domain.  As a matter of simple decency, your social
 
10
 * obligations are to credit the source and to coordinate any changes you
 
11
 * make back to the origin repository.  These obligations are non-
 
12
 * binding for public domain software, but they are to be seriously
 
13
 * handled nonetheless.
 
14
 */
 
15
 
 
16
#ifndef __BIBLESYNC_HH__
 
17
#define __BIBLESYNC_HH__
 
18
 
 
19
// XIPHOS-SPECIFIC - THIS #INCLUDE TO BE REMOVED WHEN
 
20
// BIBLESYNC IS EXTRICATED TO AN INDEPENDENT LIBRARY.
 
21
#include <glib/gi18n.h>
 
22
 
 
23
#include "biblesync-version.hh"
 
24
 
 
25
//
 
26
// Bible Sync Protocol.
 
27
// http://biblesyncprotocol.wikispaces.com/
 
28
//
 
29
// BSP provides a classroom type of arrangement, where one person
 
30
// (speaker) is in charge of inducing others' (audience) Bible
 
31
// software to navigate as speaker requires.  The speaker only
 
32
// xmits and the audience only recvs.
 
33
// BSP also provides a personal mode which both xmits and recvs, where
 
34
// one user works with multiple programs across several devices,
 
35
// also suitable for small teams working together, such as translators.
 
36
// BSP is implemented using multicast UDP with small packets in a
 
37
// simple format employing a few bytes of packet control followed by a
 
38
// series of newline-terminated "name=value" pairs.
 
39
//
 
40
// * Application interface *
 
41
//
 
42
// - object creation.
 
43
//      BibleSync *YourBibleSyncObjectPtr = new BibleSync(app, version, user);
 
44
//              create exactly one.
 
45
//              identify the application, its version, and the user.
 
46
//
 
47
// - mode selection.
 
48
//      setMode(BSP_MODE_xyz, your_void_nav_func, "passphrase");
 
49
//              invoke a mode, including net.setup as needed.
 
50
//              xyz = { DISABLE, PERSONAL, SPEAKER, AUDIENCE }.
 
51
//                 DISABLE kills it, shuts off network access.
 
52
//                 PERSONAL is bidirectional.
 
53
//                 SPEAKER xmits only.
 
54
//                 AUDIENCE recvs only.
 
55
//      => empty passphrase ("") means re-use existing passphrase.
 
56
//      => for any active mode, the application must then start polling using
 
57
//         the receiver, BibleSync::Receive(), and stop polling when mode
 
58
//         goes to DISABLE.  if Receive() is called while disabled, it will
 
59
//         return FALSE to indicate its polled use should stop, otherwise TRUE.
 
60
//      => interface for your_void_nav_func:
 
61
//              (char cmd,
 
62
//               string bible, string ref, string alt,
 
63
//               string group, string domain,
 
64
//               string info,  string dump)
 
65
//              there are 6 your_void_nav_func() use cases, identified in cmd:
 
66
//              1. 'E' (error) for network errors & malformed packets.
 
67
//                 only info + dump are useful.
 
68
//              2. 'M' (mismatch) against passphrase or mode or listen status.
 
69
//                 info == "announce" or "sync" or "beacon" (+ user @ [ipaddr])
 
70
//                         sync:     bible, ref, alt, group, domain as arrived.
 
71
//                         announce: presence message in alt.
 
72
//                            also, individual elements are also available:
 
73
//                            overload: bible   ref       group    domain
 
74
//                                      user    [ipaddr]  app+ver  device
 
75
//                 dump available.
 
76
//              3. 'A' (announce)
 
77
//                 presence message in alt.  dump available.
 
78
//              4. 'N' (navigation)
 
79
//                 bible, ref, alt, group, domain as arrived.
 
80
//                 info + dump available.
 
81
//              5. 'S' (new speaker)
 
82
//                 param overload as above.  alt == sender UUID.
 
83
//                 alt is the SPEAKER-KEY.  see listenToSpeaker().
 
84
//              6. 'D' (dead speaker)
 
85
//                 opposite of new speaker.  only param is alt == UUID.
 
86
//
 
87
// - get current mode.
 
88
//      BibleSync_mode getMode().
 
89
//
 
90
// - get current passphrase, for default use when setting a new one.
 
91
//      string getPassphrase().
 
92
//
 
93
// - receive navigation.
 
94
//      BibleSync::Receive(YourBibleSyncObjPtr);        // *-* poll often *-*
 
95
//              see note below; calls your_void_nav_func().
 
96
//
 
97
// - send navigation.
 
98
//      BibleSync_xmit_status retval =
 
99
//              Transmit(BSP_SYNC,
 
100
//                       "NASB", "John.3.16", "some alt ref",
 
101
//                       "1", "BIBLE-VERSE");
 
102
//        params: type (sync only), bible, ref, alt-ref, group, domain.
 
103
//        all params have defaults.
 
104
//      => it is the application's responsibility to send well-formed verse
 
105
//         references.
 
106
//
 
107
// - set self as private
 
108
//      bool setPrivate(boolean);
 
109
//        sets outgoing TTL to zero so no one hears you off-machine.
 
110
//
 
111
// - allow another speaker to drive us
 
112
//      void listenToSpeaker(bool listen, string speakerkey)
 
113
//              say yes/no to listening.
 
114
//              speakerkey was given during nav_func 'S'.
 
115
//
 
116
// Receive() USAGE NOTE:
 
117
// the application must call BibleSync::Receive(YourBibleSyncObjPtr)
 
118
// frequently.  For example:
 
119
//    g_timeout_add(2000,       // 2sec in msec.
 
120
//                  (GSourceFunc)BibleSync::Receive,
 
121
//                  biblesyncobj);      // of type (BibleSync *).
 
122
// g_timeout_add is a glib function for polled function calls.
 
123
// this will induce timed-interval calls to the function, as long
 
124
// as the function returns TRUE; upon returning FALSE, calls stop.
 
125
// other than with glib, accomplish the same thing somehow else.
 
126
// Receive is a static method accessible from C or C++.  it must be
 
127
// called with the pointer to your BibleSync object in order that
 
128
// object context be re-entered.  the internal receive routine
 
129
// is private.
 
130
//
 
131
// Note on speaker beacons:
 
132
// Protocol operates using periodic (10sec) beacons of speaker availability.
 
133
// By default, audience accepts listening to the first available speaker,
 
134
// thereafter ignores any more, but includes them in the list of available
 
135
// speakers and notifies the app of their availability (see above, 'S'/'D').
 
136
// Override this behavior choice however wished, using listenToSpeaker() in
 
137
// reaction to 'S' events or on user request.
 
138
// Speakers who stop xmitting beacons timeout, are declared dead, and
 
139
// removed after 30sec beacon silence, with app notification ('D').
 
140
// Observe that pure Speaker clears the speaker list and by default ignores
 
141
// all newly-identified claimants to speaker status.  Again, this is default
 
142
// behavior, but it makes no sense to try to listen to one as the mode is
 
143
// a mismatch.
 
144
// Note also that Personal is both speaker and audience.
 
145
 
 
146
using namespace std;
 
147
 
 
148
#include <map>
 
149
#include <string>
 
150
 
 
151
#include <memory.h>
 
152
#include <stdio.h>
 
153
#include <stdlib.h>
 
154
#include <stdint.h>
 
155
 
 
156
#include <sys/types.h>
 
157
#include <unistd.h>
 
158
#include <time.h>
 
159
 
 
160
#ifndef WIN32
 
161
#include <sys/utsname.h>
 
162
#include <arpa/inet.h>
 
163
#include <netinet/in.h>
 
164
#include <sys/socket.h>
 
165
#include <uuid/uuid.h>
 
166
#else
 
167
#define uuid_t  UUID
 
168
#include <winsock2.h>
 
169
#include <windows.h>
 
170
#include <ws2tcpip.h>
 
171
#endif
 
172
 
 
173
typedef enum _BibleSync_mode {
 
174
    BSP_MODE_DISABLE,
 
175
    BSP_MODE_PERSONAL,
 
176
    BSP_MODE_SPEAKER,
 
177
    BSP_MODE_AUDIENCE,
 
178
    N_BSP_MODE
 
179
} BibleSync_mode;
 
180
 
 
181
typedef enum _BibleSync_xmit_status {
 
182
    BSP_XMIT_OK,
 
183
    BSP_XMIT_FAILED,
 
184
    BSP_XMIT_NO_SOCKET,
 
185
    BSP_XMIT_BAD_TYPE,
 
186
    BSP_XMIT_NO_AUDIENCE_XMIT,
 
187
    BSP_XMIT_RECEIVING,
 
188
    N_BSP_XMIT
 
189
} BibleSync_xmit_status;
 
190
 
 
191
// args: cmd, bible, verse, alt, group, domain, info, dump.
 
192
typedef void (*BibleSync_navigate)(char,
 
193
                                   string, string, string,
 
194
                                   string, string,
 
195
                                   string, string);
 
196
 
 
197
#ifndef TRUE
 
198
#define TRUE 1
 
199
#define FALSE 0
 
200
#endif
 
201
 
 
202
#ifndef min
 
203
#define min(a,b)        (((a) < (b)) ? (a) : (b))
 
204
#endif
 
205
 
 
206
// message structure constants
 
207
#define BSP_MULTICAST   "239.225.27.227"
 
208
#define BSP_PORT        22272
 
209
#define BSP_MAX_SIZE    1280    // in spec, it's 512.  experimenting.
 
210
#define BSP_RES_SIZE    6       // unused bytes, fill out header to 32.
 
211
#define BSP_HEADER_SIZE 32
 
212
#define BSP_MAX_PAYLOAD (BSP_MAX_SIZE - BSP_HEADER_SIZE)
 
213
 
 
214
// message indications
 
215
#define BSP_MAGIC       htonl(0x409CAF11)
 
216
#define BSP_PROTOCOL    2
 
217
 
 
218
// message types
 
219
#define BSP_ANNOUNCE    1       // presence announcement.
 
220
#define BSP_SYNC        2       // navigation synchronization.
 
221
#define BSP_BEACON      3       // speaker availability beacon.
 
222
// beacon packet is identical to presence announcement except for type.
 
223
 
 
224
// beacon constants
 
225
#define BSP_BEACON_COUNT        10      // xmit every N calls of Receive().
 
226
#define BSP_BEACON_MULTIPLIER   3       // multiplier for aging to death.
 
227
 
 
228
// message content names.
 
229
#define BSP_APP_NAME                    "app.name"              // req'd
 
230
#define BSP_APP_VERSION                 "app.version"           // opt
 
231
#define BSP_APP_INSTANCE_UUID           "app.inst.uuid"         // req'd
 
232
#define BSP_APP_OS                      "app.os"                // opt
 
233
#define BSP_APP_DEVICE                  "app.device"            // opt
 
234
#define BSP_APP_USER                    "app.user"              // req'd
 
235
#define BSP_MSG_SYNC_DOMAIN             "msg.sync.domain"       // req'd
 
236
#define BSP_MSG_SYNC_VERSE              "msg.sync.verse"        // req'd
 
237
#define BSP_MSG_SYNC_ALTVERSE           "msg.sync.altVerse"     // opt
 
238
#define BSP_MSG_SYNC_BIBLEABBREV        "msg.sync.bibleAbbrev"  // req'd
 
239
#define BSP_MSG_SYNC_GROUP              "msg.sync.group"        // req'd
 
240
#define BSP_MSG_PASSPHRASE              "msg.sync.passPhrase"   // req'd
 
241
 
 
242
// required number of fields to send (out) or verify (in).
 
243
#define BSP_FIELDS_RECV_ANNOUNCE        4
 
244
#define BSP_FIELDS_RECV_SYNC            8
 
245
#define BSP_FIELDS_XMIT_ANNOUNCE        7
 
246
#define BSP_FIELDS_XMIT_SYNC            12
 
247
 
 
248
#ifdef linux
 
249
# define        BSP_OS  "Linux"
 
250
#else
 
251
# ifdef WIN32
 
252
#  define       BSP_OS  "Windows"
 
253
# else
 
254
#  define       BSP_OS  "UNIX"
 
255
# endif
 
256
#endif
 
257
 
 
258
#define BSP_UUID_PRINT_LENGTH           37      // actually 36, plus '\0'.
 
259
 
 
260
class BibleSync {
 
261
 
 
262
private:
 
263
 
 
264
    // simple name/value pairs.
 
265
    typedef std::map < string, string > BibleSyncContent;
 
266
 
 
267
    typedef struct _BibleSyncMessage {
 
268
        uint32_t  magic;
 
269
        uint8_t   version;
 
270
        uint8_t   msg_type;
 
271
        uint16_t  num_packets;
 
272
        uint16_t  index_packet;
 
273
        uint8_t   reserved[BSP_RES_SIZE];
 
274
        uuid_t    uuid;
 
275
        char      body[BSP_MAX_PAYLOAD+1];      // +1 for stuffing '\0'.
 
276
    } BibleSyncMessage;
 
277
 
 
278
    typedef struct _BibleSyncSpeaker {
 
279
        bool      listen;                       // nav for this guy?
 
280
        uint8_t   countdown;                    // lifetime aging.
 
281
        string    addr;                         // for spoof check.
 
282
    } BibleSyncSpeaker;
 
283
 
 
284
    // key string is origin uuid.
 
285
    typedef std::map < string, BibleSyncSpeaker > BibleSyncSpeakerMap;
 
286
    typedef BibleSyncSpeakerMap::iterator BibleSyncSpeakerMapIterator;
 
287
 
 
288
    // self identification.
 
289
    string BibleSync_version;
 
290
 
 
291
    // application identifiers.
 
292
    string application;
 
293
    string version;
 
294
    string user;
 
295
    string device;
 
296
 
 
297
    // currently processing received navigation.
 
298
    // prevents use of Transmit.
 
299
    bool receiving;
 
300
 
 
301
    // when xmit-capable, we xmit BSP_BEACON every N calls of Receive().
 
302
    uint8_t beacon_countdown;
 
303
 
 
304
    // track currently-known speaker set.
 
305
    BibleSyncSpeakerMap speakers;
 
306
 
 
307
    // what operational mode we're in.
 
308
    BibleSync_mode mode;
 
309
 
 
310
    // callback by which Receive induces navigation.
 
311
    BibleSync_navigate nav_func;
 
312
 
 
313
    // privacy
 
314
    string passphrase;
 
315
 
 
316
    // network access
 
317
    struct sockaddr_in server, client;
 
318
    int server_fd, client_fd;
 
319
    struct ip_mreq multicast_req;
 
320
 
 
321
    // default address discoverer, for multicast configuration.
 
322
    void InterfaceAddress();
 
323
    struct in_addr interface_addr;
 
324
 
 
325
    // unique identification.
 
326
    uuid_t uuid;
 
327
    char uuid_string[BSP_UUID_PRINT_LENGTH];    // printable
 
328
 
 
329
    // socket init and listener start, called from setMode().
 
330
    string Setup();
 
331
 
 
332
    // dispose of network access.
 
333
    void Shutdown();
 
334
 
 
335
    // real receiver.
 
336
    int ReceiveInternal();              // C++ object context.
 
337
    int InitSelectRead(char *, struct sockaddr_in *, BibleSyncMessage *);
 
338
 
 
339
    // speaker list management.
 
340
    void ageSpeakers();
 
341
    void clearSpeakers();
 
342
 
 
343
    // uuid dumper;
 
344
    void uuid_dump(uuid_t &u, char *destination);
 
345
    char uuid_dump_string[BSP_UUID_PRINT_LENGTH];
 
346
    void uuid_gen(uuid_t &u);           // differentiates linux/win32.
 
347
 
 
348
#ifdef linux
 
349
    // network self-analysis, borrowed from the net.
 
350
    int get_default_if_name(char *name, socklen_t size);
 
351
    int parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo);
 
352
    int readNlSock(int sockFd, char *bufPtr, size_t buf_size,
 
353
                   unsigned int seqNum, unsigned int pId);
 
354
#else
 
355
    // no other support routines needed for Windows/Solaris/BSD.
 
356
#endif /* linux */
 
357
 
 
358
public:
 
359
    BibleSync(string a, string v, string u);
 
360
    ~BibleSync();
 
361
 
 
362
    // operation.
 
363
    BibleSync_mode setMode(BibleSync_mode m,
 
364
                           BibleSync_navigate n = NULL,
 
365
                           string p = "");
 
366
    inline BibleSync_mode getMode(void) { return mode; };
 
367
 
 
368
    // library identification.
 
369
    inline string getVersion(void) { return BibleSync_version; };
 
370
 
 
371
    // obtain passphrase, for default choice.
 
372
    inline string getPassphrase(void) { return passphrase; };
 
373
 
 
374
    // audience receiver
 
375
    static int Receive(void *myself); // assume C context: poll from timeout.
 
376
 
 
377
    // speaker transmitter
 
378
    BibleSync_xmit_status Transmit(char message_type = BSP_SYNC,
 
379
                                   string bible  = "KJV",
 
380
                                   string ref    = "Gen.1.1",
 
381
                                   string alt    = "",
 
382
                                   string group  = "1",
 
383
                                   string domain = "BIBLE-VERSE");
 
384
 
 
385
    // set privacy using TTL 0 in personal mode.
 
386
    bool setPrivate(bool privacy);
 
387
 
 
388
    // say whether you want to hear from this speaker.
 
389
    void listenToSpeaker(bool listen, string speakerkey);
 
390
};
 
391
 
 
392
#endif // __BIBLESYNC_HH__