Files
PlantAI-dev/tools/pymol-env/include/aws/io/socket.h
T
2026-08-03 18:42:47 +08:00

470 lines
20 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#ifndef AWS_IO_SOCKET_H
#define AWS_IO_SOCKET_H
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#include <aws/io/channel.h>
#include <aws/io/io.h>
AWS_PUSH_SANE_WARNING_LEVEL
enum aws_socket_domain {
AWS_SOCKET_IPV4,
AWS_SOCKET_IPV6,
/* Unix domain sockets (or at least something like them) */
AWS_SOCKET_LOCAL,
/* VSOCK used in inter-VM communication */
AWS_SOCKET_VSOCK,
};
enum aws_socket_type {
/* A streaming socket sends reliable messages over a two-way connection.
* This means TCP when used with IPV4/6, and Unix domain sockets, when used with
* AWS_SOCKET_LOCAL*/
AWS_SOCKET_STREAM,
/* A datagram socket is connectionless and sends unreliable messages.
* This means UDP when used with IPV4/6.
* LOCAL and VSOCK sockets are not compatible with DGRAM.*/
AWS_SOCKET_DGRAM,
};
/**
* Socket Implementation type. Decides which socket implementation is used. If set to
* `AWS_SOCKET_IMPL_PLATFORM_DEFAULT`, it will automatically use the platform’s default.
*
* PLATFORM DEFAULT SOCKET IMPLEMENTATION TYPE
* Linux | AWS_SOCKET_IMPL_POSIX
* Windows | AWS_SOCKET_IMPL_WINSOCK
* BSD Variants| AWS_SOCKET_IMPL_POSIX
* MacOS | AWS_SOCKET_IMPL_POSIX
* iOS | AWS_SOCKET_IMPL_APPLE_NETWORK_FRAMEWORK
*/
enum aws_socket_impl_type {
AWS_SOCKET_IMPL_PLATFORM_DEFAULT = 0,
AWS_SOCKET_IMPL_POSIX,
AWS_SOCKET_IMPL_WINSOCK,
AWS_SOCKET_IMPL_APPLE_NETWORK_FRAMEWORK,
};
#define AWS_NETWORK_INTERFACE_NAME_MAX 16
typedef void(aws_socket_on_shutdown_complete_fn)(void *user_data);
struct aws_socket_options {
enum aws_socket_type type;
enum aws_socket_domain domain;
enum aws_socket_impl_type impl_type;
uint32_t connect_timeout_ms;
/* Keepalive properties are TCP only.
* Set keepalive true to periodically transmit messages for detecting a disconnected peer.
* If interval or timeout are zero, then default values are used. */
uint16_t keep_alive_interval_sec;
uint16_t keep_alive_timeout_sec;
/* If set, sets the number of keep alive probes allowed to fail before the connection is considered
* lost. If zero OS defaults are used. On Windows, this option is meaningless until Windows 10 1703.*/
uint16_t keep_alive_max_failed_probes;
bool keepalive;
/**
* THIS IS AN EXPERIMENTAL AND UNSTABLE API
* (Optional)
* This property is used to bind the socket to a particular network interface by name, such as eth0 and ens32.
* If this is empty, the socket will not be bound to any interface and will use OS defaults. If the provided name
* is invalid, `aws_socket_init()` will error out with AWS_IO_SOCKET_INVALID_OPTIONS. This option is only
* supported on Linux, macOS(bsd socket), and platforms that have either SO_BINDTODEVICE or IP_BOUND_IF. It is not
* supported on Windows and Apple Network Framework. `AWS_ERROR_PLATFORM_NOT_SUPPORTED` will be raised on
* unsupported platforms.
*/
char network_interface_name[AWS_NETWORK_INTERFACE_NAME_MAX];
};
struct aws_socket;
/**
* Called in client mode when an outgoing connection has succeeded or an error has occurred.
* If the connection was successful error_code will be AWS_ERROR_SUCCESS and the socket has already been assigned
* to the event loop specified in aws_socket_connect().
*
* If an error occurred error_code will be non-zero.
*/
typedef void(aws_socket_on_connection_result_fn)(struct aws_socket *socket, int error_code, void *user_data);
/**
* Called by a listening socket when a listener accept has successfully initialized or an error has occurred.
* If the listener was successful error_code will be AWS_ERROR_SUCCESS and the socket has already been assigned
* to the event loop specified in aws_socket_start_accept().
*
* If an error occurred error_code will be non-zero.
*/
typedef void(aws_socket_on_accept_started_fn)(struct aws_socket *socket, int error_code, void *user_data);
/**
* Called by a listening socket when either an incoming connection has been received or an error occurred.
*
* In the normal use-case, this function will be called multiple times over the lifetime of a single listening socket.
* new_socket is already connected and initialized, and is using the same options and allocator as the listening socket.
* A user may want to call aws_socket_set_options() on the new socket if different options are desired.
*
* new_socket is not yet assigned to an event-loop. The user should call aws_socket_assign_to_event_loop() before
* performing IO operations. The user must call `aws_socket_clean_up()` and "aws_mem_release()" when they're done with
* the new_socket, to free it.
*
* When error_code is AWS_ERROR_SUCCESS, new_socket is the recently accepted connection.
* If error_code is non-zero, an error occurred and you should aws_socket_close() the socket.
*
* Do not call aws_socket_clean_up() from this callback.
*/
typedef void(aws_socket_on_accept_result_fn)(
struct aws_socket *socket,
int error_code,
struct aws_socket *new_socket,
void *user_data);
/**
* Callback for when the data passed to a call to aws_socket_write() has either completed or failed.
* On success, error_code will be AWS_ERROR_SUCCESS.
*
* `socket` may be NULL in the callback if the socket is released and cleaned up before the callback is triggered.
*/
typedef void(
aws_socket_on_write_completed_fn)(struct aws_socket *socket, int error_code, size_t bytes_written, void *user_data);
/**
* Callback for when socket is either readable (edge-triggered) or when an error has occurred. If the socket is
* readable, error_code will be AWS_ERROR_SUCCESS.
*
* `socket` may be NULL in the callback if the socket is released and cleaned up before the callback is triggered.
*/
typedef void(aws_socket_on_readable_fn)(struct aws_socket *socket, int error_code, void *user_data);
#ifdef _WIN32
# define AWS_ADDRESS_MAX_LEN 256
#else
# include <sys/un.h>
# define AWS_ADDRESS_MAX_LEN sizeof(((struct sockaddr_un *)0)->sun_path)
#endif
struct aws_socket_endpoint {
char address[AWS_ADDRESS_MAX_LEN];
uint32_t port;
};
struct aws_socket {
struct aws_socket_vtable *vtable;
struct aws_allocator *allocator;
struct aws_socket_endpoint local_endpoint;
struct aws_socket_endpoint remote_endpoint;
struct aws_socket_options options;
struct aws_io_handle io_handle;
struct aws_event_loop *event_loop;
struct aws_channel_handler *handler;
int state;
aws_socket_on_readable_fn *readable_fn;
void *readable_user_data;
aws_socket_on_connection_result_fn *connection_result_fn;
aws_socket_on_accept_result_fn *accept_result_fn;
void *connect_accept_user_data;
void *impl;
};
struct aws_socket_connect_options {
const struct aws_socket_endpoint *remote_endpoint;
struct aws_event_loop *event_loop;
aws_socket_on_connection_result_fn *on_connection_result;
void *user_data;
/*
* This is only set when using Apple SecItem for TLS negotiation.
* Apple Network Connections using SecItem require all TLS configuration options at the point of
* creating the socket slot as it handles both the TCP and TLS negotiation before returning a
* valid socket for use.
*/
struct aws_tls_connection_options *tls_connection_options;
};
struct aws_socket_listener_options {
aws_socket_on_accept_result_fn *on_accept_result;
void *on_accept_result_user_data;
// This callback is invoked when the listener starts accepting incoming connections.
// If the callback set, the socket must not be released before the callback invoked.
aws_socket_on_accept_started_fn *on_accept_start;
void *on_accept_start_user_data;
};
struct aws_socket_bind_options {
const struct aws_socket_endpoint *local_endpoint;
void *user_data;
/*
* This is only set when using Apple SecItem for TLS negotiation.
* Apple Network Connections using SecItem require all TLS configuration options at the point of
* creating the socket slot as it handles both the TCP and TLS negotiation before returning a
* valid socket for use.
* Socket bind also needs an event loop to run its verification block.
*/
struct aws_event_loop *event_loop;
struct aws_tls_connection_options *tls_connection_options;
};
struct aws_byte_buf;
struct aws_byte_cursor;
struct aws_string;
AWS_EXTERN_C_BEGIN
/**
* Initializes a socket object with socket options. options will be copied.
*/
AWS_IO_API int aws_socket_init(
struct aws_socket *socket,
struct aws_allocator *alloc,
const struct aws_socket_options *options);
/**
* Shuts down any pending operations on the socket, and cleans up state. The socket object can be re-initialized after
* this operation. This function calls aws_socket_close. If you have not already called aws_socket_close() on the
* socket, all of the rules for aws_socket_close() apply here. In this case it will not fail if you use the function
* improperly, but on some platforms you will certainly leak memory.
*
* If the socket has already been closed, you can safely, call this from any thread.
*/
AWS_IO_API void aws_socket_clean_up(struct aws_socket *socket);
/**
* Connects to a remote endpoint. In UDP, this simply binds the socket to a remote address for use with
* `aws_socket_write()`, and if the operation is successful, the socket can immediately be used for write operations.
*
* In TCP, LOCAL and VSOCK this function will not block. If the return value is successful, then you must wait on the
* `on_connection_result()` callback to be invoked before using the socket.
*
* If an event_loop is provided for UDP sockets, a notification will be sent on
* on_connection_result in the event-loop's thread. Upon completion, the socket will already be assigned
* an event loop. If NULL is passed for UDP, it will immediately return upon success, but you must call
* aws_socket_assign_to_event_loop before use.
*/
AWS_IO_API int aws_socket_connect(struct aws_socket *socket, struct aws_socket_connect_options *socket_connect_options);
/**
* Binds the socket to a local address. In UDP mode, the socket is ready for `aws_socket_read()` operations. In
* connection oriented modes, you still must call `aws_socket_listen()` and `aws_socket_start_accept()` before using the
* socket. local_endpoint is copied.
*/
AWS_IO_API int aws_socket_bind(struct aws_socket *socket, struct aws_socket_bind_options *socket_bind_options);
/**
* Get the local address which the socket is bound to.
* Raises an error if no address is bound.
*/
AWS_IO_API int aws_socket_get_bound_address(const struct aws_socket *socket, struct aws_socket_endpoint *out_address);
/**
* TCP, LOCAL and VSOCK only. Sets up the socket to listen on the address bound to in `aws_socket_bind()`.
*/
AWS_IO_API int aws_socket_listen(struct aws_socket *socket, int backlog_size);
/**
* TCP, LOCAL and VSOCK only. The socket will begin accepting new connections. This is an asynchronous operation. New
* connections or errors will arrive via the `on_accept_result` callback.
*
* aws_socket_bind() and aws_socket_listen() must be called before calling this function.
*
*/
AWS_IO_API int aws_socket_start_accept(
struct aws_socket *socket,
struct aws_event_loop *accept_loop,
struct aws_socket_listener_options options);
/**
* TCP, LOCAL and VSOCK only. The listening socket will stop accepting new connections.
* It is safe to call `aws_socket_start_accept()` again after
* this operation. This can be called from any thread but be aware,
* on some platforms, if you call this from outside of the current event loop's thread, it will block
* until the event loop finishes processing the request for unsubscribe in it's own thread.
*/
AWS_IO_API int aws_socket_stop_accept(struct aws_socket *socket);
/**
* Calls `close()` on the socket and unregisters all io operations from the event loop. This function must be called
* from the event-loop's thread unless this is a listening socket. If it's a listening socket it can be called from any
* non-event-loop thread or the event-loop the socket is currently assigned to. If called from outside the event-loop,
* this function will block waiting on the socket to close. If this is called from an event-loop thread other than
* the one it's assigned to, it presents the possibility of a deadlock, so don't do it.
*
* If you are using Apple Network Framework, you should always call this function from an event-loop thread regardless
* it is a server or client socket.
*/
AWS_IO_API int aws_socket_close(struct aws_socket *socket);
/**
* Calls `shutdown()` on the socket based on direction.
*/
AWS_IO_API int aws_socket_shutdown_dir(struct aws_socket *socket, enum aws_channel_direction dir);
/**
* Sets new socket options on the underlying socket.
*/
AWS_IO_API int aws_socket_set_options(struct aws_socket *socket, const struct aws_socket_options *options);
/**
* Assigns the socket to the event-loop. The socket will begin receiving read/write/error notifications after this call.
*
* Note: If you called connect for TCP or Unix Domain Sockets and received a connection_success callback, this has
* already happened. You only need to call this function when:
*
* a.) This socket is a server socket (e.g. a result of a call to start_accept())
* b.) This socket is a UDP socket.
*/
AWS_IO_API int aws_socket_assign_to_event_loop(struct aws_socket *socket, struct aws_event_loop *event_loop);
/**
* Gets the event-loop the socket is assigned to.
*/
AWS_IO_API struct aws_event_loop *aws_socket_get_event_loop(struct aws_socket *socket);
/**
* Subscribes on_readable to notifications when the socket goes readable (edge-triggered). Errors will also be received
* in the callback.
*
* Note! This function is technically not thread safe, but we do not enforce which thread you call from.
* It's your responsibility to either call this in safely (e.g. just don't call it in parallel from multiple threads) or
* schedule a task to call it. If you call it before your first call to read, it will be fine.
*/
AWS_IO_API int aws_socket_subscribe_to_readable_events(
struct aws_socket *socket,
aws_socket_on_readable_fn *on_readable,
void *user_data);
/**
* Reads from the socket. This call is non-blocking and will return `AWS_IO_SOCKET_READ_WOULD_BLOCK` if no data is
* available. `read` is the amount of data read into `buffer`.
*
* Attempts to read enough to fill all remaining space in the buffer, from `buffer->len` to `buffer->capacity`.
* `buffer->len` is updated to reflect the buffer's new length.
*
*
* Use aws_socket_subscribe_to_readable_events() to receive notifications of when the socket goes readable.
*
* NOTE! This function must be called from the event-loop used in aws_socket_assign_to_event_loop
*/
AWS_IO_API int aws_socket_read(struct aws_socket *socket, struct aws_byte_buf *buffer, size_t *amount_read);
/**
* Writes to the socket. This call is non-blocking and will attempt to write as much as it can, but will queue any
* remaining portion of the data for write when available. written_fn will be invoked once the entire cursor has been
* written, or the write failed or was cancelled.
*
* NOTE! This function must be called from the event-loop used in aws_socket_assign_to_event_loop
*
* For client sockets, connect() and aws_socket_assign_to_event_loop() must be called before calling this.
*
* For incoming sockets from a listener, aws_socket_assign_to_event_loop() must be called first.
*/
AWS_IO_API int aws_socket_write(
struct aws_socket *socket,
const struct aws_byte_cursor *cursor,
aws_socket_on_write_completed_fn *written_fn,
void *user_data);
/**
* Apple Network Framework only. The callback that will triggered when aws_socket_close() finished. The callback
* will be called from the socket event loop.
*/
AWS_IO_API int aws_socket_set_close_complete_callback(
struct aws_socket *socket,
aws_socket_on_shutdown_complete_fn fn,
void *user_data);
/**
* Apple Network Framework only. The callback that will triggered when aws_socket_cleanup() finished. And
* it is only safe to release the socket afterwards. The callback will be called from the socket event loop.
*/
AWS_IO_API int aws_socket_set_cleanup_complete_callback(
struct aws_socket *socket,
aws_socket_on_shutdown_complete_fn fn,
void *user_data);
/**
* Gets the latest error from the socket. If no error has occurred AWS_OP_SUCCESS will be returned. This function does
* not raise any errors to the installed error handlers.
*/
AWS_IO_API int aws_socket_get_error(struct aws_socket *socket);
/**
* Returns true if the socket is still open (doesn't mean connected or listening, only that it hasn't had close()
* called.
*/
AWS_IO_API bool aws_socket_is_open(struct aws_socket *socket);
/**
* Raises AWS_IO_SOCKET_INVALID_ADDRESS and logs an error if connecting to this port is illegal.
* For example, port must be in range 1-65535 to connect with IPv4.
* These port values would fail eventually in aws_socket_connect(),
* but you can use this function to validate earlier.
*/
AWS_IO_API int aws_socket_validate_port_for_connect(uint32_t port, enum aws_socket_domain domain);
/**
* Raises AWS_IO_SOCKET_INVALID_ADDRESS and logs an error if binding to this port is illegal.
* For example, port must in range 0-65535 to bind with IPv4.
* These port values would fail eventually in aws_socket_bind(),
* but you can use this function to validate earlier.
*/
AWS_IO_API int aws_socket_validate_port_for_bind(uint32_t port, enum aws_socket_domain domain);
/**
* Assigns a random address (UUID) for use with AWS_SOCKET_LOCAL (Unix Domain Sockets).
* For use in internal tests only.
*/
AWS_IO_API void aws_socket_endpoint_init_local_address_for_test(struct aws_socket_endpoint *endpoint);
/**
* Validates whether the network interface name is valid. On Windows, it will always return false since we don't support
* network_interface_name on Windows */
AWS_IO_API bool aws_is_network_interface_name_valid(const char *interface_name);
/**
* Get default impl type based on the platform.
* For user in internal tests only.
*/
AWS_IO_API enum aws_socket_impl_type aws_socket_get_default_impl_type(void);
/**
* Parse an IPv4 address string and convert it to binary representation.
*
* This function converts a string representation of an IPv4 address
* into its binary network byte order (big-endian) representation.
*
* @param src The IPv4 address string to parse. Must be a valid IPv4 address in dotted decimal notation.
* @param dst Pointer to a uint32_t where the parsed address will be stored in network byte order.
*
* @return AWS_OP_SUCCESS on success, or AWS_OP_ERR on failure.
* On failure, aws_last_error() will be set to:
* - AWS_IO_SOCKET_INVALID_ADDRESS if the input string is not a valid IPv4 address
*/
AWS_IO_API int aws_parse_ipv4_address(const struct aws_string *src, uint32_t *dst);
/**
* Parse an IPv6 address string and convert it to binary representation.
*
* This function converts a string representation of an IPv6 address
* into its binary network byte order(big-endian) representation.
*
* @param src The IPv6 address string to parse. Must be a valid IPv6 address in standard notation.
* @param dst Pointer to an aws_byte_buf where the parsed address will be appended.
* The buffer must have at least 16 bytes of available capacity.
* The parsed 16-byte IPv6 address will be appended to the buffer and
* the buffer's length will be increased by 16.
*
* @return AWS_OP_SUCCESS on success, or AWS_OP_ERR on failure.
* On failure, aws_last_error() will be set to:
* - AWS_IO_SOCKET_INVALID_ADDRESS if the input string is not a valid IPv6 address
* - AWS_ERROR_SHORT_BUFFER if the destination buffer doesn't have enough capacity
*/
AWS_IO_API int aws_parse_ipv6_address(const struct aws_string *src, struct aws_byte_buf *dst);
AWS_EXTERN_C_END
AWS_POP_SANE_WARNING_LEVEL
#endif /* AWS_IO_SOCKET_H */