mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 15:03:34 +00:00
Polyfill IPv6 on non-Linux
This commit is contained in:
parent
b73e35c6fa
commit
0547eabcd6
10 changed files with 185 additions and 78 deletions
|
@ -18,7 +18,6 @@
|
||||||
#define in_addr_t uint32_t
|
#define in_addr_t uint32_t
|
||||||
#define in_addr_t uint32_t
|
#define in_addr_t uint32_t
|
||||||
#define in_port_t uint16_t
|
#define in_port_t uint16_t
|
||||||
#define in_port_t uint16_t
|
|
||||||
#define ino_t uint64_t
|
#define ino_t uint64_t
|
||||||
#define key_t int32_t
|
#define key_t int32_t
|
||||||
#define loff_t int64_t
|
#define loff_t int64_t
|
||||||
|
|
|
@ -38,6 +38,12 @@ OpenBSD Sorting (BSD-3)\\n\
|
||||||
Copyright 1993 The Regents of the University of California\"");
|
Copyright 1993 The Regents of the University of California\"");
|
||||||
asm(".include \"libc/disclaimer.inc\"");
|
asm(".include \"libc/disclaimer.inc\"");
|
||||||
|
|
||||||
|
#define SWAPTYPE_BYTEV 1
|
||||||
|
#define SWAPTYPE_INTV 2
|
||||||
|
#define SWAPTYPE_LONGV 3
|
||||||
|
#define SWAPTYPE_INT 4
|
||||||
|
#define SWAPTYPE_LONG 5
|
||||||
|
|
||||||
#define CMPPAR int (*cmp)(const void *, const void *, void *),void *arg
|
#define CMPPAR int (*cmp)(const void *, const void *, void *),void *arg
|
||||||
#define CMPARG cmp, arg
|
#define CMPARG cmp, arg
|
||||||
#define CMP(a, b) cmp(a, b, arg)
|
#define CMP(a, b) cmp(a, b, arg)
|
||||||
|
@ -46,30 +52,6 @@ asm(".include \"libc/disclaimer.inc\"");
|
||||||
static inline char *med3(char *, char *, char *, CMPPAR);
|
static inline char *med3(char *, char *, char *, CMPPAR);
|
||||||
static inline void swapfunc(char *, char *, size_t, int);
|
static inline void swapfunc(char *, char *, size_t, int);
|
||||||
|
|
||||||
/*
|
|
||||||
* Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
|
|
||||||
*
|
|
||||||
* This version differs from Bentley & McIlroy in the following ways:
|
|
||||||
* 1. The partition value is swapped into a[0] instead of being
|
|
||||||
* stored out of line.
|
|
||||||
*
|
|
||||||
* 2. The swap function can swap 32-bit aligned elements on 64-bit
|
|
||||||
* platforms instead of swapping them as byte-aligned.
|
|
||||||
*
|
|
||||||
* 3. It uses David Musser's introsort algorithm to fall back to
|
|
||||||
* heapsort(3) when the recursion depth reaches 2*lg(n + 1).
|
|
||||||
* This avoids quicksort's quadratic behavior for pathological
|
|
||||||
* input without appreciably changing the average run time.
|
|
||||||
*
|
|
||||||
* 4. Tail recursion is eliminated when sorting the larger of two
|
|
||||||
* subpartitions to save stack space.
|
|
||||||
*/
|
|
||||||
#define SWAPTYPE_BYTEV 1
|
|
||||||
#define SWAPTYPE_INTV 2
|
|
||||||
#define SWAPTYPE_LONGV 3
|
|
||||||
#define SWAPTYPE_INT 4
|
|
||||||
#define SWAPTYPE_LONG 5
|
|
||||||
|
|
||||||
#define TYPE_ALIGNED(TYPE, a, es) \
|
#define TYPE_ALIGNED(TYPE, a, es) \
|
||||||
(((char *)a - (char *)0) % sizeof(TYPE) == 0 && es % sizeof(TYPE) == 0)
|
(((char *)a - (char *)0) % sizeof(TYPE) == 0 && es % sizeof(TYPE) == 0)
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
#include "libc/sock/struct/sockaddr.internal.h"
|
#include "libc/sock/struct/sockaddr.internal.h"
|
||||||
|
#include "libc/sock/struct/sockaddr6-bsd.internal.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/af.h"
|
#include "libc/sysv/consts/af.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
@ -41,6 +42,21 @@ int sockaddr2bsd(const void *addr, uint32_t addrsize,
|
||||||
} else {
|
} else {
|
||||||
return einval();
|
return einval();
|
||||||
}
|
}
|
||||||
|
} else if (((struct sockaddr *)addr)->sa_family == AF_INET6) {
|
||||||
|
if (addrsize >= sizeof(struct sockaddr_in6)) {
|
||||||
|
out_addr->sin6.sin6_len = 0;
|
||||||
|
out_addr->sin6.sin6_family = AF_INET6;
|
||||||
|
out_addr->sin6.sin6_port = ((struct sockaddr_in6 *)addr)->sin6_port;
|
||||||
|
out_addr->sin6.sin6_flowinfo =
|
||||||
|
((struct sockaddr_in6 *)addr)->sin6_flowinfo;
|
||||||
|
out_addr->sin6.sin6_addr = ((struct sockaddr_in6 *)addr)->sin6_addr;
|
||||||
|
out_addr->sin6.sin6_scope_id =
|
||||||
|
((struct sockaddr_in6 *)addr)->sin6_scope_id;
|
||||||
|
*out_addrsize = sizeof(struct sockaddr_in6_bsd);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return einval();
|
||||||
|
}
|
||||||
} else if (((struct sockaddr *)addr)->sa_family == AF_UNIX) {
|
} else if (((struct sockaddr *)addr)->sa_family == AF_UNIX) {
|
||||||
famsize = sizeof(((struct sockaddr_un *)addr)->sun_family);
|
famsize = sizeof(((struct sockaddr_un *)addr)->sun_family);
|
||||||
if (addrsize >= famsize &&
|
if (addrsize >= famsize &&
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
#include "libc/sock/struct/sockaddr.internal.h"
|
#include "libc/sock/struct/sockaddr.internal.h"
|
||||||
|
#include "libc/sock/struct/sockaddr6-bsd.internal.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/af.h"
|
#include "libc/sysv/consts/af.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
@ -42,6 +43,16 @@ void sockaddr2linux(const union sockaddr_storage_bsd *addr, uint32_t addrsize,
|
||||||
out_addr->sin.sin_addr = addr->sin.sin_addr;
|
out_addr->sin.sin_addr = addr->sin.sin_addr;
|
||||||
*inout_addrsize = sizeof(struct sockaddr_in);
|
*inout_addrsize = sizeof(struct sockaddr_in);
|
||||||
}
|
}
|
||||||
|
} else if (addr->sa.sa_family == AF_INET6) {
|
||||||
|
if (addrsize >= sizeof(struct sockaddr_in6_bsd) &&
|
||||||
|
size >= sizeof(struct sockaddr_in6)) {
|
||||||
|
out_addr->sin6.sin6_family = AF_INET6;
|
||||||
|
out_addr->sin6.sin6_port = addr->sin6.sin6_port;
|
||||||
|
out_addr->sin6.sin6_addr = addr->sin6.sin6_addr;
|
||||||
|
out_addr->sin6.sin6_flowinfo = addr->sin6.sin6_flowinfo;
|
||||||
|
out_addr->sin6.sin6_scope_id = addr->sin6.sin6_scope_id;
|
||||||
|
*inout_addrsize = sizeof(struct sockaddr_in6);
|
||||||
|
}
|
||||||
} else if (addr->sa.sa_family == AF_UNIX) {
|
} else if (addr->sa.sa_family == AF_UNIX) {
|
||||||
if (addrsize >=
|
if (addrsize >=
|
||||||
sizeof(addr->sun.sun_len) + sizeof(addr->sun.sun_family) &&
|
sizeof(addr->sun.sun_len) + sizeof(addr->sun.sun_family) &&
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define COSMOPOLITAN_LIBC_SOCK_STRUCT_SOCKADDR_INTERNAL_H_
|
#define COSMOPOLITAN_LIBC_SOCK_STRUCT_SOCKADDR_INTERNAL_H_
|
||||||
#include "libc/mem/alloca.h"
|
#include "libc/mem/alloca.h"
|
||||||
#include "libc/sock/struct/sockaddr.h"
|
#include "libc/sock/struct/sockaddr.h"
|
||||||
|
#include "libc/sock/struct/sockaddr6-bsd.internal.h"
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
|
@ -29,12 +30,14 @@ struct sockaddr_un_bsd {
|
||||||
union sockaddr_storage_bsd {
|
union sockaddr_storage_bsd {
|
||||||
struct sockaddr_bsd sa;
|
struct sockaddr_bsd sa;
|
||||||
struct sockaddr_in_bsd sin;
|
struct sockaddr_in_bsd sin;
|
||||||
|
struct sockaddr_in6_bsd sin6;
|
||||||
struct sockaddr_un_bsd sun;
|
struct sockaddr_un_bsd sun;
|
||||||
};
|
};
|
||||||
|
|
||||||
union sockaddr_storage_linux {
|
union sockaddr_storage_linux {
|
||||||
struct sockaddr sa;
|
struct sockaddr sa;
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
|
struct sockaddr_in6 sin6;
|
||||||
struct sockaddr_un sun;
|
struct sockaddr_un sun;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
18
libc/sock/struct/sockaddr6-bsd.internal.h
Normal file
18
libc/sock/struct/sockaddr6-bsd.internal.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef COSMOPOLITAN_LIBC_SOCK_STRUCT_SOCKADDR6_BSD_INTERNAL_H_
|
||||||
|
#define COSMOPOLITAN_LIBC_SOCK_STRUCT_SOCKADDR6_BSD_INTERNAL_H_
|
||||||
|
#include "libc/sock/struct/sockaddr6.h"
|
||||||
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
|
struct sockaddr_in6_bsd {
|
||||||
|
uint8_t sin6_len;
|
||||||
|
uint8_t sin6_family;
|
||||||
|
uint16_t sin6_port;
|
||||||
|
uint32_t sin6_flowinfo;
|
||||||
|
struct in6_addr sin6_addr;
|
||||||
|
uint32_t sin6_scope_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
COSMOPOLITAN_C_END_
|
||||||
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
#endif /* COSMOPOLITAN_LIBC_SOCK_STRUCT_SOCKADDR6_BSD_INTERNAL_H_ */
|
|
@ -17,47 +17,22 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/dce.h"
|
|
||||||
#include "libc/intrin/asan.internal.h"
|
|
||||||
#include "libc/macros.internal.h"
|
|
||||||
#include "libc/nexgen32e/bsr.h"
|
|
||||||
#include "libc/nexgen32e/x86feature.h"
|
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
|
||||||
forceinline void longsorter(long *x, size_t n, size_t t) {
|
static void longsorter(long *A, size_t n) {
|
||||||
long a, b, c;
|
long t, p;
|
||||||
size_t i, p, q;
|
size_t i, j;
|
||||||
for (p = t; p > 0; p >>= 1) {
|
if (n < 2) return;
|
||||||
for (i = 0; i < n - p; ++i) {
|
for (p = A[n / 2], i = 0, j = n - 1;; i++, j--) {
|
||||||
if (!(i & p)) {
|
while (A[i] < p) i++;
|
||||||
a = x[i + 0];
|
while (A[j] > p) j--;
|
||||||
b = x[i + p];
|
if (i >= j) break;
|
||||||
if (a > b) c = a, a = b, b = c;
|
t = A[i];
|
||||||
x[i + 0] = a;
|
A[i] = A[j];
|
||||||
x[i + p] = b;
|
A[j] = t;
|
||||||
}
|
|
||||||
}
|
|
||||||
for (q = t; q > p; q >>= 1) {
|
|
||||||
for (i = 0; i < n - q; ++i) {
|
|
||||||
if (!(i & p)) {
|
|
||||||
a = x[i + p];
|
|
||||||
b = x[i + q];
|
|
||||||
if (a > b) c = a, a = b, b = c;
|
|
||||||
x[i + p] = a;
|
|
||||||
x[i + q] = b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
longsorter(A, i);
|
||||||
|
longsorter(A + i, n - i);
|
||||||
static microarchitecture("avx2") optimizespeed noasan
|
|
||||||
void longsort_avx2(long *x, size_t n, size_t t) {
|
|
||||||
longsorter(x, n, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
static optimizesize noasan void longsort_pure(long *x, size_t n, size_t t) {
|
|
||||||
longsorter(x, n, t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -67,21 +42,9 @@ static optimizesize noasan void longsort_pure(long *x, size_t n, size_t t) {
|
||||||
* -Lord Capulet
|
* -Lord Capulet
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void longsort(long *x, size_t n) {
|
void longsort(long *A, size_t n) {
|
||||||
size_t t, m;
|
longsorter(A, n);
|
||||||
if (IsAsan()) {
|
|
||||||
if (__builtin_mul_overflow(n, sizeof(long), &m)) m = -1;
|
|
||||||
__asan_verify(x, m);
|
|
||||||
}
|
|
||||||
if (n > 1) {
|
|
||||||
t = 1ul << bsrl(n - 1);
|
|
||||||
if (!IsTiny() && X86_HAVE(AVX2)) {
|
|
||||||
longsort_avx2(x, n, t);
|
|
||||||
} else {
|
|
||||||
longsort_pure(x, n, t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (n > 1000) {
|
if (n > 1000) {
|
||||||
STRACE("longsort(%p, %'zu)", x, n);
|
STRACE("longsort(%p, %'zu)", A, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/nexgen32e/bsr.h"
|
#include "libc/nexgen32e/bsr.h"
|
||||||
#include "libc/runtime/gc.internal.h"
|
#include "libc/runtime/gc.internal.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/stdio/rand.h"
|
#include "libc/stdio/rand.h"
|
||||||
#include "libc/stdio/stdio.h"
|
#include "libc/stdio/stdio.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
@ -62,10 +63,15 @@ TEST(qsort, equivalence_random) {
|
||||||
qsort(b, n, sizeof(long), CompareLong);
|
qsort(b, n, sizeof(long), CompareLong);
|
||||||
heapsort(c, n, sizeof(long), CompareLong);
|
heapsort(c, n, sizeof(long), CompareLong);
|
||||||
ASSERT_EQ(0, memcmp(b, c, n * sizeof(long)));
|
ASSERT_EQ(0, memcmp(b, c, n * sizeof(long)));
|
||||||
|
memcpy(c, a, n * sizeof(long));
|
||||||
mergesort(c, n, sizeof(long), CompareLong);
|
mergesort(c, n, sizeof(long), CompareLong);
|
||||||
ASSERT_EQ(0, memcmp(b, c, n * sizeof(long)));
|
ASSERT_EQ(0, memcmp(b, c, n * sizeof(long)));
|
||||||
|
memcpy(c, a, n * sizeof(long));
|
||||||
smoothsort(c, n, sizeof(long), CompareLong);
|
smoothsort(c, n, sizeof(long), CompareLong);
|
||||||
ASSERT_EQ(0, memcmp(b, c, n * sizeof(long)));
|
ASSERT_EQ(0, memcmp(b, c, n * sizeof(long)));
|
||||||
|
memcpy(c, a, n * sizeof(long));
|
||||||
|
longsort(c, n);
|
||||||
|
ASSERT_EQ(0, memcmp(b, c, n * sizeof(long)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(qsort, equivalence_reverse) {
|
TEST(qsort, equivalence_reverse) {
|
||||||
|
@ -80,10 +86,15 @@ TEST(qsort, equivalence_reverse) {
|
||||||
qsort(b, n, sizeof(long), CompareLong);
|
qsort(b, n, sizeof(long), CompareLong);
|
||||||
heapsort(c, n, sizeof(long), CompareLong);
|
heapsort(c, n, sizeof(long), CompareLong);
|
||||||
ASSERT_EQ(0, memcmp(b, c, n * sizeof(long)));
|
ASSERT_EQ(0, memcmp(b, c, n * sizeof(long)));
|
||||||
|
memcpy(c, a, n * sizeof(long));
|
||||||
mergesort(c, n, sizeof(long), CompareLong);
|
mergesort(c, n, sizeof(long), CompareLong);
|
||||||
ASSERT_EQ(0, memcmp(b, c, n * sizeof(long)));
|
ASSERT_EQ(0, memcmp(b, c, n * sizeof(long)));
|
||||||
|
memcpy(c, a, n * sizeof(long));
|
||||||
smoothsort(c, n, sizeof(long), CompareLong);
|
smoothsort(c, n, sizeof(long), CompareLong);
|
||||||
ASSERT_EQ(0, memcmp(b, c, n * sizeof(long)));
|
ASSERT_EQ(0, memcmp(b, c, n * sizeof(long)));
|
||||||
|
memcpy(c, a, n * sizeof(long));
|
||||||
|
longsort(c, n);
|
||||||
|
ASSERT_EQ(0, memcmp(b, c, n * sizeof(long)));
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCH(qsort, bench) {
|
BENCH(qsort, bench) {
|
||||||
|
@ -102,6 +113,8 @@ BENCH(qsort, bench) {
|
||||||
mergesort(p2, n, sizeof(long), CompareLong));
|
mergesort(p2, n, sizeof(long), CompareLong));
|
||||||
EZBENCH2("smoothsort nearly", memcpy(p2, p1, n * sizeof(long)),
|
EZBENCH2("smoothsort nearly", memcpy(p2, p1, n * sizeof(long)),
|
||||||
smoothsort(p2, n, sizeof(long), CompareLong));
|
smoothsort(p2, n, sizeof(long), CompareLong));
|
||||||
|
EZBENCH2("longsort nearly", memcpy(p2, p1, n * sizeof(long)),
|
||||||
|
longsort(p2, n));
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
for (i = 0; i < n; ++i) p1[i] = n - i;
|
for (i = 0; i < n; ++i) p1[i] = n - i;
|
||||||
|
@ -113,6 +126,8 @@ BENCH(qsort, bench) {
|
||||||
mergesort(p2, n, sizeof(long), CompareLong));
|
mergesort(p2, n, sizeof(long), CompareLong));
|
||||||
EZBENCH2("smoothsort reverse", memcpy(p2, p1, n * sizeof(long)),
|
EZBENCH2("smoothsort reverse", memcpy(p2, p1, n * sizeof(long)),
|
||||||
smoothsort(p2, n, sizeof(long), CompareLong));
|
smoothsort(p2, n, sizeof(long), CompareLong));
|
||||||
|
EZBENCH2("longsort reverse", memcpy(p2, p1, n * sizeof(long)),
|
||||||
|
longsort(p2, n));
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
rngset(p1, n * sizeof(long), 0, 0);
|
rngset(p1, n * sizeof(long), 0, 0);
|
||||||
|
@ -124,6 +139,8 @@ BENCH(qsort, bench) {
|
||||||
mergesort(p2, n, sizeof(long), CompareLong));
|
mergesort(p2, n, sizeof(long), CompareLong));
|
||||||
EZBENCH2("smoothsort random", memcpy(p2, p1, n * sizeof(long)),
|
EZBENCH2("smoothsort random", memcpy(p2, p1, n * sizeof(long)),
|
||||||
smoothsort(p2, n, sizeof(long), CompareLong));
|
smoothsort(p2, n, sizeof(long), CompareLong));
|
||||||
|
EZBENCH2("longsort random", memcpy(p2, p1, n * sizeof(long)),
|
||||||
|
longsort(p2, n));
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
for (i = 0; i < n / 2; ++i) {
|
for (i = 0; i < n / 2; ++i) {
|
||||||
|
@ -138,4 +155,5 @@ BENCH(qsort, bench) {
|
||||||
mergesort(p2, n, sizeof(long), CompareLong));
|
mergesort(p2, n, sizeof(long), CompareLong));
|
||||||
EZBENCH2("smoothsort 2n", memcpy(p2, p1, n * sizeof(long)),
|
EZBENCH2("smoothsort 2n", memcpy(p2, p1, n * sizeof(long)),
|
||||||
smoothsort(p2, n, sizeof(long), CompareLong));
|
smoothsort(p2, n, sizeof(long), CompareLong));
|
||||||
|
EZBENCH2("longsort 2n", memcpy(p2, p1, n * sizeof(long)), longsort(p2, n));
|
||||||
}
|
}
|
||||||
|
|
93
test/libc/sock/socket_test.c
Normal file
93
test/libc/sock/socket_test.c
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/sock/sock.h"
|
||||||
|
#include "libc/sock/struct/sockaddr.h"
|
||||||
|
#include "libc/sock/struct/sockaddr6.h"
|
||||||
|
#include "libc/sysv/consts/af.h"
|
||||||
|
#include "libc/sysv/consts/ipproto.h"
|
||||||
|
#include "libc/sysv/consts/limits.h"
|
||||||
|
#include "libc/sysv/consts/sock.h"
|
||||||
|
#include "libc/testlib/testlib.h"
|
||||||
|
|
||||||
|
TEST(ipv4, test) {
|
||||||
|
int ws, pid;
|
||||||
|
char buf[16] = {0};
|
||||||
|
int64_t inoffset;
|
||||||
|
uint32_t addrsize = sizeof(struct sockaddr_in);
|
||||||
|
struct sockaddr_in addr = {
|
||||||
|
.sin_family = AF_INET,
|
||||||
|
.sin_addr.s_addr = htonl(0x7f000001),
|
||||||
|
};
|
||||||
|
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||||
|
ASSERT_SYS(0, 0, bind(3, &addr, sizeof(addr)));
|
||||||
|
ASSERT_SYS(0, 0, getsockname(3, &addr, &addrsize));
|
||||||
|
ASSERT_SYS(0, 0, listen(3, SOMAXCONN));
|
||||||
|
ASSERT_NE(-1, (pid = fork()));
|
||||||
|
if (!pid) {
|
||||||
|
ASSERT_SYS(0, 4, accept(3, &addr, &addrsize));
|
||||||
|
ASSERT_SYS(0, 5, send(4, "hello", 5, 0));
|
||||||
|
ASSERT_SYS(0, 0, close(4));
|
||||||
|
ASSERT_SYS(0, 0, close(3));
|
||||||
|
_Exit(0);
|
||||||
|
}
|
||||||
|
EXPECT_SYS(0, 0, close(3));
|
||||||
|
EXPECT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||||
|
EXPECT_SYS(0, 0, connect(3, &addr, sizeof(addr)));
|
||||||
|
EXPECT_SYS(0, 5, read(3, buf, 16));
|
||||||
|
EXPECT_STREQ("hello", buf);
|
||||||
|
EXPECT_SYS(0, 0, close(3));
|
||||||
|
EXPECT_NE(-1, wait(&ws));
|
||||||
|
ASSERT_TRUE(WIFEXITED(ws));
|
||||||
|
ASSERT_EQ(0, WEXITSTATUS(ws));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ipv6, test) {
|
||||||
|
int ws, pid;
|
||||||
|
char buf[16] = {0};
|
||||||
|
int64_t inoffset;
|
||||||
|
uint32_t addrsize = sizeof(struct sockaddr_in6);
|
||||||
|
struct sockaddr_in6 addr = {
|
||||||
|
.sin6_family = AF_INET6,
|
||||||
|
.sin6_addr.s6_addr[15] = 1,
|
||||||
|
};
|
||||||
|
ASSERT_SYS(0, 3, socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP));
|
||||||
|
ASSERT_SYS(0, 0, bind(3, &addr, sizeof(addr)));
|
||||||
|
ASSERT_SYS(0, 0, getsockname(3, &addr, &addrsize));
|
||||||
|
ASSERT_EQ(AF_INET6, addr.sin6_family);
|
||||||
|
ASSERT_NE(0, addr.sin6_port);
|
||||||
|
ASSERT_SYS(0, 0, listen(3, SOMAXCONN));
|
||||||
|
ASSERT_NE(-1, (pid = fork()));
|
||||||
|
if (!pid) {
|
||||||
|
ASSERT_SYS(0, 4, accept(3, &addr, &addrsize));
|
||||||
|
ASSERT_SYS(0, 5, send(4, "hello", 5, 0));
|
||||||
|
ASSERT_SYS(0, 0, close(4));
|
||||||
|
ASSERT_SYS(0, 0, close(3));
|
||||||
|
_Exit(0);
|
||||||
|
}
|
||||||
|
EXPECT_SYS(0, 0, close(3));
|
||||||
|
EXPECT_SYS(0, 3, socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP));
|
||||||
|
EXPECT_SYS(0, 0, connect(3, &addr, sizeof(addr)));
|
||||||
|
EXPECT_SYS(0, 5, read(3, buf, 16));
|
||||||
|
EXPECT_STREQ("hello", buf);
|
||||||
|
EXPECT_SYS(0, 0, close(3));
|
||||||
|
EXPECT_NE(-1, wait(&ws));
|
||||||
|
ASSERT_TRUE(WIFEXITED(ws));
|
||||||
|
ASSERT_EQ(0, WEXITSTATUS(ws));
|
||||||
|
}
|
|
@ -69,6 +69,10 @@ o/$(MODE)/test/libc/sock/sendrecvmsg_test.com.runs \
|
||||||
o/$(MODE)/test/libc/sock/nointernet_test.com.runs: \
|
o/$(MODE)/test/libc/sock/nointernet_test.com.runs: \
|
||||||
private .PLEDGE = stdio rpath wpath cpath fattr proc inet recvfd sendfd
|
private .PLEDGE = stdio rpath wpath cpath fattr proc inet recvfd sendfd
|
||||||
|
|
||||||
|
o/$(MODE)/test/libc/sock/socket_test.com.runs: .INTERNET = 1 # todo: ipv6 filtering
|
||||||
|
o/$(MODE)/test/libc/sock/socket_test.com.runs: \
|
||||||
|
private .PLEDGE = stdio rpath wpath cpath fattr proc inet
|
||||||
|
|
||||||
$(TEST_LIBC_SOCK_OBJS): test/libc/sock/test.mk
|
$(TEST_LIBC_SOCK_OBJS): test/libc/sock/test.mk
|
||||||
|
|
||||||
.PHONY: o/$(MODE)/test/libc/sock
|
.PHONY: o/$(MODE)/test/libc/sock
|
||||||
|
|
Loading…
Reference in a new issue