ObjFW  Check-in [707206e796]

Overview
Comment:OFDDPSocket: Bind with network, node & port
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | appletalk
Files: files | file ages | folders
SHA3-256: 707206e796d30c84b2265f5e1aa725fe5cce74d49af7404f7c46d6bbc5e04e1e
User & Date: js on 2022-10-22 18:32:59
Other Links: branch diff | manifest | tags
Context
2022-10-22
18:46
Merge trunk into branch "appletalk" check-in: d1c9ed8498 user: js tags: appletalk
18:32
OFDDPSocket: Bind with network, node & port check-in: 707206e796 user: js tags: appletalk
18:21
Merge trunk into branch "appletalk" check-in: ec6ee4c269 user: js tags: appletalk
Changes

Modified src/OFDDPSocket.h from [23be4cf8bc] to [f44d814690].

64
65
66
67
68
69
70
71

72
73
74



75
76
77
64
65
66
67
68
69
70

71
72
73

74
75
76
77
78
79







-
+


-
+
+
+



/**
 * @brief Bind the socket to the specified network, node and port with the
 *	  specified packet type.
 *
 * @param port The port to bind to. 0 means to pick one and return it via the
 *	       returned socket address.
 * @return The address on which this socket can be reached
 * @throw OFBindFailedException Binding failed
 * @throw OFBindDDPSockeFailedException Binding failed
 * @throw OFAlreadyConnectedException The socket is already bound
 */
- (OFSocketAddress)bindToPort: (uint8_t)port;
- (OFSocketAddress)bindToNetwork: (uint16_t)network
			    node: (uint8_t)node
			    port: (uint8_t)port;
@end

OF_ASSUME_NONNULL_END

Modified src/OFDDPSocket.m from [d78813a978] to [b54a9f63cf].

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
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







-
+
+
+









-
+




-
-
-
+
+
+
+
+
















-
-
-
+
+
+
+
+














-
-
-
+
+
+
+
+







-
-
-
+
+
+
+
+






#import "OFAlreadyConnectedException.h"
#import "OFBindDDPSocketFailedException.h"

@implementation OFDDPSocket
@dynamic delegate;

- (OFSocketAddress)bindToPort: (uint8_t)port
- (OFSocketAddress)bindToNetwork: (uint16_t)network
			    node: (uint8_t)node
			    port: (uint8_t)port
{
	OFSocketAddress address;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];

	address = OFSocketAddressMakeAppleTalk(0, 0, port);
	address = OFSocketAddressMakeAppleTalk(network, node, port);

	if ((_socket = socket(address.sockaddr.at.sat_family,
	    SOCK_DGRAM | SOCK_CLOEXEC, 0)) == OFInvalidSocketHandle)
		@throw [OFBindDDPSocketFailedException
		    exceptionWithPort: port
			       socket: self
				errNo: OFSocketErrNo()];
		    exceptionWithNetwork: network
				    node: node
				    port: port
				  socket: self
				   errNo: OFSocketErrNo()];

	_canBlock = true;

#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC)
	if ((flags = fcntl(_socket, F_GETFD, 0)) != -1)
		fcntl(_socket, F_SETFD, flags | FD_CLOEXEC);
#endif

	if (bind(_socket, (struct sockaddr *)&address.sockaddr,
	    address.length) != 0) {
		int errNo = OFSocketErrNo();

		closesocket(_socket);
		_socket = OFInvalidSocketHandle;

		@throw [OFBindDDPSocketFailedException
		    exceptionWithPort: port
			       socket: self
				errNo: errNo];
		    exceptionWithNetwork: network
				    node: node
				    port: port
				  socket: self
				   errNo: errNo];
	}

	memset(&address, 0, sizeof(address));
	address.family = OFSocketAddressFamilyAppleTalk;
	address.length = (socklen_t)sizeof(address.sockaddr);

	if (OFGetSockName(_socket, (struct sockaddr *)&address.sockaddr,
	    &address.length) != 0) {
		int errNo = OFSocketErrNo();

		closesocket(_socket);
		_socket = OFInvalidSocketHandle;

		@throw [OFBindDDPSocketFailedException
		    exceptionWithPort: port
			       socket: self
				errNo: errNo];
		    exceptionWithNetwork: network
				    node: node
				    port: port
				  socket: self
				   errNo: errNo];
	}

	if (address.sockaddr.at.sat_family != AF_APPLETALK) {
		closesocket(_socket);
		_socket = OFInvalidSocketHandle;

		@throw [OFBindDDPSocketFailedException
		    exceptionWithPort: port
			       socket: self
				errNo: EAFNOSUPPORT];
		    exceptionWithNetwork: network
				    node: node
				    port: port
				  socket: self
				   errNo: EAFNOSUPPORT];
	}

	return address;
}
@end

Modified src/exceptions/OFBindDDPSocketFailedException.h from [7d1260c80c] to [218affa1e0].

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
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







+
-
+


+
+
+
+
+
+
+
+
+
+








+
+
-
+




-
-
-
+
+
+
+
+







+
+
-
+




-
-
-
+
+
+
+
+





 *	  ObjFW/OFBindDDPSocketFailedException.h
 *
 * @brief An exception indicating that binding a DDP socket failed.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFBindDDPSocketFailedException: OFBindSocketFailedException
{
	uint16_t _network;
	uint8_t _port;
	uint8_t _node, _port;
}

/**
 * @brief The DDP network on which binding failed.
 */
@property (readonly, nonatomic) uint16_t network;

/**
 * @brief The DDP node for which binding failed.
 */
@property (readonly, nonatomic) uint8_t node;

/**
 * @brief The DDP port on which binding failed.
 */
@property (readonly, nonatomic) uint8_t port;

/**
 * @brief Creates a new, autoreleased bind DDP socket failed exception.
 *
 * @param network The DDP network on which binding failed
 * @param node The DDP node for which binding failed
 * @param port The DDP port to which binding failed
 * @param port The DDP port on which binding failed
 * @param socket The socket which could not be bound
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased bind DDP socket failed exception
 */
+ (instancetype)exceptionWithPort: (uint8_t)port
			   socket: (id)socket
			    errNo: (int)errNo;
+ (instancetype)exceptionWithNetwork: (uint16_t)network
				node: (uint8_t)node
				port: (uint8_t)port
			      socket: (id)socket
			       errNo: (int)errNo;

+ (instancetype)exceptionWithSocket: (id)socket
			      errNo: (int)errNo OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated bind DDP socket failed exception.
 *
 * @param network The DDP network on which binding failed
 * @param node The DDP node for which binding failed
 * @param port The DDP port to which binding failed
 * @param port The DDP port on which binding failed
 * @param socket The socket which could not be bound
 * @param errNo The errno of the error that occurred
 * @return An initialized bind DDP socket failed exception
 */
- (instancetype)initWithPort: (uint8_t)port
		      socket: (id)socket
		       errNo: (int)errNo OF_DESIGNATED_INITIALIZER;
- (instancetype)initWithNetwork: (uint16_t)network
			   node: (uint8_t)node
			   port: (uint8_t)port
			 socket: (id)socket
			  errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)initWithSocket: (id)socket errNo: (int)errNo OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFBindDDPSocketFailedException.m from [cebffb005f] to [dbb639a5e2].

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
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







-
+






-
-
-
+
+
+
+
+

-
-
-
+
+
+
+
+







-
-
-
+
+
+
+
+




+
+












+
-
-
+
+


#include "config.h"

#import "OFBindDDPSocketFailedException.h"
#import "OFData.h"
#import "OFString.h"

@implementation OFBindDDPSocketFailedException
@synthesize port = _port;
@synthesize network = _network, node = _node, port = _port;

+ (instancetype)exceptionWithSocket: (id)sock errNo: (int)errNo
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithPort: (uint8_t)port
			   socket: (id)sock
			    errNo: (int)errNo
+ (instancetype)exceptionWithNetwork: (uint16_t)network
				node: (uint8_t)node
				port: (uint8_t)port
			      socket: (id)sock
			       errNo: (int)errNo
{
	return [[[self alloc] initWithPort: port
				    socket: sock
				     errNo: errNo] autorelease];
	return [[[self alloc] initWithNetwork: network
					 node: node
					 port: port
				       socket: sock
					errNo: errNo] autorelease];
}

- (instancetype)initWithSocket: (id)sock errNo: (int)errNo
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithPort: (uint8_t)port
		      socket: (id)sock
		       errNo: (int)errNo
- (instancetype)initWithNetwork: (uint16_t)network
			   node: (uint8_t)node
			   port: (uint8_t)port
			 socket: (id)sock
			  errNo: (int)errNo
{
	self = [super initWithSocket: sock errNo: errNo];

	@try {
		_network = network;
		_node = node;
		_port = port;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"Binding to port %" @PRIx8 @" of node %" @PRIx8 @" on network "
	    @"Binding to port %" @PRIx8 @" failed in socket of type %@: %@",
	    _port, [_socket class], OFStrError(_errNo)];
	    @"%" PRIx16 @" failed in socket of type %@: %@",
	    _port, _node, _network, [_socket class], OFStrError(_errNo)];
}
@end

Modified tests/OFDDPSocketTests.m from [e1d2cac77d] to [cbe290bc1c].

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
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







+
-
+





-
+





-
+







	OFDDPSocket *sock;
	OFSocketAddress address1, address2;
	char buffer[5];

	TEST(@"+[socket]", (sock = [OFDDPSocket socket]))

	@try {
		TEST(@"-[bindToNetwork:node:port:]",
		TEST(@"-[bindToPort:]", R(address1 = [sock bindToPort: 0]))
		    R(address1 = [sock bindToNetwork: 0 node: 0 port: 0]))
	} @catch (OFBindSocketFailedException *e) {
		switch (e.errNo) {
		case EAFNOSUPPORT:
			[OFStdOut setForegroundColor: [OFColor lime]];
			[OFStdOut writeLine:
			    @"\r[OFDDPSocket] -[bindToPort:] "
			    @"\r[OFDDPSocket] -[bindToNetwork:node:port:] "
			    @"AppleTalk unsupported, skipping tests"];
			break;
		case EADDRNOTAVAIL:
			[OFStdOut setForegroundColor: [OFColor lime]];
			[OFStdOut writeLine:
			    @"\r[OFDDPSocket] -[bindToPort:]: "
			    @"\r[OFDDPSocket] -[bindToNetwork:node:port:] "
			    @"AppleTalk not configured, skipping tests"];
			break;
		default:
			@throw e;
		}

		objc_autoreleasePoolPop(pool);