Merge dev/socket into main (#1393)

Implement more socket APIs, refer to #1336 and below PRs:
- Implement wasi_addr_resolve function (#1319)
- Fix socket-api byte order issue when host/network order are the same (#1327)
- Enhance sock_addr_local syscall (#1320)
- Implement sock_addr_remote syscall (#1360)
- Add support for IPv6 in WAMR (#1411)
- Implement ns lookup allowlist (#1420)
- Implement sock_send_to and sock_recv_from system calls (#1457)
- Added http downloader and multicast socket options (#1467)
- Fix `bind()` calls to receive the correct size of `sockaddr` structure (#1490)
- Assert on correct parameters (#1505)
- Copy only received bytes from socket recv buffer into the app buffer (#1497)

Co-authored-by: Marcin Kolny <mkolny@amazon.com>
Co-authored-by: Marcin Kolny <marcin.kolny@gmail.com>
Co-authored-by: Callum Macmillan <callumimacmillan@gmail.com>
This commit is contained in:
Wenyong Huang
2022-09-22 21:46:14 +08:00
committed by GitHub
parent 32d2d16908
commit 78b5c5b484
31 changed files with 6345 additions and 438 deletions

View File

@ -292,16 +292,29 @@ os_sem_unlink(const char *name);
* need to implement these APIs
*/
typedef union {
uint32 ipv4;
uint16 ipv6[8];
uint8 data[1];
} bh_ip_addr_buffer_t;
typedef struct {
bh_ip_addr_buffer_t addr_bufer;
uint16 port;
bool is_ipv4;
} bh_sockaddr_t;
/**
* Create a socket
*
* @param sock [OUTPUT] the pointer of socket
* @param tcp_or_udp 1 for tcp, 0 for udp
* @param is_ipv4 true for IPv4, false for IPv6
* @param is_tcp true for tcp, false for udp
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_create(bh_socket_t *sock, int tcp_or_udp);
os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp);
/**
* Assign the address and port to the socket
@ -380,6 +393,22 @@ os_socket_connect(bh_socket_t socket, const char *addr, int port);
int
os_socket_recv(bh_socket_t socket, void *buf, unsigned int len);
/**
* Blocking receive message from a socket.
*
* @param socket the socket to send message
* @param buf the buffer to store the data
* @param len length of the buffer, this API does not guarantee that
* [len] bytes are received
* @param flags control the operation
* @param src_addr source address
*
* @return number of bytes sent if success, -1 otherwise
*/
int
os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags,
bh_sockaddr_t *src_addr);
/**
* Blocking send message on a socket
*
@ -392,6 +421,21 @@ os_socket_recv(bh_socket_t socket, void *buf, unsigned int len);
int
os_socket_send(bh_socket_t socket, const void *buf, unsigned int len);
/**
* Blocking send message on a socket to the target address
*
* @param socket the socket to send message
* @param buf the buffer of data to be sent
* @param len length of the buffer
* @param flags control the operation
* @param dest_addr target address
*
* @return number of bytes sent if success, -1 otherwise
*/
int
os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len,
int flags, const bh_sockaddr_t *dest_addr);
/**
* Close a socket
*
@ -416,13 +460,522 @@ os_socket_shutdown(bh_socket_t socket);
* converts cp into a number in host byte order suitable for use as
* an Internet network address
*
* @param cp a string in IPv4 numbers-and-dots notation
* @param is_ipv4 a flag that indicates whether the string is an IPv4 or
* IPv6 address
*
* @return On success, the converted address is returned.
* @param cp a string in IPv4 numbers-and-dots notation or IPv6
* numbers-and-colons notation
*
* @param out an output buffer to store binary address
*
* @return On success, the function returns 0.
* If the input is invalid, -1 is returned
*/
int
os_socket_inet_network(const char *cp, uint32 *out);
os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out);
typedef struct {
bh_sockaddr_t sockaddr;
uint8_t is_tcp;
} bh_addr_info_t;
/**
* Resolve a host a hostname and a service to one or more IP addresses
*
* @param host a host to resolve
*
* @param service a service to find a port for
*
* @param hint_is_tcp an optional flag that determines a preferred socket type
(TCP or UDP).
*
* @param hint_is_ipv4 an optional flag that determines a preferred address
family (IPv4 or IPv6)
*
* @param addr_info a buffer for resolved addresses
*
* @param addr_info_size a size of the buffer for resolved addresses
* @param max_info_size a maximum number of addresses available (can be bigger
or smaller than buffer size)
* @return On success, the function returns 0; otherwise, it returns -1
*/
int
os_socket_addr_resolve(const char *host, const char *service,
uint8_t *hint_is_tcp, uint8_t *hint_is_ipv4,
bh_addr_info_t *addr_info, size_t addr_info_size,
size_t *max_info_size);
/**
* Returns an binary address and a port of the local socket
*
* @param socket the local socket
*
* @param sockaddr a buffer for storing the address
*
* @return On success, returns 0; otherwise, it returns -1.
*/
int
os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr);
/**
* Returns an binary address and a port of the remote socket
*
* @param socket the remote socket
*
* @param sockaddr a buffer for storing the address
*
* @return On success, returns 0; otherwise, it returns -1.
*/
int
os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr);
/**
* Set the maximum send buffer size.
*
* @param socket the socket to set
* @param bufsiz requested kernel buffer size
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_set_send_buf_size(bh_socket_t socket, size_t bufsiz);
/**
* Get the maximum send buffer size.
*
* @param socket the socket to set
* @param bufsiz the returned kernel buffer size
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_get_send_buf_size(bh_socket_t socket, size_t *bufsiz);
/**
* Set the maximum receive buffer size.
*
* @param socket the socket to set
* @param bufsiz requested kernel buffer size
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_set_recv_buf_size(bh_socket_t socket, size_t bufsiz);
/**
* Get the maximum receive buffer size.
*
* @param socket the socket to set
* @param bufsiz the returned kernel buffer size
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_get_recv_buf_size(bh_socket_t socket, size_t *bufsiz);
/**
* Enable sending of keep-alive messages on connection-oriented sockets
*
* @param socket the socket to set the flag
* @param is_enabled 1 to enable or 0 to disable
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_set_keep_alive(bh_socket_t socket, bool is_enabled);
/**
* Get if sending of keep-alive messages on connection-oriented sockets is
* enabled
*
* @param socket the socket to check
* @param is_enabled 1 if enabled or 0 if disabled
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_get_keep_alive(bh_socket_t socket, bool *is_enabled);
/**
* Set the send timeout until reporting an error
*
* @param socket the socket to set
* @param time_us microseconds until timeout
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_set_send_timeout(bh_socket_t socket, uint64 timeout_us);
/**
* Get the send timeout until reporting an error
*
* @param socket the socket to set
* @param time_us the returned microseconds until timeout
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_get_send_timeout(bh_socket_t socket, uint64 *timeout_us);
/**
* Set the recv timeout until reporting an error
*
* @param socket the socket to set
* @param time_us microseconds until timeout
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_set_recv_timeout(bh_socket_t socket, uint64 timeout_us);
/**
* Get the recv timeout until reporting an error
*
* @param socket the socket to set
* @param time_us the returned microseconds until timeout
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_get_recv_timeout(bh_socket_t socket, uint64 *timeout_us);
/**
* Enable re-use of local addresses
*
* @param socket the socket to set
* @param is_enabled 1 to enable or 0 to disable
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_set_reuse_addr(bh_socket_t socket, bool is_enabled);
/**
* Get whether re-use of local addresses is enabled
*
* @param socket the socket to set
* @param is_enabled 1 for enabled or 0 for disabled
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_get_reuse_addr(bh_socket_t socket, bool *is_enabled);
/**
* Enable re-use of local ports
*
* @param socket the socket to set
* @param is_enabled 1 to enable or 0 to disable
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_set_reuse_port(bh_socket_t socket, bool is_enabled);
/**
* Get whether re-use of local ports is enabled
*
* @param socket the socket to set
* @param is_enabled 1 for enabled or 0 for disabled
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_get_reuse_port(bh_socket_t socket, bool *is_enabled);
/**
* Set the linger options for the given socket
*
* @param socket the socket to set
* @param is_enabled whether linger is enabled
* @param linger_s linger time (seconds)
* @return 0 if success, -1 otherwise
*/
int
os_socket_set_linger(bh_socket_t socket, bool is_enabled, int linger_s);
/**
* Get the linger options for the given socket
*
* @param socket the socket to get
* @param is_enabled whether linger is enabled
* @param linger_s linger time (seconds)
* @return 0 if success, -1 otherwise
*/
int
os_socket_get_linger(bh_socket_t socket, bool *is_enabled, int *linger_s);
/**
* Set no delay TCP
* If set, disable the Nagle algorithm.
* This means that segments are always sent as soon as possible,
* even if there is only a small amount of data
*
* @param socket the socket to set the flag
* @param is_enabled 1 to enable or 0 to disable
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_set_tcp_no_delay(bh_socket_t socket, bool is_enabled);
/**
* Get no delay TCP
* If set, disable the Nagle algorithm.
* This means that segments are always sent as soon as possible,
* even if there is only a small amount of data
*
* @param socket the socket to check
* @param is_enabled 1 if enabled or 0 if disabled
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_get_tcp_no_delay(bh_socket_t socket, bool *is_enabled);
/**
* Enable/Disable tcp quickack mode
* In quickack mode, acks are sent immediately, rather than delayed if needed in
* accordance to normal TCP operation
*
* @param socket the socket to set the flag
* @param is_enabled 1 to enable or 0 to disable
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_set_tcp_quick_ack(bh_socket_t socket, bool is_enabled);
/**
* Enable/Disable tcp quickack mode
* In quickack mode, acks are sent immediately, rather than delayed if needed in
* accordance to normal TCP operation
*
* @param socket the socket to check
* @param is_enabled 1 if enabled or 0 if disabled
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_get_tcp_quick_ack(bh_socket_t socket, bool *is_enabled);
/**
* Set the time the connection needs to remain idle before sending keepalive
* probes
*
* @param socket the socket to set
* @param time_s seconds until keepalive probes are sent
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_set_tcp_keep_idle(bh_socket_t socket, uint32_t time_s);
/**
* Gets the time the connection needs to remain idle before sending keepalive
* probes
*
* @param socket the socket to check
* @param time_s seconds until keepalive probes are sent
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_get_tcp_keep_idle(bh_socket_t socket, uint32_t *time_s);
/**
* Set the time between individual keepalive probes
*
* @param socket the socket to set
* @param time_us seconds between individual keepalive probes
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_set_tcp_keep_intvl(bh_socket_t socket, uint32_t time_s);
/**
* Get the time between individual keepalive probes
*
* @param socket the socket to get
* @param time_s seconds between individual keepalive probes
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_get_tcp_keep_intvl(bh_socket_t socket, uint32_t *time_s);
/**
* Set use of TCP Fast Open
*
* @param socket the socket to set
* @param is_enabled 1 to enable or 0 to disable
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_set_tcp_fastopen_connect(bh_socket_t socket, bool is_enabled);
/**
* Get whether use of TCP Fast Open is enabled
*
* @param socket the socket to get
* @param is_enabled 1 to enabled or 0 to disabled
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_get_tcp_fastopen_connect(bh_socket_t socket, bool *is_enabled);
/**
* Set enable or disable IPv4 or IPv6 multicast loopback.
*
* @param socket the socket to set
* @param ipv6 true to set ipv6 loopback or false for ipv4
* @param is_enabled 1 to enable or 0 to disable
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_set_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool is_enabled);
/**
* Get enable or disable IPv4 or IPv6 multicast loopback.
*
* @param socket the socket to check
* @param ipv6 true to set ipv6 loopback or false for ipv4
* @param is_enabled 1 for enabled or 0 for disabled
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_get_ip_multicast_loop(bh_socket_t socket, bool ipv6,
bool *is_enabled);
/**
* Add membership to a group
*
* @param socket the socket to add membership to
* @param imr_multiaddr the group multicast address (IPv4 or IPv6)
* @param imr_interface the interface to join on
* @param is_ipv6 whether the imr_multiaddr is IPv4 or IPv6 (true for IPv6)
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_set_ip_add_membership(bh_socket_t socket,
bh_ip_addr_buffer_t *imr_multiaddr,
uint32_t imr_interface, bool is_ipv6);
/**
* Drop membership of a group
*
* @param socket the socket to drop membership to
* @param imr_multiaddr the group multicast address (IPv4 or IPv6)
* @param imr_interface the interface to join on
* @param is_ipv6 whether the imr_multiaddr is IPv4 or IPv6 (true for IPv6)
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_set_ip_drop_membership(bh_socket_t socket,
bh_ip_addr_buffer_t *imr_multiaddr,
uint32_t imr_interface, bool is_ipv6);
/**
* Set the current time-to-live field that is
* used in every packet sent from this socket.
* @param socket the socket to set the flag
* @param ttl_s time to live (seconds)
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_set_ip_ttl(bh_socket_t socket, uint8_t ttl_s);
/**
* Retrieve the current time-to-live field that is
* used in every packet sent from this socket.
* @param socket the socket to set the flag
* @param ttl_s time to live (seconds)
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_get_ip_ttl(bh_socket_t socket, uint8_t *ttl_s);
/**
* Set the time-to-live value of outgoing multicast
* packets for this socket
* @param socket the socket to set the flag
* @param ttl_s time to live (seconds)
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_set_ip_multicast_ttl(bh_socket_t socket, uint8_t ttl_s);
/**
* Read the time-to-live value of outgoing multicast
* packets for this socket
* @param socket the socket to set the flag
* @param ttl_s time to live (seconds)
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_get_ip_multicast_ttl(bh_socket_t socket, uint8_t *ttl_s);
/**
* Restrict to sending and receiving IPv6 packets only
*
* @param socket the socket to set
* @param is_enabled 1 to enable or 0 to disable
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_set_ipv6_only(bh_socket_t socket, bool is_enabled);
/**
* Get whether only sending and receiving IPv6 packets
*
* @param socket the socket to check
* @param is_enabled 1 for enabled or 0 for disabled
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_get_ipv6_only(bh_socket_t socket, bool *is_enabled);
/**
* Set whether broadcast is enabled
* When enabled, datagram sockets are allowed
* to send packets to a broadcast address.
*
* @param socket the socket to set the flag
* @param is_enabled 1 to enable or 0 to disable
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_set_broadcast(bh_socket_t socket, bool is_enabled);
/**
* Get whether broadcast is enabled
* When enabled, datagram sockets are allowed
* to send packets to a broadcast address.
*
* @param socket the socket to check
* @param is_enabled 1 if enabled or 0 if disabled
*
* @return 0 if success, -1 otherwise
*/
int
os_socket_get_broadcast(bh_socket_t socket, bool *is_enabled);
#ifdef __cplusplus
}