ObjFW  Check-in [4a5822e7c0]

Overview
Comment:Add OFIPXSocket
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 4a5822e7c06e358588ef4b2f365de2b7c69b891652a3192f3a0d54b97370664f
User & Date: js on 2020-04-25 23:02:16
Other Links: manifest | tags
Context
2020-04-26
09:13
Skip IPX tests when IPX is not configured check-in: 1d6d86241a user: js tags: trunk
2020-04-25
23:02
Add OFIPXSocket check-in: 4a5822e7c0 user: js tags: trunk
17:05
Add OFDatagramSocket as base class for OFUDPSocket check-in: b02c4b05bb user: js tags: trunk
Changes

Modified configure.ac from [8e938279fe] to [8421da9224].

1326
1327
1328
1329
1330
1331
1332




1333
1334
1335
1336
1337
1338
1339
			[Whether we have netinet/in.h])
	])
	AC_CHECK_HEADER(netinet/tcp.h, [
		AC_DEFINE(OF_HAVE_NETINET_TCP_H, 1,
			[Whether we have netinet/tcp.h])
	])
	AC_CHECK_HEADERS([arpa/inet.h netdb.h])





	AC_CHECK_MEMBER([struct sockaddr_in6.sin6_addr], [
		AC_EGREP_CPP(egrep_cpp_yes, [
			#ifdef _WIN32
			typedef int BOOL;
			#endif








>
>
>
>







1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
			[Whether we have netinet/in.h])
	])
	AC_CHECK_HEADER(netinet/tcp.h, [
		AC_DEFINE(OF_HAVE_NETINET_TCP_H, 1,
			[Whether we have netinet/tcp.h])
	])
	AC_CHECK_HEADERS([arpa/inet.h netdb.h])
	AC_CHECK_HEADER(netipx/ipx.h, [
		AC_DEFINE(OF_HAVE_NETIPX_IPX_H, 1,
			[Whether we have netipx/ipx.h])
	])

	AC_CHECK_MEMBER([struct sockaddr_in6.sin6_addr], [
		AC_EGREP_CPP(egrep_cpp_yes, [
			#ifdef _WIN32
			typedef int BOOL;
			#endif

1375
1376
1377
1378
1379
1380
1381









































































1382
1383
1384
1385
1386
1387
1388
		#   include <winsock2.h>
		#  endif
		# endif
		# include <windows.h>
		# include <ws2tcpip.h>
		#endif
	])










































































	AC_CHECK_FUNCS(paccept accept4, break)

	AC_CHECK_FUNCS(kqueue1 kqueue, [
		AC_DEFINE(HAVE_KQUEUE, 1, [Whether we have kqueue])
		AC_SUBST(OFKQUEUEKERNELEVENTOBSERVER_M,
			"OFKqueueKernelEventObserver.m")







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
		#   include <winsock2.h>
		#  endif
		# endif
		# include <windows.h>
		# include <ws2tcpip.h>
		#endif
	])

	AC_CHECK_MEMBER(struct sockaddr_ipx.sipx_network, [], [
		AC_CHECK_MEMBER(struct sockaddr_ipx.sa_netnum, [], [], [
			#ifdef _WIN32
			typedef int BOOL;
			#endif

			#ifdef OF_HAVE_NETIPX_IPX_H
			# include <netipx/ipx.h>
			#endif

			#ifdef _WIN32
			# ifdef __MINGW32__
			#  include <_mingw.h>
			#  ifdef __MINGW64_VERSION_MAJOR
			#   include <winsock2.h>
			#  endif
			# endif
			# include <windows.h>
			# include <wsipx.h>
			#endif
		])
	], [
		#ifdef _WIN32
		typedef int BOOL;
		#endif

		#ifdef OF_HAVE_NETIPX_IPX_H
		# include <netipx/ipx.h>
		#endif

		#ifdef _WIN32
		# ifdef __MINGW32__
		#  include <_mingw.h>
		#  ifdef __MINGW64_VERSION_MAJOR
		#   include <winsock2.h>
		#  endif
		# endif
		# include <windows.h>
		# include <wsipx.h>
		#endif
	])
	AS_IF([test x"$ac_cv_member_struct_sockaddr_ipx_sipx_network" = x"yes" \
	    -o x"$ac_cv_member_struct_sockaddr_ipx_sa_netnum" = x"yes"], [
		AC_EGREP_CPP(egrep_cpp_yes, [
			#ifdef _WIN32
			typedef int BOOL;
			#endif

			#ifdef OF_HAVE_SYS_SOCKET_H
			# include <sys/socket.h>
			#endif

			#ifdef _WIN32
			# ifdef __MINGW32__
			#  include <_mingw.h>
			#  ifdef __MINGW64_VERSION_MAJOR
			#   include <winsock2.h>
			#  endif
			# endif
			# include <windows.h>
			# include <wsipx.h>
			#endif

			#ifdef AF_IPX
			egrep_cpp_yes
			#endif
		], [
			AC_DEFINE(OF_HAVE_IPX, 1, [Whether we have IPX/SPX])
			AC_SUBST(OFIPXSOCKET_M, OFIPXSocket.m)
			AC_SUBST(OFIPXSOCKETTESTS_M, OFIPXSocketTests.m)
		])
	])

	AC_CHECK_FUNCS(paccept accept4, break)

	AC_CHECK_FUNCS(kqueue1 kqueue, [
		AC_DEFINE(HAVE_KQUEUE, 1, [Whether we have kqueue])
		AC_SUBST(OFKQUEUEKERNELEVENTOBSERVER_M,
			"OFKqueueKernelEventObserver.m")

Modified extra.mk.in from [5582088805] to [d873097dd9].

56
57
58
59
60
61
62


63
64
65
66
67
68
69
OFARC = @OFARC@
OFBLOCKTESTS_M = @OFBLOCKTESTS_M@
OFDNS = @OFDNS@
OFEPOLLKERNELEVENTOBSERVER_M = @OFEPOLLKERNELEVENTOBSERVER_M@
OFHASH = @OFHASH@
OFHTTP = @OFHTTP@
OFHTTPCLIENTTESTS_M = @OFHTTPCLIENTTESTS_M@


OFKQUEUEKERNELEVENTOBSERVER_M = @OFKQUEUEKERNELEVENTOBSERVER_M@
OFPOLLKERNELEVENTOBSERVER_M = @OFPOLLKERNELEVENTOBSERVER_M@
OFPROCESS_M = @OFPROCESS_M@
OFSELECTKERNELEVENTOBSERVER_M = @OFSELECTKERNELEVENTOBSERVER_M@
OFSTDIOSTREAM_WIN32CONSOLE_M = @OFSTDIOSTREAM_WIN32CONSOLE_M@
REEXPORT_RUNTIME = @REEXPORT_RUNTIME@
REEXPORT_RUNTIME_FRAMEWORK = @REEXPORT_RUNTIME_FRAMEWORK@







>
>







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
OFARC = @OFARC@
OFBLOCKTESTS_M = @OFBLOCKTESTS_M@
OFDNS = @OFDNS@
OFEPOLLKERNELEVENTOBSERVER_M = @OFEPOLLKERNELEVENTOBSERVER_M@
OFHASH = @OFHASH@
OFHTTP = @OFHTTP@
OFHTTPCLIENTTESTS_M = @OFHTTPCLIENTTESTS_M@
OFIPXSOCKETTESTS_M = @OFIPXSOCKETTESTS_M@
OFIPXSOCKET_M = @OFIPXSOCKET_M@
OFKQUEUEKERNELEVENTOBSERVER_M = @OFKQUEUEKERNELEVENTOBSERVER_M@
OFPOLLKERNELEVENTOBSERVER_M = @OFPOLLKERNELEVENTOBSERVER_M@
OFPROCESS_M = @OFPROCESS_M@
OFSELECTKERNELEVENTOBSERVER_M = @OFSELECTKERNELEVENTOBSERVER_M@
OFSTDIOSTREAM_WIN32CONSOLE_M = @OFSTDIOSTREAM_WIN32CONSOLE_M@
REEXPORT_RUNTIME = @REEXPORT_RUNTIME@
REEXPORT_RUNTIME_FRAMEWORK = @REEXPORT_RUNTIME_FRAMEWORK@

Modified src/Makefile from [451a33d977] to [bd2f730fa8].

141
142
143
144
145
146
147

148
149
150
151
152
153
154
	       OFDatagramSocket.m		\
	       OFHTTPClient.m			\
	       OFHTTPCookie.m			\
	       OFHTTPCookieManager.m		\
	       OFHTTPRequest.m			\
	       OFHTTPResponse.m			\
	       OFHTTPServer.m			\

	       OFStreamSocket.m			\
	       OFTCPSocket.m			\
	       OFUDPSocket.m			\
	       socket.m
SRCS_THREADS = OFCondition.m		\
	       OFMutex.m		\
	       OFRecursiveMutex.m	\







>







141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
	       OFDatagramSocket.m		\
	       OFHTTPClient.m			\
	       OFHTTPCookie.m			\
	       OFHTTPCookieManager.m		\
	       OFHTTPRequest.m			\
	       OFHTTPResponse.m			\
	       OFHTTPServer.m			\
	       ${OFIPXSOCKET_M}			\
	       OFStreamSocket.m			\
	       OFTCPSocket.m			\
	       OFUDPSocket.m			\
	       socket.m
SRCS_THREADS = OFCondition.m		\
	       OFMutex.m		\
	       OFRecursiveMutex.m	\

Modified src/OFDNSResolver.m from [ff93d36ccb] to [dbbe2fd8c5].

1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
			     didPerformQuery: context->_query
				    response: response
				   exception: exception];

	return false;
}

-	  (bool)socket: (OFUDPSocket *)sock
  didReceiveIntoBuffer: (void *)buffer
		length: (size_t)length
		sender: (const of_socket_address_t *)sender
	     exception: (id)exception
{
	if (exception != nil)
		return true;







|







1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
			     didPerformQuery: context->_query
				    response: response
				   exception: exception];

	return false;
}

-	  (bool)socket: (OFDatagramSocket *)sock
  didReceiveIntoBuffer: (void *)buffer
		length: (size_t)length
		sender: (const of_socket_address_t *)sender
	     exception: (id)exception
{
	if (exception != nil)
		return true;

Modified src/OFDatagramSocket.h from [1d2fee88b0] to [2ecd0e6700].

21
22
23
24
25
26
27

28
29
30
31
32
33
34

#import "socket.h"

OF_ASSUME_NONNULL_BEGIN

/*! @file */


@class OFDatagramSocket;

#ifdef OF_HAVE_BLOCKS
/*!
 * @brief A block which is called when a packet has been received.
 *
 * @param socket The datagram socket which received a packet







>







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

#import "socket.h"

OF_ASSUME_NONNULL_BEGIN

/*! @file */

@class OFData;
@class OFDatagramSocket;

#ifdef OF_HAVE_BLOCKS
/*!
 * @brief A block which is called when a packet has been received.
 *
 * @param socket The datagram socket which received a packet
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
-	  (bool)socket: (OFDatagramSocket *)socket
  didReceiveIntoBuffer: (void *)buffer
		length: (size_t)length
		sender: (const of_socket_address_t *_Nonnull)sender
	     exception: (nullable id)exception;

/*!
 * @brief This which is called when a packet has been sent.
 *
 * @param socket The datagram socket which sent a packet
 * @param data The data which was sent
 * @param receiver The receiver for the packet
 * @param exception An exception that occurred while sending, or nil on success
 * @return The data to repeat the send with or nil if it should not repeat
 */







|







81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
-	  (bool)socket: (OFDatagramSocket *)socket
  didReceiveIntoBuffer: (void *)buffer
		length: (size_t)length
		sender: (const of_socket_address_t *_Nonnull)sender
	     exception: (nullable id)exception;

/*!
 * @brief This method is called when a packet has been sent.
 *
 * @param socket The datagram socket which sent a packet
 * @param data The data which was sent
 * @param receiver The receiver for the packet
 * @param exception An exception that occurred while sending, or nil on success
 * @return The data to repeat the send with or nil if it should not repeat
 */

Modified src/OFDatagramSocket.m from [48a59d618d] to [702374f5eb].

164
165
166
167
168
169
170





171
172
173
174
175
176
177
	case AF_INET:
		sender->family = OF_SOCKET_ADDRESS_FAMILY_IPV4;
		break;
#ifdef OF_HAVE_IPV6
	case AF_INET6:
		sender->family = OF_SOCKET_ADDRESS_FAMILY_IPV6;
		break;





#endif
	default:
		sender->family = OF_SOCKET_ADDRESS_FAMILY_UNKNOWN;
		break;
	}

	return ret;







>
>
>
>
>







164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
	case AF_INET:
		sender->family = OF_SOCKET_ADDRESS_FAMILY_IPV4;
		break;
#ifdef OF_HAVE_IPV6
	case AF_INET6:
		sender->family = OF_SOCKET_ADDRESS_FAMILY_IPV6;
		break;
#endif
#ifdef OF_HAVE_IPX
	case AF_IPX:
		sender->family = OF_SOCKET_ADDRESS_FAMILY_IPX;
		break;
#endif
	default:
		sender->family = OF_SOCKET_ADDRESS_FAMILY_UNKNOWN;
		break;
	}

	return ret;

Added src/OFIPXSocket.h version [cd5803206b].































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
 *               2018, 2019, 2020
 *   Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFDatagramSocket.h"

OF_ASSUME_NONNULL_BEGIN

@class OFString;

/*!
 * @protocol OFIPXSocketDelegate OFIPXSocket.h ObjFW/OFIPXSocket.h
 *
 * @brief A delegate for OFIPXSocket.
 */
@protocol OFIPXSocketDelegate <OFDatagramSocketDelegate>
@end

/*!
 * @class OFIPXSocket OFIPXSocket.h ObjFW/OFIPXSocket.h
 *
 * @brief A class which provides methods to create and use IPX sockets.
 *
 * Addresses are of type @ref of_socket_address_t. You can use
 * @ref of_socket_address_ipx to create an address or
 * @ref of_socket_address_ipx_get to get the IPX network, node and port
 * (somtimes also called socket number).
 *
 * @warning Even though the OFCopying protocol is implemented, it does *not*
 *	    return an independent copy of the socket, but instead retains it.
 *	    This is so that the socket can be used as a key for a dictionary,
 *	    so context can be associated with a socket. Using a socket in more
 *	    than one thread at the same time is not thread-safe, even if copy
 *	    was called to create one "instance" for every thread!
 */
@interface OFIPXSocket: OFDatagramSocket
{
#ifndef OF_WINDOWS
	uint8_t _packetType;
#endif
	OF_RESERVE_IVARS(4)
}

/*!
 * @brief The delegate for asynchronous operations on the socket.
 *
 * @note The delegate is retained for as long as asynchronous operations are
 *	 still outstanding.
 */
@property OF_NULLABLE_PROPERTY (assign, nonatomic)
    id <OFIPXSocketDelegate> delegate;

/*!
 * @brief Binds the socket to the specified network, node and port with the
 *	  specified packet type.
 *
 * @param port The port (sometimes called socket number) to bind to. 0 means to
 *	       pick one and return it.
 * @param packetType The packet type to use on the socket
 * @return The address on which this socket can be reached
 */
- (of_socket_address_t)bindToPort: (uint16_t)port
		       packetType: (uint8_t)packetType;
@end

OF_ASSUME_NONNULL_END

Added src/OFIPXSocket.m version [d3e8a6a40e].











































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
 *               2018, 2019, 2020
 *   Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <errno.h>

#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif

#import "OFIPXSocket.h"

#import "OFAlreadyConnectedException.h"
#import "OFBindFailedException.h"

#import "socket.h"
#import "socket_helpers.h"

@implementation OFIPXSocket
@dynamic delegate;

- (of_socket_address_t)bindToPort: (uint16_t)port
		       packetType: (uint8_t)packetType
{
	const unsigned char zeroNode[IPX_NODE_LEN] = { 0 };
	of_socket_address_t address;
	int protocol = 0;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC)
	int flags;
#endif

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

	address = of_socket_address_ipx(0, zeroNode, port);

#ifdef OF_WINDOWS
	protocol = NSPROTO_IPX + packetType;
#else
	_packetType = address.sockaddr.ipx.sipx_type = packetType;
#endif

	if ((_socket = socket(address.sockaddr.sockaddr.sa_family,
	    SOCK_DGRAM | SOCK_CLOEXEC, protocol)) == INVALID_SOCKET)
		@throw [OFBindFailedException
		    exceptionWithPort: port
			   packetType: packetType
			       socket: self
				errNo: of_socket_errno()];

	_blocking = 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, &address.sockaddr.sockaddr, address.length) != 0) {
		int errNo = of_socket_errno();

		closesocket(_socket);
		_socket = INVALID_SOCKET;

		@throw [OFBindFailedException exceptionWithPort: port
						     packetType: packetType
							 socket: self
							  errNo: errNo];
	}

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

	if (of_getsockname(_socket, &address.sockaddr.sockaddr,
	    &address.length) != 0) {
		int errNo = of_socket_errno();

		closesocket(_socket);
		_socket = INVALID_SOCKET;

		@throw [OFBindFailedException exceptionWithPort: port
						     packetType: packetType
							 socket: self
							  errNo: errNo];
	}

	if (address.sockaddr.sockaddr.sa_family != AF_IPX) {
		closesocket(_socket);
		_socket = INVALID_SOCKET;

		@throw [OFBindFailedException exceptionWithPort: port
						     packetType: packetType
							 socket: self
							  errNo: EAFNOSUPPORT];
	}

	return address;
}

#ifndef OF_WINDOWS
- (void)sendBuffer: (const void *)buffer
	    length: (size_t)length
	  receiver: (const of_socket_address_t *)receiver
{
	of_socket_address_t fixedReceiver;

	memcpy(&fixedReceiver, receiver, sizeof(fixedReceiver));

	/* If it's not IPX, no fix-up needed - it will fail anyway. */
	if (fixedReceiver.family == OF_SOCKET_ADDRESS_FAMILY_IPX)
		fixedReceiver.sockaddr.ipx.sipx_type = _packetType;

	[super sendBuffer: buffer
		   length: length
		 receiver: &fixedReceiver];
}
#endif
@end

Modified src/OFUDPSocket.h from [1edfbebe15] to [34be8eb48d].

49
50
51
52
53
54
55

56
57
58
59
60
61
62
 *	    was called to create one "instance" for every thread!
 */
@interface OFUDPSocket: OFDatagramSocket
{
#ifdef OF_WII
	uint16_t _port;
#endif

}

/*!
 * @brief The delegate for asynchronous operations on the socket.
 *
 * @note The delegate is retained for as long as asynchronous operations are
 *	 still outstanding.







>







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
 *	    was called to create one "instance" for every thread!
 */
@interface OFUDPSocket: OFDatagramSocket
{
#ifdef OF_WII
	uint16_t _port;
#endif
	OF_RESERVE_IVARS(4)
}

/*!
 * @brief The delegate for asynchronous operations on the socket.
 *
 * @note The delegate is retained for as long as asynchronous operations are
 *	 still outstanding.

Modified src/ObjFW.h from [a4b5d0b98c] to [fc9f9015ac].

74
75
76
77
78
79
80



81
82
83
84
85
86
87
# import "OFUDPSocket.h"
# import "OFTLSSocket.h"
# import "OFKernelEventObserver.h"
# import "OFDNSQuery.h"
# import "OFDNSResourceRecord.h"
# import "OFDNSResponse.h"
# import "OFDNSResolver.h"



#endif
#ifdef OF_HAVE_SOCKETS
# ifdef OF_HAVE_THREADS
#  import "OFHTTPClient.h"
# endif
# import "OFHTTPCookie.h"
# import "OFHTTPCookieManager.h"







>
>
>







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# import "OFUDPSocket.h"
# import "OFTLSSocket.h"
# import "OFKernelEventObserver.h"
# import "OFDNSQuery.h"
# import "OFDNSResourceRecord.h"
# import "OFDNSResponse.h"
# import "OFDNSResolver.h"
# ifdef OF_HAVE_IPX
#  import "OFIPXSocket.h"
# endif
#endif
#ifdef OF_HAVE_SOCKETS
# ifdef OF_HAVE_THREADS
#  import "OFHTTPClient.h"
# endif
# import "OFHTTPCookie.h"
# import "OFHTTPCookieManager.h"

Modified src/exceptions/OFBindFailedException.h from [de856810d3] to [5b18a08191].

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

#import "OFException.h"

#ifndef OF_HAVE_SOCKETS
# error No sockets available!
#endif



OF_ASSUME_NONNULL_BEGIN

/*!
 * @class OFBindFailedException \
 *	  OFBindFailedException.h ObjFW/OFBindFailedException.h
 *
 * @brief An exception indicating that binding a socket failed.
 */
@interface OFBindFailedException: OFException
{
	id _socket;

	OFString *_host;
	uint16_t _port;


	int _errNo;
}

/*!
 * @brief The host on which binding failed.
 */
@property (readonly, nonatomic) OFString *host;

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






/*!
 * @brief The socket which could not be bound.
 */
@property (readonly, nonatomic) id socket;

/*!
 * @brief The errno of the error that occurred.







>
>












>


>
>













>
>
>
>
>







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

#import "OFException.h"

#ifndef OF_HAVE_SOCKETS
# error No sockets available!
#endif

#import "socket.h"

OF_ASSUME_NONNULL_BEGIN

/*!
 * @class OFBindFailedException \
 *	  OFBindFailedException.h ObjFW/OFBindFailedException.h
 *
 * @brief An exception indicating that binding a socket failed.
 */
@interface OFBindFailedException: OFException
{
	id _socket;
	/* IP */
	OFString *_host;
	uint16_t _port;
	/* IPX */
	uint8_t _packetType;
	int _errNo;
}

/*!
 * @brief The host on which binding failed.
 */
@property (readonly, nonatomic) OFString *host;

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

/*!
 * @brief The IPX packet type for which binding failed.
 */
@property (readonly, nonatomic) uint8_t packetType;

/*!
 * @brief The socket which could not be bound.
 */
@property (readonly, nonatomic) id socket;

/*!
 * @brief The errno of the error that occurred.
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
 * @return A new, autoreleased bind failed exception
 */
+ (instancetype)exceptionWithHost: (OFString *)host
			     port: (uint16_t)port
			   socket: (id)socket
			    errNo: (int)errNo;















- (instancetype)init OF_UNAVAILABLE;

/*!
 * @brief Initializes an already allocated bind failed exception.
 *
 * @param host The host on which binding failed
 * @param port The 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 failed exception
 */
- (instancetype)initWithHost: (OFString *)host
			port: (uint16_t)port
		      socket: (id)socket
		       errNo: (int)errNo OF_DESIGNATED_INITIALIZER;














@end

OF_ASSUME_NONNULL_END







>
>
>
>
>
>
>
>
>
>
>
>
>
>














|
>
>
>
>
>
>
>
>
>
>
>
>
>
>



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
 * @return A new, autoreleased bind failed exception
 */
+ (instancetype)exceptionWithHost: (OFString *)host
			     port: (uint16_t)port
			   socket: (id)socket
			    errNo: (int)errNo;

/*!
 * @brief Creates a new, autoreleased bind failed exception.
 *
 * @param port The IPX port to which binding failed
 * @param packetType The IPX packet type for 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 failed exception
 */
+ (instancetype)exceptionWithPort: (uint16_t)port
		       packetType: (uint8_t)packetType
			   socket: (id)socket
			    errNo: (int)errNo;

- (instancetype)init OF_UNAVAILABLE;

/*!
 * @brief Initializes an already allocated bind failed exception.
 *
 * @param host The host on which binding failed
 * @param port The 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 failed exception
 */
- (instancetype)initWithHost: (OFString *)host
			port: (uint16_t)port
		      socket: (id)socket
		       errNo: (int)errNo;

/*!
 * @brief Initializes an already allocated bind failed exception.
 *
 * @param port The IPX port to which binding failed
 * @param packetType The IPX packet type for 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 failed exception
 */
- (instancetype)initWithPort: (uint16_t)port
		  packetType: (uint8_t)packetType
		      socket: (id)socket
		       errNo: (int)errNo;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFBindFailedException.m from [a4be0b4e2f] to [47b287ba77].

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

#include "config.h"

#import "OFBindFailedException.h"
#import "OFString.h"

@implementation OFBindFailedException
@synthesize host = _host, port = _port, socket = _socket, errNo = _errNo;


+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithHost: (OFString *)host
			     port: (uint16_t)port
			   socket: (id)socket
			    errNo: (int)errNo
{
	return [[[self alloc] initWithHost: host
				      port: port











				    socket: socket
				     errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD







|
>













>
>
>
>
>
>
>
>
>
>
>







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

#include "config.h"

#import "OFBindFailedException.h"
#import "OFString.h"

@implementation OFBindFailedException
@synthesize host = _host, port = _port, packetType = _packetType;
@synthesize socket = _socket, errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithHost: (OFString *)host
			     port: (uint16_t)port
			   socket: (id)socket
			    errNo: (int)errNo
{
	return [[[self alloc] initWithHost: host
				      port: port
				    socket: socket
				     errNo: errNo] autorelease];
}

+ (instancetype)exceptionWithPort: (uint16_t)port
		       packetType: (uint8_t)packetType
			   socket: (id)socket
			    errNo: (int)errNo
{
	return [[[self alloc] initWithPort: port
				packetType: packetType
				    socket: socket
				     errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
59
60
61
62
63
64
65




















66
67
68
69
70
71
72
73
74
75
76

77
78
79
80





81
82
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}





















- (void)dealloc
{
	[_host release];
	[_socket release];

	[super dealloc];
}

- (OFString *)description
{

	return [OFString stringWithFormat:
	    @"Binding to port %" @PRIu16 @" on host %@ failed in socket of "
	    @"type %@: %@",
	    _port, _host, [_socket class], of_strerror(_errNo)];





}
@end







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











>
|
|
|
|
>
>
>
>
>


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
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithPort: (uint16_t)port
		  packetType: (uint8_t)packetType
		      socket: (id)socket
		       errNo: (int)errNo
{
	self = [super init];

	@try {
		_port = port;
		_packetType = packetType;
		_socket = [socket retain];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_host release];
	[_socket release];

	[super dealloc];
}

- (OFString *)description
{
	if (_host != nil)
		return [OFString stringWithFormat:
		    @"Binding to port %" @PRIu16 @" on host %@ failed in "
		    @"socket of type %@: %@",
		    _port, _host, [_socket class], of_strerror(_errNo)];
	else
		return [OFString stringWithFormat:
		    @"Binding to port %" @PRIx16 @" for packet type %" @PRIx8
		    @" failed in socket of type %@: %@",
		    _port, _packetType, [_socket class], of_strerror(_errNo)];
}
@end

Modified src/objfw-defs.h.in from [96b18781fc] to [5b298a3b39].

11
12
13
14
15
16
17

18
19
20
21

22
23
24
25
26
27
28
#undef OF_HAVE_BUILTIN_BSWAP32
#undef OF_HAVE_BUILTIN_BSWAP64
#undef OF_HAVE_CHMOD
#undef OF_HAVE_CHOWN
#undef OF_HAVE_FILES
#undef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
#undef OF_HAVE_IPV6

#undef OF_HAVE_LIMITS_H
#undef OF_HAVE_LINK
#undef OF_HAVE_MAX_ALIGN_T
#undef OF_HAVE_NETINET_IN_H

#undef OF_HAVE_OSATOMIC
#undef OF_HAVE_OSATOMIC_64
#undef OF_HAVE_PIPE
#undef OF_HAVE_PLEDGE
#undef OF_HAVE_PLUGINS
#undef OF_HAVE_PROCESSES
#undef OF_HAVE_PTHREADS







>




>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#undef OF_HAVE_BUILTIN_BSWAP32
#undef OF_HAVE_BUILTIN_BSWAP64
#undef OF_HAVE_CHMOD
#undef OF_HAVE_CHOWN
#undef OF_HAVE_FILES
#undef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
#undef OF_HAVE_IPV6
#undef OF_HAVE_IPX
#undef OF_HAVE_LIMITS_H
#undef OF_HAVE_LINK
#undef OF_HAVE_MAX_ALIGN_T
#undef OF_HAVE_NETINET_IN_H
#undef OF_HAVE_NETIPX_IPX_H
#undef OF_HAVE_OSATOMIC
#undef OF_HAVE_OSATOMIC_64
#undef OF_HAVE_PIPE
#undef OF_HAVE_PLEDGE
#undef OF_HAVE_PLUGINS
#undef OF_HAVE_PROCESSES
#undef OF_HAVE_PTHREADS

Modified src/socket.h from [f8e3143cfa] to [797887223d].

30
31
32
33
34
35
36



37
38
39
40
41
42



43
44
45
46
47
48
49
#endif
#ifdef OF_HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef OF_HAVE_NETINET_TCP_H
# include <netinet/tcp.h>
#endif




#include "platform.h"

#ifdef OF_WINDOWS
# include <windows.h>
# include <ws2tcpip.h>



#endif

/*! @file */

#ifdef OF_WII
# include <network.h>
#endif







>
>
>






>
>
>







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
#endif
#ifdef OF_HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef OF_HAVE_NETINET_TCP_H
# include <netinet/tcp.h>
#endif
#ifdef OF_HAVE_NETIPX_IPX_H
# include <netipx/ipx.h>
#endif

#include "platform.h"

#ifdef OF_WINDOWS
# include <windows.h>
# include <ws2tcpip.h>
# ifdef OF_HAVE_IPX
#  include <wsipx.h>
# endif
#endif

/*! @file */

#ifdef OF_WII
# include <network.h>
#endif
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
typedef enum {
	/** An unknown address family. */
	OF_SOCKET_ADDRESS_FAMILY_UNKNOWN,
	/** IPv4 */
	OF_SOCKET_ADDRESS_FAMILY_IPV4,
	/** IPv6 */
	OF_SOCKET_ADDRESS_FAMILY_IPV6,


	/** Any address family */
	OF_SOCKET_ADDRESS_FAMILY_ANY = 255
} of_socket_address_family_t;

#ifndef OF_HAVE_IPV6
struct sockaddr_in6 {
	sa_family_t sin6_family;
	in_port_t sin6_port;
	uint32_t sin6_flowinfo;
	struct in6_addr {
		uint8_t s6_addr[16];
	} sin6_addr;
	uint32_t sin6_scope_id;
};
#endif



















/*!
 * @struct of_socket_address_t socket.h ObjFW/socket.h
 *
 * @brief A struct which represents a host / port pair for a socket.
 */
struct OF_BOXABLE of_socket_address_t {
	/*
	 * Even though struct sockaddr contains the family, we need to use our
	 * own family, as we need to support storing an IPv6 address on systems
	 * that don't support IPv6. These may not have AF_INET6 defined and we
	 * can't just define it, as the value is system-dependent and might
	 * clash with an existing value.
	 */
	of_socket_address_family_t family;
	union {
		struct sockaddr sockaddr;
		struct sockaddr_in in;
		struct sockaddr_in6 in6;

	} sockaddr;
	socklen_t length;
};
typedef struct of_socket_address_t of_socket_address_t;

#ifdef __cplusplus
extern "C" {







>
>















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



















>







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
typedef enum {
	/** An unknown address family. */
	OF_SOCKET_ADDRESS_FAMILY_UNKNOWN,
	/** IPv4 */
	OF_SOCKET_ADDRESS_FAMILY_IPV4,
	/** IPv6 */
	OF_SOCKET_ADDRESS_FAMILY_IPV6,
	/** IPX */
	OF_SOCKET_ADDRESS_FAMILY_IPX,
	/** Any address family */
	OF_SOCKET_ADDRESS_FAMILY_ANY = 255
} of_socket_address_family_t;

#ifndef OF_HAVE_IPV6
struct sockaddr_in6 {
	sa_family_t sin6_family;
	in_port_t sin6_port;
	uint32_t sin6_flowinfo;
	struct in6_addr {
		uint8_t s6_addr[16];
	} sin6_addr;
	uint32_t sin6_scope_id;
};
#endif

#ifndef OF_HAVE_IPX
# define IPX_NODE_LEN 6
struct sockaddr_ipx {
	sa_family_t sipx_family;
	uint32_t sipx_network;
	unsigned char sipx_node[IPX_NODE_LEN];
	uint16_t sipx_port;
	uint8_t sipx_type;
};
#endif
#ifdef OF_WINDOWS
# define IPX_NODE_LEN 6
# define sipx_family sa_family
# define sipx_network sa_netnum
# define sipx_node sa_nodenum
# define sipx_port sa_socket
#endif

/*!
 * @struct of_socket_address_t socket.h ObjFW/socket.h
 *
 * @brief A struct which represents a host / port pair for a socket.
 */
struct OF_BOXABLE of_socket_address_t {
	/*
	 * Even though struct sockaddr contains the family, we need to use our
	 * own family, as we need to support storing an IPv6 address on systems
	 * that don't support IPv6. These may not have AF_INET6 defined and we
	 * can't just define it, as the value is system-dependent and might
	 * clash with an existing value.
	 */
	of_socket_address_family_t family;
	union {
		struct sockaddr sockaddr;
		struct sockaddr_in in;
		struct sockaddr_in6 in6;
		struct sockaddr_ipx ipx;
	} sockaddr;
	socklen_t length;
};
typedef struct of_socket_address_t of_socket_address_t;

#ifdef __cplusplus
extern "C" {
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
 * @param IP The IPv4 to parse
 * @param port The port to use
 * @return The parsed IPv4 and port as an of_socket_address_t
 */
extern of_socket_address_t of_socket_address_parse_ipv4(
    OFString *IP, uint16_t port);

#ifdef OF_HAVE_IPV6
/*!
 * @brief Parses the specified IPv6 and port into an of_socket_address_t.
 *
 * @param IP The IPv6 to parse
 * @param port The port to use
 * @return The parsed IPv6 and port as an of_socket_address_t
 */
extern of_socket_address_t of_socket_address_parse_ipv6(
    OFString *IP, uint16_t port);
#endif










/*!
 * @brief Compares two of_socket_address_t for equality.
 *
 * @param address1 The address to compare with the second address
 * @param address2 The second address
 * @return Whether the two addresses are equal







<









|
>
>
>
>
>
>
>
>
>







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
 * @param IP The IPv4 to parse
 * @param port The port to use
 * @return The parsed IPv4 and port as an of_socket_address_t
 */
extern of_socket_address_t of_socket_address_parse_ipv4(
    OFString *IP, uint16_t port);


/*!
 * @brief Parses the specified IPv6 and port into an of_socket_address_t.
 *
 * @param IP The IPv6 to parse
 * @param port The port to use
 * @return The parsed IPv6 and port as an of_socket_address_t
 */
extern of_socket_address_t of_socket_address_parse_ipv6(
    OFString *IP, uint16_t port);

/*!
 * @brief Creates an IPX address for the specified network, node and port.
 *
 * @param network The IPX network
 * @param node The node in the IPX network
 * @param port The IPX port (sometimes called socket number) on the node
 */
extern of_socket_address_t of_socket_address_ipx(uint32_t network,
    const unsigned char node[_Nonnull IPX_NODE_LEN], uint16_t port);

/*!
 * @brief Compares two of_socket_address_t for equality.
 *
 * @param address1 The address to compare with the second address
 * @param address2 The second address
 * @return Whether the two addresses are equal
210
211
212
213
214
215
216












217
218
219
220
221
222
223
 *
 * @param address The address on which to get the port
 * @return The port of the address
 */
extern uint16_t of_socket_address_get_port(
    const of_socket_address_t *_Nonnull address);













extern bool of_socket_init(void);
#if defined(OF_HAVE_THREADS) && defined(OF_AMIGAOS)
extern void of_socket_deinit(void);
#endif
extern int of_socket_errno(void);
#if !defined(OF_WII) && !defined(OF_NINTENDO_3DS)
extern int of_getsockname(of_socket_t sock, struct sockaddr *restrict addr,







>
>
>
>
>
>
>
>
>
>
>
>







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
 *
 * @param address The address on which to get the port
 * @return The port of the address
 */
extern uint16_t of_socket_address_get_port(
    const of_socket_address_t *_Nonnull address);

/*!
 * @brief Gets the IPX network, node and port from an IPX address.
 *
 * @param address The address on which to get the IPX network, node and port
 * @param network The IPX network
 * @param node A buffer to store the node
 * @param port The IPX port (sometimes called socket number) on the node
 */
extern void of_socket_address_ipx_get(
    const of_socket_address_t *_Nonnull address, uint32_t *_Nonnull network,
    unsigned char node[_Nonnull IPX_NODE_LEN], uint16_t *_Nonnull port);

extern bool of_socket_init(void);
#if defined(OF_HAVE_THREADS) && defined(OF_AMIGAOS)
extern void of_socket_deinit(void);
#endif
extern int of_socket_errno(void);
#if !defined(OF_WII) && !defined(OF_NINTENDO_3DS)
extern int of_getsockname(of_socket_t sock, struct sockaddr *restrict addr,

Modified src/socket.m from [41dfcc5d04] to [685346fedf].

503
504
505
506
507
508
509
























510
511
512
513
514
515
516

517
518
519
520
521
522
523
{
	@try {
		return of_socket_address_parse_ipv6(IP, port);
	} @catch (OFInvalidFormatException *e) {
		return of_socket_address_parse_ipv4(IP, port);
	}
}

























bool
of_socket_address_equal(const of_socket_address_t *address1,
    const of_socket_address_t *address2)
{
	const struct sockaddr_in *addrIn1, *addrIn2;
	const struct sockaddr_in6 *addrIn6_1, *addrIn6_2;


	if (address1->family != address2->family)
		return false;

	switch (address1->family) {
	case OF_SOCKET_ADDRESS_FAMILY_IPV4:
#if defined(OF_WII) || defined(OF_NINTENDO_3DS)







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







>







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
{
	@try {
		return of_socket_address_parse_ipv6(IP, port);
	} @catch (OFInvalidFormatException *e) {
		return of_socket_address_parse_ipv4(IP, port);
	}
}

of_socket_address_t
of_socket_address_ipx(uint32_t network, const unsigned char node[IPX_NODE_LEN],
    uint16_t port)
{
	of_socket_address_t ret;

	memset(&ret, '\0', sizeof(ret));
	ret.family = OF_SOCKET_ADDRESS_FAMILY_IPX;
	ret.length = sizeof(ret.sockaddr.ipx);

#ifdef AF_IPX
	ret.sockaddr.ipx.sipx_family = AF_IPX;
#else
	ret.sockaddr.ipx.sipx_family = AF_UNSPEC;
#endif
	network = OF_BSWAP32_IF_LE(network);
	memcpy(&ret.sockaddr.ipx.sipx_network, &network,
	    sizeof(ret.sockaddr.ipx.sipx_network));
	memcpy(ret.sockaddr.ipx.sipx_node, node, IPX_NODE_LEN);
	ret.sockaddr.ipx.sipx_port = OF_BSWAP16_IF_LE(port);

	return ret;
}

bool
of_socket_address_equal(const of_socket_address_t *address1,
    const of_socket_address_t *address2)
{
	const struct sockaddr_in *addrIn1, *addrIn2;
	const struct sockaddr_in6 *addrIn6_1, *addrIn6_2;
	const struct sockaddr_ipx *addrIPX1, *addrIPX2;

	if (address1->family != address2->family)
		return false;

	switch (address1->family) {
	case OF_SOCKET_ADDRESS_FAMILY_IPV4:
#if defined(OF_WII) || defined(OF_NINTENDO_3DS)
549
550
551
552
553
554
555


















556
557
558
559
560
561
562
		if (addrIn6_1->sin6_port != addrIn6_2->sin6_port)
			return false;
		if (memcmp(addrIn6_1->sin6_addr.s6_addr,
		    addrIn6_2->sin6_addr.s6_addr,
		    sizeof(addrIn6_1->sin6_addr.s6_addr)) != 0)
			return false;



















		break;
	default:
		@throw [OFInvalidArgumentException exception];
	}

	return true;
}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
		if (addrIn6_1->sin6_port != addrIn6_2->sin6_port)
			return false;
		if (memcmp(addrIn6_1->sin6_addr.s6_addr,
		    addrIn6_2->sin6_addr.s6_addr,
		    sizeof(addrIn6_1->sin6_addr.s6_addr)) != 0)
			return false;

		break;
	case OF_SOCKET_ADDRESS_FAMILY_IPX:
		if (address1->length < (socklen_t)sizeof(struct sockaddr_ipx) ||
		    address2->length < (socklen_t)sizeof(struct sockaddr_ipx))
			@throw [OFInvalidArgumentException exception];

		addrIPX1 = &address1->sockaddr.ipx;
		addrIPX2 = &address2->sockaddr.ipx;

		if (addrIPX1->sipx_port != addrIPX2->sipx_port)
			return false;
		if (memcmp(&addrIPX1->sipx_network, &addrIPX2->sipx_network,
		    4) != 0)
			return false;
		if (memcmp(addrIPX1->sipx_node, addrIPX2->sipx_node,
		    IPX_NODE_LEN) != 0)
			return false;

		break;
	default:
		@throw [OFInvalidArgumentException exception];
	}

	return true;
}
595
596
597
598
599
600
601




















602
603
604
605
606
607
608
		OF_HASH_ADD(hash, address->sockaddr.in6.sin6_port);

		for (size_t i = 0;
		    i < sizeof(address->sockaddr.in6.sin6_addr.s6_addr); i++)
			OF_HASH_ADD(hash,
			    address->sockaddr.in6.sin6_addr.s6_addr[i]);





















		break;
	default:
		@throw [OFInvalidArgumentException exception];
	}

	OF_HASH_FINALIZE(hash);








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
		OF_HASH_ADD(hash, address->sockaddr.in6.sin6_port);

		for (size_t i = 0;
		    i < sizeof(address->sockaddr.in6.sin6_addr.s6_addr); i++)
			OF_HASH_ADD(hash,
			    address->sockaddr.in6.sin6_addr.s6_addr[i]);

		break;
	case OF_SOCKET_ADDRESS_FAMILY_IPX:;
		unsigned char network[
		    sizeof(address->sockaddr.ipx.sipx_network)];

		if (address->length < (socklen_t)sizeof(struct sockaddr_ipx))
			@throw [OFInvalidArgumentException exception];

		OF_HASH_ADD(hash, address->sockaddr.ipx.sipx_port >> 8);
		OF_HASH_ADD(hash, address->sockaddr.ipx.sipx_port);

		memcpy(network, &address->sockaddr.ipx.sipx_network,
		    sizeof(network));

		for (size_t i = 0; i < sizeof(network); i++)
			OF_HASH_ADD(hash, network[i]);

		for (size_t i = 0; i < IPX_NODE_LEN; i++)
			OF_HASH_ADD(hash, address->sockaddr.ipx.sipx_node[i]);

		break;
	default:
		@throw [OFInvalidArgumentException exception];
	}

	OF_HASH_FINALIZE(hash);

728
729
730
731
732
733
734


735
736
737
738













of_socket_address_get_port(const of_socket_address_t *address)
{
	switch (address->family) {
	case OF_SOCKET_ADDRESS_FAMILY_IPV4:
		return OF_BSWAP16_IF_LE(address->sockaddr.in.sin_port);
	case OF_SOCKET_ADDRESS_FAMILY_IPV6:
		return OF_BSWAP16_IF_LE(address->sockaddr.in6.sin6_port);


	default:
		@throw [OFInvalidArgumentException exception];
	}
}




















>
>




>
>
>
>
>
>
>
>
>
>
>
>
>
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
of_socket_address_get_port(const of_socket_address_t *address)
{
	switch (address->family) {
	case OF_SOCKET_ADDRESS_FAMILY_IPV4:
		return OF_BSWAP16_IF_LE(address->sockaddr.in.sin_port);
	case OF_SOCKET_ADDRESS_FAMILY_IPV6:
		return OF_BSWAP16_IF_LE(address->sockaddr.in6.sin6_port);
	case OF_SOCKET_ADDRESS_FAMILY_IPX:
		return OF_BSWAP16_IF_LE(address->sockaddr.ipx.sipx_port);
	default:
		@throw [OFInvalidArgumentException exception];
	}
}

void
of_socket_address_ipx_get(const of_socket_address_t *address, uint32_t *network,
    unsigned char node[IPX_NODE_LEN], uint16_t *port)
{
	if (address->family != OF_SOCKET_ADDRESS_FAMILY_IPX)
		@throw [OFInvalidArgumentException exception];

	memcpy(network, &address->sockaddr.ipx.sipx_network, sizeof(*network));
	*network = OF_BSWAP32_IF_LE(*network);
	memcpy(node, address->sockaddr.ipx.sipx_node, IPX_NODE_LEN);
	*port = OF_BSWAP16_IF_LE(address->sockaddr.ipx.sipx_port);
}

Modified tests/Makefile from [ecae39d9f0] to [9e51c1dedf].

14
15
16
17
18
19
20

21
22
23
24
25
26
27
       OFASN1DERValueTests.m		\
       OFArrayTests.m			\
       ${OFBLOCKTESTS_M}		\
       OFCharacterSetTests.m		\
       OFDataTests.m			\
       OFDateTests.m			\
       OFDictionaryTests.m		\

       OFInvocationTests.m		\
       OFJSONTests.m			\
       OFListTests.m			\
       OFLocaleTests.m			\
       OFMethodSignatureTests.m		\
       OFNumberTests.m			\
       OFObjectTests.m			\







>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
       OFASN1DERValueTests.m		\
       OFArrayTests.m			\
       ${OFBLOCKTESTS_M}		\
       OFCharacterSetTests.m		\
       OFDataTests.m			\
       OFDateTests.m			\
       OFDictionaryTests.m		\
       ${OFIPXSOCKETTESTS_M}		\
       OFInvocationTests.m		\
       OFJSONTests.m			\
       OFListTests.m			\
       OFLocaleTests.m			\
       OFMethodSignatureTests.m		\
       OFNumberTests.m			\
       OFObjectTests.m			\

Added tests/OFIPXSocketTests.m version [165fd0dcaf].









































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
 *               2018, 2019, 2020
 *   Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <errno.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFIPXSocket";

@implementation TestsAppDelegate (OFIPXSocketTests)
- (void)IPXSocketTests
{
	void *pool = objc_autoreleasePoolPush();
	OFIPXSocket *sock;
	of_socket_address_t address1, address2;
	char buffer[5];

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

	@try {
		TEST(@"-[bindToPort:packetType:]",
		    R(address1 = [sock bindToPort: 0
				       packetType: 0]))
	} @catch (OFBindFailedException *e) {
		if (e.errNo != EAFNOSUPPORT)
			@throw e;

		[self outputString: @"[OFIPXSocket] -[bindToPort:packetType:]: "
				    @"IPX unsupported, skipping tests\n"
			   inColor: GREEN];

		objc_autoreleasePoolPop(pool);
		return;
	}

	TEST(@"-[sendBuffer:length:receiver:]",
	    R([sock sendBuffer: "Hello"
			length: 5
		      receiver: &address1]))

	TEST(@"-[receiveIntoBuffer:length:sender:]",
	    [sock receiveIntoBuffer: buffer
			     length: 5
			     sender: &address2] == 5 &&
	    memcmp(buffer, "Hello", 5) == 0 &&
	    of_socket_address_equal(&address1, &address2) &&
	    of_socket_address_hash(&address1) ==
	    of_socket_address_hash(&address2))

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/TestsAppDelegate.h from [5225801e87] to [667b7617f0].

137
138
139
140
141
142
143




144
145
146
147
148
149
150
@interface TestsAppDelegate (OFHTTPCookieManagerTests)
- (void)HTTPCookieManagerTests;
@end

@interface TestsAppDelegate (OFINIFileTests)
- (void)INIFileTests;
@end





@interface TestsAppDelegate (OFInvocationTests)
- (void)invocationTests;
@end

@interface TestsAppDelegate (OFJSONTests)
- (void)JSONTests;







>
>
>
>







137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
@interface TestsAppDelegate (OFHTTPCookieManagerTests)
- (void)HTTPCookieManagerTests;
@end

@interface TestsAppDelegate (OFINIFileTests)
- (void)INIFileTests;
@end

@interface TestsAppDelegate (OFIPXSocketTests)
- (void)IPXSocketTests;
@end

@interface TestsAppDelegate (OFInvocationTests)
- (void)invocationTests;
@end

@interface TestsAppDelegate (OFJSONTests)
- (void)JSONTests;

Modified tests/TestsAppDelegate.m from [a3883fdd4c] to [6f16d81614].

411
412
413
414
415
416
417



418
419
420
421
422
423
424
#if defined(OF_HAVE_FILES) && defined(HAVE_CODEPAGE_437)
	[self INIFileTests];
#endif
#ifdef OF_HAVE_SOCKETS
	[self socketTests];
	[self TCPSocketTests];
	[self UDPSocketTests];



	[self kernelEventObserverTests];
#endif
#ifdef OF_HAVE_THREADS
	[self threadTests];
#endif
	[self URLTests];
#if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS)







>
>
>







411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
#if defined(OF_HAVE_FILES) && defined(HAVE_CODEPAGE_437)
	[self INIFileTests];
#endif
#ifdef OF_HAVE_SOCKETS
	[self socketTests];
	[self TCPSocketTests];
	[self UDPSocketTests];
# ifdef OF_HAVE_IPX
	[self IPXSocketTests];
# endif
	[self kernelEventObserverTests];
#endif
#ifdef OF_HAVE_THREADS
	[self threadTests];
#endif
	[self URLTests];
#if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS)