-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathtdsocket.h
More file actions
797 lines (697 loc) · 23.9 KB
/
tdsocket.h
File metadata and controls
797 lines (697 loc) · 23.9 KB
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
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
/*
* $Id$
*
* SocketAPI implementation for the sctplib.
* Copyright (C) 2005-2026 by Thomas Dreibholz
*
* Realized in co-operation between
* - Siemens AG
* - University of Duisburg-Essen, Institute for Experimental Mathematics
* - Münster University of Applied Sciences, Burgsteinfurt
*
* Acknowledgement
* This work was partially funded by the Bundesministerium fuer Bildung und
* Forschung (BMBF) of the Federal Republic of Germany (Foerderkennzeichen 01AK045).
* The authors alone are responsible for the contents.
*
* 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 program. If not, see <http://www.gnu.org/licenses/>.
*
* Contact: discussion@sctp.de
* thomas.dreibholz@gmail.com
* tuexen@fh-muenster.de
*
* Purpose: Socket Implementation
*
*/
#ifndef TDSOCKET_H
#define TDSOCKET_H
#include "tdsystem.h"
#include "internetaddress.h"
#include "internetflow.h"
#include "ext_socket.h"
#include <fcntl.h>
/**
* UDP header size.
*/
const cardinal UDPHeaderSize = 8;
/**
* IPv4 header size.
*/
const cardinal IPv4HeaderSize = 20;
/**
* IPv6 header size.
*/
const cardinal IPv6HeaderSize = 40;
/**
* This class manages a socket. IPv6 support is automatically available,
* when supported by the system.
*
* @short Socket
* @author Thomas Dreibholz (thomas.dreibholz@gmail.com)
* @version 1.0
*/
class Socket
{
// ====== Definitions ====================================================
public:
enum SocketFamily {
UndefinedSocketFamily = -1,
IP = 255,
IPv4 = AF_INET, // Do not use IPv4/IPv6,
IPv6 = AF_INET6, // use IP instead!
Unix = AF_UNIX
};
enum SocketType {
UndefinedSocketType = -1,
UDP = SOCK_DGRAM,
Datagram = SOCK_DGRAM,
TCP = SOCK_STREAM,
Stream = SOCK_STREAM,
Raw = SOCK_RAW,
RDM = SOCK_RDM,
SeqPacket = SOCK_SEQPACKET
};
enum SocketProtocol {
UndefinedSocketProtocol = -1,
Default = 0,
ICMPv4 = IPPROTO_ICMP,
ICMPv6 = IPPROTO_ICMPV6,
SCTP = IPPROTO_SCTP
};
enum GetSocketAddressFlags {
GLAF_HideLoopback = (1 << 0),
GLAF_HideLinkLocal = (1 << 1),
GLAF_HideSiteLocal = (1 << 2),
GLAF_HideLocal = GLAF_HideLoopback|GLAF_HideLinkLocal|GLAF_HideSiteLocal,
GLAF_HideAnycast = (1 << 3),
GLAF_HideMulticast = (1 << 4),
GLAF_HideBroadcast = (1 << 5),
GLAF_HideReserved = (1 << 6),
GLAF_Default = GLAF_HideLoopback|GLAF_HideLinkLocal|Socket::GLAF_HideSiteLocal|GLAF_HideBroadcast|GLAF_HideMulticast|GLAF_HideAnycast
};
// ====== Constructor/Destructor =========================================
/**
* Constructor.
*/
Socket();
/**
* Constructor for a new socket. For automatic usage of IPv6 when available,
* set communication family to IP. Use IPv4/IPv6 only if a special
* protocol version is necessary!
* The creation success can be checked using ready() method.
*
* @param family Communication family (e.g. IP).
* @param socketType Socket type (e.g. TCP, UDP).
* @param socketProtocol Socket protocol (e.g. Default).
*
* @see ready
*/
Socket(const integer family,
const integer socketType,
const integer socketProtocol = Default);
/**
* Destructor.
*/
~Socket();
// ====== Create/close socket ============================================
/**
* Close existing socket and create new socket. For automatic usage of
* IPv6 when available, set communication family to IP.
* Use IPv4/IPv6 only if a special protocol version is necessary!
*
* @param socketFamily Communication family (e.g. IP).
* @param socketType Socket type (e.g. TCP, UDP).
* @param socketProtocol Socket protocol (e.g. Default).
* @return true, if creation was sucessful; false otherwise.
*/
bool create(const integer socketFamily = IP,
const integer socketType = TCP,
const integer socketProtocol = Default);
/**
* Close socket.
*/
void close();
/**
* Shutdown full-duplex connection partial or completely.
* SHUT_RD - further receives will be disallowed.
* SHUT_WR - further sends will be disallowed.
* SHUT_RDWR - further sends and receives will be disallowed.
*
* @param shutdownLevel SHUT_RD, SHUT_WR, SHUT_RDWR.
*/
void shutdown(const cardinal shutdownLevel);
// ====== Socket properties ==============================================
/**
* Get socket's family.
*
* @return Socket family.
*/
inline integer getFamily() const;
/**
* Get socket's type.
*
* @return Socket type.
*/
inline integer getType() const;
/**
* Get socket's protocol.
*
* @return Socket protocol.
*/
inline integer getProtocol() const;
// ====== Socket control functions =======================================
/**
* Check, if socket is ready.
*
* @return true, if socket is ready; false otherwise.
*/
inline bool ready() const;
/**
* Bind socket to given address. If address is null address, then
* INADDR_ANY and an automatically selected port will be used.
*
* @param address Socket address.
* @return true on success; false otherwise.
*/
bool bind(const SocketAddress& address = InternetAddress());
/**
O * Bind socket to one or more given addresses. If no addresses are given,
* INADDR_ANY and an automatically selected port will be used.
*
* @param addressArray Array of socket addresses.
* @param addresses Number of addresses.
* @param flags Flags.
* @return true on success; false otherwise.
*/
bool bindx(const SocketAddress** addressArray = NULL,
const cardinal addresses = 0,
const integer flags = 0);
/**
* Set socket to listen mode with given backlog (queue length for sockets
* waiting for acception).
*
* @param backlog Backlog.
* @return true on success; false otherwise.
*/
bool listen(const cardinal backlog = 5);
/**
* Accept a connection.
*
* @param address Reference to store SocketAddress object to with peer's address to (NULL to skip).
* @return New socket.
*/
Socket* accept(SocketAddress** address = NULL);
/**
* Connect socket to given address. A value for traffic class is supported
* if the connection is an IPv6 connection; otherwise it is ignored.
*
* @param address Address.
* @param trafficClass Traffic class of the connection (IPv6 only!)
* @return true on success; false otherwise.
*/
bool connect(const SocketAddress& address, const card8 trafficClass = 0);
/**
* Connect socket to destination given by list of addresses. A value for
* traffic class is supported if the connection is an IPv6 connection;
* otherwise it is ignored.
*
* @param address Address.
* @param trafficClass Traffic class of the connection (IPv6 only!)
* @return true on success; false otherwise.
*/
bool connectx(const SocketAddress** addressArray,
const size_t addresses);
// ====== Error code =====================================================
/**
* Get last error code. It will be reset to 0 after copying.
*
* @return Last error code.
*/
inline integer getLastError();
// ====== Socket options =================================================
/**
* Get socket option (wrapper for getsockopt());
*
* @param level Level (e.g. SOL_SOCKET).
* @param optionNumber Option (e.g. SO_REUSEADDR).
* @param optionValue Memory to store option got from getsockopt().
* @param optionLength Memory with size of option memory.
* @return Result from getsockopt().
*/
inline integer getSocketOption(const cardinal level,
const cardinal optionNumber,
void* optionValue,
socklen_t* optionLength);
/**
* Get SO_LINGER option of socket.
*
* @return SO_LINGER value.
*/
cardinal getSoLinger();
/**
* Get SO_REUSEADDR option of socket.
*
* @return SO_REUSEADDR value.
*/
bool getSoReuseAddress();
/**
* Get SO_BROADCAST option of socket.
*
* @return SO_BROADCAST value.
*/
bool getSoBroadcast();
/**
* Get TCP_NODELAY option of socket.
*
* @return TCP_NODELAY value.
*/
bool getTCPNoDelay();
/**
* Check, if blocking mode is on.
*
* @return true, if blocking mode is on; false otherwise.
*/
bool getBlockingMode();
/**
* Get socket option (wrapper for getsockopt());
*
* @param level Level (e.g. SOL_SOCKET).
* @param optionNumber Option (e.g. SO_REUSEADDR).
* @param optionValue Memory with option.
* @param optionLength Length of option memory.
* @return Result from setsockopt().
*/
inline integer setSocketOption(const cardinal level,
const cardinal optionNumber,
const void* optionValue,
const socklen_t optionLength);
/**
* Set SO_LINGER option of socket.
*
* @param on true to set linger on; false otherwise.
* @param linger SO_LINGER in seconds.
* @return true for success; false otherwise.
*/
bool setSoLinger(const bool on, const cardinal linger);
/**
* Set SO_REUSEADDR option of socket.
*
* @param on true to set SO_REUSEADDR on; false otherwise.
* @return true for success; false otherwise.
*/
bool setSoReuseAddress(const bool on);
/**
* Set SO_BROADCAST option of socket.
*
* @param on true to set SO_BROADCAST on; false otherwise.
* @return true for success; false otherwise.
*/
bool setSoBroadcast(const bool on);
/**
* Set TCP_NODELAY option of socket.
*
* @param on true to set TCP_NODELAY on; false otherwise.
* @return true for success; false otherwise.
*/
bool setTCPNoDelay(const bool on);
/**
* Set blocking mode.
*
* @param on True to set blocking mode, false to unset.
* @param true for success; false otherwise.
* @return true for success; false otherwise.
*/
bool setBlockingMode(const bool on);
// ====== Get flow label/traffic class ===================================
/**
* Get flow label of the connection.
*
* @return Flow label of the connection or 0, if there is no flow label.
*
* @see connect
*/
inline card32 getSendFlowLabel() const;
/**
* Get traffic class of the connection.
*
* @return Traffic class of the connection or 0, if there is no traffic class.
*
* @see connect
*/
inline card8 getSendTrafficClass() const;
/**
* Get last received flow label.
*
* @return Last received flow label or 0, if there is no flow label.
*/
inline card32 getReceivedFlowLabel() const;
/**
* Get last received traffic class.
*
* @return Last received traffic class or 0, if there is no traffic class.
*/
inline card8 getReceivedTrafficClass() const;
// ====== I/O functions ==================================================
/**
* Wrapper for send().
* send() will set the packet's traffic class, if trafficClass is not 0.
* In this case, the packet will be sent by sendto() to the destination
* address, the socket is connected to!
*
* @param buffer Buffer with data to send.
* @param length Length of data to send.
* @param flags Flags for sendto().
* @param trafficClass Traffic class for packet.
* @return Bytes sent or error code < 0.
*/
ssize_t send(const void* buffer,
const size_t length,
const integer flags = 0,
const card8 trafficClass = 0x00);
/**
* Wrapper for sendto().
* sendto() will set the packet's traffic class, if trafficClass is not 0.
*
* @param buffer Buffer with data to send.
* @param length Length of data to send.
* @param flags Flags for sendto().
* @param receiver Address of receiver.
* @param trafficClass Traffic class for packet.
* @return Bytes sent or error code < 0.
*/
ssize_t sendTo(const void* buffer,
const size_t length,
const integer flags,
const SocketAddress& receiver,
const card8 trafficClass = 0x00);
/**
* Wrapper for sendmsg().
*
* @param msg Message.
* @param flags Flags.
* @param trafficClass Traffic class for packet.
* @return Result of sendmsg() call.
*/
ssize_t sendMsg(const struct msghdr* msg,
const integer flags,
const card8 trafficClass = 0x00);
/**
* Wrapper for write().
*
* @param buffer Buffer with data to write
* @param length Length of data to write
* @return Bytes sent or error code < 0.
*/
inline ssize_t write(const void* buffer,
const size_t length);
/**
* Wrapper for recv().
*
* @param buffer Buffer to read data to.
* @param length Maximum length of data to be received.
* @param flags Flags for recvmsg().
* @return Bytes read or error code < 0.
*/
inline ssize_t receive(void* buffer,
const size_t length,
integer& flags);
/**
* Wrapper for recvfrom().
*
* @param buffer Buffer to receive data to.
* @param length Maximum length of data to be received.
* @param sender Address to store sender's address.
* @param flags Flags for recvmsg().
* @return Bytes received or error code < 0.
*/
ssize_t receiveFrom(void* buffer,
const size_t length,
SocketAddress& sender,
integer& flags);
/**
* Wrapper for recvmsg().
*
* @param msg Message.
* @param flags Flags for recvmsg().
* @param internalCall Internal usage only; set to false.
* @return Result of recvmsg() call.
*/
ssize_t receiveMsg(struct msghdr* msg,
const integer flags,
const bool internalCall = false);
/**
* Wrapper for read().
*
* @param buffer Buffer to read data to.
* @param length Maximum length of data to be received.
* @return Bytes read or error code < 0.
*/
inline ssize_t read(void* buffer,
const size_t length);
/**
* Wrapper for fcntl().
*
* @param cmd Command.
* @param arg Argument.
* @return Result of fcntl() call.
*/
inline integer fcntl(const integer cmd, long arg);
/**
* Wrapper for fcntl().
*
* @param cmd Command.
* @param lock Lock.
* @return Result of fcntl() call.
*/
inline integer fcntl(const integer cmd, struct flock* lock);
/**
* Wrapper for ioctl().
*
* @param request Request.
* @param argp Argument.
* @return Result of ioctl() call.
*/
inline integer ioctl(const integer request, const void* argp);
// ====== Get address ====================================================
/**
* Get the socket's address. Note: A socket has to be bound to an address
* and port or connected to a peer first to let the socket have an address!
*
* @param address Reference to SocketAddress to write address to.
* @return true, if call was successful; false otherwise.
*
* @see bind
* @see connect
* @see getPeerAddress
*/
bool getSocketAddress(SocketAddress& address) const;
/**
* Get the peer's address. Note: A socket has to be connected to a peer
* first to get a peer address!
*
* @param address Reference to SocketAddress to write address to.
* @return true, if call was successful; false otherwise.
*
* @see bind
* @see connect
* @see getSocketAddress
*/
bool getPeerAddress(SocketAddress& address) const;
// ====== Multicast functions ============================================
/**
* Add multicast membership.
*
* @param address Multicast address.
* @param interface Interface name.
* @return true for success; false otherwise.
*/
inline bool addMulticastMembership(const SocketAddress& address,
const char* interface = NULL);
/**
* Drop multicast membership.
*
* @param address Multicast address.
* @param interface Interface name.
* @return true for success; false otherwise.
*/
inline bool dropMulticastMembership(const SocketAddress& address,
const char* interface = NULL);
/**
* Get multicast loop mode.
*
* @return true if multicast loop is enabled, false otherwise.
*/
bool getMulticastLoop();
/**
* Set multicast loop mode.
*
* @param on true to enable, false to disable.
* @return true for success; false otherwise.
*/
bool setMulticastLoop(const bool on);
/**
* Get multicast TTL.
*
* @return Multicast TTL.
*/
card8 getMulticastTTL();
/**
* Set multicast TTL.
*
* @param ttl TTL.
* @return true for success; false otherwise.
*/
bool setMulticastTTL(const card8 ttl);
// ====== IPv6 flow functions ============================================
/**
* Allocate a new flow to a given destination. A InternetFlow object is
* returned, the value flow.getFlowLabel() will not be 0, if the allocFlow()
* call was successful.
*
* @param address Address of the destination.
* @param flowLabel Flowlabel; 0 for random value.
* @param shareLevel Share level for flow label.
* @return InternetFlow.
*/
InternetFlow allocFlow(const InternetAddress& address,
const card32 flowLabel = 0,
const card8 shareLevel = 2);
/**
* Free a flow.
*
* @param flow Flow to be freed.
*/
void freeFlow(InternetFlow& flow);
/**
* Renew a flow label allocation with given expires and linger
* (default 6) values. The expires value gives the seconds to go
* until the flow label expires, the linger value gives the timeout in
* seconds the freed flow label cannot be allocated again.
*
* @param flow Flow to be renewed.
* @param expires Seconds until the flow label expires.
* @param linger Linger (default 6).
* @return true on success; false otherwise.
*/
bool renewFlow(InternetFlow& flow,
const cardinal expires,
const cardinal linger = 6);
/**
* Renew current flow's flow label allocation with given expires and linger
* (default 6) values.
*
* @param expires Seconds until the flow label expires.
* @param linger Linger (default 6).
* @return true on success; false otherwise.
*/
bool renewFlow(const cardinal expires,
const cardinal linger = 6);
// ====== Bind pair of sockets ===========================================
/**
* Bind a pair of sockets to a given address and port number
* x and x + 1. x will be a random number, if given port number is 0.
*
* @param socket1 First socket.
* @param socket2 Second socket.
* @param address Address (e.g ipv6-localhost:0) or NULL for Any address.
*
* @see bind
*/
static bool bindSocketPair(Socket& socket1,
Socket& socket2,
const SocketAddress& address = InternetAddress());
/**
* Bind a pair of sockets to a given address and port number
* x and x + 1. x will be a random number, if given port number is 0.
* If no addresses are given, INADDR_ANY and an automatically
* selected port will be used.
*
* @param socket1 First socket.
* @param socket2 Second socket.
* @param addressArray Array of socket addresses.
* @param addresses Number of addresses.
* @param flags bindx() flags.
*
* @see bindx
*/
static bool bindxSocketPair(Socket& socket1,
Socket& socket2,
const SocketAddress** addressArray = NULL,
const cardinal addresses = 0,
const integer flags = 0);
// ====== Get system's socket descriptor =================================
/**
* Get system's socket descriptor.
* Warning: It is not recommended to manipulate the socket directly.
* Use Socket's methods instead.
*
* @return Socket descriptor.
*/
inline int getSystemSocketDescriptor() const;
// ====== Obtaining Local addresses ======================================
/**
* Get list of all local addresses (IPv4 and IPv6 are currently supported).
* The resulting list has to be deallocated using SocketAddress::deleteAddressList().
*
* @param addressList Reference to store address list to.
* @param numberOfNets Reference to store number of addresses to.
* @param flags Flags.
* @return true for success; false otherwise.
*
* @see SocketAddress#deleteAddressList
*/
static bool getLocalAddressList(SocketAddress**& addressList,
cardinal& numberOfNets,
const cardinal flags = GLAF_Default);
// ====== Constants ======================================================
/**
* Minimum port number for bind()'s automatic port selection.
*
* @see bind
*/
static const cardinal MinAutoSelectPort = 16384;
/**
* Maximum port number for bind()'s automatic port selection.
*
* @see bind
*/
static const cardinal MaxAutoSelectPort = 61000;
// ====== Private data ===================================================
private:
friend class TrafficShaper;
void init();
bool setTypeOfService(const card8 trafficClass);
ssize_t recvFrom(int fd,
void* buf,
const size_t len,
integer& flags,
struct sockaddr* addr,
socklen_t* addrlen);
bool multicastMembership(const SocketAddress& address,
const char* interface,
const bool add);
void packSocketAddressArray(const sockaddr_storage* addrArray,
const size_t addrs,
sockaddr* packedArray);
int SocketDescriptor;
integer Family;
integer Type;
integer Protocol;
card32 SendFlow;
card32 ReceivedFlow;
integer LastError;
cardinal Backlog;
sockaddr* Destination;
};
#include "tdsocket.icc"
#endif