31#define MAX_USER_BUFF_SIZE ((size_t)(100*1024*1024))
32#define DEFAULT_BUFF_SIZE 8192
33#define MAX_ARRAY_KEY_SIZE 128
40static GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
41static __declspec(thread) LPFN_WSARECVMSG WSARecvMsg =
NULL;
42inline ssize_t recvmsg(
int sockfd,
struct msghdr *
msg,
int flags)
47 if (WSARecvMsg ==
NULL) {
48 int res = WSAIoctl((SOCKET) sockfd, SIO_GET_EXTENSION_FUNCTION_POINTER,
49 &WSARecvMsg_GUID,
sizeof(WSARecvMsg_GUID),
50 &WSARecvMsg,
sizeof(WSARecvMsg),
58 return WSARecvMsg((SOCKET)sockfd,
msg, &recvd,
NULL,
NULL) == 0
62inline ssize_t sendmsg(
int sockfd,
const struct msghdr *
msg,
int flags)
71#define LONG_CHECK_VALID_INT(l, arg_pos) \
73 if ((l) < INT_MIN || (l) > INT_MAX) { \
74 zend_argument_value_error((arg_pos), "must be between %d and %d", INT_MIN, INT_MAX); \
85static void ancillary_registery_free_elem(
zval *el) {
90static MUTEX_T ancillary_mutex;
92static void init_ancillary_registry(
void)
96 ancillary_registry.initialized = 1;
100#define PUT_ENTRY(sizev, var_size, calc, from, to, level, type) \
101 entry.size = sizev; \
102 entry.var_el_size = var_size; \
103 entry.calc_space = calc; \
104 entry.from_array = from; \
105 entry.to_array = to; \
106 key.cmsg_level = level; \
107 key.cmsg_type = type; \
108 zend_hash_str_update_mem(&ancillary_registry.ht, (char*)&key, sizeof(key), (void*)&entry, sizeof(entry))
110#if defined(IPV6_PKTINFO) && defined(HAVE_IPV6)
111 PUT_ENTRY(
sizeof(
struct in6_pktinfo), 0, 0, from_zval_write_in6_pktinfo,
115#if defined(IPV6_HOPLIMIT) && defined(HAVE_IPV6)
120#if defined(IPV6_TCLASS) && defined(HAVE_IPV6)
126#ifdef HAVE_STRUCT_UCRED
127 PUT_ENTRY(
sizeof(
struct ucred), 0, 0, from_zval_write_ucred,
130 PUT_ENTRY(
sizeof(
struct cmsgcred), 0, 0, from_zval_write_ucred,
135#if defined(LOCAL_CREDS_PERSISTENT)
136 PUT_ENTRY(SOCKCRED2SIZE(1), 1, 0, from_zval_write_ucred,
138#elif defined(LOCAL_CREDS)
139 PUT_ENTRY(SOCKCREDSIZE(1), 1, 0, from_zval_write_ucred,
144 PUT_ENTRY(0,
sizeof(
int), calculate_scm_rights_space, from_zval_write_fd_array,
149static void destroy_ancillary_registry(
void)
151 if (ancillary_registry.initialized) {
153 ancillary_registry.initialized = 0;
162 tsrm_mutex_lock(ancillary_mutex);
164 if (!ancillary_registry.initialized) {
165 init_ancillary_registry();
168 tsrm_mutex_unlock(ancillary_mutex);
171 if ((entry = zend_hash_str_find_ptr(&ancillary_registry.ht, (
char*)&
key,
sizeof(
key))) !=
NULL) {
183 php_socket *php_sock;
184 struct msghdr *msghdr;
196 php_sock = Z_SOCKET_P(zsocket);
197 ENSURE_SOCKET_VALID(php_sock);
200 sizeof(*msghdr),
"msghdr", &allocations, &
err);
207 res = sendmsg(php_sock->bsd_socket, msghdr, (
int)
flags);
212 PHP_SOCKET_ERROR(php_sock,
"Error in sendmsg",
errno);
224 php_socket *php_sock;
226 struct msghdr *msghdr;
237 php_sock = Z_SOCKET_P(zsocket);
238 ENSURE_SOCKET_VALID(php_sock);
241 sizeof(*msghdr),
"msghdr", &allocations, &
err);
248 res = recvmsg(php_sock->bsd_socket, msghdr, (
int)
flags);
259 "msghdr", kv, &
err, &tmp);
265 if (!
err.has_error) {
317 size_t total_size = CMSG_SPACE(
size);
320 || total_size <
size ) {
346 "support sticky IPV6_PKTINFO");
356 sizeof(
struct in6_pktinfo),
"in6_pktinfo", &allocations, &
err);
362 optlen =
sizeof(
struct in6_pktinfo);
372 retval = setsockopt(php_sock->bsd_socket, level, optname, opt_ptr, optlen);
374 PHP_SOCKET_ERROR(php_sock,
"Unable to set socket option",
errno);
394 size =
sizeof(
struct in6_pktinfo);
395 reader = &to_zval_read_in6_pktinfo;
403 res = getsockopt(php_sock->bsd_socket, level, optname,
buffer, &
size);
405 PHP_SOCKET_ERROR(php_sock,
"unable to get socket option",
errno);
426 ancillary_mutex = tsrm_mutex_alloc();
433 tsrm_mutex_free(ancillary_mutex);
436 destroy_ancillary_registry();
assert(mixed $assertion, Throwable|string|null $description=null)
void * from_zval_run_conversions(const zval *container, php_socket *sock, from_zval_write_field *writer, size_t struct_size, const char *top_name, zend_llist **allocations, struct err_s *err)
void to_zval_read_msghdr(const char *msghdr_c, zval *zv, res_context *ctx)
void from_zval_write_msghdr_recv(const zval *container, char *msghdr_c, ser_context *ctx)
void allocations_dispose(zend_llist **allocations)
const struct key_value empty_key_value_list[]
void from_zval_write_int(const zval *arr_value, char *field, ser_context *ctx)
void err_msg_dispose(struct err_s *err)
void from_zval_write_msghdr_send(const zval *container, char *msghdr_c, ser_context *ctx)
void to_zval_read_int(const char *data, zval *zv, res_context *ctx)
zval * to_zval_run_conversions(const char *structure, to_zval_read_field *reader, const char *top_name, const struct key_value *key_value_pairs, struct err_s *err, zval *zv)
void to_zval_read_field(const char *data, zval *zv, res_context *ctx)
zend_class_entry * socket_ce
char * sockets_strerror(int error)
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
unsigned char key[REFLECTION_KEY_LEN]
#define PUT_ENTRY(sizev, var_size, calc, from, to, level, type)
#define LONG_CHECK_VALID_INT(l, arg_pos)
void php_socket_sendrecvmsg_shutdown(SHUTDOWN_FUNC_ARGS)
ancillary_reg_entry * get_ancillary_reg_entry(int cmsg_level, int msg_type)
void php_socket_sendrecvmsg_init(INIT_FUNC_ARGS)
int php_do_setsockopt_ipv6_rfc3542(php_socket *php_sock, int level, int optname, zval *arg4)
int php_do_getsockopt_ipv6_rfc3542(php_socket *php_sock, int level, int optname, zval *result)
socket_cmsg_space(int $level, int $type, int $num=0)
socket_sendmsg(Socket $socket, array $message, int $flags=0)
socket_recvmsg(Socket $socket, array &$message, int $flags=0)
ZEND_API ZEND_COLD void zend_value_error(const char *format,...)
ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec,...)
ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format,...)
#define ecalloc(nmemb, size)
#define pefree(ptr, persistent)
ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent)
struct _zend_llist zend_llist
#define SHUTDOWN_FUNC_ARGS
struct _zend_array HashTable
#define ZVAL_COPY_VALUE(z, v)
ZEND_API void zval_ptr_dtor(zval *zval_ptr)