pax_global_header00006660000000000000000000000064132657565130014527gustar00rootroot0000000000000052 comment=588631bab353895314702abc48841d0fec310510 biblesync-1.2.0/000077500000000000000000000000001326575651300135015ustar00rootroot00000000000000biblesync-1.2.0/.gitignore000066400000000000000000000000161326575651300154660ustar00rootroot00000000000000**.swp build/ biblesync-1.2.0/AUTHORS000066400000000000000000000000201326575651300145410ustar00rootroot00000000000000Karl Kleinpaste biblesync-1.2.0/CMakeLists.txt000066400000000000000000000117431326575651300162470ustar00rootroot00000000000000# Accepted options # - BUILD_SHARED_LIBS (default FALSE) - set to true to build shared libraries # - CMAKE_INSTALL_PREFIX (default "/usr/local") - set to directory where you want libs installed # - LIBDIR (default "CMAKE_INSTALL_PREFIX/lib") - set to directory where binaries should be installed # - MANDIR (default "CMAKE_INSTALL_PREFIX/share/man/man7") - set to directory where manual pages should be installed # - INCLUDEDIR (default "CMAKE_INSTALL_PREFIX/include") - set to directory where header files should be installed # - BIBLESYNC_SOVERSION (defaults to BIBLESYNC_VERSION) - Manually set the SOVERSION of the installed file PROJECT(libbiblesync CXX) SET(BIBLESYNC_VERSION 1.2.0) # A required CMake line CMAKE_MINIMUM_REQUIRED(VERSION 2.8) # Where our custom Find* files are located SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") # Just a variable so if we expand to more files we only have to edit one place SET(biblesync_sources src/biblesync.cc) SET(biblesync_headers include/biblesync.hh "${CMAKE_CURRENT_BINARY_DIR}/include/biblesync-version.hh") # Set a library to build (the fact that it is "biblesync" and matches the name # in the PROJECT declaration above is purely a matter of choice and convention and # need not be the case. We can also add additional libraries if we wanted to have # multiple products from this build process IF(BUILD_SHARED_LIBS) ADD_LIBRARY(biblesync SHARED ${biblesync_sources}) SET(SHAREDLIB_FALSE "#") ELSE(BUILD_SHARED_LIBS) ADD_LIBRARY(biblesync STATIC ${biblesync_sources}) SET(SHAREDLIB_TRUE "#") ENDIF(BUILD_SHARED_LIBS) # Set the default headers location INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/include") INCLUDE_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/include") # System defines IF(WIN32) MESSAGE(STATUS "Building for Win32") ADD_DEFINITIONS(-DWIN32) TARGET_LINK_LIBRARIES(biblesync "ws2_32" "rpcrt4" "intl") ELSE(WIN32) # Headers and linkage from libuuid FIND_PACKAGE(UUID REQUIRED) INCLUDE_DIRECTORIES("${UUID_INCLUDE_DIRS}") TARGET_LINK_LIBRARIES(biblesync "${UUID_LIBRARIES}") ENDIF(WIN32) # Allow build systems to specify non-standard install locations IF(NOT CMAKE_INSTALL_PREFIX) SET(PREFIX "/usr/local") ELSE(NOT CMAKE_INSTALL_PREFIX) SET(PREFIX "${CMAKE_INSTALL_PREFIX}") ENDIF(NOT CMAKE_INSTALL_PREFIX) MESSAGE(STATUS "Will install to: ${PREFIX}") SET(LIBDIR "${PREFIX}/lib" CACHE STRING "Object code library install directory. Defaults to CMAKE_INSTALL_PREFIX/lib") SET(MANDIR "${PREFIX}/share/man/man7" CACHE STRING "Manual page install directory. Defaults to CMAKE_INSTALL_PREFIX/share/man/man7") SET(INCLUDEDIR "${PREFIX}/include/biblesync" CACHE STRING "Header library install directory. Defaults to CMAKE_INSTALL_PREFIX/include/biblecync") ########################################################################################## # Copied from Sword's code to handle the setting of version numbers ########################################################################################## # Post-processing of variables MACRO(PROCESS_VERSION LEVEL VALUE) SET(BIBLESYNC_VERSION_${LEVEL} ${VALUE}) IF(${VALUE} LESS 10) SET(${LEVEL} "00${VALUE}") ELSEIF(${VALUE} LESS 100) SET(${LEVEL} "0${VALUE}") ELSE() SET(${LEVEL} "${VALUE}") ENDIF() ENDMACRO() STRING(REGEX MATCHALL "^([0-9]+)\\.([0-9]+)\\.([0-9]+)\\.?([0-9]+)?$" BIBLESYNC_VERSION_PARTS "${BIBLESYNC_VERSION}") # We don't always have a nano version IF("${CMAKE_MATCH_4}" STREQUAL "") SET(CMAKE_MATCH_4 "0") ENDIF("${CMAKE_MATCH_4}" STREQUAL "") SET(BIBLESYNC_VERSION_MAJOR ${CMAKE_MATCH_1}) # No post-processing on this, so it's not octal PROCESS_VERSION("MINOR" ${CMAKE_MATCH_2}) PROCESS_VERSION("MICRO" ${CMAKE_MATCH_3}) PROCESS_VERSION("NANO" ${CMAKE_MATCH_4}) SET(BIBLESYNC_VERSION_STR "${BIBLESYNC_VERSION}") SET(BIBLESYNC_VERSION_NUM "${BIBLESYNC_VERSION_MAJOR}${MINOR}${MICRO}${NANO}") ########################################################################################## # End of copy from Sword's code ########################################################################################## # Set the SOVERSION of the package, for binary compatibility tracking INCLUDE("${CMAKE_CURRENT_SOURCE_DIR}/cmake/soversion.cmake") # Set the variables in the .in file CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/include/biblesync-version.hh.in ${CMAKE_CURRENT_BINARY_DIR}/include/biblesync-version.hh @ONLY) CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/biblesync.spec.in ${CMAKE_CURRENT_BINARY_DIR}/biblesync.spec @ONLY) CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/biblesync.pc.in ${CMAKE_CURRENT_BINARY_DIR}/biblesync.pc @ONLY) # Install both the library and its headers INSTALL(TARGETS biblesync DESTINATION "${LIBDIR}") INSTALL(FILES ${biblesync_headers} DESTINATION "${INCLUDEDIR}") INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/biblesync.pc" DESTINATION "${LIBDIR}/pkgconfig") INSTALL(FILES "${CMAKE_CURRENT_SOURCE_DIR}/man/biblesync.7" DESTINATION "${MANDIR}") biblesync-1.2.0/COPYING000066400000000000000000000007661326575651300145450ustar00rootroot00000000000000/* * BibleSync library * Karl Kleinpaste, May 2014 * * All files related to implementation of BibleSync, including program * source, READMEs, manual pages, and related similar documents, are in * the public domain. As a matter of simple decency, your social * obligations are to credit the source and to coordinate any changes you * make back to the origin repository. These obligations are non- * binding for public domain software, but they are to be seriously * handled nonetheless. */ biblesync-1.2.0/ChangeLog000066400000000000000000000007071326575651300152570ustar00rootroot000000000000002014-10-31 karl * Anti-spoof: xmit 1st beacon before presence announcement (1.1.1). * Spoof downgraded from error to mismatch. 2014-10-26 karl * Upgraded speakerkey UUID as 1st class parameter in nav_func (1.1.0). 2014-05-20 karl * Upgraded protocol for speaker beacon (1.0.2). 2014-05-11 karl * Created BibleSync library as distinct entity. biblesync-1.2.0/INSTALL000066400000000000000000000012231326575651300145300ustar00rootroot00000000000000Linux: $ mkdir -p build/linux && cd build/linux $ cmake -DBUILD_SHARED_LIBS=TRUE -DCMAKE_INSTALL_PREFIX=/usr -DLIBDIR=/usr/lib64 ../.. $ make && sudo make install Note use of /usr/lib64, which is appropriate for Fedora x86_64; perhaps use just /usr/lib instead if your system is different. Cross-compiling Win32 using MinGW: $ . win32.opts $ mkdir build/win32 && cd build/win32 $ cmake $WIN32_OPTS -DBUILD_SHARED_LIBS=TRUE ../.. $ make && sudo make install Some versions of CMake result in files being mis-installed in the system's /usr/lib instead of e.g. /usr/i686-w64-mingw32/sys-root/mingw/lib. Watch the resulting paths chosen carefully. biblesync-1.2.0/LICENSE000066400000000000000000000000541326575651300145050ustar00rootroot00000000000000There is no license. See the file COPYING. biblesync-1.2.0/README.md000066400000000000000000000032461326575651300147650ustar00rootroot00000000000000# BibleSync This is a C++ single class library encapsulating a protocol conduit. The premise is that there is a local network over which to multicast Bible navigation, and someone, possibly several someones, will transmit, and others will receive. The choices for when you decide to xmit and what to do when you recv are up to you as the application designer. Access to the conduit is by creating the object, setting the mode, calling Transmit() to xmit nav events, and arranging the frequent polling of Receive() to recv nav events. There is more than just navigation to be handled; there are live/dead events for potential Speakers as well as mismatches, presence announcements, and errors. There is a programming reference biblesync.7 which explains the details, both from a high level view of the essentials of the protocol's behavior and at a low level of how you create, access, and use the conduit class. The (single) BibleSync object should persist throughout the life of your application, but at any time you can set the mode to "disable," and preferably stop the receive polling, and then re-enable it later as the user needs. Much work has been done in integrating this library into its first application, Xiphos. It is useful to examine Xiphos' code to see where and how integration has been done. Get a Xiphos source tree using: ~~~ git clone https://github.com/crosswire/xiphos ~~~ ...and see: - `main/biblesync-glue.*` for incoming event handling and "glue" routines. - `main/sword.cc` for initialization + how xmit is handled. - `gnome2/search_dialog.c` and `gnome2/sidebar.c` for verse list xmit. - `gnome2/preferences_dialog.c` and `ui/prefs.glade` for configuration UI. biblesync-1.2.0/WIRESHARK000066400000000000000000000001461326575651300147640ustar00rootroot00000000000000use this expression to trace BibleSync. watch both net device and loopback. ip.addr == 239.225.27.227 biblesync-1.2.0/biblesync-v1.png000066400000000000000000000637571326575651300165270ustar00rootroot00000000000000PNG  IHDRgAMA asRGB cHRMz&u0`:pQ<bKGD pHYsHHFk>f}IDATxgQ/Wuz ;Ξ<(ʶer6`96pL!6lYV4f4y›:U?,i<ҽGzUU0-m@cDDx*AZ 0d@ L#!FPQ" $("23)b̜$j۶m[f>D$*J " @Z04h Q Ir3?5A8(!"(Ɇ@P<"j"&adxS%:" ,OU IB"F5dF N(@HBVR?UQ2RN T'K#E㒚`B1OFS3[an AԀC^E#x bakfшƙX'"`'קBMlnQϣ߀+1a!7 Ĺ@ !/]h[b!!kH !e%8%O9%I}D%уt lk7v Ulܲ]8+K0CRb!0F@jڀ0kw߳{01ݑ`l'o<ƛHI !)aHt:?%2K!L6?'@ӂA"x#!6ЌRϧ-¿A 6W\UnϿ;zϯ}khdU5bGdkXG!* =a2)Xshu\s̋n;]{Y'?_tV#i@ifcPaB R=JXGJQ hF\#ӾK7jm]~9g3Hc  pȄY 6b@ Bf ZA.Z BF\쬪{K7כV/wz@  iҧ JhuP4&)ٙߓ^D_gw^*8˼&HYb D3 ("T%D`q\HyѶ^l:ܯgA;&,jDʌ*Ji{$)qni"_ֿ}C3]gνHjRE Yb' 8rtLM"ˠTҴߪԣKg^̺w۞RQ콈V 1 Qp1 gj( HKB;\{&޴0y?gw͛d:6&7^R10E%H`T\DRA" LĤj`c8k8*Z(!GL复$hN@(G@(B* ( LTIȮQ"t{.ot6m,Ii8VdX}M'4YmkM12iLQH|eۑ )\WA=XחU3E,"sF1ı~ I1WEљye]ӹ^87UȦƎwз6M8sΦ}GublPJ3u2^6frMZe*cgڻ}ߡ@vTy+/ΊӉ@RԺȗU7K&[拻lxSN#_ ڣߗŠ?ϼG[כ&2&:h !JM$9t͡?C=WN-5~å;X&{=E].L.1\BJfuH\FmϦtJuq<}eivcoVrǼ~B6&'0խf&slyCw(Q4IEbW׾_\{元v"gDP ejbb1-{On%ٙ>8/ȱD@ f@RE@>]8= 04 Uc V $;ΜUNBn-2X;S]#vtZ 1ϟxgt$aqFOnF0rK[Ù[׾yiya@a0wy%ϑ{H^<z$BZ#D"BD@8=OYB,Y &jɦlwm/{y[&UVd(us ĪL@մigI>.]*͙g;|ީ=FCl^0}u=s`N@6-Woۀ1Zl7V̗Xf (B%K/~`!= NFvǝi*?}q. qbtt?Ħްe0ąPm g_al2pHxM_Y lQetS|xCqӆg\ukhAmxj~Z׬zXhTE鴗GƝ<%Mh#AGYi+:+@# U[DWUnmj5]bT}L2&+zZʍ;]WA=lS9 7v*%Z0<϶_>PtޙE 8 J$Gb̨=SDρ矧Th#KJ|%$ S"pQ#Wzm<)`Ƽaћ?7}s5~m[8=n  -p]y& #5h܍1cM$%$qiE dBF15:gWXD8&*I Mܞ篹ww??Sy'J%;jkCNP uclt_ty]g][{?S= `4z}*tg H_pfL b !Q& '4M0AF(${>@@HEb4A6"E+RH" B 5JXz d&ԑE YC$Q@@g3{151׾,^;g$eP"O;˥.ft/;wfxmոT/]E0D!1h;? wBћ]ZA›^΍xڗ_iTbZ{M~b#a)js2& L`AP %0yArP@!Q2HbdP OBd(@Hb`"`!A>Qj0E`"FD MK1@Zڦq4b"I00"A)fA p^R*e(gqK|._b̦nW< C hgؿ{L v\7rݯ||/[izl*ۉ K+vtԦ ˋ>Wols#{ƒ}w_3oĘ#"K1v?cG+2cr - B b``+,ID@šRD: nB (&!+y jQ"A Ȟ"PiAcԈNӞJ)RHDPP 3I~0448]w;ټ516T.f}7M7ER$d!4gg?{pxzXR2uMsxFo]1$P's4ڈo+w>k+;DFNOwn?|D-; (DlFpѶYπvظU것ѱѕpqe8WsYa[50ef"V I)C9!ZJolbX`$@B& LO"JDEqBDX$"L&fm!JTkimپ0s܎7vbÜNH!B3Ҋ.j]XYL)m RH)eQYvo~kMm݄EU7dNQ=˟;dً^W3xڳs+3Sȧʪ1;Tadgnol6zDDh|  tLt~עL`K!i7Ȥaa#=`ھc+ Jn$hdزXp ;j]F FD@ @ b72J1(@1T@HIr72mTs{Ll_m˺ẁ uMQ:k߈*2!(,0F%5hK]L(i%n.tj$Av"s8m߰=saUn7hx/xH"*k$?@ EEi&iXEE1S*9}tIE CW[=2Z)m-Qc9BPFe P$ #C"0#M>(Z"#6GH D!-s3غyӳΞ榶Lwg ߄j=5.}mv8\(V#WRvHE3ql/dttL 5R$DdtYڃά,?t^yM y_l#ܳ=Nǿ~AyXabL$Jt/s+56<9>Nnj;D5N=wy] ż-TickjkN2n2&ז 7[%A )D$EwY'.zn/Niֹ`fȜSCҡѡq;W/^\uP̔aW,$`":%)@ChBQwyԙ7cglڹ0;S$ bZMm`Pm`ƶmlF@<8b  4A_Fa!aB`2QPm"V(g2g,¶/]`~.X Ϭ %7a9{?Iu"9T9m0bso|t[߂ŃRH$y+.tXYV9 rTN9^C(=J0B$&>(BC(TT1YME.2X_W8h)KM,'S#D-6o>gsvغq^qfj:4^եՍWT:^XfG#jfTQF4rQU(<1s4*4 xϙLGe7Ev6iX8=j[vבzY]7?| gZ&$ωWpue4..^寽M:5ozQ?4ꝱFk ,h6M"L$s -3 ( 3""L A #2. ,Q4wuB7=w™g_yn.Rz-^Z~/N7Z BJpi`N]۷<.ٱm{'qжPt78,q(kjdݤkBACIO$sN 1@Vp+s; 6_{>ֶf.n\]\ ΍_s5?xfTGBktH0X+( 3Y60Je)]uuWwƒk:7~{mf11QX?SE@3ذ:XOnkf7;RzK/!TT 0ZWduߓӽtn7?׿|3箐xpypts,>@E$PJ UINnr3Jh-K\[g;u睵cg.hE| uwǚPJl㫚C{~R݂AW:zQ#%t"~B1Dw|ÐNUK៿r[/5׾7|{5[`6@]0DZ RJuAx]W[6|7/^ݷ8U_붙>)qjke<41YҌ6tLnH7,\2p~Ǖ{!n8>w{CEXEH2rX@eE'SJ"yGP@? ܝ۟}9tlwCBtV0A]qpjQJ!0<r8rLjwm+)(%X2cdb~Cgfshw{l}Gn۳wづ`*V@!Ԥ:q Ү]{ѕ]usb3yj7:zZ<ܬ[뚚WQ"`$"Go䓊IƕuŮ+VX5'LL,푐b ZC(ɶt,TS2<'f&d`&  2"B ;v4$Tiw|)Oy[_qek/xغs-kkE/0 כֿ_<e}3(xkܼzp؎KvV0j! " QG@LI YI"uY E$lIDN֝x7Rg~ؼy|7n*vF4iuTuf"Y(ee\0rYR]9n1kل"kKw{ ēqAp1 /%)(Frե+KZYxC}Satś_uKCGî2 ϕ x>B?[J+:~{X $J2$dDR2^2HͨY&j$ (jΪEPRyLeY"r&u9o4;;֩&9duڙ$NҾT iGtfkNwZ23=V8kk˺| tx3qS裈B,7cGd )=ɶIѐP $  L@" J%(5TUy=cƯ=SڻDۡ^1WΦ,Dnnckc Y"),"Bd %D'{ E #@ TjFMDo%(AH%  $P*Փc`dl% T22T ں{ Bptҥ\* ZH[FDB#YhA]9DA}E( C$@ rAŰr=sxIK\z4\P;ݟ;|h[۸_+5ElmqC+d{ry4;;f/A=W\ݛZ[uk5UcbA^ |ƃG86UQRD(XFW32K&)F%6 d \.gWiP ɤ~8K nz{ @$&@(@F BfI:2B@ȏGO)FDqÈpg5I@-W-$ʍ^]u\&)T",&E&zIA J0ʶszjν{<|EPD&•PD c>$lf}z?%|鴢gOr:ɄD@ɷQ*B&<A0 12ID! J38WdɅ<9x]{Ư$=#CL6#ղ*2:1_v-?OݷxtS8˫N( \[ԅ'+) Ͳ^}=*YA*5d; E^PI&b_ʈ󟸶O3stA(iP -$.^?kze_>k{1<v49BH)gCv]}kϙ= km Eǃ~ЅVL ` u<օkbb4wUnT6Bf0YeSؚ5*F.sUo99pXUE<~J$-B> N{ ΃Ȅ) O.ӽv=BceelѰ46fԌq풵wI[m]V5y*dL P8<J?rGZ-BudVN OM(,bm0ڄ`4,N}l疱#ClcRKJrtI=(2=.JE_mE0H[c]zCSPe.%IdBXN^( aun(eJ2wgE"3EJyvܚblcJ<"K5eq6Ft" FX/$M]4b;wbaӡ2mNC=J$ZJ"jm>%4])$a$gEDz (!>Z,V0H@ X@Z@qC)tރq<ɀ8. cE@t .,w aadRQv|M~Pc_ldυ~#2iA K S$OI3| ,baWnsrR*AHXg)L4BUݎG>+BXͤ cޓi[H" XD*9@R֛o7Z&Bt%]uRj7?o|ǡx֖geW^f< c & P*Fþ~־W׳/vzX[%K:Y% eS% ѭd 21Eѳ߫ecs?ck00@`Dh n=0ԇf)׌MQUг:i>ri"aPt00ə;QI* "!c;s|]X[#۹6Afeӄ OIf>eQ9uhX)T:O06fGPJmAL>2y-P ŅbyF&Rf!J F2j6XYR'R!  LKH >O!J(Y`P(Y !L@$ V{%yI NuL0qrzrGN2NޠL>W ')yr?IL|j|iz%O(yF4JQ4=MOizQeƵ4! UP[6t[::рozr/ૢurIVAFkB7eK3m oHZcS)Er6` cipQ /JL\6ILmӨ i1TUW:edۦTH|# qXgQRKYdd,PS!bZ7 !)kԣP (c LXEj3',Z dR1f6 HS.iTԪ)ML؅}J=1!M6am(Sbɸ,!хIXn֦YhmKh"@ҳQӮjd׭;6R@*ҕĦPt#OS*rզ#CbeN˲4ijC&mK65_宙#(ȒpPZ5՞麍{9@]zl},#o$3)5-(v LuCˉIvӦz'& Ehp*Y:HHZiÔdTfTȽ 1s"?=$6 Ov_t׿*<,vHe|,XHj +gL(#t31W2c\ڵc"6s[ <4Jiٺք,KwޭKN1fCS?f=ZƟ7ҵu5're;xօ)&P`)֍egV\I~ՁCʊiѨlKg97} vb{]M4 pˮ>^7xg;?[LԩZlFЛmvFYEE7[)V㱿cf;xKE-mc7in `a2m]4 !(f8d>mڎTCV :|c菅^|ON$Gh ݩImDof8-d}ZkUUL ĩ$,˯^xۛb.5Έ1z .%@'HI,8j-._yQxHUSd|;^smM)˒@ ?|$(w̋k.}x|TJ$Ah r`@J@dk?iˍHK.HwnR߹酗uiRE ~T}䣻:1C^@;|CSϾt XFp]$uD) H9A)?w?kȤBE$dd߸+frEOtUkY;.%;~?T`2J6AbZG @tkw?Is.}_avEJ ``6ֺQP ;$ m lrTڹ!Au|{;6-ZSl]s?뭎k䙧,}FIR_ f)0Z^>~3L5(ILM$zhls# $_a_?BwsaƁ]o7oxr[V~yQؼw|7 zߡ/-B Q @&Q4gaҴ7acfiaiMc>m)ikǏ>4<謞(gO" U%fZFȊ[?s٦zW(3:Kx/OJ^nFbn_R3ʨ^f8nFYߥ~ʃËk~O~o\[;1qWfNc ;$q*M18x.1 *~kb(kfYHB́+6v׌)@G饚-Up=mƶ3.q8G;º# ޸߰XOͩGHGHV^DA㚌^ߧrZpX*2mlҗDN{ába^\ѝY0(hR܏HoZA 3/ 5Q QH+.MX4$]wRxL_;?3YSPg.V­~?t^}4VO9W|AaV_?W{J$rgY;0pޏ}ב[ (F" #7XTnɨt!D" I@U`ANw?rΏ~OO,y.< @?ug_"b4Ǜl 0qcWzn `sWL` BpBHʈ&pϡT>|[L_FPynt{f Bi$ *IG|_T]o"k!1޴훿1dg# C+:0 cH^EфɓZp 5];rWsozYfueݵןPj1yxiÍ˄<ͯy5o~%7,p۶3#~MĐ2mLT:5 xhHHЇq1E A1&4l*q͜/>Or'o1g:y3>G4(vζֽAQ5Mbkכݷ|>rm;?WGx=+HU/.Mw{9 w}dWP2\"`)Táz7*o}4TID ":$a\=~:?Arz ԖtW~ắwQ R~xXTg7X$=w{edāQiYDՔNo,Xub>橞RvpΗЌ0W(XTp{ݲ׼bS'oJ Lm߹C_@ ;cU(G4 ;߭q WGٯ O F4ߜv^)c<GT{ʮC:1ghua+wh|}K?ՃOƉ Q1$ a`+L(Vy'Rl"i n"'*@)fx( i%.$@vBak3hĀrC ':N?a'F*2*BAg뇎]|qsU[a󶗥:r`x==WABbUY d9Ju D84]$c^N58g7Q_5i mYW;J(dE7g_R=MgKͯgMgWtׯם_j @&ZA ֫WzV;v\#[PSKbn/z.Qmx$D5i@Fԇbk?~ϼ{!au6#8|o?~b^: ZCI:EÍ#_fR!gN r;6%aO^$2?Iwa|s^R; TtgS(4QfW27Q `p3@( jVW_vw>~c$|hsA)kyW}u;/}}w?pIE@4gg$O},{_ϼ9BxmG|Ң>ϒty MT :pFU9X$x[f̓LI+"dn#H a؁kf6d׏mMwulˮ>oP"Hpp8W䝕ֶRWbAzTQz-A|fq8d/K.H@!9Wֵ5WE:2P$WW~{)S8I5AL!4(FJbVaЕ={? ׮BmdW Z7"($RҐu"(!-_\^OG_nht$,)0h#h@](^(J XI) %%[9cH1$ү=BZ6:NlS[]>a .})92Qv :ϵ'/SӰ^wऌ~c H }{7>{rPt MP1I,, S ]lC;4 ,Ԫz|xÑ{=lnb!"PH3*@~b +ѯCG\&@$IJFaTZ3X|u/]Y_eWq?gf5hnouͷ-? :Oh˺b6plzHp#X?D}D=--!̆7lҫp!"Fݷ[}OL%I]f @sw{6_τMs_{箫oihe8-KoiXH<™q̍SP__ JҠzBz]&[WX?ΓNT҂cNHw>u>ݦaXٵYoݶq\McdXolRtcSd=/D PH!5tsCm$|avD> РBcRR*kTvqETb4eͬ6ͳ )kLj\ϩqqJRf̗@٦P+b.&ό :8nM +pØܫ3\r~kU:EG%)&Ø밺Bdir1u3 +-"P'9`Zt*"jmD ա9J򎪅^eRDudfqE P$E,Zx!"s+9 @juȔ(ˣʵB"I(5@"1kPNrFrsCzJ 9I!mL+"2Wa!9HB{bV|7eֲa<ɓ^"Gk[rJ u*x&XR5CFOBȑA[>%-r((cE@w%$F%k j h=+qLX(N2J-NAk"/rM$',@ejߌk$P( #t|J${e4H 3:{e СTJ6Z N0`LeƑHD B vu 1ێNX@0{ZЕ±EѧXYOL>"YFdBY22@=Q`m$-%(Q!3r^&2|I9x`LUNQey$؀L%` FHaS&jHT"qd R!׽B"S̉`UH R֨GJ FA*‚D%Ddr1DDiBN %E@^Irn`kvhh+Cp4V6G[eRe*q͓;աi&"I@bUpɤ*Hs L b(!B,ŠQ)KuRiL *x#*fOVK%QX.6àP1`8DJ^uwY-U%YI|?)s:HeL=s qS54Y"4{ceughMt\ۃKu",(3P$`^g+n*P2M1Q4BDE)=EqzjVN>N|  ېB7d2I;2%^o:Q:t2[ap2l|+rLظ}YַiԺm)1iigb^BNIӦιO<<>75Ǯ.,~CΖ/z֮W_}՗x5_XV܍Zu6Ёvat慿_WU6ur_|gߵKȉ҂uήox~Oɡ9޽w}g,/ kD\r;Dt緿>/z=J)hA[_? :NҬNÇJC+}?K8 A\y֯rgε)lx}+zY:ǖ~Kgvq'9o$6/o]\rwA,DdʤPaBRlooyd * ]󋿽;D&{`X:W^zkv~gǯs[Ʒw~n`U=yns~ݝ]?dy{9x rb#RZYpfek9sʋ> YbMW W_VaZ\<Ej2XfYg,pkI踹q ?K}=s]Pk9Ɨ+Ct̬7_w];8iľe۶>6wO*DC^&QiTm'u׶FH慒zsѹf~G8Ik޽{8ՕCV _^h\%bǡN NېnTornc<\n5 2w [8EbC}@bB//7}xh/]9mZ_Ϸ?%;>cRYZ{vח?WSs# ڂN9kz`x^w{4*yA Z9ˇǷߠrlKٸ?-o*>Cbt4o:mo/}Kޏkv*AUMI}h#";uK憟B>-6fS{*!7Ʊ!NHD֚/y7{pE*3OP:yW?)1&^,)IH vT(8[ \b>? kZHaS&{89/ ^?oB3iu^_?17ә 6N"w?>Eף))}~wvw*c<L DP6/gx7^~Gnf"yD48Ads¨yby321<))IzYß:<|x3p0Q=#IzY2 yHTdPZ kEHQP+0vJhgfnAu7[C J !Ģ(:: "QiPw堜qр , ZhJ P)Kyjkc6PvҤ2Jl2~Me=;^煍'_oud؏\gozU_fu%r_n\γ/p3dBwst!'ZS\]y1*#mY/ n.v%JH6Qji6G f$qT ݷ >ƛ`,ehfoۄ@ڍ⃡)A6yFB8#2s:Bhs $@PffE`:euʸReKM7Wl=P#"ApddfctuҪxd-0d@Ns\*ұYv\̴]AJeAEׄ.)Lu"}x.92L^zA>Ogj%UYJ7S3nwMo [p[u5{ur`_U7fWԓ3kpN:-2imxs3jpp)׾zzwZPآN#B-H:$02k!*#u9@&Cyc?vw̟iq׼_"VyۂZusݰ@Sž(秣)ښ Lek;=lMiȫn#`rv欚dhib 33ꡗqcwxdGy`^k+jjaY4 Q`?Զ}O\h@^ !Š=90wtZ$9xIafTXfHRPXuM'CA:^h  7M|IDI\;)r{2#*̸J<;Z/':vb,eF>w¬`M1Ч<d21A ~ϵ?_ ^Yuys6owYW)zҚa;::"oE7_1B51:]گ+d;! 6ƿH5Z툴rtJoDes׷P!C}9͛~ls"zF*Tey9ӥTj+Qd%g+[gzEtK_.qûQ“ op/[6WKt0^Krt_zE}T$c+1ׅ>Pl69\Za^pe‹G~iHY\6u%>)ֆ2'p"ZOd|֯/>[7~)$J92)Rv=$0S&JY ¶Ik[>&bZF%P?w`FDR/Bg}A0p+7-{*Ye;z_>oz>3GSI;zcput}p Cad5K/ mW=s/)'$8uI=M+Kf-pm:JJJ-tLᎯ]>[= ^QU6dp+qY {eé5-uaU]M.=PE΍lBȆ18* m=a˸+I`Dr֖㦈L:eoƨʩU8: ԗ`3^yO-uKvqQr_{KߥuCہ1=|gBGEx" Q`Zg uf>s#]_84E->ڶIwVR| MH+ɪ Νyog?1?[>9G_ܳ\щ(k%8=5nXUjN1 jt`g?&+Ƕ{v&R3Xu!vh+ \_^PU*e@y5Gа8ZOqlz[ۻ5Ͽdxveĕ{垛^o׹OL%{n>?˯Xnqiˮo(.={䚳`!X@b$UB -{okCTƼ !Jct3&+4Ad$|4qXL/|'t6-/^.O RT5As˽0χ+ .:~ښ~:Z!!L9HʧLl13F8xMmJ"l޽sz:QC& Uߝ Lݸp/э? i8e꒕sxw>G`,^m??Ogz;ʒu#%$B hIEԦ7~>I&A1 0xZ3-+['d\eƻ.-;_|;pG PqnRId+qO]ϻjq HiLdݟ3a;`;w{_v85'cH <9n8~{s3_gCaZeZ X,W=)O.qI;N)RÕi(DDfFD"RJ !b!)eQEQ$IRx78|жx|x/!d9Rʲc2RJ" cc~m?;-b93/>qYh5+K4$NFۄ{DT$ ^C$IQ蜛0k W1 &8ẢǘYk,hUTQ`8ɐtc܄&<58"L r2 '@yN~v|+$FYJ099%B DԈYK_M-P( =1IȌIBA> si M5s'` k.O RY:1L(̂9"?bO>'71~Gu  44=>jE'y_mwP@& x $!#!':1' ̉z)ך'׎HGkN:с &ZX Z0Y3O ~*OT TI9 a2)h!50$5!UR% s9sB0`؟WJ Ш(*&֩d(BEOH7pZB(ubD p+ es,OH1pMj3/FJK"2\)IC4Rw<wQH Qczk"Op4R3%>1( (HBⱻb>CAAOE4BdK(*iPx^J2m$ ig$1A3 CNu_4Yy·q4g~d,"Iu! (ό8;66%tEXtdate:create2014-04-19T22:47:51-04:00l7%tEXtdate:modify2012-10-28T20:49:12-04:00H%tEXtjpeg:colorspace2,uU tEXtjpeg:sampling-factor1x1,1x1,1x1ptEXtxmpMM:DerivedFrom$IENDB`biblesync-1.2.0/biblesync.pc.in000066400000000000000000000005541326575651300164100ustar00rootroot00000000000000prefix=@PREFIX@ exec_prefix=@EXEC_PREFIX@ libdir=@LIBDIR@ includedir=@INCLUDEDIR@ Name: BibleSync Description: Bible software multicast co-navigation Version: @BIBLESYNC_VERSION_STR@ @SHAREDLIB_TRUE@Libs: -L${libdir} -lbiblesync @SHAREDLIB_FALSE@Libs: -L${libdir} -lbiblesync @LIBS@ Libs.private: -L${libdir} -lbiblesync @LIBS@ Cflags: -I${includedir}/bibleysnc biblesync-1.2.0/biblesync.spec.in000066400000000000000000000045341326575651300167420ustar00rootroot00000000000000Name: biblesync Version: @BIBLESYNC_VERSION@ Release: 1xi%{?dist} Summary: A Cross-platform library for sharing Bible navigation Group: System Environment/Libraries License: Public Domain URL: https://github.com/karlkleinpaste/biblesync Source0: http://downloads.sourceforge.net/gnomesword/biblesync-%{version}.tar.gz BuildRequires: intltool BuildRequires: libuuid-devel BuildRequires: cmake %description BibleSync is a multicast protocol to support Bible software shared co- navigation. It uses LAN multicast in either a personal/small team mutual navigation motif or in a classroom environment where there are Speakers plus the Audience. It provides a complete yet minimal public interface to support mode setting, setup for packet reception, transmit on local navigation, and handling of incoming packets. This library is not specific to any particular Bible software framework, completely agnostic as to structure of layers above BibleSync. %package devel Summary: Development files for %{name} Requires: %{name}%{?_isa} = %{version}-%{release} Requires: libuuid-devel%{?_isa} %description devel This package contains libraries and header files for developing applications that use %{name}. %prep %setup -q %build mkdir build pushd build %cmake -DLIBDIR=%{_libdir} .. -DCMAKE_SHARED_LINKER_FLAGS="-Wl,--as-needed" make %{?_smp_mflags} popd %install pushd build make install DESTDIR=%{buildroot} popd %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %files %doc LICENSE %{_libdir}/libbiblesync.so.%{version} %files devel %doc AUTHORS COPYING ChangeLog README WIRESHARK %{_includedir}/biblesync %{_libdir}/pkgconfig/biblesync.pc %{_libdir}/libbiblesync.so %{_mandir}/man7/biblesync.7* %changelog * Fri Oct 31 2014 Karl Kleinpaste - 1.1.1-1 - Anti-spoof improvements. * Sun Oct 26 2014 Karl Kleinpaste - 1.1.0-1 - Speakerkey becomes 1st class arg in nav_func. * Mon Aug 04 2014 Greg Hellings - 1.0.2-4 - Final import form * Sat Jul 19 2014 Greg Hellings - 1.0.2-3 - Package review feedback * Mon Jul 07 2014 Greg Hellings - 1.0.2-2 - Initial build * Thu Jun 12 2014 Karl Kleinpaste - 1.0.2-1 - Update 1.0.2 and make .spec work for the 1st time. * Sun May 11 2014 Karl Kleinpaste - 1.0.0 - Version 1.0.0 biblesync-1.2.0/cmake/000077500000000000000000000000001326575651300145615ustar00rootroot00000000000000biblesync-1.2.0/cmake/FindUUID.cmake000066400000000000000000000053121326575651300171330ustar00rootroot00000000000000# - Try to find UUID # Once done this will define # # UUID_FOUND - system has UUID # UUID_INCLUDE_DIRS - the UUID include directory # UUID_LIBRARIES - Link these to use UUID # UUID_DEFINITIONS - Compiler switches required for using UUID # # Copyright (c) 2006 Andreas Schneider # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # if (UUID_LIBRARIES AND UUID_INCLUDE_DIRS) # in cache already set(UUID_FOUND TRUE) else (UUID_LIBRARIES AND UUID_INCLUDE_DIRS) find_path(UUID_INCLUDE_DIR NAMES uuid/uuid.h PATHS ${UUID_DIR}/include $ENV{UUID_DIR}/include $ENV{UUID_DIR} ${DELTA3D_EXT_DIR}/inc $ENV{DELTA_ROOT}/ext/inc $ENV{DELTA_ROOT} ~/Library/Frameworks /Library/Frameworks /usr/local/include /usr/include /usr/include/gdal /sw/include # Fink /opt/local/include # DarwinPorts /opt/csw/include # Blastwave /opt/include [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session\ Manager\\Environment;OSG_ROOT]/include /usr/freeware/include ) find_library(UUID_LIBRARY NAMES uuid PATHS ${UUID_DIR}/lib $ENV{UUID_DIR}/lib $ENV{UUID_DIR} ${DELTA3D_EXT_DIR}/lib $ENV{DELTA_ROOT}/ext/lib $ENV{DELTA_ROOT} $ENV{OSG_ROOT}/lib ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/lib /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ) find_library(UUID_LIBRARY_DEBUG NAMES uuidd PATHS ${UUID_DIR}/lib $ENV{UUID_DIR}/lib $ENV{UUID_DIR} ${DELTA3D_EXT_DIR}/lib $ENV{DELTA_ROOT}/ext/lib $ENV{DELTA_ROOT} $ENV{OSG_ROOT}/lib ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/lib /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ) set(UUID_INCLUDE_DIRS ${UUID_INCLUDE_DIR} ) set(UUID_LIBRARIES ${UUID_LIBRARY} ) if (UUID_INCLUDE_DIRS AND UUID_LIBRARIES) set(UUID_FOUND TRUE) endif (UUID_INCLUDE_DIRS AND UUID_LIBRARIES) if (UUID_FOUND) if (NOT UUID_FIND_QUIETLY) message(STATUS "Found UUID: ${UUID_LIBRARIES}") endif (NOT UUID_FIND_QUIETLY) else (UUID_FOUND) if (UUID_FIND_REQUIRED) message(FATAL_ERROR "Could not find UUID") endif (UUID_FIND_REQUIRED) endif (UUID_FOUND) # show the UUID_INCLUDE_DIRS and UUID_LIBRARIES variables only in the advanced view mark_as_advanced(UUID_INCLUDE_DIRS UUID_LIBRARIES) endif (UUID_LIBRARIES AND UUID_INCLUDE_DIRS) biblesync-1.2.0/cmake/soversion.cmake000066400000000000000000000007111326575651300176110ustar00rootroot00000000000000IF(NOT BIBLESYNC_SOVERSION AND BUILD_SHARED_LIBS) SET(BIBLESYNC_SOVERSION ${BIBLESYNC_VERSION}) ELSE(NOT BIBLESYNC_SOVERSION AND BUILD_SHARED_LIBS) SET(BIBLESYNC_SOVERSION ${BIBLESYNC_SOVERSION}) ENDIF(NOT BIBLESYNC_SOVERSION AND BUILD_SHARED_LIBS) IF(BUILD_SHARED_LIBS) SET_TARGET_PROPERTIES(biblesync PROPERTIES SOVERSION ${BIBLESYNC_SOVERSION}) MESSAGE(STATUS "Setting SOVERSION to ${BIBLESYNC_SOVERSION}") ENDIF(BUILD_SHARED_LIBS) biblesync-1.2.0/include/000077500000000000000000000000001326575651300151245ustar00rootroot00000000000000biblesync-1.2.0/include/biblesync-version.hh.in000066400000000000000000000020451326575651300215100ustar00rootroot00000000000000/****************************************************************************** * * biblesync-version.h - version constants. * * BibleSync library * Karl Kleinpaste, May 2014 * * All files related to implementation of BibleSync, including program * source, READMEs, manual pages, and related similar documents, are in * the public domain. As a matter of simple decency, your social * obligations are to credit the source and to coordinate any changes you * make back to the origin repository. These obligations are non- * binding for public domain software, but they are to be seriously * handled nonetheless. */ #ifndef BIBLESYNC_VERSION_HH #define BIBLESYNC_VERSION_HH #define BIBLESYNC_VERSION_NUM @BIBLESYNC_VERSION_NUM@ #define BIBLESYNC_VERSION_STR "@BIBLESYNC_VERSION_STR@" #define BIBLESYNC_VERSION_MAJOR @BIBLESYNC_VERSION_MAJOR@ #define BIBLESYNC_VERSION_MINOR @BIBLESYNC_VERSION_MINOR@ #define BIBLESYNC_VERSION_MICRO @BIBLESYNC_VERSION_MICRO@ #define BIBLESYNC_VERSION_NANO @BIBLESYNC_VERSION_NANO@ #endif // BIBLESYNC_VERSION_HH biblesync-1.2.0/include/biblesync.hh000066400000000000000000000336211326575651300174240ustar00rootroot00000000000000/* * BibleSync library * biblesync.hh * * Karl Kleinpaste, May 2014 * * All files related to implementation of BibleSync, including program * source, READMEs, manual pages, and related similar documents, are in * the public domain. As a matter of simple decency, your social * obligations are to credit the source and to coordinate any changes you * make back to the origin repository. These obligations are non- * binding for public domain software, but they are to be seriously * handled nonetheless. */ #ifndef __BIBLESYNC_HH__ #define __BIBLESYNC_HH__ #include #ifndef _ #define _(x) gettext(x) #endif #include "biblesync-version.hh" // // Bible Sync Protocol. // http://biblesyncprotocol.wikispaces.com/ // // BSP provides a classroom type of arrangement, where one person // (speaker) is in charge of inducing others' (audience) Bible // software to navigate as speaker requires. The speaker only // xmits and the audience only recvs. // BSP also provides a personal mode which both xmits and recvs, where // one user works with multiple programs across several devices, // also suitable for small teams working together, such as translators. // BSP is implemented using multicast UDP with small packets in a // simple format employing a few bytes of packet control followed by a // series of newline-terminated "name=value" pairs. // // * Application interface * // // - object creation. // BibleSync *YourBibleSyncObjectPtr = new BibleSync(app, version, user); // create exactly one. // identify the application, its version, and the user. // // - mode selection. // setMode(BSP_MODE_xyz, your_void_nav_func, "passphrase"); // invoke a mode, including net.setup as needed. // xyz = { DISABLE, PERSONAL, SPEAKER, AUDIENCE }. // DISABLE kills it, shuts off network access. // PERSONAL is bidirectional. // SPEAKER xmits only. // AUDIENCE recvs only. // => empty passphrase ("") means re-use existing passphrase. // => for any active mode, the application must then start polling using // the receiver, BibleSync::Receive(), and stop polling when mode // goes to DISABLE. if Receive() is called while disabled, it will // return FALSE to indicate its polled use should stop, otherwise TRUE. // => interface for your_void_nav_func: // (char cmd, string speakerkey, // string bible, string ref, string alt, // string group, string domain, // string info, string dump) // there are 6 your_void_nav_func() use cases, identified in cmd. // non-error cases provide valid speakerkey (UUID), else it is "". // 1. 'A' (announce) // presence message in alt. dump available. // 2. 'N' (navigation) // bible, ref, alt, group, domain as arrived. // info + dump available. // 3. 'M' (mismatch) against passphrase or mode or listen status. // info == "announce" or "sync" or "beacon" (+ user @ [ipaddr]) // sync: bible, ref, alt, group, domain as arrived. // announce: presence message in alt. // also, individual elements are also available: // overload: bible ref group domain // user [ipaddr] app+ver device // dump available. // 4. 'S' (new speaker) // param overload as above. alt unused. see listenToSpeaker(). // 5. 'D' (dead speaker) // opposite of new speaker. only param is speakerkey. // 6. 'E' (error) for network errors & malformed packets. // only info + dump are useful. // // - get current mode. // BibleSync_mode getMode(). // // - get current passphrase, for default use when setting a new one. // string getPassphrase(). // // - receive navigation. // BibleSync::Receive(YourBibleSyncObjPtr); // *-* poll often *-* // see note below; calls your_void_nav_func(). // // - send navigation. // BibleSync_xmit_status retval = // Transmit("NASB", "John.3.16", "some alt ref", "1", "BIBLE-VERSE"); // params: bible, ref, alt-ref, group, domain. // all params have defaults. // => it is the application's responsibility to send well-formed verse // references. // // - set self as private // bool setPrivate(boolean); // sets outgoing TTL to zero so no one hears you off-machine. // applicable only to BSP_PERSONAL mode. // // - set beacon count based on frequency of calling Receive() // void setBeaconCount(int); // how often will your app call Receive()? // divide 10 by that, call setBeaconCount(result). // // - set new username // void setUser(string); // for apps (such as Bishop) which allow the user to set the friendly name // and which may be changed at some point whle BibleSync runs. // // - allow another speaker to drive us // void listenToSpeaker(bool listen, string speakerkey) // say yes/no to listening. // // Receive() USAGE NOTE: // the application must call BibleSync::Receive(YourBibleSyncObjPtr) // frequently. For example: // g_timeout_add(1000, // 1sec in msec. // (GSourceFunc)BibleSync::Receive, // biblesyncobj); // of type (BibleSync *). // g_timeout_add is a glib function for polled function calls. // this will induce timed-interval calls to the function, as long // as the function returns TRUE; upon returning FALSE, calls stop. // other than with glib, accomplish the same thing somehow else. // Receive is a static method accessible from C or C++. it must be // called with the pointer to your BibleSync object in order that // object context be re-entered. the internal receive routine // is private. // // Note on speaker beacons: // Protocol operates using periodic (10sec) beacons of speaker availability. // By default, PERSONAL & AUDIENCE accepts listening to 1st announced speaker, // thereafter ignores any more, but includes them in the list of available // speakers and notifies the app of their availability (see above, 'S'/'D'). // Override this behavior choice however desired, using listenToSpeaker() in // reaction to 'S' events or on user request. // Speakers who stop xmitting beacons will timeout, be declared dead, and // removed after 30sec beacon silence, with app notification ('D'). // Observe that pure Speaker clears the speaker list and by default ignores // all newly-identified claimants to speaker status. Again, this is default // behavior, but it makes no sense to try to listen to one as the mode is // a mismatch. // Note also that Personal is both speaker and audience. #include #include #include #include #include #include #include #include #include #ifndef WIN32 #include #include #include #include #include #else #define uuid_t UUID #include #include #include #endif using namespace std; typedef enum _BibleSync_mode { BSP_MODE_DISABLE, BSP_MODE_PERSONAL, BSP_MODE_SPEAKER, BSP_MODE_AUDIENCE, N_BSP_MODE } BibleSync_mode; typedef enum _BibleSync_xmit_status { BSP_XMIT_OK, BSP_XMIT_FAILED, BSP_XMIT_NO_SOCKET, BSP_XMIT_BAD_TYPE, BSP_XMIT_NO_AUDIENCE_XMIT, BSP_XMIT_RECEIVING, N_BSP_XMIT } BibleSync_xmit_status; // args: cmd, speakerkey, bible, verse, alt, group, domain, info, dump. typedef void (*BibleSync_navigate)(char, string, string, string, string, string, string, string, string); #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #ifndef min #define min(a,b) (((a) < (b)) ? (a) : (b)) #endif // message structure constants #define BSP_MULTICAST "239.225.27.227" #define BSP_PORT 22272 #define BSP_MAX_SIZE 1280 // in spec, it's 512. experimenting. #define BSP_RES_SIZE 6 // unused bytes, fill out header to 32. #define BSP_HEADER_SIZE 32 #define BSP_MAX_PAYLOAD (BSP_MAX_SIZE - BSP_HEADER_SIZE) // message indications #define BSP_MAGIC htonl(0x409CAF11) #define BSP_PROTOCOL 2 // message types #define BSP_ANNOUNCE 1 // presence announcement. #define BSP_SYNC 2 // navigation synchronization. #define BSP_BEACON 3 // speaker availability beacon. // beacon packet is identical to presence announcement except for type. // beacon constants #define BSP_BEACON_COUNT 10 // xmit every N calls of Receive(). #define BSP_BEACON_MULTIPLIER 3 // multiplier for aging to death. // message content names. #define BSP_APP_NAME "app.name" // req'd #define BSP_APP_VERSION "app.version" // opt #define BSP_APP_INSTANCE_UUID "app.inst.uuid" // req'd #define BSP_APP_OS "app.os" // opt #define BSP_APP_DEVICE "app.device" // opt #define BSP_APP_USER "app.user" // req'd #define BSP_MSG_SYNC_DOMAIN "msg.sync.domain" // req'd #define BSP_MSG_SYNC_VERSE "msg.sync.verse" // req'd #define BSP_MSG_SYNC_ALTVERSE "msg.sync.altVerse" // opt #define BSP_MSG_SYNC_BIBLEABBREV "msg.sync.bibleAbbrev" // req'd #define BSP_MSG_SYNC_GROUP "msg.sync.group" // req'd #define BSP_MSG_PASSPHRASE "msg.sync.passPhrase" // req'd // required number of fields to send (out) or verify (in). #define BSP_FIELDS_RECV_ANNOUNCE 4 #define BSP_FIELDS_RECV_SYNC 8 #define BSP_FIELDS_XMIT_ANNOUNCE 7 #define BSP_FIELDS_XMIT_SYNC 12 #ifdef linux # define BSP_OS "Linux" #else # ifdef WIN32 # define BSP_OS "Windows" # else # define BSP_OS "UNIX" # endif #endif #define BSP_UUID_PRINT_LENGTH 37 // actually 36, plus '\0'. class BibleSync { private: // simple name/value pairs. typedef std::map < string, string > BibleSyncContent; typedef struct _BibleSyncMessage { uint32_t magic; uint8_t version; uint8_t msg_type; uint16_t num_packets; uint16_t index_packet; uint8_t reserved[BSP_RES_SIZE]; uuid_t uuid; char body[BSP_MAX_PAYLOAD+1]; // +1 for stuffing '\0'. } BibleSyncMessage; typedef struct _BibleSyncSpeaker { bool listen; // nav for this guy? uint8_t countdown; // lifetime aging. string addr; // for spoof check. } BibleSyncSpeaker; // key string is origin uuid. typedef std::map < string, BibleSyncSpeaker > BibleSyncSpeakerMap; typedef BibleSyncSpeakerMap::iterator BibleSyncSpeakerMapIterator; // self identification. string BibleSync_version; // application identifiers. string application; string version; string user; string device; // currently processing received navigation. // prevents use of Transmit. bool receiving; // when xmit-capable, we xmit BSP_BEACON every N calls of Receive(). uint8_t beacon_countdown; // progress toward our next beacon xmit uint8_t beacon_count; // how many Receive() calls between beacon xmits // track currently-known speaker set. BibleSyncSpeakerMap speakers; // what operational mode we're in. BibleSync_mode mode; // callback by which Receive induces navigation. BibleSync_navigate nav_func; // privacy string passphrase; // network access struct sockaddr_in server, client; int server_fd, client_fd; struct ip_mreq multicast_req; // default address discoverer, for multicast configuration. void InterfaceAddress(); struct in_addr interface_addr; // unique identification. uuid_t uuid; char uuid_string[BSP_UUID_PRINT_LENGTH]; // printable // socket init and listener start, called from setMode(). string Setup(); // dispose of network access. void Shutdown(); // real receiver. int ReceiveInternal(); // C++ object context. int InitSelectRead(char *, struct sockaddr_in *, BibleSyncMessage *); // real transmitter. BibleSync_xmit_status TransmitInternal(char message_type = BSP_SYNC, string bible = "KJV", string ref = "Gen.1.1", string alt = "", string group = "1", string domain = "BIBLE-VERSE"); // speaker list management. void ageSpeakers(); void clearSpeakers(); // uuid dumper; void uuid_dump(uuid_t &u, char *destination); char uuid_dump_string[BSP_UUID_PRINT_LENGTH]; void uuid_gen(uuid_t &u); // differentiates linux/win32. #ifdef linux // network self-analysis, borrowed from the net. int get_default_if_name(char *name, socklen_t size); int parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo); int readNlSock(int sockFd, char *bufPtr, size_t buf_size, unsigned int seqNum, unsigned int pId); #else // no other support routines needed for Windows/Solaris/BSD. #endif /* linux */ public: BibleSync(string a, string v, string u); ~BibleSync(); // operation. BibleSync_mode setMode(BibleSync_mode m, BibleSync_navigate n = NULL, string p = ""); inline BibleSync_mode getMode(void) { return mode; }; // library identification. inline string getVersion(void) { return BibleSync_version; }; // obtain passphrase, for default choice. inline string getPassphrase(void) { return passphrase; }; // audience receiver static int Receive(void *myself); // assume C context: poll from timeout. // speaker transmitter // public interface permits only BSP_SYNC transmission. // there is no reason for an app to send presence or beacon on its own. inline BibleSync_xmit_status Transmit(string bible = "KJV", string ref = "Gen.1.1", string alt = "", string group = "1", string domain = "BIBLE-VERSE") { return TransmitInternal(BSP_SYNC, bible, ref, alt, group, domain); } // set privacy using TTL 0 in personal mode. bool setPrivate(bool privacy); // say whether you want to hear from this speaker. void listenToSpeaker(bool listen, string speakerkey); // Speaker beacon must go out roughly every 10 seconds, // set count to approx divisor. how often does your app call Receive()? // every second, default 10. // every 2 seconds, use 5. // every 3 seconds, use 3 (9 seconds, fine). // value is force-bounded [3..10]. inline void setBeaconCount(uint8_t count) { if (count > 10) count = 10; if (count < 3) count = 3; beacon_count = count; } // set new user name // useful for apps that can change the name on the fly (e.g. Bishop). inline void setUser(string u) { user = u; } }; #endif // __BIBLESYNC_HH__ biblesync-1.2.0/man/000077500000000000000000000000001326575651300142545ustar00rootroot00000000000000biblesync-1.2.0/man/.nroff.cmd000077500000000000000000000001751326575651300161370ustar00rootroot00000000000000#!/bin/sh -x nroff -ms specification.n | sed -e 's/‐/-/g' -e 's/^/ /' -e 's/^ $//' -e 's/$/\r/' > specification2.txt biblesync-1.2.0/man/biblesync.7000066400000000000000000000352571326575651300163320ustar00rootroot00000000000000.\" BibleSync library .\" Karl Kleinpaste, May 2014 .\" .\" All files related to implementation of BibleSync, including program .\" source, READMEs, manual pages, and related similar documents, are in .\" the public domain. As a matter of simple decency, your social .\" obligations are to credit the source and to coordinate any changes you .\" make back to the origin repository. These obligations are non- .\" binding for public domain software, but they are to be seriously .\" handled nonetheless. .TH BIBLESYNC 7 2014-10-31 "Linux" "Linux Programmer's Manual" .SH NAME biblesync \- multicast navigation synchronization in Bible programs .SH SYNOPSIS .nf .B #include .sp .BI "typedef enum" _BibleSync_mode " {" .br .BI " " BSP_MODE_DISABLE "," .br .BI " " BSP_MODE_PERSONAL "," .br .BI " " BSP_MODE_SPEAKER "," .br .BI " " BSP_MODE_AUDIENCE "," .br .BI " " N_BSP_MODE .br .BI "} BibleSync_mode;" .sp .BI "typedef enum" _BibleSync_xmit_status " {" .br .BI " " BSP_XMIT_OK "," .br .BI " " BSP_XMIT_FAILED "," .br .BI " " BSP_XMIT_NO_SOCKET "," .br .BI " " BSP_XMIT_BAD_TYPE "," .br .BI " " BSP_XMIT_NO_AUDIENCE_XMIT "," .br .BI " " BSP_XMIT_RECEIVING "," .br .BI " " N_BSP_XMIT .br .BI "} BibleSync_xmit_status;" .sp .BI "#define BSP_ANNOUNCE 1" .br .BI "#define BSP_SYNC 2" .br .BI "#define BSP_BEACON 3" .sp .BI "typedef void (*BibleSync_navigate)(char " cmd ", string " speakerkey "," .br .BI " string " bible ", string " ref ", string " alt "," .br .BI " string " group ", string " domain "," .br .BI " string " info ", string " dump ");" .sp Public interface: .sp .BI "BibleSync *object = new BibleSync(string " application "," .br .BI " string " version "," .br .BI " string " user ");" .sp .BI "BibleSync_mode BibleSync::setMode(BibleSync_mode " mode "," .br .BI " BibleSync_navigate *" nav_func "," .br .BI " string " passPhrase ");" .br .BI "BibleSync_mode BibleSync::getMode(void);" .br .BI "string BibleSync::getVersion(void);" .br .BI "string BibleSync::getPassphrase(void);" .br .BI "BibleSync_xmit_status BibleSync::Transmit(string " bible ", string " ref ", string " alt "," .br .BI " string " group ", string " domain ");" .br .BI "static int BibleSync::Receive(void *" object ");" .br .BI "bool BibleSync::setPrivate(bool " privacy ");" .br .BI "void BibleSync::setBeaconCount(uint8_t " count ");" .br .BI "void BibleSync::listenToSpeaker(bool " listen ", string " speakerkey ");" .fi .SH DESCRIPTION .I BibleSync is a published protocol specification by which cooperating Bible programs navigate together. It is implemented as a C++ class providing a small, clean interface including basic setup, take-down, transmit, polled receive, and a bare few utility methods. The value of .I BibleSync is found in several examples: A single user may have multiple programs, or multiple computers/devices, all of which he wishes to follow along together. Similarly, a group of people working closely together, such as translators, can stay together as they work. In an instructional motif, .I BibleSync takes either the active or passive mode, providing for a unidirectional navigation control. .SH BIBLESYNC ESSENTIALS .I BibleSync communicates using local multicast. Three operational modes are provided: Personal, Speaker, or Audience. In Personal mode, BibleSync operates as a peer among peers, both sending and receiving navigation synchronization on the shared local multicast network. Applications are expected to respond appropriately to navigation, and to send synchronization events of their own as the user moves about his Bible. In Speaker or Audience mode, .I BibleSync either transmits only (Speaker) or receives only (Audience) navigation. The Audience is expected to follow along with the Speaker's direction. The Speaker ignores incoming navigation; the Audience transmits no navigation. The difference between Personal and Speaker/Audience is thus strictly as to whether both sides of the conversation are active for each participant. On startup of the protocol, BibleSync transmits a presence announcement, informing other communication partners of the application's participation. .I BibleSync makes this announcement available to the application; whether the application shows these announcements to the user is the application designer's choice. Thereafter, as appropriate to the operational mode selected, BibleSync is tasked with polled reception of incoming navigation event packets and transmission of navigation event packets on the user's part. Transmitters (Personal and Speaker modes) issue availability beacons every 10 seconds. Received beacons for previously-unknown Speakers are handed up to the application. These beacons provide for receivers (Personal and Audience modes) to maintain a managed list of available Speakers. Furthermore, when a transmitter ceases to issue beacons, its presence in the list of available Speakers is aged out until being removed after 30 seconds of beacon silence. The application is again informed when a Speaker goes dead. Default listening behavior is that the first Speaker heard via beacon is marked for listening. Other transmitters claiming Speaker status via beacon are initially ignored, but their presence is made known to the application. This provides for the application to maintain a list from which the user can select Speakers he wishes to synchronize his application. It is useful for the application to provide blanket "listen to all" and "listen to none" functions, as well as per-Speaker selections, informing .I BibleSync of these choices. In any case, this default "first Speaker only" policy can be overridden by the application with any other policy desired, through the use of .BI listenToSpeaker() as the application designer requires. Synchronization events include 5 data elements: The Bible abbreviation; the verse reference; an alternate reference (if desired; not required) which may allow the application to interpret better based on variant versification; a synchronization group identifier; and the domain. The group identifier is a single digit between 1 and 9. The specification is imprecise as to this parameter's use. The initial implementation of .I BibleSync in .I Xiphos uses the synchronization group as an indicator of the tab number in its tabbed interface: Not only is the Bible navigated, but the tab in which to navigate is selected. The domain parameter is currently fixed as "BIBLE-VERSE". This will be put to greater use in future revisions of the protocol. .I BibleSync transmits no packet when the application leaves the conversation. Only the 3 packet types BSP_ANNOUNCE, BSP_SYNC, and BSP_BEACON are defined in the protocol. .SH PUBLIC INTERFACE .SS Object creation The application must create a single BibleSync object, identifying the application's name, its version, and the user. .SS setMode setMode identifies how .I BibleSync should behave. The application must provide as well the navigation callback function by which .I BibleSync will inform the application of incoming events; the callback makes all the navigation parameters provided in event packets available to the application. setMode returns the resulting mode. The application provides the passphrase to be used as well; this argument defaults to "" (empty string), indicating that the existing passphrase should be left in place. .SS getMode The application may request the current mode. .SS getVersion The version string of the library itself is returned. .SS getPassphrase Intended for use when preparing to enter any active mode, the application may request the current passphrase, so as to provide a default. .SS Transmit The protocol requires all the indicated parameters, but all have defaults in .BI Transmit: KJV, Gen.1.1, empty alternate, 1, and BIBLE-VERSE. .SS Receive This is a static method accessible from either C or C++. It must be called with the object pointer so as to re-enter object context for the private internal receiver. .BI Receive() must be called regularly (i.e. polled) as long as it continues to return TRUE. When it returns FALSE, it means that the mode has changed to BSP_MODE_DISABLE, and the scheduled polling should stop. See also the note below on polled reception. .SS setPrivate In the circumstance where the user has multiple programs running on a single computer and does not want his navigation broadcast outside that single system, when in Personal mode, the application may also request privacy. The effect is to set multicast TTL to zero, meaning that packets will not go out on the wire. .SS setBeaconCount Beacon transmission occurs during every Nth call to Receive(); the default value is 10. This presumes the application will call Receive() once per second. If the application will call Receive() less frequently, divide that time (say, 2 seconds) into 10 to get a value (5) to use with this call. Use setBeaconCount() prior to enabling Personal or Speaker mode. .SS listenToSpeaker Aside from default listen behavior detailed above, the application specifically asks to listen or not to listen to specific Speakers. The key is as provided during the notification of a new Speaker. .SH RECEIVE USE CASES There are 6 values for the .I cmd parameter of the .I nav_func. In all cases, the .I dump parameter provides the raw content of an arriving packet. .SS 'A' Announce. A general presence message is in .I alt, and the individual elements are also available, as overloaded use of the parameters: .I bible contains the user; .I ref contains the IP address; .I group contains the application name and version; and .I domain contains the device identification. .SS 'N' Navigation. The .I bible, ref, alt, group, and .I domain parameters are presented as they arrived. .I info and .I dump are also available. .SS 'S' Speaker's initial recognition from beacon receipt. Overloaded parameters are available as for presence announcements. .SS 'D' Dead Speaker. .I speakerkey holds the UUID key of a previously-identified application which is no longer a candidate for listening. .SS 'M' Mismatch. The incoming event packet is mismatched, either against the current passphrase or for a navigation synchronization packet when .I BibleSync is in Speaker mode. The .I info parameter begins with either "announce" or "sync", plus the user and IP address from whom the packet came. As well, in the sync case, the regular .I bible, ref, alt, group, and .I domain parameters are available. In the announce case, the presence message is in .I alt, with overloaded individual parameters as previously described. .SS 'E' Error. This indicates network errors and malformed packets. The application's .I nav_func is provided only the .I info and .I dump parameters. .SH NOTES .SS Polled reception The application must provide a means by which to poll regularly for incoming packets. In .I Xiphos, which is built on GTK and GLib, this is readily provided by mechanisms like g_timeout_add(), which sets a regular interval call of the indicated function. GLib will re-schedule the call as long as the called function returns TRUE. When it returns FALSE, GLib un-schedules the call. .BI Receive() adheres to this straightforward convention. Therefore, it is imperative that every time the application moves from disabled to any non-disabled mode, Receive is again scheduled for polled use. A 1-second poll interval is expected. Brief experience during development has shown that longer intervals lead to a perception of lag. During every .BI Receive() call, all waiting packets are processed. .SS No datalink security .I BibleSync is a protocol defined for a friendly environment. It offers no security in its current specification, and any packet sniffer such as wireshark(1) or tcpdump(8) can see the entire conversation. The specification makes passing reference to future encryption, but at this time none is implemented. .SS Managed Speaker lists The addition of transmitter beacons was a result of initial experience showing that it can be too easy for a user to mis-start BibleSync, or for a malicious user to interject himself into serious work. The goal of beacons is to provide a means by which, on the one hand, the user can be made aware of who is attempting to be a Speaker and, on the other hand, confine the set of Speakers whom the user will permit to make synchronization changes in the application. The simplest use of 'S' new Speaker notification events is to respond with .BI "listenToSpeaker(" true ", " speakerkey ")" which in effect makes .I BibleSync behave as though there are no beacons. More serious use of 'S'/'D' is for the application to manage its own sense of available Speakers, providing a means by which the user can make sensible selections about how to react to each Speaker's presence. .I BibleSync can be told to listen to legitimate Speakers, and to ignore interlopers, whether intended maliciously or merely due to other users' inadvertent behavior. .SS Sending verse lists One of the better uses of .I BibleSync is in sharing verse lists. Consider a relatively weak application, perhaps on a mobile device, and a desktop-based application with strong search capability. Run searches on the desktop, and send the result via .I BibleSync to the mobile app. The .I ref parameter is not confined to a single reference. In normal citation syntax, the verse reference may consist of semicolon-separated references, comma-separated verses, and hyphen-separated ranges. Be aware that the specification has a relatively short limit on packet size, so that at most a few dozen references will be sent. .SS Standard reference syntax It is the responsibility of the application to transmit references in standard format. .I BibleSync neither validates nor converts the application's incoming .I bible, ref, and .I alt parameters. The specification references the BibleRef and OSIS specifications. .SH SEE ALSO http://biblesyncprotocol.wikispaces.com (user "General_Public", password "password"), http://semanticbible.com/bibleref/bibleref-specification.html, .BR socket(2), .BR setsockopt(2), .BR select(2), .BR recvfrom(2), .BR sendto(2), and .BR ip(7), especially sections on .I IP_ADD_MEMBERSHIP, .I IP_MULTICAST_IF, .I IP_MULTICAST_LOOP, and .I IP_MULTICAST_TTL. biblesync-1.2.0/man/biblesync.7.txt000066400000000000000000000363641326575651300171500ustar00rootroot00000000000000BIBLESYNC(7) Linux Programmer's Manual BIBLESYNC(7) NAME biblesync - multicast navigation synchronization in Bible programs SYNOPSIS #include typedef enum_BibleSync_mode { BSP_MODE_DISABLE, BSP_MODE_PERSONAL, BSP_MODE_SPEAKER, BSP_MODE_AUDIENCE, N_BSP_MODE } BibleSync_mode; typedef enum_BibleSync_xmit_status { BSP_XMIT_OK, BSP_XMIT_FAILED, BSP_XMIT_NO_SOCKET, BSP_XMIT_BAD_TYPE, BSP_XMIT_NO_AUDIENCE_XMIT, BSP_XMIT_RECEIVING, N_BSP_XMIT } BibleSync_xmit_status; #define BSP_ANNOUNCE 1 #define BSP_SYNC 2 #define BSP_BEACON 3 typedef void (*BibleSync_navigate)(char cmd, string speakerkey, string bible, string ref, string alt, string group, string domain, string info, string dump); Public interface: BibleSync *object = new BibleSync(string application, string version, string user); BibleSync_mode BibleSync::setMode(BibleSync_mode mode, BibleSync_navigate *nav_func, string passPhrase); BibleSync_mode BibleSync::getMode(void); string BibleSync::getVersion(void); string BibleSync::getPassphrase(void); BibleSync_xmit_status BibleSync::Transmit(string bible, string ref, string alt, string group, string domain); static int BibleSync::Receive(void *object); bool BibleSync::setPrivate(bool privacy); void BibleSync::listenToSpeaker(bool listen, string speakerkey); DESCRIPTION BibleSync is a published protocol specification by which cooperating Bible programs navigate together. It is implemented as a C++ class providing a small, clean interface including basic setup, take-down, transmit, polled receive, and a bare few utility methods. The value of BibleSync is found in several examples: A single user may have multiple programs, or multiple comput- ers/devices, all of which he wishes to follow along together. Similarly, a group of people working closely together, such as transla- tors, can stay together as they work. In an instructional motif, BibleSync takes either the active or passive mode, providing for a unidirectional navigation control. BIBLESYNC ESSENTIALS BibleSync communicates using local multicast. Three operational modes are provided: Personal, Speaker, or Audience. In Personal mode, BibleSync operates as a peer among peers, both send- ing and receiving navigation synchronization on the shared local multi- cast network. Applications are expected to respond appropriately to navigation, and to send synchronization events of their own as the user moves about his Bible. In Speaker or Audience mode, BibleSync either transmits only (Speaker) or receives only (Audience) navigation. The Audience is expected to follow along with the Speaker's direction. The Speaker ignores incom- ing navigation; the Audience transmits no navigation. The difference between Personal and Speaker/Audience is thus strictly as to whether both sides of the conversation are active for each par- ticipant. On startup of the protocol, BibleSync transmits a presence announce- ment, informing other communication partners of the application's par- ticipation. BibleSync makes this announcement available to the appli- cation; whether the application shows these announcements to the user is the application designer's choice. Thereafter, as appropriate to the operational mode selected, BibleSync is tasked with polled reception of incoming navigation event packets and transmission of navigation event packets on the user's part. Transmitters (Personal and Speaker modes) issue availability beacons every 10 seconds. Received beacons for previously-unknown Speakers are handed up to the application. These beacons provide for receivers (Personal and Audience modes) to maintain a managed list of available Speakers. Furthermore, when a transmitter ceases to issue beacons, its presence in the list of available Speakers is aged out until being removed after 30 seconds of beacon silence. The application is again informed when a Speaker goes dead. Default listening behavior is that the first Speaker heard via beacon is marked for listening. Other transmitters claiming Speaker status via beacon are initially ignored, but their presence is made known to the application. This provides for the application to maintain a list from which the user can select Speakers he wishes to synchronize his application. It is useful for the application to provide blanket "lis- ten to all" and "listen to none" functions, as well as per-Speaker selections, informing BibleSync of these choices. In any case, this default "first Speaker only" policy can be overridden by the applica- tion with any other policy desired, through the use of listenToS- peaker() as the application designer requires. Synchronization events include 5 data elements: The Bible abbreviation; the verse reference; an alternate reference (if desired; not required) which may allow the application to interpret better based on variant versification; a synchronization group identifier; and the domain. The group identifier is a single digit between 1 and 9. The specifica- tion is imprecise as to this parameter's use. The initial implementa- tion of BibleSync in Xiphos uses the synchronization group as an indi- cator of the tab number in its tabbed interface: Not only is the Bible navigated, but the tab in which to navigate is selected. The domain parameter is currently fixed as "BIBLE-VERSE". This will be put to greater use in future revisions of the protocol. BibleSync transmits no packet when the application leaves the conversa- tion. Only the 3 packet types BSP_ANNOUNCE, BSP_SYNC, and BSP_BEACON are defined in the protocol. PUBLIC INTERFACE Object creation The application must create a single BibleSync object, identifying the application's name, its version, and the user. setMode setMode identifies how BibleSync should behave. The application must provide as well the navigation callback function by which BibleSync will inform the application of incoming events; the callback makes all the navigation parameters provided in event packets available to the application. setMode returns the resulting mode. The application pro- vides the passphrase to be used as well; this argument defaults to "" (empty string), indicating that the existing passphrase should be left in place. getMode The application may request the current mode. getVersion The version string of the library itself is returned. getPassphrase Intended for use when preparing to enter any active mode, the applica- tion may request the current passphrase, so as to provide a default. Transmit The protocol requires all the indicated parameters, but all have defaults in Transmit: KJV, Gen.1.1, empty alternate, 1, and BIBLE-VERSE. Receive This is a static method accessible from either C or C++. It must be called with the object pointer so as to re-enter object context for the private internal receiver. Receive() must be called regularly (i.e. polled) as long as it continues to return TRUE. When it returns FALSE, it means that the mode has changed to BSP_MODE_DISABLE, and the sched- uled polling should stop. See also the note below on polled reception. setPrivate In the circumstance where the user has multiple programs running on a single computer and does not want his navigation broadcast outside that single system, when in Personal mode, the application may also request privacy. The effect is to set multicast TTL to zero, meaning that packets will not go out on the wire. setBeaconCount Beacon transmission occurs during every Nth call to Receive(); the default value is 10. This presumes the application will call Receive() once per second. If the application will call Receive() less frequently, divide that time (say, 2 seconds) into 10 to get a value (5) to use with this call. Use setBeaconCount() prior to enabling Personal or Speaker mode. listenToSpeaker Aside from default listen behavior detailed above, the application specifically asks to listen or not to listen to specific Speakers. The key is as provided during the notification of a new Speaker. RECEIVE USE CASES There are 6 values for the cmd parameter of the nav_func. In all cases, the dump parameter provides the raw content of an arriving packet. 'A' Announce. A general presence message is in alt, and the individual elements are also available, as overloaded use of the parameters: bible contains the user; ref contains the IP address; group contains the application name and version; and domain contains the device identifi- cation. 'N' Navigation. The bible, ref, alt, group, and domain parameters are pre- sented as they arrived. info and dump are also available. 'S' Speaker's initial recognition from beacon receipt. Overloaded parame- ters are available as for presence announcements. 'D' Dead Speaker. speakerkey holds the UUID key of a previously-identified application which is no longer a candidate for listening. 'M' Mismatch. The incoming event packet is mismatched, either against the current passphrase or for a navigation synchronization packet when BibleSync is in Speaker mode. The info parameter begins with either "announce" or "sync", plus the user and IP address from whom the packet came. As well, in the sync case, the regular bible, ref, alt, group, and domain parameters are available. In the announce case, the pres- ence message is in alt, with overloaded individual parameters as previ- ously described. 'E' Error. This indicates network errors and malformed packets. The application's nav_func is provided only the info and dump parameters. NOTES Polled reception The application must provide a means by which to poll regularly for incoming packets. In Xiphos, which is built on GTK and GLib, this is readily provided by mechanisms like g_timeout_add(), which sets a regu- lar interval call of the indicated function. GLib will re-schedule the call as long as the called function returns TRUE. When it returns FALSE, GLib un-schedules the call. Receive() adheres to this straight- forward convention. Therefore, it is imperative that every time the application moves from disabled to any non-disabled mode, Receive is again scheduled for polled use. A 1-second poll interval is expected. Brief experience during develop- ment has shown that longer intervals lead to a perception of lag. During every Receive() call, all waiting packets are processed. No datalink security BibleSync is a protocol defined for a friendly environment. It offers no security in its current specification, and any packet sniffer such as wireshark(1) or tcpdump(8) can see the entire conversation. The specification makes passing reference to future encryption, but at this time none is implemented. Managed Speaker lists The addition of transmitter beacons was a result of initial experience showing that it can be too easy for a user to mis-start BibleSync, or for a malicious user to interject himself into serious work. The goal of beacons is to provide a means by which, on the one hand, the user can be made aware of who is attempting to be a Speaker and, on the other hand, confine the set of Speakers whom the user will permit to make synchronization changes in the application. The simplest use of 'S' new Speaker notification events is to respond with listenToS- peaker(true, speakerkey) which in effect makes BibleSync behave as though there are no beacons. More serious use of 'S'/'D' is for the application to manage its own sense of available Speakers, providing a means by which the user can make sensible selections about how to react to each Speaker's presence. BibleSync can be told to listen to legiti- mate Speakers, and to ignore interlopers, whether intended maliciously or merely due to other users' inadvertent behavior. Sending verse lists One of the better uses of BibleSync is in sharing verse lists. Con- sider a relatively weak application, perhaps on a mobile device, and a desktop-based application with strong search capability. Run searches on the desktop, and send the result via BibleSync to the mobile app. The ref parameter is not confined to a single reference. In normal citation syntax, the verse reference may consist of semicolon-separated references, comma-separated verses, and hyphen-separated ranges. Be aware that the specification has a relatively short limit on packet size, so that at most a few dozen references will be sent. Standard reference syntax It is the responsibility of the application to transmit references in standard format. BibleSync neither validates nor converts the applica- tion's incoming bible, ref, and alt parameters. The specification ref- erences the BibleRef and OSIS specifications. SEE ALSO http://biblesyncprotocol.wikispaces.com (user "General_Public", pass- word "password"), http://semanticbible.com/bibleref/bibleref-specifica- tion.html, socket(2), setsockopt(2), select(2), recvfrom(2), sendto(2), and ip(7), especially sections on IP_ADD_MEMBERSHIP, IP_MULTICAST_IF, IP_MULTICAST_LOOP, and IP_MULTICAST_TTL. Linux 2018-04-10 BIBLESYNC(7) biblesync-1.2.0/man/specification.n000066400000000000000000000326341326575651300172630ustar00rootroot00000000000000.pl 10.0i .po 0 .ll 7.2i .lt 7.2i .nr LL 7.2i .nr LT 7.2i .ds LF Stergiou et al .ds RF [Page %] .ds CF .ds LH RFC -BSP- .ds RH 15 June 2014 .ds CH BibleSync Protocol - DRAFT .hy 0 .ad l .in 0 Network Working Group C. Stergiou et al Request for Comments: -BSP- BibleSync WG 15 June 2014 .ce A Standard for Synchronized Co-Navigation of Bible Programs .ti 0 Status of this Memo .fi .in 3 This memo describes a protocol by which cooperating Bible programs with LAN access use multicast navigation packets to share navigation of programs. This is a standard recommended for interoperation in any network-aware Bible program. Distribution of this memo is unlimited. .ti 0 Overview and Rationale Use of multiple Bible applications is common and requires repeated operations in order to remain synchronized among the applications used. Scenarios for this use include a single user working with more than one application, possibly on more than one computer; a small group working together; or a classroom environment where a set of speakers has an audience who follow the speakers' direction. BibleSync provides a means by which network-aware applications can provide navigation packets when the user moves his Bible to a new reference, and receive navigation packets from other users. The protocol sends reference indicators, not content. .ti 0 Operational Modes BibleSync defines three modes: Personal, Speaker, and Audience. In Personal mode, the application both sends and listens to navigation. In Speaker mode, the application sends but does not listen, and conversely in Audience mode, the application listens but does not send. Speaker and Audience modes are each in effect half of Personal mode. .ti 0 Network Addressing Multicast address 239.225.27.227 is used with UDP port 22272. Typical TTL of 1, default in most systems, is used in the normal case. In the special case of strictly personal usage by one user with more than one application on a single host, a privacy mode is available by setting multicast TTL to 0, so the user's entirely internal navigation is not also heard over the wire. .ti 0 Packet Structure Payload maximum length is 1280 bytes. Within this, the first 32 bytes are a header identifying the sender's protocol version, message type, and UUID, and the remaining space consists of name/value pairs, within which a number of the names are required for each of the defined message types. In C++, the complete structure is represented below, with field details following: typedef struct { uint32_t magic; // 4 bytes uint8_t version; // 1 byte uint8_t msg_type; // 1 byte uint16_t num_packets; // 2 bytes uint16_t index_packet; // 2 bytes uint8_t reserved[6]; // 6 bytes uuid_t uuid; // 16 bytes char body[1248]; } BibleSyncMessage; The magic value is 0x409CAF11, by which to determine that a packet is intended for BibleSync. The protocol version is 2. Three message types are defined: 1 = presence announcement, 2 = navigation synchronization, 3 = speaker availability beacon. Currently BibleSync is specified as a single packet protocol, but the number of packets and packet index fields are included for possible future expansion. At this time, number of packets must be 1 and packet index must be 0. The application provides a UUID (see RFC 4122). The UUID is consistent through the life of the application, i.e., it is generated once when BibleSync first begins to be used, and that value is not re-generated as long as the application runs. Six bytes are reserved for possible future definition. Packet maximum size (1.25 Kbytes) was chosen on the basis of staying within one MSS on a typical Ethernet. .ti 0 Packet Type Overview The presence packet announces the application's participation in the conversation. It is non-essential, but useful if the application designer chooses to make it visible to the user. The navigation packet specifies a Bible name and a reference. It may also contain an alternate reference to provide a second means of interpretation so that e.g. differing Bible versifications might be accommodated. An application sends navigation synchronization when the user navigates the application to a new reference point. A listening application receives the reference information and navigates there without needing user interaction. The speaker beacon packet is identical to the presence announcement except for having message type 3, and is sent by transmitting applications every 10 seconds. .ti 0 Speaker Beacons An exclusion mechanism was deemed necessary during early experimentation with the first implementation that provided only presence announcement and navigation synchronization. It was found to be too easy for a confused or malicious user to mis-start BibleSync in his application in Personal or Speaker mode and thereby to navigate other users' applications inappropriately, because all claims to speaker status were implicitly accepted by the mere arrival of navigation packets. Beacons provide this exclusion, by which senders (Personal or Speaker mode) advertise their availability to be listened to by receivers (Personal or Audience mode). It is up to the application designer to implement an appropriate listen policy, for which the default should be that the first beacon-recognized speaker is automatically listened to, and subsequent beacons are recognized as potential speakers but are ignored. This handles the usual good case where, in a classroom setting, a single application in Speaker mode correctly identifies itself and all other participating applications in Audience mode need to listen to that speaker. Another application subsequently claiming speaker status is operating in error, and is to be ignored. The application must provide a means by which error or malice on the part of potential speakers is managed, that is, by which the user can choose which potential speakers should be heard and which should be ignored. For example, if a proper speaker and an interloper are both claiming speaker status by sending beacons, and a newly-started application begins to listen, it may first hear the interloper's beacon and begin listening to it. The user must be able to consult a list of potential speakers and pick the one(s) actually needed. Beacons must be sent at least every 10 seconds. Receivers must track speaker beacons, aging speakers toward removal. Each new beacon for a speaker restarts its aging countdown. A potential speaker that has gone beacon-silent for 30 seconds is considered a dead speaker and is removed from the list of available speakers. Navigation synchronization received without beacon support is ignored. .ti 0 Name/value Pairs Names may be constructed from any characters other than '=', newline, and NUL. Values may be constructed from any characters other than newline and NUL. Name/value pairs are newline-terminated, not newline-separated. The distinction means that the last pair also must end in a newline. Continuation lines are not supported. There are 12 names defined for use in the body. The application may provide any others its designer finds useful, but these names define the protocol's interoperability. 1. msg.sync.passPhrase .in 7 Required. A free-form phrase to separate distinct BibleSync conversations. This allows e.g. multiple Bible classes to be taught without mutual interference. A packet not matching the receiver's passphrase is ignored. .in 3 2. app.inst.uuid .in 7 Required. The application's UUID, repeated in printable form. .in 3 3. app.user .in 7 Required. Identification of the human user. .in 3 4. app.name .in 7 Required. Identification of the application. .in 3 5. app.version .in 7 Optional; recommended. The application's version stamp. .in 3 6. app.os .in 7 Optional. Identification of the OS under which the application runs. .in 3 7. app.device .in 7 Optional. Identification of the application's device (hardware). .in 3 8. msg.sync.bibleAbbrev .in 7 Required in navigation. The short textual name of the Bible (e.g. "KJV"). .in 3 9. msg.sync.verse .in 7 Required in navigation. A textual Bible reference. It is the application's responsibility to use appropriate reference syntax; see references below for OSIS and BibleRef. This value may not be just a single reference, that is, it may be a multiple reference generated as a search result or a cross-reference footnote in the sender's application. In general, multiple references can be specified using ';' to separate complete references, ',' to separate individual verses, and '-' to identify a verse or chapter range. The application designer must remain aware that the packet size limit means that at most a few dozen references will fit. A receiving application should present a multiple reference to the user as a selection list without navigating. .in 3 10. msg.sync.altVerse .in 7 Optional. Another textual Bible reference, used as a possible assist to applications that might not parse the primary reference in msg.sync.verse. .in 3 11. msg.sync.group .in 7 Required in navigation. A synchronization group number, a single ASCII digit, '1' through '9', the interpretation of which is left to the application. This may be used to identify a related group of windows displayed by the application, or a tab number within a tabbed interface, or a wrapping sequential identification of synchronization. The application should send group '1' if it has no specific need for this, and may ignore it on navigation receipt if such values have no meaning. .in 3 12. msg.sync.domain .in 7 Required in navigation. This field has a fixed value of "BIBLE-VERSE" but its use will be expanded in future revisions. .in 3 .ti 0 Security Considerations BibleSync is a protocol defined for a friendly environment. It transmits cleartext with no anticipation of encrypted content, and any packet sniffer can see what is going on, including the passphrase (that being nothing more than a conversation discriminant). Spoofing must be defended against. That is, the identity of a speaker is visible to all, and a malicious user can generate artificial packets which appear to be from someone else, thereby possibly impersonating a legitimate speaker and inducing others' applications to navigate inappropriately. The application should retain enough information from the first beacon received from each speaker so that subsequent packets can be verified. Specifically, the application should check that the UUID of a packet is coming from the same IP address from which the speaker was first heard. It is important that the first beacon be transmitted before the presence announcement, because both contain the UUID, and an interloper could begin to impersonate the legitimate speaker via contrived beacons and navigation before the legitimate speaker himself begins to transmit his own. The UUID's presence in the 1st beacon packet prevents interlopers from being able to do this. .ti 0 Example Packets .nf Presence announcement: magic: 0x409caf11 version: 0x02 type: 0x01 uuid: 00112233-4455-6677-8899-aabbccddeeff #pkt: 1 pkt index: 0 app.name=TestBibleApp app.inst.uuid=00112233-4455-6677-8899-aabbccddeeff app.user=John Doe (jdoe) msg.sync.passPhrase=qwerty Beacon is identical to presence announcement except for being type 3. Navigation: magic: 0x409caf11 version: 0x02 type: 0x02 uuid: 00112233-4455-6677-8899-aabbccddeeff #pkt: 1 pkt index: 0 app.name=TestBibleApp app.inst.uuid=00112233-4455-6677-8899-aabbccddeeff app.user=John Doe (jdoe) msg.sync.passPhrase=qwerty msg.sync.domain=BIBLE-VERSE msg.sync.group=1 msg.sync.bibleAbbrev=NET msg.sync.verse=Rom.14.4 Additional name/value examples, optional use: app.version=2.7a app.os=Linux app.device=i686 msg.sync.altVerse=1Mac.1.2 Real-world example, using all defined names: magic: 0x409caf11 version: 0x02 type: 0x02 (sync) uuid: 49b387bd-6324-4a2e-871a-4b24e065bff7 #pkt: 1 pkt index: 0 app.name=Xiphos app.version=3.2.1 app.inst.uuid=49b387bd-6324-4a2e-871a-4b24e065bff7 app.os=Linux app.device=x86_64: Linux @ awol.kleinpaste.org app.user=Karl Kleinpaste (karl) msg.sync.passPhrase=BibleSync msg.sync.domain=BIBLE-VERSE msg.sync.group=1 msg.sync.bibleAbbrev=NET msg.sync.altVerse= msg.sync.verse=Rom.14.4 .ti 0 References .nf Original specification: http://biblesyncprotocol.wikispaces.com (u:General_Public p:password) OSIS: http://www.bibletechnologies.net/ BibleRef: http://semanticbible.com/bibleref/bibleref-specification.html UUID: RFC 4122 This specification alters and extends technical aspects of the original specification (cf. wikispaces, above), notably max packet size, size and alignment of header, speaker beacons, use of app.user, and stipulations regarding name composition and newline separation. That document includes usage and policy details not appropriate to this form of specification. .ti 0 Copyright No copyright is claimed. All documents, descriptions, manual pages, and source code for BibleSync are in the public domain. .ti 0 Contributor Addresses .nf Costas Stergiou Karl Kleinpaste William Mills Tim Morton Craig Rairdin biblesync-1.2.0/man/specification.txt000066400000000000000000000413251326575651300176420ustar00rootroot00000000000000 Network Working Group C. Stergiou et al Request for Comments: -BSP- BibleSync WG 15 June 2014 A Standard for Synchronized Co-Navigation of Bible Programs Status of this Memo This memo describes a protocol by which cooperating Bible programs with LAN access use multicast navigation packets to share navigation of programs. This is a standard recommended for interoperation in any network-aware Bible program. Distribution of this memo is unlimited. Overview and Rationale Use of multiple Bible applications is common and requires repeated operations in order to remain synchronized among the applications used. Scenarios for this use include a single user working with more than one application, possibly on more than one computer; a small group working together; or a classroom environment where a set of speakers has an audience who follow the speakers’ direction. BibleSync provides a means by which network-aware applications can provide navigation packets when the user moves his Bible to a new reference, and receive navigation packets from other users. The protocol sends reference indicators, not content. Operational Modes BibleSync defines three modes: Personal, Speaker, and Audience. In Personal mode, the application both sends and listens to navigation. In Speaker mode, the application sends but does not listen, and conversely in Audience mode, the application listens but does not send. Speaker and Audience modes are each in effect half of Personal mode. Network Addressing Multicast address 239.225.27.227 is used with UDP port 22272. Typical TTL of 1, default in most systems, is used in the normal case. In the special case of strictly personal usage by one user with more than one application on a single host, a privacy mode is available by setting multicast TTL to 0, so the user’s entirely internal navigation is not also heard over the wire. Stergiou et al [Page 1] RFC -BSP- BibleSync Protocol - DRAFT 15 June 2014 Packet Structure Payload maximum length is 1280 bytes. Within this, the first 32 bytes are a header identifying the sender’s protocol version, message type, and UUID, and the remaining space consists of name/value pairs, within which a number of the names are required for each of the defined message types. In C++, the complete structure is represented below, with field details following: typedef struct { uint32_t magic; // 4 bytes uint8_t version; // 1 byte uint8_t msg_type; // 1 byte uint16_t num_packets; // 2 bytes uint16_t index_packet; // 2 bytes uint8_t reserved[6]; // 6 bytes uuid_t uuid; // 16 bytes char body[1248]; } BibleSyncMessage; The magic value is 0x409CAF11, by which to determine that a packet is intended for BibleSync. The protocol version is 2. Three message types are defined: 1 = presence announcement, 2 = navigation synchronization, 3 = speaker availability beacon. Currently BibleSync is specified as a single packet protocol, but the number of packets and packet index fields are included for possible future expansion. At this time, number of packets must be 1 and packet index must be 0. The application provides a UUID (see RFC 4122). The UUID is consistent through the life of the application, i.e., it is generated once when BibleSync first begins to be used, and that value is not re-generated as long as the application runs. Six bytes are reserved for possible future definition. Packet maximum size (1.25 Kbytes) was chosen on the basis of staying within one MSS on a typical Ethernet. Packet Type Overview The presence packet announces the application’s participation in the conversation. It is non-essential, but useful if the application designer chooses to make it visible to the user. Stergiou et al [Page 2] RFC -BSP- BibleSync Protocol - DRAFT 15 June 2014 The navigation packet specifies a Bible name and a reference. It may also contain an alternate reference to provide a second means of interpretation so that e.g. differing Bible versifications might be accommodated. An application sends navigation synchronization when the user navigates the application to a new reference point. A listening application receives the reference information and navigates there without needing user interaction. The speaker beacon packet is identical to the presence announcement except for having message type 3, and is sent by transmitting applications every 10 seconds. Speaker Beacons An exclusion mechanism was deemed necessary during early experimentation with the first implementation that provided only presence announcement and navigation synchronization. It was found to be too easy for a confused or malicious user to mis-start BibleSync in his application in Personal or Speaker mode and thereby to navigate other users’ applications inappropriately, because all claims to speaker status were implicitly accepted by the mere arrival of navigation packets. Beacons provide this exclusion, by which senders (Personal or Speaker mode) advertise their availability to be listened to by receivers (Personal or Audience mode). It is up to the application designer to implement an appropriate listen policy, for which the default should be that the first beacon-recognized speaker is automatically listened to, and subsequent beacons are recognized as potential speakers but are ignored. This handles the usual good case where, in a classroom setting, a single application in Speaker mode correctly identifies itself and all other participating applications in Audience mode need to listen to that speaker. Another application subsequently claiming speaker status is operating in error, and is to be ignored. The application must provide a means by which error or malice on the part of potential speakers is managed, that is, by which the user can choose which potential speakers should be heard and which should be ignored. For example, if a proper speaker and an interloper are both claiming speaker status by sending beacons, and a newly-started application begins to listen, it may first hear the interloper’s beacon and begin listening to it. The user must be able to consult a list of potential speakers and pick the one(s) actually needed. Beacons must be sent at least every 10 seconds. Receivers must track speaker beacons, aging speakers toward removal. Each new beacon for a speaker restarts its aging countdown. A potential speaker that has gone beacon-silent for 30 seconds is considered a dead speaker and is Stergiou et al [Page 3] RFC -BSP- BibleSync Protocol - DRAFT 15 June 2014 removed from the list of available speakers. Navigation synchronization received without beacon support is ignored. Name/value Pairs Names may be constructed from any characters other than ’=’, newline, and NUL. Values may be constructed from any characters other than newline and NUL. Name/value pairs are newline-terminated, not newline-separated. The distinction means that the last pair also must end in a newline. Continuation lines are not supported. There are 12 names defined for use in the body. The application may provide any others its designer finds useful, but these names define the protocol’s interoperability. 1. msg.sync.passPhrase Required. A free-form phrase to separate distinct BibleSync conversations. This allows e.g. multiple Bible classes to be taught without mutual interference. A packet not matching the receiver’s passphrase is ignored. 2. app.inst.uuid Required. The application’s UUID, repeated in printable form. 3. app.user Required. Identification of the human user. 4. app.name Required. Identification of the application. 5. app.version Optional; recommended. The application’s version stamp. 6. app.os Optional. Identification of the OS under which the application runs. Stergiou et al [Page 4] RFC -BSP- BibleSync Protocol - DRAFT 15 June 2014 7. app.device Optional. Identification of the application’s device (hardware). 8. msg.sync.bibleAbbrev Required in navigation. The short textual name of the Bible (e.g. "KJV"). 9. msg.sync.verse Required in navigation. A textual Bible reference. It is the application’s responsibility to use appropriate reference syntax; see references below for OSIS and BibleRef. This value may not be just a single reference, that is, it may be a multiple reference generated as a search result or a cross-reference footnote in the sender’s application. In general, multiple references can be specified using ’;’ to separate complete references, ’,’ to separate individual verses, and ’-’ to identify a verse or chapter range. The application designer must remain aware that the packet size limit means that at most a few dozen references will fit. A receiving application should present a multiple reference to the user as a selection list without navigating. 10. msg.sync.altVerse Optional. Another textual Bible reference, used as a possible assist to applications that might not parse the primary reference in msg.sync.verse. 11. msg.sync.group Required in navigation. A synchronization group number, a single ASCII digit, ’1’ through ’9’, the interpretation of which is left to the application. This may be used to identify a related group of windows displayed by the application, or a tab number within a tabbed interface, or a wrapping sequential identification of synchronization. The application should send group ’1’ if it has no specific need for this, and may ignore it on navigation receipt if such values have no meaning. 12. msg.sync.domain Required in navigation. This field has a fixed value of "BIBLE- VERSE" but its use will be expanded in future revisions. Stergiou et al [Page 5] RFC -BSP- BibleSync Protocol - DRAFT 15 June 2014 Security Considerations BibleSync is a protocol defined for a friendly environment. It transmits cleartext with no anticipation of encrypted content, and any packet sniffer can see what is going on, including the passphrase (that being nothing more than a conversation discriminant). Spoofing must be defended against. That is, the identity of a speaker is visible to all, and a malicious user can generate artificial packets which appear to be from someone else, thereby possibly impersonating a legitimate speaker and inducing others’ applications to navigate inappropriately. The application should retain enough information from the first beacon received from each speaker so that subsequent packets can be verified. Specifically, the application should check that the UUID of a packet is coming from the same IP address from which the speaker was first heard. It is important that the first beacon be transmitted before the presence announcement, because both contain the UUID, and an interloper could begin to impersonate the legitimate speaker via contrived beacons and navigation before the legitimate speaker himself begins to transmit his own. The UUID’s presence in the 1st beacon packet prevents interlopers from being able to do this. Example Packets Presence announcement: magic: 0x409caf11 version: 0x02 type: 0x01 uuid: 00112233-4455-6677-8899-aabbccddeeff #pkt: 1 pkt index: 0 app.name=TestBibleApp app.inst.uuid=00112233-4455-6677-8899-aabbccddeeff app.user=John Doe (jdoe) msg.sync.passPhrase=qwerty Beacon is identical to presence announcement except for being type 3. Navigation: magic: 0x409caf11 version: 0x02 type: 0x02 uuid: 00112233-4455-6677-8899-aabbccddeeff #pkt: 1 pkt index: 0 Stergiou et al [Page 6] RFC -BSP- BibleSync Protocol - DRAFT 15 June 2014 app.name=TestBibleApp app.inst.uuid=00112233-4455-6677-8899-aabbccddeeff app.user=John Doe (jdoe) msg.sync.passPhrase=qwerty msg.sync.domain=BIBLE-VERSE msg.sync.group=1 msg.sync.bibleAbbrev=NET msg.sync.verse=Rom.14.4 Additional name/value examples, optional use: app.version=2.7a app.os=Linux app.device=i686 msg.sync.altVerse=1Mac.1.2 Real-world example, using all defined names: magic: 0x409caf11 version: 0x02 type: 0x02 (sync) uuid: 49b387bd-6324-4a2e-871a-4b24e065bff7 #pkt: 1 pkt index: 0 app.name=Xiphos app.version=3.2.1 app.inst.uuid=49b387bd-6324-4a2e-871a-4b24e065bff7 app.os=Linux app.device=x86_64: Linux @ awol.kleinpaste.org app.user=Karl Kleinpaste (karl) msg.sync.passPhrase=BibleSync msg.sync.domain=BIBLE-VERSE msg.sync.group=1 msg.sync.bibleAbbrev=NET msg.sync.altVerse= msg.sync.verse=Rom.14.4 References Original specification: http://biblesyncprotocol.wikispaces.com (u:General_Public p:password) OSIS: http://www.bibletechnologies.net/ BibleRef: http://semanticbible.com/bibleref/bibleref-specification.html UUID: RFC 4122 Stergiou et al [Page 7] RFC -BSP- BibleSync Protocol - DRAFT 15 June 2014 This specification alters and extends technical aspects of the original specification (cf. wikispaces, above), notably max packet size, size and alignment of header, speaker beacons, use of app.user, and stipulations regarding name composition and newline separation. That document includes usage and policy details not appropriate to this form of specification. Copyright No copyright is claimed. All documents, descriptions, manual pages, and source code for BibleSync are in the public domain. Contributor Addresses Costas Stergiou Karl Kleinpaste William Mills Tim Morton Craig Rairdin Stergiou et al [Page 8] biblesync-1.2.0/pix/000077500000000000000000000000001326575651300143015ustar00rootroot00000000000000biblesync-1.2.0/pix/biblesync-v1-30.png000066400000000000000000000077101326575651300175320ustar00rootroot00000000000000PNG  IHDR7'$oGgAMA asRGB cHRMz&u0`:pQ<bKGD pHYsHHFk>VIDATXXi]u>~244f#EFR[eb\$JAr L(TY"@616BlBviFY4mw# A&IܺuwO;_7z!"u G8 dVI(.H0&S.آibYD Bd*UҙSY6Yt+:?_5(DFiLEZJ`e.nHt.Pc;mc_CcDIuGu 3"8-Di$[;^œ!"7tATAwYԺf+b,ˣajS x.R!/ZJk$5q qokW^OquqOpo˧^Zxrq+]̰P~zg] S0Hrx΋\clqw.~6a3&lDޭ/wF,Rco% " 0"Me=F/HӒ:2]+P]Sp90}>nF1ϮXyEE@D@_˹/8gJWEHnuKZ3ƖY춍2dήr 7/Hz,N4bDܬH,G(Q 10FU@*H*o|UrJhJ:[2 Um??w ,Sj;N"7WMfabwdk.V|``@u54ܤ7Ο^ɘ3|jJMP X>TKQ*T(NH1=UI> RMie:n|ʝwi3kCrP;>MiF1Ґ34tGA)C40 8"g ⩤pyްmOnKW,*JY^'45wN{IR1i J" C8eWW񸺁df]]Q"^9|Iq!h/ P82pb[n2'g?Cy\&Yli|QӍ;gn"DϫfmĿW/=H`Z M /I+K>-S~뮻v/_@ q҉wޞ84"Eb[uۚXkNjaxԊ~cX,5YKK&POIM[J\.REPż]_Wr1{`ԲsNk/wݷa }/5,b/5Yk׫A?kOͮtduT_y(uv3aBWbi`q>ǟUNf_0_al%#;|K\$8/Mv:^yJ/fx?mvSJ-􂓒 Okތ:/AAD=iMr`vL4inq+7<ePΜ>eۿhn[{੺`K.nX}૯6Z Y.*JR\.vܺZFqT|ۏo\s7Ȏ\"H!A^> }YUʊD5Oz:WZc㖍NW)  ³0$0+ uaG;#@mV|$1AU|J*X(EAAv3a(a8 w*'\@ ǜ*OrU"ɽ4EA0#H4P@h! Z>:d&eWm1 rnǃ}hXWr! 9^յBaUq E{1HZzvu\[L]glsY3e!W%޽Qhץ-dZŅ|ݭF}w8K ݻ*;/&5 bsLcR(;3^"c: }&Fj~Mn2]Qs ,'/h^swf5Xs|ެͬLFqU wĝ-Y ɽe,eo',2]qa q.#8#]taG_{(ڌ5a|"rvE*NqTi^ĩC=,QÅoXٵUPYZx]lwuO?K5-M0DT) eG"kdc^{KerpK~<J=)Ȥd.^9>pC htt|t9v]Dɉi9a&u: DG<$C MߩBMrR%tEXtdate:create2014-04-26T00:16:24-04:00k%tEXtdate:modify2014-04-26T00:16:24-04:00xtEXtjpeg:colorspace2,uU tEXtjpeg:sampling-factor1x1,1x1,1x1ptEXtxmpMM:DerivedFrom$IENDB`biblesync-1.2.0/pix/biblesync-v1-40.png000066400000000000000000000141271326575651300175330ustar00rootroot00000000000000PNG  IHDRI4IgAMA asRGB cHRMz&u0`:pQ<bKGD pHYsHHFk>IDAThzy_E[Uwmo{ #a&JC#= 8@lalF@  (#!lhFȞ}w; QfUP>A "%8KV033;GԮ,P̬`"I.K@3+B~pMT@ʑcwH˔)ʧDn_I8CL  csu08%X犣C]S=^!(ZDD̒4MyB@+̎ eq/88i7{1__cÂWljR9B 8*o7R48 ) z3S3-.,NX2ڧ}l.ɶ{\NKDLۛt?J A$< e>_?9/"= B%DTI}rpYcJhv:㺩!xuBZ `@7\JDʓиc$PRHOHELhI=M*qX^{uӖQi[鎊][ӻo]FS׏X'<ɓEEN$k41$'H !HA vwf%o7 j-3`BƆLkcfRsLfᏮOۄ;V5SowNPs5kblt ?w%ڍ O7Bo)Ϟxpwp2ZGz)`$R,;xɃmDic,A䵶NӞӖS6ʈxh0I5΄miMh#~t Fʆ w} 23WwVu67.+W5Vq}>8 p;0` I*Ȕh|23#󎎝ba?~ZvqЬֶElbzlGv bbss1_vӓdA(vZ!H|;G޳ϬIk}#N*bvij;]g@mQ!G&67ziCmcg<26yS* mzi'k82@}8/׿ܾf'O B=;yJ8M9h2 =;3 A,m&Y~6G 8`"aB `Gl`>xѿxk?`7D,hB:<KI/ . A<A$,:OOl1}Z"΁;ÜwƜVktB 6Q+Z Y@4:G10Ll8DgHXEVGq)9|8M"!=fM\gcT3(FLH 51j1*Z/ 3)^ %@-o2G~DNd^]gƊ L7Tdacs H揞\Ў"EKܰk~m}cUkkKLh>h76VY6p!:5/hpđ^G[5pTC[G~sC3󎫿0Gy? Ǽl^r~029Wپ}ǭ|ll/@^ ~pvjg~LcH v|^,ih c" ltqdo:Û63;xEkٟƷ{~]|ac$40u҆cFF,g|.ֲΝ?g-_K؏'isWsf+uV]OO'`}=+[7t6q璋ޟ3k>IŻ#/PO]N՞Wv'Z K.,-+ss7|C'q]pq`?'$-g]{Gp'CzTr1'V{vA5zww9%6 v,IZu.YgOdՁYk:n^zM(¶IӾs،Y\R3]M;]3v#Q`L4sutuFۅz Ϙ[ iJjc+۶N;Q̚g Xi]o¬ m'xVvRZ=1/\V8źڲp3[jmv__I[4t"W$mْfqG6w?ezg/kyi2֔_|KCǟ: ’\^\Gi1GM/74+X 30=-꣟bO9ja&CI㕪fxH7 bpH5)VxmP\B9Ӣk^uk8<{~+f7?|ߣ=7ܲJ3mi(.E^xp p҇ Ba5;{g%V$Z4,\{}ƛ˯_ѓ#?+K\L+"T[<<_+㇟dዱR:__-&@؀F"$Fʕ۲g#q(0vwq.|ΙG\w-͞B&_^X>jppܩ3o!嫛7 7BD읶L\arАfHHZohBD1ͱc`) )A$ FBc |g)sDd-4́uL)mU/̎7\$qì LpqI8vӁ*y3+kUvN V_hdkǛH00n['3LƩꔂDDBk""Vj" %kk#R*+Xk@\Oh"Gpƚ3 $C1Avax_i 29:+B@7&扮}Zbگn<2ȁb73R@x< )0ľ6&HpN,,<aI&}MzNo}†wO듙@⭲s4QT/o>Zyؐ)e%;ʹP-Mٷ;Dyпw]{>t,ɑ(16AcB(CPQ dDB&d& ;Tӫ3%tEXtdate:create2014-04-26T00:16:24-04:00k%tEXtdate:modify2014-04-26T00:16:24-04:00xtEXtjpeg:colorspace2,uU tEXtjpeg:sampling-factor1x1,1x1,1x1ptEXtxmpMM:DerivedFrom$IENDB`biblesync-1.2.0/pix/biblesync-v1-50.png000066400000000000000000000212541326575651300175330ustar00rootroot00000000000000PNG  IHDR\ATJgAMA asRGB cHRMz&u0`:pQ<bKGD pHYsHHFk>!:IDATx{weUZk} u+vW]M':@7QQ1"̈A<FD̏0 "b@eEPrhi:wUuWuӹ眽Zǭn@Gv_'"gs&I * f|' "DZD|AA< (H@Q!  2/D|sn"kD@,mzy D1$艁$4 윖 @{D"""{X@f!bR2J/SE~LOb&]~@um  {z @ Jkh|R_5aA +lsz)áFÿrF%d` TR> >| gY(ECQa ֐{M.o MbW,Ho6}uˍ 7?u^z4ʧSV9$vq ҂y7q;Ɂ JA+ˆ81]kǿq2!g}i6Go2Zp_DTY'GRl; M.8{W/+.ۇ4,؜]|n\* ǵ;81# I{ЀI_@jS#AZ)c4j#D)5x&n^ro_h ~$8(}1G8?X{H6s饥"S !$Qāg;v45e+Ķ [W?maam({V@[WǓ͙`b*o tՉ_~mTA$7gN$Qփ ֦6GoROA=aP1w,Xo\أB?JNwa(5Tom[-կ􂽊+V&6iz\~)ss( $||/fsJQ=F$AeCrj?zajɲڔ(K@$ }wݽɃsh>_,-{QL~pUvez}+`f*жA'.ås3=ZEA@]ntP:oo6A[DS vi; \otvInT*Sx_;yɗ@EQ!J=  S+ κ^@s@""$Dt|&Ӽ1d'dա~Ux7o2Jv:4ya]xW;39||$X3g.Zڔ<gB@B$" :~ !":;ϪSh"!`A-@33;)q1)TJ]_-'hNѩk~q*yo9̴A(K1&G vkwv NM]*wfq9V -5mj=__閫6]Ϫp [G~٪,c1/z`Oc-}uy(sL21QKga˖˾ QK {KA_{J7/M)`txcXmf[1 ,NG 0);@ ʡsW/ZR^H3~j=2OdՉZcGb1@Elh" @ [jrh<pyw;|`zuyĉKHس$mLԊHA/U|!xŗ& qsP6Y%u;Lߜs(m0TQ9٫fQOv@#Z9zlz*b@+YPQ3zK`Xy!jck[ё$e"DAؑ`¢4#aDG53,׏5 uc;&zQ7ٞH9BmS v̘[\F@ ; fkk7x$ ]]88jI MFnܹuF @cwrŇ}Py&Y?:yK}ΑT@d6H깇>s~9;~fl^u/>t^wYnRiVQ8DmzÅw}]KH?'Z̃PPp`NphQ:8=蹧?n a_ĩfKOO2ј޸>ټW!Hځr_x^l3v=>r~.5&ڼԎvY ,Y:yAw+^_߁bgu_7@f"O)Ϝ$xPexx?^?y ^]͂3=斋D4 k'Ym {܉w%Ju\qyދizÚ*WZ2 ?6Zc?V;3+i:gX?[赠Baxfq=Tr{შTyuf262""a>*qeq~ӬANCG\<}z[+Y7ӺotH#kZ~SpxmmYE'?.z+51DAf*$T*}հQKc~Z5A(h#Wo餝c.։GݼeM;=ţVS3&k6{ 8[w !9&aWxʺIK];uq" d<2ryAqd>ry\*?% ">c|z{IMog6Kg.h BV[uk`V2تP$t'(úچdҴ{{۫@Dp$Q.TS=;<۠x-NQ[M6PE@ D2q<yOO]_v/OsN>=rnW}O `0¤P@PPw=` @BdA&NFD􈞠X QP@Y@ D wR`BdFFj""`FD"zПюe6K]'ͺb ̬֩@@6w9J۹K6;kMcKր<,w֒D|$A=!:g}mbv9'N זkrْ*!i3[ P? F k%+ qj<֭_ZoށWY'.ջE/Zrӌ7l%{xхɟ}o>B$r'HK)Fr6H2[_U^)c_,Ӆ#^ﶜ4{&ng~G=q=7R//tJS|Û_ \2d?qoD : P>hmPi%={^T.L GΝ31<,9xfy=Eý_rR5́V_xP+Cg[mecAZaH.ἁaGfic!'9D>˿5ۖp:} R*ć=7իw5zuW.<=;u7l1/8p+^>g~(LFy$>@w_n?0X `6͖vۿ ,l[xN6U=w=xs8ۗx)+PoxsQqwF>w:KtoF=X/IjԂ /+ \eܿ|3ϴ:%s?cD@&ࠫ'S= )$+Hk ^A0}¹ 7w1̨@9HB t{  xX>s]8u wW=okk7EIy}KtPިoƶ|ELkj=ZB @ߒ'k6~#8홦ZͪT>5Y}5ݵŋZ&՛L%#7o{24)W)$ =rN Ď||ʷ\9m~&g&Jzl--BVZ{'e`s>}U/ &_\}H+JlbsB~gaqj>~o\j ^ox+ h=]q=/9j?فp===," G9|F#@cKZ͙[[a_>Prc@KC\FJ/{)d4 *ZHRUs 9Tal>1I1D|ܱ/XwOFFu-(ŠՋyT;[/7U}wâkK_ S-ͤ؏-QL y9H@z{_Is?QwS{2_^. ;PDt>1U~ss:ApVA6SuFag[OOd f-ΓhNoQm}1{MQG}jb뺷;_4M]|!]nųcUrs1@s$j!>g*YԷ4j>Sם)W=vM3@vNGx\- N4c1 mπl}1ҙiuSKp+YJBK+-ށgT g,:Ž)CUf|na+Y1d"(o8quGo:rJϕ$I; ;az Xvɛb\[Po*͖]`\@&D=kx{w>L]: `1Ah"H5՜BV#e9T]*R93Y9 v&g &rjC e'Q*DUֹ ΚؘlW92O݃!l=1s9)Ra0 ta !uY9E!Z 0Pc lĆ2ǹaֵvF"EH QA-@%2Y}k`3Y""m`Pȃ a b9<}n` Ij ˜#ɐ7u-]h!I2 XC/T÷%ՅniQDDj\RF`&+Q\s`ASy2%qm'yMa SQ!ZV I {O*U>[qiO>(m,OWW]v3K졝YqmiK ~ɬw,<7"*3,dG}h&nW>Ԭ:toh&Մ,<`nh[A)OS/\TCϕrdX`[*/uv^2rc&<之GmjIOl껐6woh~2>,ۺ<dA>lyyr'>m|'/{ OtI':{qŹqtz˖Yg*w:EK(j 8vø}sM:o8̉+\77ony|k_9SV ~&ʚ:9;幯?r_}cɦM &wG)\_ h 9]zMo*߾֟47T^^o?iXAViU ksU68ݲVtJWzO;eg1]䉞?uwO仁6*;@ lX3Q!2PT)0y^ƇGQU^2"yʡ7W/N ޽o6qh·h k_^u>~}ZԃD.xhמIƦu*vQ6w챍;o{5Ҟa IPŊR9g"ARAtż^\?Ga"1(&p#9ȖE?ݡʑ끱@)3߭LH[`yqx5YyƒCb.m+ƌp(w_|+'Vff6vS9%uW|_04W0ll'qyu쉪 #P '>g:k'ȹ3iN`ʚٶ=>Y7+rM[3q#u`%Iyookj=&ʃ*BmEN/gN|.w?yԊoEhD[*duۙ;pOYޱED ck\ߺضaW{hn zY@B$ijRW\8`'*\ 3uT+{X)9OuicW0d| 2s* ӉjmaB@Y;8*.vg*z*ZajL@J3#Q۝V,ζMxJEvj;biީ 'PAsl{{˦0I/@ʷlu352ZV9&6mƴ5n{PĹyTQHDH)YE"zkQ)"*c{A݉308[9[֢V;wRZw {HS 0 3*,`taL, hZ X"4 #$$B^b+: X DDNRJѳ'%wPA "O4u6cW;)%DCc< tiCq" D?=QAdWl "BN!. g;n "23 3#"d^DDS2kWtA<ґxV#y`DB^Q:T ;|'%ґ OO  hH<@@vJٻT=Dvg-uUtrR }~'ȓ[):w~>r@yr:lչOT"!k kiQV(|޼3g{NL"FB-y)R QDAhJiK)aU6 using namespace std; // sync is a proper superset of announce & beacon, // both inbound as well as outbound. // in these 2 arrays of strings, sync-specific // fields are placed after announce fields. // see field_count in ReceiveInternal + TransmitInternal. static string inbound_required[] = { BSP_APP_NAME, BSP_APP_INSTANCE_UUID, BSP_APP_USER, BSP_MSG_PASSPHRASE, BSP_MSG_SYNC_DOMAIN, BSP_MSG_SYNC_VERSE, BSP_MSG_SYNC_BIBLEABBREV, BSP_MSG_SYNC_GROUP }; static string outbound_fill[] = { BSP_APP_NAME, BSP_APP_VERSION, BSP_APP_INSTANCE_UUID, BSP_APP_OS, BSP_APP_DEVICE, BSP_APP_USER, BSP_MSG_PASSPHRASE, BSP_MSG_SYNC_DOMAIN, BSP_MSG_SYNC_GROUP, BSP_MSG_SYNC_BIBLEABBREV, BSP_MSG_SYNC_ALTVERSE, BSP_MSG_SYNC_VERSE // last: could go overly long, risk cutoff. }; // BibleSync class constructor. // args identify the user of the class, by application, version, and user. BibleSync::BibleSync(string a, string v, string u) : BibleSync_version(BIBLESYNC_VERSION_STR), application(a), version(v), user(u), receiving(false), beacon_countdown(0), beacon_count(BSP_BEACON_COUNT), mode(BSP_MODE_DISABLE), nav_func(NULL), passphrase("BibleSync"), server_fd(-1), client_fd(-1) { #ifndef WIN32 // cobble together a description of this machine. struct utsname uts; uname(&uts); device = (string)uts.machine + ": " + uts.sysname + " @ " + uts.nodename; #else device = "Windows PC"; #endif interface_addr.s_addr = htonl(0x7f000001); // 127.0.0.1 // identify ourselves uniquely. uuid_gen(uuid); uuid_dump(uuid, uuid_string); } #define BSP (string)"BibleSync: " #define EMPTY (string)"" // BibleSync class destructor. // kill it all off. BibleSync::~BibleSync() { if ((client_fd >= 0) || (server_fd >= 0)) Shutdown(); } // mode choice and setup invocation. BibleSync_mode BibleSync::setMode(BibleSync_mode m, BibleSync_navigate n, string p) { if ((mode == BSP_MODE_DISABLE) || ((mode != BSP_MODE_DISABLE) && (n != NULL))) // oops. { mode = m; if (p != "") { passphrase = p; // use existing. } nav_func = n; if (mode == BSP_MODE_DISABLE) Shutdown(); } else { Shutdown(); } string result = Setup(); if (result != "") { if (nav_func != NULL) (*nav_func)('E', EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, BSP + _("network setup errors."), result); Shutdown(); } return mode; } // network init w/listener start. string BibleSync::Setup() { string retval = ""; bool ok_so_far = true; if (mode == BSP_MODE_DISABLE) Shutdown(); else { // learn the address to which to assign for multicast. InterfaceAddress(); // prepare both xmitter and recvr, even though one or the other might // be not generally in use in classroom setting (viz. announce). // in "personal" mode, user is both server and client, because he // receives nav from other programs, and sends nav to them, as peers. // speaker == "client" insofar as he xmits nav to audience. if (client_fd < 0) { if ((client_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { ok_so_far = false; retval += _(" client socket"); } else { // basic xmit socket initialization. memset((char *) &client, 0, sizeof(client)); client.sin_family = AF_INET; client.sin_port = htons(BSP_PORT); client.sin_addr.s_addr = inet_addr(BSP_MULTICAST); // enable listening to our own multicast via loopback. char loop=1; if (setsockopt(client_fd, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loop, sizeof(loop)) < 0) { ok_so_far = false; retval += " IP_MULTICAST_LOOP"; } else { // multicast join. if (setsockopt(client_fd, IPPROTO_IP, IP_MULTICAST_IF, (char *)&interface_addr, sizeof(interface_addr)) < 0) { ok_so_far = false; retval += (string)" IP_MULTICAST_IF " + inet_ntoa(interface_addr); } } // client is now ready for sendto(2) calls. } } // one way or another, if we got this far with a valid socket, // and the app is in a public mode, "TTL 0" privacy makes no sense. if (ok_so_far && (client_fd >= 0) && ((mode == BSP_MODE_SPEAKER) || (mode == BSP_MODE_AUDIENCE))) { setPrivate(false); } // audience == "server" insofar as he recvs nav from speaker. if (ok_so_far && (server_fd < 0)) { if ((server_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { ok_so_far = false; retval += _(" server socket"); } else { int reuse = 1; if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0) { ok_so_far = false; retval += " SO_REUSEADDR"; } memset((char *) &server, 0, sizeof(server)); server.sin_family = AF_INET; server.sin_port = htons(BSP_PORT); server.sin_addr.s_addr = INADDR_ANY; // make it receive-ready. if (bind(server_fd, (struct sockaddr*)&server, sizeof(server)) == -1) { ok_so_far = false; retval += " bind"; } // multicast join. multicast_req.imr_multiaddr.s_addr = inet_addr(BSP_MULTICAST); multicast_req.imr_interface.s_addr = interface_addr.s_addr; if (setsockopt(server_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&multicast_req, sizeof(multicast_req)) < 0) { ok_so_far = false; retval += " IP_ADD_MEMBERSHIP"; } // bind(2) leaves us ready for recvfrom(2) calls. } } // if we are either kind of speaker, we must broadcast our first // beacon immediately, to avoid a presence announcement from going // out first, giving our uuid, and allowing time for a malicious // user to start faking his own beacons & nav using our uuid. if ((mode == BSP_MODE_PERSONAL) || (mode == BSP_MODE_SPEAKER)) { TransmitInternal(BSP_BEACON); beacon_countdown = beacon_count; // speaker mode => speaker list has become irrelevant. if (mode == BSP_MODE_SPEAKER) { clearSpeakers(); } } else // audience only. { beacon_countdown = 0; } // now that we're alive, tell the network world that we're here. if (retval == "") TransmitInternal(BSP_ANNOUNCE); } return retval; } // disposal of network access. void BibleSync::Shutdown() { // managed speaker list shutdown. clearSpeakers(); // network shutdown. close(server_fd); close(client_fd); server_fd = client_fd = -1; // internal shutdown. mode = BSP_MODE_DISABLE; nav_func = NULL; } // pick the OS' generation flavor. void BibleSync::uuid_gen(uuid_t &u) { #ifndef WIN32 uuid_generate(u); #else UuidCreate(&u); #endif /* WIN32 */ } // conversion of UUID to printable form. void BibleSync::uuid_dump(uuid_t &u, char *destination) { unsigned char *s = (unsigned char *)&u; snprintf((char *)destination, BSP_UUID_PRINT_LENGTH, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[8], s[9], s[10], s[11], s[12], s[13], s[14], s[15]); } // receiver, object-less, generally from C. // to be called with "myself" as userdata. // this exists so as to be able to dive from object-less C context // into C++ context with reference to "this", the BibleSync object. int BibleSync::Receive(void *myself) { // dive back into object context. return ((BibleSync *)myself)->ReceiveInternal(); } // receiver, in C++ object context. // note that, in expected usage, and per usage by glib's g_timeout_add(), // return TRUE means the function is prepared to be called again, // and return FALSE means the function calls should stop until something // changes. we return FALSE only when mode has been set to BSP_MODE_DISABLE. // ==> THEREFORE... // whenever the application sets any enabled mode, it must also arrange for // Receive() to begin being called regularly. #define DEBUG_LENGTH (4*BSP_MAX_SIZE) // print is bigger than raw int BibleSync::ReceiveInternal() { if (mode == BSP_MODE_DISABLE) return FALSE; // done: un-schedule polling. // nav_func unset => no point trying; no network => just leave. if ((nav_func == NULL) || (server_fd < 0)) return TRUE; char dump[DEBUG_LENGTH]; struct sockaddr_in source; BibleSyncMessage bsp; int recv_size = 0; // anything non-empty here is at least legitimate network traffic. // whether it passes muster for BibleSync is another matter. while ((recv_size = InitSelectRead(dump, &source, &bsp)) > 0) { ((char*)&bsp)[recv_size] = '\0'; // as an ordinary C string // dump content into something humanly useful. uuid_dump(bsp.uuid, uuid_dump_string); snprintf(dump, DEBUG_LENGTH-1, "[%s]\nmagic: 0x%08x\nversion: 0x%02x\ntype: 0x%02x (%s)\n" "uuid: %s\n#pkt: %d\npkt index: %d\n\n-*- body -*-\n%s", inet_ntoa(source.sin_addr), ntohl(bsp.magic), bsp.version, bsp.msg_type, ((bsp.msg_type == BSP_ANNOUNCE) ? "announce" : ((bsp.msg_type == BSP_SYNC) ? "sync" : ((bsp.msg_type == BSP_BEACON) ? "beacon" : "*???*"))), uuid_dump_string, bsp.num_packets, bsp.index_packet, bsp.body); // validate message: fixed values. if (bsp.magic != BSP_MAGIC) (*nav_func)('E', EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, BSP + _("bad magic"), dump); else if (bsp.version != BSP_PROTOCOL) (*nav_func)('E', EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, BSP + _("bad protocol version"), dump); else if ((bsp.msg_type != BSP_ANNOUNCE) && (bsp.msg_type != BSP_SYNC) && (bsp.msg_type != BSP_BEACON)) (*nav_func)('E', EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, BSP + _("bad msg type"), dump); else if (bsp.num_packets != 1) (*nav_func)('E', EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, BSP + _("bad packet count"), dump); else if (bsp.index_packet != 0) (*nav_func)('E', EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, BSP + _("bad packet index"), dump); // basic header sanity tests passed. now parse body content. else { bool ok_so_far(true); char *name, *value; BibleSyncContent content; // structure test and content retrieval // "name=value\n" for each. for (char *s = bsp.body; ok_so_far && *s; ++s) { name = s; // newline terminator of name/value pair. if ((s = strchr(s, '\n')) == NULL) { ok_so_far = false; break; } else { *s = '\0'; // NUL-terminate assignment (end of value). // separator ('=') between name and value. if ((value = strchr(name, '=')) == NULL) { ok_so_far = false; break; } else { *(value++) = '\0'; // NUL-terminate name. // valid content. content[name] = value; } } } if (!ok_so_far) { (*nav_func)('E', EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, BSP + _("bad body format"), dump); } else { // verify minimum body content. int field_count = ((bsp.msg_type == BSP_SYNC) ? BSP_FIELDS_RECV_SYNC : BSP_FIELDS_RECV_ANNOUNCE); // or beacon. for (int i = 0; i < field_count; ++i) { if (content.find(inbound_required[i]) == content.end()) { ok_so_far = false; string info = BSP + _("missing required header ") + inbound_required[i] + "."; (*nav_func)('E', EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, info, dump); // don't break -- find all missing. } } if (ok_so_far) { // find listening status for this guy. string pkt_uuid = content.find(BSP_APP_INSTANCE_UUID)->second; BibleSyncSpeakerMapIterator object = speakers.find(pkt_uuid); string source_addr = inet_ntoa(source.sin_addr); bool listening; // spoof & listen check: if (object != speakers.end()) { // is some legit xmitter's UUID being borrowed? if (object->second.addr != source_addr) // spoof? { // spock: "forbid...forbid!" (*nav_func)('M', pkt_uuid, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, BSP + _("Spoof stopped: ") + pkt_uuid + " from " + source_addr + " instead of " + object->second.addr, dump); continue; } listening = object->second.listen; } else { listening = false; // not in map => ignore. } // loopback is enabled: reject self-uuid packets. unsigned int i; unsigned char *incoming = (unsigned char *)&uuid; unsigned char *mine = (unsigned char *)&bsp.uuid; for (i = 0; i < sizeof(uuid_t); ++i) { if (incoming[i] != mine[i]) break; // not ourselves. } // if we end the loop without early break, // then we matched UUID for ourselves. // i.e. we're hearing an echo of ourselves. ignore. if (i == sizeof(uuid_t)) { #if 0 (*nav_func)('E', pkt_uuid, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, BSP + _("Ignoring echo."), dump); #endif continue; } // give reference items initial filler content. string bible = "<>", ref = "<>", alt = "<>", group = "<>", domain = "<>", info = "<>"; char cmd; string version = content.find(BSP_APP_VERSION)->second; if (version == "") version = (string)"(version?)"; // generally good, so extract interesting content. if (bsp.msg_type == BSP_SYNC) { // regular synchronized navigation bible = content.find(BSP_MSG_SYNC_BIBLEABBREV)->second; ref = content.find(BSP_MSG_SYNC_VERSE)->second; alt = content.find(BSP_MSG_SYNC_ALTVERSE)->second; group = content.find(BSP_MSG_SYNC_GROUP)->second; domain = content.find(BSP_MSG_SYNC_DOMAIN)->second; if (domain != "BIBLE-VERSE") { cmd = 'E'; info = BSP + _("Domain not 'BIBLE-VERSE': ") + domain; } else if ((group.length() != 1) || (group.c_str()[0] < '1') || (group.c_str()[0] > '9')) { cmd = 'E'; info = BSP + _("Invalid group: ") + group; } else if (((mode == BSP_MODE_PERSONAL) || // (receiver || (mode == BSP_MODE_AUDIENCE)) && // receiver) && listening && // being heard && (passphrase == // match content.find(BSP_MSG_PASSPHRASE)->second)) { cmd = 'N'; // navigation } else { cmd = 'M'; // mismatch info = (string)"sync: " + content.find(BSP_APP_USER)->second + " @ " + source_addr; } } else if (bsp.msg_type == BSP_ANNOUNCE) { // construct user's presence announcement bible = content.find(BSP_APP_USER)->second; ref = source_addr; group = content.find(BSP_APP_NAME)->second + " " + version; domain = content.find(BSP_APP_DEVICE)->second; alt = BSP + content.find(BSP_APP_USER)->second + _(" present at ") + source_addr + _(" using ") + group + "."; info = (string)"announce: " + content.find(BSP_APP_USER)->second + " @ " + source_addr; cmd = ((passphrase == content.find(BSP_MSG_PASSPHRASE)->second) ? 'A' // presence announcement : 'M'); // mismatch } else // bsp.msg_type == BSP_BEACON { bible = content.find(BSP_APP_USER)->second; ref = source_addr; group = content.find(BSP_APP_NAME)->second + " " + version; domain = content.find(BSP_APP_DEVICE)->second; info = (string)"beacon: " + content.find(BSP_APP_USER)->second + " @ " + source_addr; if (passphrase == content.find(BSP_MSG_PASSPHRASE)->second) { cmd = ((object == speakers.end()) ? 'S' // unknown: potential speaker. : 'x'); // known: don't tell app again. unsigned int old_speakers_size, new_speakers_size; old_speakers_size = speakers.size(); // whether previously known or not, // a beacon (re)starts the aging countdown. speakers[pkt_uuid].countdown = beacon_count * BSP_BEACON_MULTIPLIER; new_speakers_size = speakers.size(); // record address for first-time-seen beacon, // for anti-spoof checks in the future. if (cmd == 'S') speakers[pkt_uuid].addr = source_addr; if (mode == BSP_MODE_SPEAKER) { // speaker listens to no one. speakers[pkt_uuid].listen = false; } else { // listen to 1st speaker, ignore everyone else. // the app can make other choices. if (cmd == 'S') { speakers[pkt_uuid].listen = ((old_speakers_size == 0) && (new_speakers_size == 1)); } // else someone previously known: don't touch. } } else { cmd = 'M'; // mismatch. } } // delivery to application. if (cmd != 'x') { receiving = true; // re-xmit lock. (*nav_func)(cmd, pkt_uuid, bible, ref, alt, group, domain, info, dump); receiving = false; // re-xmit unlock. } } } } } // beacon-related tasks: others' aging and sending our beacon. ageSpeakers(); if (((mode == BSP_MODE_PERSONAL) || (mode == BSP_MODE_SPEAKER)) && (--beacon_countdown == 0)) { TransmitInternal(BSP_BEACON); beacon_countdown = beacon_count; } return TRUE; } // network read access. // do full initialization, no-wait select, and no-wait recvfrom // to get potential nav data. returns size acquired. // controls 'while' in ReceiveInternal(). int BibleSync::InitSelectRead(char *dump, struct sockaddr_in *source, BibleSyncMessage *buffer) { struct timeval tv = { 0, 0 }; // select returns immediately fd_set read_set; int recv_size = 0; #ifndef WIN32 // yes, really: // linux insists on unsigned int, win32 insists on int. // each complains bitterly of invalid conversion if wrongly used. unsigned #endif int source_length = sizeof(*source); strcpy(dump, _("[no dump ready]")); // initial, pre-read filler FD_ZERO(&read_set); FD_SET(server_fd, &read_set); if (select(server_fd+1, &read_set, NULL, NULL, &tv) < 0) { (*nav_func)('E', EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, BSP + _("select < 0"), dump); return -1; } if ((FD_ISSET(server_fd, &read_set)) && ((recv_size = recvfrom(server_fd, (char *)buffer, BSP_MAX_SIZE, 0, (sockaddr *)source, &source_length)) < 0)) { (*nav_func)('E', EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, BSP + _("recvfrom < 0"), dump); return -1; } return recv_size; } // speaker transmitter // sanity checks for permission to xmit, // then format and ship it. BibleSync_xmit_status BibleSync::TransmitInternal(char message_type, string bible, string ref, string alt, string group, string domain) { if (mode == BSP_MODE_DISABLE) return BSP_XMIT_FAILED; if (receiving && (message_type == BSP_SYNC)) return BSP_XMIT_RECEIVING; // if this occurs, app re-xmit'd. *NO*. if (client_fd < 0) return BSP_XMIT_NO_SOCKET; if ((message_type != BSP_ANNOUNCE) && (message_type != BSP_SYNC) && (message_type != BSP_BEACON)) return BSP_XMIT_BAD_TYPE; if ((mode == BSP_MODE_AUDIENCE) && ((message_type == BSP_SYNC) || (message_type == BSP_BEACON))) return BSP_XMIT_NO_AUDIENCE_XMIT; BibleSyncContent content; BibleSyncMessage bsp; string body = ""; // all name/value pairs. content[BSP_APP_NAME] = application; content[BSP_APP_VERSION] = version; content[BSP_APP_USER] = user; content[BSP_APP_DEVICE] = device; content[BSP_APP_OS] = BSP_OS; content[BSP_APP_INSTANCE_UUID] = uuid_string; content[BSP_MSG_SYNC_BIBLEABBREV] = bible; content[BSP_MSG_SYNC_VERSE] = ref; content[BSP_MSG_SYNC_ALTVERSE] = alt; content[BSP_MSG_SYNC_GROUP] = group; content[BSP_MSG_SYNC_DOMAIN] = domain; content[BSP_MSG_PASSPHRASE] = passphrase; // header. bsp.magic = BSP_MAGIC; bsp.version = BSP_PROTOCOL; bsp.msg_type = message_type; bsp.num_packets = 1; bsp.index_packet = 0; memcpy((void *)&bsp.uuid, (const void *)&uuid, sizeof(uuid_t)); memset((void *)&bsp.reserved, 0, BSP_RES_SIZE); // body prep. int field_count = ((message_type == BSP_SYNC) ? BSP_FIELDS_XMIT_SYNC : BSP_FIELDS_XMIT_ANNOUNCE); // or beacon. for (int i = 0; i < field_count; ++i) { body += outbound_fill[i] + "=" + content[outbound_fill[i]] + "\n"; } // ship it. strncpy(bsp.body, body.c_str(), BSP_MAX_PAYLOAD); unsigned int xmit_size = min(BSP_MAX_SIZE, BSP_HEADER_SIZE + body.length()); // force last == newline: attempt to preserve body format when long. ((unsigned char*)&bsp)[BSP_MAX_SIZE-1] = '\n'; BibleSync_xmit_status retval; if (sendto(client_fd, (char *)&bsp, xmit_size, 0, (struct sockaddr *)&client, sizeof(client)) >= 0) { retval = BSP_XMIT_OK; } else { retval = BSP_XMIT_FAILED; (*nav_func)('E', EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, BSP + _("Transmit failed.\n"), _("Unable to multicast; BibleSync is now disabled. " "If your network connection changed while this program " "was active, it may be sufficient to re-enable.")); Shutdown(); } return retval; } // // privacy setting. // only when in personal mode, allow setting TTL 0 // so that packets do not leave this box. only programs // running right here will hear. // bool BibleSync::setPrivate(bool privacy) { if (mode != BSP_MODE_PERSONAL) privacy = false; // regardless of caller intent. int ttl = (privacy ? 0 : 1); return (setsockopt(client_fd, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl)) >= 0); } // // user decision to listen or not to a certain speaker. // speakerkey is the UUID given during (*nav_func)('S', ...). // void BibleSync::listenToSpeaker(bool listen, string speakerkey) { BibleSyncSpeakerMapIterator object = speakers.find(speakerkey); if (object != speakers.end()) { object->second.listen = listen; } } // // called from ReceiveInternal(). ages entries by one, waiting // to reach zero. on zero, call (*nav_func)('D', ...) to inform // the app that the speaker is dead, then eliminate the element. // void BibleSync::ageSpeakers() { for (BibleSyncSpeakerMapIterator object = speakers.begin(); object != speakers.end(); /* no increment here */) { BibleSyncSpeakerMapIterator victim = object++; // loop increment if (--(victim->second.countdown) == 0) { (*nav_func)('D', victim->first, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY); speakers.erase(victim); } } } // // unconditionally wipe the set of speakers clean. // first, tell the app about each one, then clear. // used when leaving Personal or Audience mode. // void BibleSync::clearSpeakers() { if (nav_func != NULL) { for (BibleSyncSpeakerMapIterator object = speakers.begin(); object != speakers.end(); ++object) { (*nav_func)('D', object->first, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY); } } speakers.clear(); } #ifndef WIN32 #ifdef linux // routines below imported from the net as workable examples. // in order to do multicast setup, we require the address // of the interface that has our default route. code below // finds the name of that interface. then getifaddrs(3) // code (taken from its man page) lets us match that name // against an entry that has the address we need. // extra includes needed only for the // route & gateway discovery code below. #include #include struct route_info { struct in_addr dstAddr; struct in_addr srcAddr; struct in_addr gateWay; char ifName[IF_NAMESIZE]; }; int BibleSync::readNlSock(int sockFd, char *bufPtr, size_t buf_size, unsigned int seqNum, unsigned int pId) { struct nlmsghdr *nlHdr; int readLen = 0, msgLen = 0; do { if((readLen = recv(sockFd, bufPtr, buf_size - msgLen, 0)) < 0) { return -1; } nlHdr = (struct nlmsghdr *)bufPtr; if((NLMSG_OK(nlHdr, readLen) == 0) || (nlHdr->nlmsg_type == NLMSG_ERROR)) { return -1; } /* check if last message */ if(nlHdr->nlmsg_type == NLMSG_DONE) { break; } else { /* else move pointer to buffer appropriately */ bufPtr += readLen; msgLen += readLen; } /* check if multi part message */ if((nlHdr->nlmsg_flags & NLM_F_MULTI) == 0) { /* return if its not */ break; } } while((nlHdr->nlmsg_seq != seqNum) || (nlHdr->nlmsg_pid != pId)); return msgLen; } int BibleSync::parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo) { struct rtmsg *rtMsg; struct rtattr *rtAttr; int rtLen; rtMsg = (struct rtmsg *)NLMSG_DATA(nlHdr); /* if route is not AF_INET or not in main table, return. */ if((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN)) return -1; rtAttr = (struct rtattr *)RTM_RTA(rtMsg); rtLen = RTM_PAYLOAD(nlHdr); for(; RTA_OK(rtAttr,rtLen); rtAttr = RTA_NEXT(rtAttr,rtLen)) { switch(rtAttr->rta_type) { case RTA_OIF: if_indextoname(*(int *)RTA_DATA(rtAttr), rtInfo->ifName); break; case RTA_GATEWAY: memcpy(&rtInfo->gateWay, RTA_DATA(rtAttr), sizeof(rtInfo->gateWay)); break; case RTA_PREFSRC: memcpy(&rtInfo->srcAddr, RTA_DATA(rtAttr), sizeof(rtInfo->srcAddr)); break; case RTA_DST: memcpy(&rtInfo->dstAddr, RTA_DATA(rtAttr), sizeof(rtInfo->dstAddr)); break; } } return 0; } int BibleSync::get_default_if_name(char *name, socklen_t size) { int found_default = 0; struct nlmsghdr *nlMsg; //struct rtmsg *rtMsg; struct route_info route_info; char msgBuf[4096]; int sock, len, msgSeq = 0; name[1] = '\0'; // pre-set, in case of error. if((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) { name[0] = 'x'; return -1; } memset(msgBuf, 0, sizeof(msgBuf)); nlMsg = (struct nlmsghdr *)msgBuf; //rtMsg = (struct rtmsg *)NLMSG_DATA(nlMsg); nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); nlMsg->nlmsg_type = RTM_GETROUTE; nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; nlMsg->nlmsg_seq = msgSeq++; nlMsg->nlmsg_pid = getpid(); if(send(sock, nlMsg, nlMsg->nlmsg_len, 0) < 0) { name[0] = 'y'; return -1; } if((len = readNlSock(sock, msgBuf, sizeof(msgBuf), msgSeq, getpid())) < 0) { name[0] = 'z'; return -1; } for(; NLMSG_OK(nlMsg,len); nlMsg = NLMSG_NEXT(nlMsg,len)) { memset(&route_info, 0, sizeof(route_info)); if ( parseRoutes(nlMsg, &route_info) < 0 ) continue; // don't check: not set up if (strstr((char *)inet_ntoa(route_info.dstAddr), "0.0.0.0")) { // copy it over strcpy(name, route_info.ifName); found_default = 1; break; } } close(sock); return found_default; } #include #include void BibleSync::InterfaceAddress() { // cancel any old interface value. // we must fail with current info, if at all. interface_addr.s_addr = htonl(0x7f000001); // 127.0.0.1 fallback char gw_if[IF_NAMESIZE]; // default gateway interface. (void)get_default_if_name(gw_if, 100); // if no error, search the interface list for that address. if (gw_if[0] != '\0') { struct ifaddrs *ifaddr, *ifa; if (getifaddrs(&ifaddr) == -1) { perror("getifaddrs"); return; } for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) continue; if ((ifa->ifa_addr->sa_family == AF_INET) && (strcmp(gw_if, ifa->ifa_name) == 0)) { interface_addr.s_addr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr; break; } } freeifaddrs(ifaddr); } return; } #else /* linux */ // Solaris & BSD. // // this seeming grotesqueness is in fact the most general command // that could be found which finds the interface holding the default // route and then collects that interface's address. handles both // solaris and bsd. in fact, it suffices for linux as well, but // we're leaving the existing code above in place for linux, if for // no other reason than that it's more likely that someone will // foolishly screw up ifconfig output format in the linux world. // #define ADDRESS "PATH=/sbin:/usr/sbin:/bin:/usr/bin " \ "ifconfig \"`netstat -rn | egrep '^0\\.0\\.0\\.0|^default' | " \ "tr ' ' '\\n' | sed -e '/^$/d' | tail -1`\" | grep 'inet ' | " \ "tr ' ' '\\n' | grep '^[0-9.][0-9.]*$' | head -1 | tr -d '\\n'" void BibleSync::InterfaceAddress() { // cancel any old interface value. // we must fail with current info, if at all. interface_addr.s_addr = htonl(0x7f000001); // 127.0.0.1 fallback FILE *c; if ((c = popen(ADDRESS, "r")) != NULL) { char addr_string[32]; fscanf(c, "%30s", addr_string); interface_addr.s_addr = inet_addr(addr_string); pclose(c); } return; } #endif /* linux */ #else /* WIN32 */ void BibleSync::InterfaceAddress() { // cancel any old interface value. // we must fail with current info, if at all. interface_addr.s_addr = htonl(0x7f000001); // 127.0.0.1 fallback // this code is rudely derived from, and courtesy of, // http://tangentsoft.net/wskfaq/examples/getifaces.html // to whom we are grateful. // this is more simplistic than the linux/unix case. // here, we simply find a functioning multicast-capable interface. WSADATA WinsockData; if (WSAStartup(MAKEWORD(2, 2), &WinsockData) != 0) { return; } SOCKET sd = WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0); if (sd == SOCKET_ERROR) { return; } INTERFACE_INFO InterfaceList[20]; unsigned long nBytesReturned; if (WSAIoctl(sd, SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList, sizeof(InterfaceList), &nBytesReturned, 0, 0) == SOCKET_ERROR) { return; } int nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO); for (int i = 0; i < nNumInterfaces; ++i) { u_long nFlags = InterfaceList[i].iiFlags; if ((nFlags & IFF_UP) && // alive. !(nFlags & IFF_LOOPBACK) && // not local. (nFlags & IFF_MULTICAST)) // multicast-capable. { sockaddr_in *pAddress; pAddress = (sockaddr_in *) & (InterfaceList[i].iiAddress); interface_addr.s_addr = pAddress->sin_addr.s_addr; break; } } return; } #endif /* WIN32 */ biblesync-1.2.0/test/000077500000000000000000000000001326575651300144605ustar00rootroot00000000000000biblesync-1.2.0/test/send-test.c000066400000000000000000000077301326575651300165410ustar00rootroot00000000000000/* * BibleSync library * biblesync.cc * * Karl Kleinpaste, May 2014 * * All files related to implementation of BibleSync, including program * source, READMEs, manual pages, and related similar documents, are in * the public domain. As a matter of simple decency, your social * obligations are to credit the source and to coordinate any changes you * make back to the origin repository. These obligations are non- * binding for public domain software, but they are to be seriously * handled nonetheless. */ #include #include #include #include #include #include #include #include #define BSP_MULTICAST "239.225.27.227" #define BSP_PORT 22272 struct in_addr localInterface; struct sockaddr_in groupSock; int sd; int datalen; char databuf[1024]; unsigned char header[] = { 0x40, 0x9c, 0xaf, 0x11, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; unsigned char body[] = "" "app.name=MUMBLE\n" "app.version=4.3.2.1.0\n" "app.inst.uuid=00112233-4455-6677-8899-aabbccddeeff\n" "app.os=FAKE=OS\n" "app.device=6809 running BeOS\n" "app.user=BSP Tester (bsp)\n" "msg.sync.passPhrase=RandomPhrase\n" "msg.sync.domain=BIBLE-VERSE\n" "msg.sync.group=1\n" "msg.sync.bibleAbbrev=KJV\n" "msg.sync.altVerse=\n" "msg.sync.verse=Gen.1.1\n" ""; unsigned char message[1281], *mptr = &message[32]; /* point at message body. */ /* * argv[1] == local interface address * argv[2] == 1 or 2 * argv[3] == other args * other args must be quoted on the command line w/trailing '\n'. * $ ./send-test 192.168.1.27 2 'msg.sync.passPhrase=TestPhrase * > ' * you can add as many other things here as you like, * all quoted/newlined as one arg. */ int main (int argc, char *argv[]) { if ((argc != 3) && (argc != 4)) { perror("arg count"); exit(1); } /* ------------------------------------------------------------*/ /* */ /* Send Multicast Datagram code example. */ /* */ /* ------------------------------------------------------------*/ /* * Create a datagram socket on which to send. */ sd = socket(AF_INET, SOCK_DGRAM, 0); if (sd < 0) { perror("opening datagram socket"); exit(1); } /* * Initialize the group sockaddr structure with a * group address of 225.1.1.1 and port 5555. */ memset((char *) &groupSock, 0, sizeof(groupSock)); groupSock.sin_family = AF_INET; groupSock.sin_addr.s_addr = inet_addr(BSP_MULTICAST); groupSock.sin_port = htons(BSP_PORT); /* * Disable loopback so you do not receive your own datagrams. */ { char loopch=1; if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loopch, sizeof(loopch)) < 0) { perror("setting IP_MULTICAST_LOOP:"); close(sd); exit(1); } } /* * Set local interface for outbound multicast datagrams. * The IP address specified must be associated with a local, * multicast-capable interface. */ localInterface.s_addr = inet_addr(argv[1]); if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF, (char *)&localInterface, sizeof(localInterface)) < 0) { perror("setting local interface"); exit(1); } /* * Send a message to the multicast group specified by the * groupSock sockaddr structure. */ memcpy(message, header, 32); message[5] = atoi(argv[2]); strcpy(mptr, body); if (argv[3]) strcat(mptr, argv[3]); if (sendto(sd, message, 32+strlen(mptr), 0, (struct sockaddr*)&groupSock, sizeof(groupSock)) < 0) { perror("sending datagram message"); } } biblesync-1.2.0/win32.opts000077500000000000000000000016251326575651300153610ustar00rootroot00000000000000#!/bin/sh WIN32_OPTS= WIN32_OPTS="$WIN32_OPTS -DCMAKE_VERBOSE_MAKEFILE=ON" WIN32_OPTS="$WIN32_OPTS -DCMAKE_INSTALL_PREFIX:PATH=/usr/i686-w64-mingw32/sys-root/mingw" WIN32_OPTS="$WIN32_OPTS -DCMAKE_INSTALL_LIBDIR:PATH=/usr/i686-w64-mingw32/sys-root/mingw/lib" WIN32_OPTS="$WIN32_OPTS -DINCLUDE_INSTALL_DIR:PATH=/usr/i686-w64-mingw32/sys-root/mingw/include" WIN32_OPTS="$WIN32_OPTS -DLIB_INSTALL_DIR:PATH=/usr/i686-w64-mingw32/sys-root/mingw/lib" WIN32_OPTS="$WIN32_OPTS -DSHARE_INSTALL_PREFIX:PATH=/usr/i686-w64-mingw32/sys-root/mingw/share" WIN32_OPTS="$WIN32_OPTS -DCMAKE_SKIP_RPATH:BOOL=ON" WIN32_OPTS="$WIN32_OPTS -DBUILD_SHARED_LIBS:BOOL=ON" WIN32_OPTS="$WIN32_OPTS -DCMAKE_TOOLCHAIN_FILE=/usr/share/mingw/toolchain-mingw32.cmake" WIN32_OPTS="$WIN32_OPTS -DLIBBIBLESYNC_LIBRARY_TYPE=Shared" WIN32_OPTS="$WIN32_OPTS -DCMAKE_BUILD_TYPE=Debug" WIN32_OPTS="$WIN32_OPTS -DCROSS_COMPILE_MINGW32=TRUE" export WIN32_OPTS biblesync-1.2.0/win64.opts000077500000000000000000000016371326575651300153710ustar00rootroot00000000000000#!/bin/sh WIN64_OPTS= WIN64_OPTS="$WIN64_OPTS -DCMAKE_VERBOSE_MAKEFILE=ON" WIN64_OPTS="$WIN64_OPTS -DCMAKE_INSTALL_PREFIX:PATH=/usr/x86_64-w64-mingw32/sys-root/mingw" WIN64_OPTS="$WIN64_OPTS -DCMAKE_INSTALL_LIBDIR:PATH=/usr/x86_64-w64-mingw32/sys-root/mingw/lib" WIN64_OPTS="$WIN64_OPTS -DINCLUDE_INSTALL_DIR:PATH=/usr/x86_64-w64-mingw32/sys-root/mingw/include" WIN64_OPTS="$WIN64_OPTS -DLIB_INSTALL_DIR:PATH=/usr/x86_64-w64-mingw32/sys-root/mingw/lib" WIN64_OPTS="$WIN64_OPTS -DSHARE_INSTALL_PREFIX:PATH=/usr/x86_64-w64-mingw32/sys-root/mingw/share" WIN64_OPTS="$WIN64_OPTS -DCMAKE_SKIP_RPATH:BOOL=ON" WIN64_OPTS="$WIN64_OPTS -DBUILD_SHARED_LIBS:BOOL=ON" WIN64_OPTS="$WIN64_OPTS -DCMAKE_TOOLCHAIN_FILE=/usr/share/mingw/toolchain-mingw64.cmake" WIN64_OPTS="$WIN64_OPTS -DLIBBIBLESYNC_LIBRARY_TYPE=Shared" WIN64_OPTS="$WIN64_OPTS -DCMAKE_BUILD_TYPE=Debug" WIN64_OPTS="$WIN64_OPTS -DCROSS_COMPILE_MINGW32=TRUE" export WIN64_OPTS