1 /*
2    gnauralnet.h
3    Depends on:
4    gnauralnet.h
5    gnauralnet_clocksync.c
6    gnauralnet_lists.c
7    gnauralnet_main.c
8    gnauralnet_socket.c
9 
10    Copyright (C) 2009  Bret Logan
11 
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 2 of the License, or
15    (at your option) any later version.
16 
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21 
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25  */
26 
27 /*
28  * This is the first attempt at GnauralNet, for now basically a hack
29  * to allow Gnaural to "talk" via TCP/IP sockets other programs. The
30  * main approach is simply to assume all communicating programs are
31  * using copies of the same Schedule file, thus the only thing that
32  * needs to be shared is the CurrentSampleCount within the running of that
33  * schedule, plus enough general timing data to estimate clock offset.
34  *
35  * */
36 
37 //gnauralnet.h: the stuff that gnaural_*.c files will need
38 #ifndef _GNAURALNET_H_
39 #define _GNAURALNET_H_
40 
41 //First the stuff that all platforms get:
42 #include <glib.h>
43 #include <gdk/gdk.h>    //needed for gdk_threads_init()
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <time.h>
47 #include <sys/types.h>
48 #include <errno.h>
49 #include <string.h>
50 #include <signal.h>     //needed for SIGINT
51 
52 //Now the stuff that is platform dependent:
53 #ifdef GNAURAL_WIN32
54 //WIN32:
55 #include <w32api.h>
56 #include <windows.h>
57 #include <winsock.h>
58 #include <lmcons.h>
59 #define GNAURAL_CLOSE_SOCKET(socket) closesocket (socket)
60 #define GNAURAL_IS_SOCKET_ERROR(status) ((status) == SOCKET_ERROR)
61 #define GNAURAL_IS_INVALID_SOCKET(socket) ((socket) == INVALID_SOCKET)
62 #define GNAURAL_IS_CONNECT_STATUS_INPROGRESS() (WSAGetLastError () == WSAEWOULDBLOCK)
63 #else
64 //UNIX:
65 #include <sys/socket.h>
66 #include <arpa/inet.h>
67 #include <netinet/in.h>
68 #include <unistd.h>
69 #include <sys/poll.h>
70 #include <unistd.h>
71 #include <fcntl.h>
72 #define SOCKET int
73 #define GNAURAL_CLOSE_SOCKET(socket) close (socket)
74 #define GNAURAL_IS_SOCKET_ERROR(status) ((status) == -1)
75 #define GNAURAL_IS_INVALID_SOCKET(socket) ((socket) < 0)
76 #define GNAURAL_IS_CONNECT_STATUS_INPROGRESS() (errno == EINPROGRESS)
77 #endif
78 
79 /* Choosing port numbers:
80  * Port numbers 1-1023 are normally reserved for privilegded
81  * processes. These ports cannot be assigned to a local end
82  * of an TCP/IP connection by a normal process. Port numbers
83  * 1024-4999 are used as so called ephemeral port numbers.
84  * These port numbers are assigned automatically by TCP and
85  * UDP if no specific port number was requested. Therefore,
86  * any normal user service should be mapped to port numbers
87  * greater or equal than 5000.
88  */
89 //g=7 n=14 a=1 u=21 r=18 a=1 l=12
90 #define GNAURALNET_PORT 7141    //Default port Gnauralnet uses; arbitrary
91 #define GN_MISSED_RECV_LIMIT 6
92 #define GNAURALNET_VERSION 0
93 #define GNAURALNET_FAILURE -1
94 #define GNAURALNET_SUCCESS 0
95 #define GNAURALNET_TRUE 1
96 #define GNAURALNET_FALSE 0
97 #define GNAURALNET_UNKNOWN 0    //KEEP ZERO, to avoid ntohl/htonl confusion
98 #define GN_MainLoopInterval_secs 1      //sets the send interval
99 #define GN_MainLoopInterval_usecs 0     //fractional part of send interval;NEVER >= 1e6
100 
101 //###################
102 //Uncomment this one to make all the gnauralnet_* code run without Gnaural:
103 //#define GN_STANDALONE
104 #define GNAURALNET_GTHREADS
105 //###################
106 
107 //these are the states gnauralnet can be in:
108 enum
109 {
110  GNAURALNET_RUNNING,
111  GNAURALNET_STOPPED,
112  GNAURALNET_WAITINGTOSTOP
113 };
114 
115 //these are the sorts of data a client can request as msgtype:
116 enum
117 {
118  GN_MSGTYPE_TIMEINFO,
119  GN_MSGTYPE_PHASEINFO,
120  GN_MSGTYPE_EMPTY,
121  GN_MSGTYPE_END
122 };
123 
124 ///////////
125 //START: Functions and variable users will want
126 extern int GN_start (int (*main_loop_function) (void *ptr), void (*GN_ProcessIncomingData) (char *MsgBuf, int sizeof_MsgBuf, struct sockaddr_in * saddr_remote));       //all you need to start gnauralnet
127 extern void GN_stop ();         //all you need to stop gnauralnet
128 
129 //user creates the following 2; see examples in gnauralnet.c:
130 extern int (*GN_MainLoop) (void *ptr);  // this gets set to whatever the user wants
131 extern int GN_MainLoop_default (void *arg);     // the built-in Main Loop, used if GN_start (NULL)
132 extern void (*GN_ProcessIncomingData) (char *MsgBuf, int sizeof_MsgBuf,
133                                        struct sockaddr_in * saddr_remote);
134 extern void GN_ProcessIncomingData_default (char *MsgBuf, int sizeof_MsgBuf,
135                                             struct sockaddr_in *saddr_remote);
136 
137 //Socket functions:
138 extern int GN_Socket_RecvMessage (SOCKET sok, char *MsgBuf, int sizeof_MsgBuf,
139                                   unsigned int secs, unsigned int usecs);
140 extern int GN_Socket_SendMessage (SOCKET sok, char *MsgBuf, int sizeof_MsgBuf,
141                                   unsigned int IP, unsigned short port);
142 extern SOCKET GN_Socket_MakeUDP (int temp_port);        //set to non-blocking
143 extern void GN_Socket_SetBlocking (SOCKET sok, int yesflag);
144 extern int GN_Socket_IsReadyForRead (int sd, unsigned int secs,
145                                      unsigned int usecs);
146 extern int GN_Socket_SetLocalInfo ();   //sets GN_My_IP, GN_My_Port, GN_My_ID
147 
148 //END: Functions and variable users will want
149 /////////////////////////////////////////////
150 
151 //////////////////////////////////////////////////////////////
152 //this is the basis for our Friend linked list.
153 typedef struct GN_Friend_type
154 {
155  //First the stuff that only gets set upon initial meeting:
156  unsigned int ID;               //Random Number, already in network order
157  unsigned int IP;               //IP sockaddr_in.sin_addr.s_addr, already in network order
158  unsigned short Port;           //already in network order
159  GTimeVal TimeOfDiscovery;      //local timestamp of when friend was met
160 
161  //Next the stuff that gets set every receive from friend:
162  unsigned int FriendCount;      //how many friends the friend knows
163  unsigned int RecvCount;
164  GTimeVal Time_Recv;            // my clock
165  //unsigned int Time_DelayOnFriend;     //time (usecs) between friend recv'ing my msg to sending theirs
166  unsigned int Time_PacketRoundTrip;     //round trip time (usecs) packed was actually on net from my send to friend's reply
167  unsigned short RunningID;      //will be 0 if not Running
168  unsigned short ScheduleFingerprint;    //will be 0 if not Running
169  unsigned int RunningSeniority; //secs participating in this Running; used to determine who has most "right" samplecount
170  double Time_AverageOffset;     //
171  unsigned int CurrentSampleCount;
172  unsigned int CurrentSampleCount_diff;
173  int LoopCount;
174 
175  //Next the stuff that gets set on sends:
176  unsigned int SendCount;
177  GTimeVal Time_Send;            //time I sent (my clock)
178  unsigned int Time_DelayOnMe;   //time from recv to my send in usecs; so far not really used internally
179 
180  //Next the stuff that gets set on both send/recv:
181  int SendRecvTally;             //incremented on send, zeroed on recv
182  //unsigned char PacketID;      //incremented every send, and set every recv -- by both friends. To have a reference to be sure packets are in-order
183  //unsigned char PacketID_expected;     //will always be one-more than PacketID;  every send, and set every recv -- by both friends. To have a reference to be sure packets are in-order
184  //char PacketID_reliability;   //keeps track of PacketID record -- incremented on correct receives, decremented on errors, limited at +/-127
185 
186  //Finally, the stuff needed to make a linked list:
187  struct GN_Friend_type *NextFriend;
188  struct GN_Friend_type *PrevFriend;
189 } GN_Friend;
190 
191 //These are only needed internally or general utility:
192 extern int GN_init ();          //called by GN_start()
193 extern void GN_cleanup ();      //called by GN_stop()
194 extern void GN_sleep (unsigned int microsecs);
195 extern void GN_FriendList_DeleteFriend (GN_Friend * curFriend);
196 extern void GN_FriendList_DeleteAll ();
197 extern void GN_FriendList_Invite (unsigned int IP,      //MUST BE IN NET ORDER
198                                   unsigned short Port); //MUST BE IN NET ORDER)
199 extern GN_Friend *GN_FriendList_AddFriend (unsigned int ID,     //MUST BE IN NET ORDER
200                                            unsigned int IP,     //MUST BE IN NET ORDER
201                                            unsigned short Port);        //MUST BE IN NET ORDER
202 extern GN_Friend *GN_FriendList_GetFriend (unsigned int ID,     //MUST BE IN NET ORDER
203                                            unsigned int IP,     //MUST BE IN NET ORDER
204                                            unsigned short Port);        //MUST BE IN NET ORDER
205 extern unsigned int GN_FriendList_FriendCount ();
206 extern GN_Friend *GN_FriendList_NextFriend ();
207 extern GN_Friend *GN_FriendList_RandomFriend (GN_Friend * excludeFriend);       //excludeFriend can be anything
208 extern void GN_ProcessOutgoingData (GN_Friend * curFriend);     //a convenience
209 extern void GN_ProcessInviteData (unsigned int InviteID,        //MUST BE IN NET ORDER
210                                   unsigned int InviteIP,        //MUST BE IN NET ORDER
211                                   unsigned short InvitePort);   //MUST BE IN NET ORDER
212 extern GN_Friend *GN_ProcessNewFriend (unsigned int ID, //MUST BE IN NET ORDER
213                                        unsigned int IP, //MUST BE IN NET ORDER
214                                        unsigned short Port);    //MUST BE IN NET ORDER)
215 extern unsigned int GN_Time_ElapsedSinceLastCall ();
216 extern void GN_Running_ProcessIncomingData (GN_Friend * curFriend);     //does the BB processing
217 extern void GN_Running_ProcessOutgoingData (GN_Friend * curFriend);     //does the BB processing
218 extern unsigned int GN_Running_GetScheduleFingerprint ();       //ONLY RUN AFTER BB IS LOADED
219 extern void GN_PrintAddressInfo (unsigned int id, unsigned int ip,
220                                  unsigned short port);
221 extern void GN_PrintFriends ();
222 extern void GN_PrintPacketContents ();
223 extern void GN_Time_ResetSeniority ();
224 
225 //From gnauralnet_clocksync.c:
226 extern int GN_Time_ProcessIncomingData (GN_Friend * curFriend);
227 void GN_Time_ProcessOutgoingData (GN_Friend * curFriend);
228 
229 //From gnauralnet_gui.c:
230 void GN_ShowInfo ();
231 
232 //Global variables:
233 extern unsigned short GN_ScheduleFingerprint;
234 typedef struct GN_Globals_type
235 {
236  int State;                     //DO NOT MOVE THIS; it gets initialized in gnauralnet_main
237  short LoopCount;               //BB data
238  unsigned int IP;               //IS IN NET ORDER
239  unsigned int ID;               //random IS IN NET ORDER
240  unsigned short FriendCount;    //holds snapshots/estimates of current number of friends in linked list
241  unsigned short LoverCount;     //holds snapshots/estimates of current number of lovers in linked list
242  unsigned short RunningID;      //0 if not in a running
243  unsigned short ScheduleFingerprint;    //gets set whenever a file is opened by Gnaural
244  GTimeVal RunningStartTime;
245  unsigned int CurrentSampleCount;       //BB data
246  unsigned short Port;           //IS IN NET ORDER
247  SOCKET Socket;                 //the one socket used by Gnaural
248  GN_Friend *FirstFriend;
249 } GN_Globals;
250 extern GN_Globals GN_My;
251 extern int GN_DebugFlag;
252 
253 //END: Functions and variable users will want
254 ///////////
255 
256 //////////////////////////////////////////////////////////////////////////
257 //This union holds all the kinds of data friends will share
258 //NOTE: compilers apparently don't necessarily pack structs
259 //the same way (aside from platform endianess -- which is another issue).
260 //TO AVOID ALL PROBLEMS, *ALWAYS* pack data in dword (32-bit/4-byte/int) sizes,
261 //because Linux always will anyway. . To illustrate, a struck like this:
262 // char, char, char, char, int
263 //or
264 // int, char, char, char, char
265 //will be 8 bytes in size, while a struct like this:
266 // char, int, char, char, char
267 //will be 12 bytes. Yuck!
268 //BTW, one like this:
269 // char
270 //will be 1 byte, and one like this:
271 // char, char
272 //will be two bytes.
273 //IMPORTANT NOTE: remember that anything bigger than a char
274 //MUST be htonx for sending then ntohx when received:
275 typedef union
276 {
277  unsigned char msgtype;         //first uchar is ALWAYS message type
278  struct TimeInfo
279  {
280   unsigned char msgtype;        //first uchar is ALWAYS message type
281   unsigned char empty;          //struct padding, can be for future use
282   unsigned short InvitePort;    //Port for the InviteIP
283   unsigned int InviteIP;        //IP address of a potential new friend
284   unsigned int InviteID;        //ID of the Invite - only used to check for friend, since IDs aren't sent in Invites
285   unsigned int ID;              //A pseudorandom number I call my ID
286   unsigned int Time_DelayOnMe;  //time (usecs) from when I recived Friend's msg to sending my own back
287   unsigned int CurrentSampleCount;
288   unsigned short FriendCount;
289   unsigned short RunningSeniority;      //secs participating in this Running
290   unsigned short RunningID;     //will be 0 if not Running
291   unsigned short ScheduleFingerprint;   //just the lower-half of the uint
292   short int LoopCount;
293  } TimeInfo;
294 } GN_CommBuffer;
295 
296 //Two are created because with one, overlapping/interleaved
297 //sends and recvs polluted each other:
298 extern GN_CommBuffer GN_SendBuffer;
299 extern GN_CommBuffer GN_RecvBuffer;
300 
301 //////////////////////////////////////////////////////////////
302 extern int GN_DebugFlag;        //make !=0 to spit out debug info
303 
304 #define GN_DBGFLAG if (0 != GN_DebugFlag)
305 #define GN_DBGOUT_STR(a,b)            GN_DBGFLAG  fprintf(stderr,"%s %d: %s %s\n",__FILE__,__LINE__,a, b);
306 #define GN_DBGOUT_INT(a,b)            GN_DBGFLAG  fprintf(stderr,"%s %d: %s %d\n",__FILE__,__LINE__,a, b);
307 #define GN_DBGOUT_UINT(a,b)           GN_DBGFLAG  fprintf(stderr,"%s %d: %s %u\n",__FILE__,__LINE__,a, b);
308 #define GN_DBGOUT_DBL(a,b)            GN_DBGFLAG  fprintf(stderr,"%s %d: %s %g\n",__FILE__,__LINE__,a, b);
309 #define GN_DBGOUT_PNT(a,b)            GN_DBGFLAG  fprintf(stderr,"%s %d: %s %p\n",__FILE__,__LINE__,a,b);
310 #define GN_DBGOUT(a)                  GN_DBGFLAG  fprintf(stderr,"%s %d: %s\n",__FILE__,__LINE__,a);
311 #define GN_DBG()                      GN_DBGFLAG  fprintf(stderr,"%s %d\n",__FILE__,__LINE__);
312 #define GN_ERROUT(a)                  GN_DBGFLAG  fprintf(stderr,"%s %d: #Error# %s\n",__FILE__,__LINE__,a);
313 
314 #endif
315