-
Notifications
You must be signed in to change notification settings - Fork 15
/
socket.h
625 lines (495 loc) · 21.1 KB
/
socket.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
/*
OGN - Open Glider Network - http://glidernet.org/
Copyright (c) 2015 The OGN Project
A detailed list of copyright holders can be found in the file "AUTHORS".
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
// =========================================================================================
#ifndef __SOCKET_H__
#define __SOCKET_H__
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
// #include <netinet/ip_icmp.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#ifndef __CYGWIN__
#include <sys/sendfile.h>
#endif
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
#ifdef __MACH__
#define MSG_NOSIGNAL 0
#endif
class SocketAddress // IP address and port
{ public:
struct sockaddr_in Address;
private:
static const int TmpStringLen = 64;
char TmpString[TmpStringLen];
public:
SocketAddress()
{ Init(); }
void Init(void)
{ Address.sin_family = AF_INET; setIP(); }
// set IP and port from an ASCII string: "IP:port", IP can be numeric or a host name
int set(const char *HostColonPort)
{ const char *Colon=strchr(HostColonPort,':');
if(Colon==0) return setIP(HostColonPort);
int Port; if(sscanf(Colon+1,"%d",&Port)!=1) return -1;
if((Port<0)||(Port>0xFFFF)) return -1;
setPort((unsigned short)Port);
int Len=Colon-HostColonPort; if(Len>=TmpStringLen) return -1;
memcpy(TmpString, HostColonPort, Len); TmpString[Len]='\0';
int Error = setIP(TmpString);
return Error; }
// set only the IP (includes DNS name resolve)
int setIP(const char *AsciiHost)
{ in_addr_t IP=inet_addr(AsciiHost);
if(IP != (in_addr_t)(-1)) { Address.sin_addr.s_addr=IP; return 0; }
struct hostent *Host = gethostbyname(AsciiHost); if(Host==0) return -1;
char *AddrPtr=Host->h_addr_list[0]; if(AddrPtr==0) return -1;
memcpy(&Address.sin_addr, Host->h_addr_list[0], Host->h_length);
return 0; }
// set the IP from a 32-bit integer
int setIP(unsigned long IP=INADDR_ANY)
{ Address.sin_addr.s_addr = htonl(IP); return 0; }
// get IP as a 32-bit integer
unsigned long getIP(void) const
{ return ntohl(Address.sin_addr.s_addr); }
// is the address defined already ?
bool isSetup(void) const
{ return getIP()!=INADDR_ANY; }
int setBroadcast(void)
{ Address.sin_addr.s_addr = htonl(INADDR_BROADCAST); return 0; }
// set the port
int setPort(unsigned short Port)
{ Address.sin_port = htons(Port); return 0; }
// get the port
unsigned short getPort(void) const
{ return ntohs(Address.sin_port); }
// get IP as an ASCII string (to print)
char *getAsciiIP(void) const
{ return inet_ntoa(Address.sin_addr); }
// get my own host name
char *getHostName(void) { return getHostName(TmpString, TmpStringLen); }
static char *getHostName(char *Name, int NameLen)
{ if(gethostname(Name, NameLen)<0) return 0;
return Name; }
// get the "IP:port" ASCII string, IP will be numeric
char *getIPColonPort(void)
{ char *IP = getAsciiIP(); if(IP==0) return IP;
if(strlen(IP)>(TmpStringLen-8)) return 0;
unsigned short Port=getPort();
sprintf(TmpString, "%s:%d", IP, Port);
return TmpString; }
#ifdef __CYGWIN__
#else
char *getRemoteHostName(void)
{ static struct hostent *HostInfo = gethostbyaddr(&Address, sizeof(Address), AF_INET);
return HostInfo->h_name; }
#endif
} ;
class SocketBuffer // data buffer for IP sockets
{ public:
char *Data; // data storage
size_t Allocated; // [bytes] allocated
size_t Len; // [bytes] filled with data
size_t Done; // [bytes] processed
static const size_t AllocUnit = 4096; // allocation step
public:
SocketBuffer()
{ Data=0; Allocated=0; Len=0; Done=0; }
~SocketBuffer()
{ Free(); }
void Free(void)
{ if(Data) { free(Data); Data=0; }
Allocated=0; Len=0; Done=0; }
size_t Relocate(size_t Size)
{ if(Size<=Allocated) return Allocated;
// printf("Relocate(%d)",Size);
size_t Units=(Size+AllocUnit-1)/AllocUnit; Size=Units*AllocUnit;
// printf(" => Units=%d, Size=%d\n", Units, Size);
Data=(char *)realloc(Data, Size); if(Data==0) Free(); else Allocated=Size;
return Allocated; }
int NullTerm(void) // put null byte at the end, thus it can be treated as a null-terminated string
{ if(Relocate(Len+1)<=0) return 0;
Data[Len]=0;
return Len; }
void Clear(void)
{ Len=0; Done=0; }
bool isDone(void) const // is all data processed ?
{ return Done==Len; }
int Delete(size_t Ofs, size_t DelLen) // delete some part of the data (involves memory move)
{ if(Ofs>=Len) return 0;
if((Ofs+DelLen)>Len) DelLen=Len-Ofs;
memcpy(Data+Ofs, Data+Ofs+DelLen, Len-DelLen); Len-=DelLen;
Data[Len]=0; return DelLen; }
int SearchLineTerm(int StartIdx=0) // search for a line terminator: \r or \n
{ size_t Idx; char Term=0;
for( Idx=StartIdx; Idx<Len; Idx++)
{ Term=Data[Idx];
if((Term=='\r')||(Term=='\n')) break; }
if(Idx>=Len) return -1; // return -1 if terminator not found
return Idx-StartIdx; } // return the line length (not including the terminator)
int ReadFromFile(char *FileName)
{ FILE *File = fopen(FileName,"r"); if(File==0) return -1;
int Total=0;
for( ; ; )
{ if(Relocate(Len+AllocUnit)<0) { fclose(File); return -1; }
int ToRead = Allocated-Len;
int Read = fread(Data+Len, 1, ToRead, File);
if(Read<0) { fclose(File); return -1; }
Len+=Read; Total+=Read; if(Read!=ToRead) break;
}
fclose(File);
return Total; }
int WriteToFile(FILE *File=stdout) const
{ int ToWrite = Len-Done; if(ToWrite<0) ToWrite=0;
int Written = fwrite(Data+Done, 1, ToWrite, File);
if(Written<0) return Written;
return Written==ToWrite ? Written:-1; }
int WriteToFile(const char *FileName) const
{ FILE *File = fopen(FileName,"w"); if(File==0) return -1;
int ToWrite = Len-Done; if(ToWrite<0) ToWrite=0;
int Written = fwrite(Data+Done, 1, ToWrite, File);
fclose(File);
if(Written<0) return Written;
return Written==ToWrite ? Written:-1; }
// -----------------------------------------------------------------------------
int LineLen(size_t Ofs=0, size_t MaxLen=256) const
{ size_t Idx=Ofs;
for( ; Idx<Len; Idx++)
{ char Byte=Data[Idx]; if( (Byte=='\r') || (Byte=='\n') ) break; }
return Idx-Ofs; }
int EOL(size_t Ofs) const
{ if(Ofs>=Len) return 0;
char Byte1=Data[Ofs];
if( (Byte1!='\r') && (Byte1!='\n') ) return 0;
Ofs++;
if(Ofs>=Len) return 1;
char Byte2=Data[Ofs];
if( (Byte2!='\r') && (Byte2!='\n') ) return 1;
if(Byte2==Byte1) return 1;
return 2; }
int getStatus(void) const
{ char Protocol[16]; int Status=0;
int FirstLineLen=LineLen(0, 128);
if(FirstLineLen<=8) return -1;
if(FirstLineLen>=128) return -1;
if(sscanf(Data, "%s %d", Protocol, &Status)!=2) return -1;
return Status; }
int getHeaderLen(void) const
{ size_t Idx=0;
for( ; ; )
{ int Len=LineLen(Idx);
int TermLen=EOL(Idx+Len);
Idx+=Len+TermLen;
if(Len==0) break; }
return Idx; }
int FindTag(const char *Tag, size_t Ofs=0)
{ size_t TagLen=strlen(Tag);
for(size_t Idx=Ofs; Idx<Len; Idx++)
{ char Byte=Data[Idx]; if(Byte!='<') continue;
if((Idx+1+TagLen)>=Len) return -1;
if(memcmp(Tag, Data+Idx+1, TagLen)==0) return Idx-Ofs; }
return -1; }
int TagLen(size_t Ofs=0) const
{ for(size_t Idx=Ofs+1; Idx<Len; Idx++)
{ char Byte=Data[Idx]; if(Byte=='>') return Idx-Ofs+1; }
return -1; }
// -----------------------------------------------------------------------------
} ;
class Socket // IP socket
{ public:
int SocketFile;
// unsigned long BytesSent, BytesReceived;
public:
Socket()
{ SocketFile=(-1); }
~Socket()
{ Close(); }
// create a socket
int Create(int Type=SOCK_STREAM, int Protocol=IPPROTO_TCP)
{ Close();
SocketFile=socket(PF_INET, Type, Protocol);
return SocketFile; }
int Create_STREAM(void) { return Create(SOCK_STREAM, IPPROTO_TCP); }
int Create_DGRAM(void) { return Create(SOCK_DGRAM, 0); }
int Copy(int NewSocketFile)
{ Close();
return SocketFile=NewSocketFile; }
// set connect/read/write to be blocking or not
int setBlocking(int Block=1)
{ int Flags = fcntl(SocketFile,F_GETFL,0);
if(Block) Flags &= ~O_NONBLOCK;
else Flags |= O_NONBLOCK;
return fcntl(SocketFile,F_SETFL,Flags); }
int setNonBlocking(void)
{ return setBlocking(0); }
// avoids waiting (in certain cases) till the socket closes completely after the previous server exits
int setReuseAddress(int Set=1)
{ return setsockopt(SocketFile, SOL_SOCKET, SO_REUSEADDR, &Set, sizeof(Set)); }
int setKeepAlive(int KeepAlive=1) // keep checking if connection alive while no data is transmitted
{ return setsockopt(SocketFile, SOL_SOCKET, SO_KEEPALIVE, &KeepAlive, sizeof(KeepAlive)); }
int setLinger(int ON, int Seconds) // gracefull behavior on socket close
{ struct linger Linger; Linger.l_onoff=ON; Linger.l_linger=Seconds;
return setsockopt(SocketFile, SOL_SOCKET, SO_LINGER, &Linger, sizeof(Linger)); }
int setNoDelay(int ON=1)
{ return setsockopt(SocketFile, IPPROTO_TCP, TCP_NODELAY, &ON, sizeof(ON)); }
int setSendBufferSize(int Bytes)
{ return setsockopt(SocketFile, SOL_SOCKET, SO_SNDBUF, &Bytes, sizeof(Bytes)); }
int getSendBufferSize(void)
{ int Bytes=0; socklen_t Size;
int Error=getsockopt(SocketFile, SOL_SOCKET, SO_SNDBUF, &Bytes, &Size);
return Error<0 ? -1:Bytes; }
int setReceiveBufferSize(int Bytes)
{ return setsockopt(SocketFile, SOL_SOCKET, SO_RCVBUF, &Bytes, sizeof(Bytes)); }
int getReceiveBufferSize(void)
{ int Bytes=0; socklen_t Size;
int Error=getsockopt(SocketFile, SOL_SOCKET, SO_RCVBUF, &Bytes, &Size);
return Error<0 ? -1:Bytes; }
/* on Cygwin send and receive timeouts seem to have no effect ...
#ifdef __WINDOWS__
int setReceiveTimeout(double Seconds) // a blocking receive() will not wait forever
{ long Time = (long)floor(1000*Seconds+0.5);
return setsockopt(SocketFile, SOL_SOCKET, SO_RCVTIMEO, &Time, sizeof(Time)); }
int setSendTimeout(double Seconds) // a blocking send() will not wait forever
{ long Time = (long)floor(1000*Seconds+0.5);
return setsockopt(SocketFile, SOL_SOCKET, SO_SNDTIMEO, &Time, sizeof(Time)); }
#endif
*/
#ifdef __CYGWIN__ // dummy routine for Cygwin, only to satify the compiler
int setReceiveTimeout(double Seconds) { return -1; }
int setSendTimeout(double Seconds) { return -1; }
#else
int setReceiveTimeout(double Seconds) // a blocking receive() will not wait forever
{ struct timeval Time;
Time.tv_sec = (long)floor(Seconds);
Time.tv_usec = (long)floor(1000000*(Seconds-Time.tv_sec)+0.5);
return setsockopt(SocketFile, SOL_SOCKET, SO_RCVTIMEO, &Time, sizeof(Time)); }
int setSendTimeout(double Seconds) // a blocking send() will not wait forever
{ struct timeval Time;
Time.tv_sec = (long)floor(Seconds);
Time.tv_usec = (long)floor(1000000*(Seconds-Time.tv_sec)+0.5);
return setsockopt(SocketFile, SOL_SOCKET, SO_SNDTIMEO, &Time, sizeof(Time)); }
#endif
#if defined(__MACH__) || defined(__CYGWIN__)
#else
int getMTU(void)
{ int Bytes;
if(ioctl(SocketFile, SIOCGIFMTU, &Bytes)<0) return -1;
return Bytes; }
#endif
int getReceiveQueue(void)
{ int Bytes;
if(ioctl(SocketFile, FIONREAD, &Bytes)<0) return -1;
return Bytes; }
int getError(void)
{ int ErrorCode=0;
socklen_t Size=sizeof(ErrorCode);
int Error=getsockopt(SocketFile, SOL_SOCKET, SO_ERROR, &ErrorCode, &Size);
return Error<0 ? -1:ErrorCode; }
int isListenning(void)
{ int Yes=0;
socklen_t Size=sizeof(Yes);
int Error=getsockopt(SocketFile, SOL_SOCKET, SO_ACCEPTCONN, &Yes, &Size);
return Error<0 ? -1:Yes; }
// listen for incoming UDP connections (become a UDP server)
int Listen_DGRAM(unsigned short ListenPort)
{ if(SocketFile<0) { if(Create_DGRAM()<0) return -1; }
setReuseAddress(1);
struct sockaddr_in ListenAddress;
ListenAddress.sin_family = AF_INET;
ListenAddress.sin_addr.s_addr = htonl(INADDR_ANY);
ListenAddress.sin_port = htons(ListenPort);
if(bind(SocketFile, (struct sockaddr *) &ListenAddress, sizeof(ListenAddress))<0)
{ Close(); return -1; }
return 0; }
// listen for incoming TCP connections (become a TCP server)
int Listen(unsigned short ListenPort, int MaxConnections=8)
{ if(SocketFile<0) { if(Create()<0) return -1; }
setReuseAddress(1);
struct sockaddr_in ListenAddress;
ListenAddress.sin_family = AF_INET;
ListenAddress.sin_addr.s_addr = htonl(INADDR_ANY);
ListenAddress.sin_port = htons(ListenPort);
if(bind(SocketFile, (struct sockaddr *) &ListenAddress, sizeof(ListenAddress))<0)
{ Close(); return -1; }
if(listen(SocketFile, MaxConnections)<0)
{ Close(); return -1; }
return 0; }
// accept a new client (when being a server)
int Accept(Socket &ClientSocket, SocketAddress &ClientAddress)
{ ClientSocket.Close();
socklen_t ClientAddressLength=sizeof(ClientAddress.Address);
return ClientSocket.SocketFile=accept(SocketFile, (struct sockaddr *) &(ClientAddress.Address), &ClientAddressLength); }
// connect to a remote server
int Connect(SocketAddress &ServerAddress)
{ if(SocketFile<0) { if(Create_STREAM()<0) return -1; } // if no socket yet, create a STREAM-type one.
socklen_t ServerAddressLength=sizeof(ServerAddress.Address);
return connect(SocketFile, (struct sockaddr *) &(ServerAddress.Address), ServerAddressLength); }
// send data (on a connected socket)
int Send(void *Message, int Bytes, int Flags=MSG_NOSIGNAL)
{ return send(SocketFile, Message, Bytes, Flags); }
int Send(const char *Message)
{ return Send((void *)Message, strlen(Message)); }
int Send(SocketBuffer &Buffer, int Flags=MSG_NOSIGNAL)
{ size_t Bytes = Buffer.Len-Buffer.Done; // if(Bytes>4096) Bytes=4096;
int SentBytes=Send(Buffer.Data+Buffer.Done, Bytes, Flags);
if(SentBytes>0) Buffer.Done+=SentBytes;
return SentBytes; }
#ifndef __CYGWIN__
int SendFile(const char *FileName)
{ int File=open(FileName, O_RDONLY); if(File<0) return File;
struct stat Stat; fstat(File, &Stat); int Size=Stat.st_size;
int Ret=sendfile(SocketFile, File, 0, Size);
close(File);
return Ret; }
#endif
// send data (on a non-connected socket)
int SendTo(const void *Message, int Bytes, SocketAddress Address, int Flags=MSG_NOSIGNAL)
{ socklen_t AddressLength=sizeof(Address.Address);
return sendto(SocketFile, Message, Bytes, Flags, (struct sockaddr *) &(Address.Address), AddressLength); }
int SendTo(const void *Message, int Bytes, int Flags=MSG_NOSIGNAL)
{ return sendto(SocketFile, Message, Bytes, Flags, 0, 0); }
// say: I won't send any more data on this connection
int SendShutdown(void)
{ return shutdown(SocketFile, SHUT_WR); }
#ifndef __CYGWIN__ // Cygwin C++ does not know abour TIOCOUTQ ?
int getSendQueue(void)
{ int Bytes;
ioctl(SocketFile, TIOCOUTQ, &Bytes);
return Bytes; }
#endif
// receive data (on a stream socket)
int Receive(void *Message, int MaxBytes, int Flags=MSG_NOSIGNAL)
{ int Len=recv(SocketFile, Message, MaxBytes, Flags);
if(Len>=0) return Len;
return errno==EWOULDBLOCK ? 0:Len; }
// receive (stream) data into a buffer
int Receive(SocketBuffer &Buffer, int Flags=MSG_NOSIGNAL)
{ size_t NewSize=Buffer.Len+Buffer.AllocUnit/2;
size_t Allocated=Buffer.Relocate(NewSize);
int MaxBytes=Allocated-Buffer.Len-1;
int ReceiveBytes=Receive(Buffer.Data+Buffer.Len, MaxBytes, Flags);
// printf("Allocated = %d, Receive(%d) => %d\n", Allocated, MaxBytes, ReceiveBytes);
if(ReceiveBytes>0) { Buffer.Len+=ReceiveBytes; Buffer.Data[Buffer.Len]=0; }
return ReceiveBytes; }
// receive data (on a non-connected socket)
int ReceiveFrom(void *Message, int MaxBytes, SocketAddress &Address, int Flags=MSG_NOSIGNAL)
{ socklen_t AddressLength=sizeof(Address.Address);
return recvfrom(SocketFile, Message, MaxBytes, Flags, (struct sockaddr *) &(Address.Address), &AddressLength); }
// tell if socket is open
int isOpen(void) const
{ return SocketFile>=0; }
// close the socket
int Close(void)
{ if(SocketFile>=0) close(SocketFile);
SocketFile=(-1); return 0; }
// get the local IP and port
int getLocalAddress(SocketAddress &Address)
{ socklen_t AddressLength=sizeof(Address.Address);
return getsockname(SocketFile, (struct sockaddr *) &(Address.Address), &AddressLength); }
// get the remote IP and port
int getRemoteAddress(SocketAddress &Address)
{ socklen_t AddressLength=sizeof(Address.Address);
return getpeername(SocketFile, (struct sockaddr *) &(Address.Address), &AddressLength); }
static void CopyNetToHost(uint32_t *Dst, uint32_t *Src, int Words)
{ for( ; Words; Words--) (*Dst++) = ntohl(*Src++); }
static void CopyHostoNet(uint32_t *Dst, uint32_t *Src, int Words)
{ for( ; Words; Words--) (*Dst++) = htonl(*Src++); }
} ;
class UDP_Sender
{ public:
Socket Sock;
const static int MaxDest = 4;
SocketAddress Dest[MaxDest];
public:
void ClearDest(void) // clear the list of destination IP's
{ for(int Idx=0; Idx<MaxDest; Idx++)
{ Dest[Idx].setIP((long unsigned int)0); }
}
int Open(void) { ClearDest(); return Sock.Create_DGRAM(); }
int isOpen(void) const { return Sock.isOpen(); }
int Close(void) { return Sock.Close(); }
int setNonBlocking(void) { return Sock.setNonBlocking(); }
int addDest(const char *Addr)
{ for(int Idx=0; Idx<MaxDest; Idx++)
{ if(Dest[Idx].getIP()==0)
{ if(Dest[Idx].set(Addr)<0) return -1;
return Idx; }
}
return -1; }
/*
int addBroadcast(void)
{ int Idx;
for( Idx=0; Idx<MaxDest; Idx++)
{ if(Dest[Idx].getIP()==0)
{ if(Dest[Idx].SetIP(INADDR_BROADCAST)<0) return -1;
return Idx; }
}
return -1; }
*/
void PrintDest(void)
{ printf("Dest[] =");
for(int Idx=0; Idx<MaxDest; Idx++)
{ if(Dest[Idx].getIP()==0) continue;
printf(" %s", Dest[Idx].getIPColonPort()); }
printf("\n");
}
int Send(uint32_t *Msg, int Words)
{ return Send((void *)Msg, Words*sizeof(uint32_t)); }
int Send(void *Msg, int Bytes)
{ int Count=0;
for( int Idx=0; Idx<MaxDest; Idx++)
{ if(Dest[Idx].getIP()==0) continue;
if(Sock.SendTo(Msg, Bytes, Dest[Idx])<0) continue;
Count++; }
return Count; }
int Receive(void *Msg, int MaxBytes, SocketAddress &Source)
{ return Sock.ReceiveFrom(Msg, MaxBytes, Source); }
} ;
class UDP_Receiver
{ public:
Socket Sock;
public:
int Open(int Port) { return Sock.Listen_DGRAM(Port); }
int Close(void) { return Sock.Close(); }
int setNonBlocking(void) { return Sock.setNonBlocking(); }
// int getPort(void) const { return Sock.}
int Receive(void *Msg, int MaxBytes, SocketAddress &Source)
{ return Sock.ReceiveFrom(Msg, MaxBytes, Source); }
int Receive(uint32_t *Msg, int MaxWords, SocketAddress &Source)
{ int Words=Sock.ReceiveFrom(Msg, MaxWords*sizeof(uint32_t), Source);
return Words<0 ? Words:Words/sizeof(uint32_t); }
} ;
// open TCP client connection to a server: return socket file number
int openTCP(const char *HostName, int Port=80)
{ struct hostent *Server = gethostbyname(HostName); if(Server==0) return -1;
struct sockaddr_in ServerAddr;
memset(&ServerAddr, 0x00, sizeof(struct sockaddr_in));
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons(Port);
memcpy(&ServerAddr.sin_addr, Server->h_addr, sizeof(ServerAddr.sin_addr));
int Socket = socket(AF_INET, SOCK_STREAM, 0); if(Socket<0) return -1;
return connect(Socket, (struct sockaddr *)&ServerAddr, sizeof(ServerAddr)); }
#endif // of __SOCKET_H__
// =========================================================================================