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
/**
 * @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 OFAlreadyConnectedException The socket is already bound
 */
- (OFSocketAddress)bindToPort: (uint8_t)port;


@end

OF_ASSUME_NONNULL_END







|


|
>
>



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 OFBindDDPSockeFailedException Binding failed
 * @throw OFAlreadyConnectedException The socket is already bound
 */
- (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

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

@implementation OFDDPSocket
@dynamic delegate;

- (OFSocketAddress)bindToPort: (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);

	if ((_socket = socket(address.sockaddr.at.sat_family,
	    SOCK_DGRAM | SOCK_CLOEXEC, 0)) == OFInvalidSocketHandle)
		@throw [OFBindDDPSocketFailedException
		    exceptionWithPort: 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];
	}

	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];
	}

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

		@throw [OFBindDDPSocketFailedException
		    exceptionWithPort: port


			       socket: self
				errNo: EAFNOSUPPORT];
	}

	return address;
}
@end







|
>
>









|




|
>
>
|
|
















|
>
>
|
|














|
>
>
|
|







|
>
>
|
|





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)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(network, node, port);

	if ((_socket = socket(address.sockaddr.at.sat_family,
	    SOCK_DGRAM | SOCK_CLOEXEC, 0)) == OFInvalidSocketHandle)
		@throw [OFBindDDPSocketFailedException
		    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
		    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
		    exceptionWithNetwork: network
				    node: node
				    port: port
				  socket: self
				   errNo: errNo];
	}

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

		@throw [OFBindDDPSocketFailedException
		    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
 *	  ObjFW/OFBindDDPSocketFailedException.h
 *
 * @brief An exception indicating that binding a DDP socket failed.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFBindDDPSocketFailedException: OFBindSocketFailedException
{

	uint8_t _port;
}











/**
 * @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 port The DDP port to 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)exceptionWithSocket: (id)socket
			      errNo: (int)errNo OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated bind DDP socket failed exception.
 *


 * @param port The DDP port to 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)initWithSocket: (id)socket errNo: (int)errNo OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END







>
|


>
>
>
>
>
>
>
>
>
>








>
>
|




|
>
>
|
|







>
>
|




|
>
>
|
|





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 _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 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)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 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)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
#include "config.h"

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

@implementation OFBindDDPSocketFailedException
@synthesize port = _port;

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

+ (instancetype)exceptionWithPort: (uint8_t)port


			   socket: (id)sock
			    errNo: (int)errNo
{
	return [[[self alloc] initWithPort: 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
{
	self = [super initWithSocket: sock errNo: errNo];

	@try {


		_port = port;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (OFString *)description
{
	return [OFString stringWithFormat:

	    @"Binding to port %" @PRIx8 @" failed in socket of type %@: %@",
	    _port, [_socket class], OFStrError(_errNo)];
}
@end







|






|
>
>
|
|

|
>
>
|
|







|
>
>
|
|




>
>












>
|
|


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 network = _network, node = _node, port = _port;

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

+ (instancetype)exceptionWithNetwork: (uint16_t)network
				node: (uint8_t)node
				port: (uint8_t)port
			      socket: (id)sock
			       errNo: (int)errNo
{
	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)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 "
	    @"%" 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
	OFDDPSocket *sock;
	OFSocketAddress address1, address2;
	char buffer[5];

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

	@try {

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

		objc_autoreleasePoolPop(pool);







>
|





|





|







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:]",
		    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] -[bindToNetwork:node:port:] "
			    @"AppleTalk unsupported, skipping tests"];
			break;
		case EADDRNOTAVAIL:
			[OFStdOut setForegroundColor: [OFColor lime]];
			[OFStdOut writeLine:
			    @"\r[OFDDPSocket] -[bindToNetwork:node:port:] "
			    @"AppleTalk not configured, skipping tests"];
			break;
		default:
			@throw e;
		}

		objc_autoreleasePoolPop(pool);