ObjFW  Diff

Differences From Artifact [21df00d3c4]:

  • File src/socket.m — part of check-in [1833194867] at 2021-01-14 02:29:31 on branch trunk — Define _HPUX_ALT_XOPEN_SOCKET_API where necessary

    There is a nasty bug in HP-UX: When using the proper socket APIs that
    take a socklen_t (which is 64 bit in LP64 mode), it still calls into
    methods that expect an int - so there is a type mismatch between the
    headers and the compiled system libraries. This leads to all socklen_t
    being interpreted as 0 (due to big endian). Defining
    _HPUX_ALT_XOPEN_SOCKET_API makes it use the correct symbols in the
    system libraries instead. (user: js, size: 21022) [annotate] [blame] [check-ins using] [more...]

To Artifact [70908a62f5]:


35
36
37
38
39
40
41

42
43
44
45
46
47
48
#import "OFString.h"

#import "OFException.h"  /* For some E* -> WSAE* defines */
#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFLockFailedException.h"

#import "OFUnlockFailedException.h"

#import "socket.h"
#import "socket_helpers.h"
#ifdef OF_HAVE_THREADS
# import "tlskey.h"
#endif







>







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#import "OFString.h"

#import "OFException.h"  /* For some E* -> WSAE* defines */
#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFLockFailedException.h"
#import "OFOutOfRangeException.h"
#import "OFUnlockFailedException.h"

#import "socket.h"
#import "socket_helpers.h"
#ifdef OF_HAVE_THREADS
# import "tlskey.h"
#endif
534
535
536
537
538
539
540





























541
542
543
544
545
546
547
548



549
550
551
552
553
554
555
	network = OF_BSWAP32_IF_LE(network);
	memcpy(&ret.sockaddr.ipx.sipx_network, &network,
	    sizeof(ret.sockaddr.ipx.sipx_network));
	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)







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








>
>
>







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
	network = OF_BSWAP32_IF_LE(network);
	memcpy(&ret.sockaddr.ipx.sipx_network, &network,
	    sizeof(ret.sockaddr.ipx.sipx_network));
	ret.sockaddr.ipx.sipx_port = OF_BSWAP16_IF_LE(port);

	return ret;
}

of_socket_address_t
of_socket_unix(OFString *path)
{
	void *pool = objc_autoreleasePoolPush();
	of_string_encoding_t encoding = [OFLocale encoding];
	size_t length = [path cStringLengthWithEncoding: encoding];
	of_socket_address_t ret;

	if (length > sizeof(ret.sockaddr.un.sun_path))
		@throw [OFOutOfRangeException exception];

	memset(&ret, '\0', sizeof(ret));
	ret.family = OF_SOCKET_ADDRESS_FAMILY_UNIX;
	ret.length = (socklen_t)(sizeof(ret.sockaddr.un) -
	    (sizeof(ret.sockaddr.un.sun_path) - length));

#ifdef AF_UNIX
	ret.sockaddr.un.sun_family = AF_UNIX;
#else
	ret.sockaddr.un.sun_family = AF_UNSPEC;
#endif
	memcpy(ret.sockaddr.un.sun_path,
	    [path cStringWithEncoding: encoding], length);

	objc_autoreleasePoolPop(pool);

	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;
	void *pool;
	OFString *path1, *path2;
	bool ret;

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

	switch (address1->family) {
	case OF_SOCKET_ADDRESS_FAMILY_IPV4:
#if defined(OF_WII) || defined(OF_NINTENDO_3DS)
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
		addrIn2 = &address2->sockaddr.in;

		if (addrIn1->sin_port != addrIn2->sin_port)
			return false;
		if (addrIn1->sin_addr.s_addr != addrIn2->sin_addr.s_addr)
			return false;

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

		addrIn6_1 = &address1->sockaddr.in6;
		addrIn6_2 = &address2->sockaddr.in6;

		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;



}

unsigned long
of_socket_address_hash(const of_socket_address_t *address)
{
	uint32_t hash;

	OF_HASH_INIT(hash);
	OF_HASH_ADD(hash, address->family);

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







|















|

















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

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





|







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
		addrIn2 = &address2->sockaddr.in;

		if (addrIn1->sin_port != addrIn2->sin_port)
			return false;
		if (addrIn1->sin_addr.s_addr != addrIn2->sin_addr.s_addr)
			return false;

		return true;
	case OF_SOCKET_ADDRESS_FAMILY_IPV6:
		if (address1->length < (socklen_t)sizeof(struct sockaddr_in6) ||
		    address2->length < (socklen_t)sizeof(struct sockaddr_in6))
			@throw [OFInvalidArgumentException exception];

		addrIn6_1 = &address1->sockaddr.in6;
		addrIn6_2 = &address2->sockaddr.in6;

		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;

		return true;
	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;

		return true;
	case OF_SOCKET_ADDRESS_FAMILY_UNIX:
		/*
		 * This is a bit tricky. The only thing that is well-defined is
		 * the path. So compare the path, and if both don't have a
		 * path, compare bytes.
		 */

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

		pool = objc_autoreleasePoolPush();

		path1 = of_socket_get_unix_path(address1);
		path2 = of_socket_get_unix_path(address2);

		if (path1 == nil && path2 == nil) {
			objc_autoreleasePoolPop(pool);

			return (memcmp(&address1->sockaddr.un,
			    &address2->sockaddr.un, address1->length) == 0);
		}

		if (path1 == nil || path2 == nil)
			ret = false;
		else
			ret = [path1 isEqual: path2];

		objc_autoreleasePoolPop(pool);

		return ret;
	default:
		@throw [OFInvalidArgumentException exception];
	}
}

unsigned long
of_socket_address_hash(const of_socket_address_t *address)
{
	unsigned long hash;

	OF_HASH_INIT(hash);
	OF_HASH_ADD(hash, address->family);

	switch (address->family) {
	case OF_SOCKET_ADDRESS_FAMILY_IPV4:
#if defined(OF_WII) || defined(OF_NINTENDO_3DS)
665
666
667
668
669
670
671






















672
673
674
675
676
677
678

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








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







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

		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;
	case OF_SOCKET_ADDRESS_FAMILY_UNIX:;
		/*
		 * This is a bit tricky. The only thing that is well-defined is
		 * the path. So hash the path if we have one, otherwise the
		 * bytes.
		 */
		void *pool = objc_autoreleasePoolPush();
		OFString *path = of_socket_get_unix_path(address);

		if (path != nil) {
			hash = [path hash];
			objc_autoreleasePoolPop(pool);
			return hash;
		}

		objc_autoreleasePoolPop(pool);

		for (socklen_t i = 0; i < address->length; i++)
			OF_HASH_ADD(hash,
			    ((const char *)&address->sockaddr.un)[i]);

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

	OF_HASH_FINALIZE(hash);

852
853
854
855
856
857
858





















    unsigned char node[IPX_NODE_LEN])
{
	if (address->family != OF_SOCKET_ADDRESS_FAMILY_IPX)
		@throw [OFInvalidArgumentException exception];

	memcpy(node, address->sockaddr.ipx.sipx_node, IPX_NODE_LEN);
}




























>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
    unsigned char node[IPX_NODE_LEN])
{
	if (address->family != OF_SOCKET_ADDRESS_FAMILY_IPX)
		@throw [OFInvalidArgumentException exception];

	memcpy(node, address->sockaddr.ipx.sipx_node, IPX_NODE_LEN);
}

OFString *
of_socket_get_unix_path(const of_socket_address_t *_Nonnull address)
{
	socklen_t maxLength = (socklen_t)sizeof(address->sockaddr.un);
	size_t length;

	if (address->family != OF_SOCKET_ADDRESS_FAMILY_UNIX ||
	    address->length > maxLength)
		@throw [OFInvalidArgumentException exception];

	length = sizeof(address->sockaddr.un.sun_path) -
	    (maxLength - address->length);

	if (length == 0)
		return nil;

	return [OFString stringWithCString: address->sockaddr.un.sun_path
				  encoding: [OFLocale encoding]
				    length: length];
}