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