diff options
Diffstat (limited to 'ext/socket/rubysocket.h')
| -rw-r--r-- | ext/socket/rubysocket.h | 219 |
1 files changed, 172 insertions, 47 deletions
diff --git a/ext/socket/rubysocket.h b/ext/socket/rubysocket.h index c74fb326ec..2ec3ab335a 100644 --- a/ext/socket/rubysocket.h +++ b/ext/socket/rubysocket.h @@ -1,12 +1,22 @@ #ifndef RUBY_SOCKET_H #define RUBY_SOCKET_H 1 -#include "ruby/ruby.h" -#include "ruby/io.h" -#include "ruby/thread.h" -#include "ruby/util.h" -#include "internal.h" +#include "ruby/config.h" +#include RUBY_EXTCONF_H + +#if defined(__sun) || defined(_AIX) +/* (Recent?) Solaris' <nfs/nfs.h> have conflicting definition of T_DATA. Let + * us honour system definition by undefining ours. + * + * See also [ruby-core:4261] + */ +# include "ruby/ruby.h" +# undef T_DATA +#endif + +#include <errno.h> #include <stdio.h> + #include <sys/types.h> #include <sys/stat.h> @@ -23,15 +33,15 @@ #endif #ifdef _WIN32 +# include <winsock2.h> +# include <ws2tcpip.h> +# include <mswsock.h> +# include <iphlpapi.h> # if defined(_MSC_VER) # undef HAVE_TYPE_STRUCT_SOCKADDR_DL # endif #else -# if defined(__BEOS__) && !defined(__HAIKU__) && !defined(BONE) -# include <net/socket.h> -# else -# include <sys/socket.h> -# endif +# include <sys/socket.h> # include <netinet/in.h> # ifdef HAVE_NETINET_IN_SYSTM_H # include <netinet/in_systm.h> @@ -39,6 +49,9 @@ # ifdef HAVE_NETINET_TCP_H # include <netinet/tcp.h> # endif +# ifdef HAVE_NETINET_TCP_FSM_H +# include <netinet/tcp_fsm.h> +# endif # ifdef HAVE_NETINET_UDP_H # include <netinet/udp.h> # endif @@ -51,16 +64,20 @@ #ifdef HAVE_NETPACKET_PACKET_H # include <netpacket/packet.h> #endif + #ifdef HAVE_NET_ETHERNET_H # include <net/ethernet.h> #endif -#include <errno.h> - #ifdef HAVE_SYS_UN_H # include <sys/un.h> #endif +#ifdef HAVE_AFUNIX_H +// Windows doesn't have sys/un.h, but it does have afunix.h just to be special: +# include <afunix.h> +#endif + #if defined(HAVE_FCNTL) # ifdef HAVE_SYS_SELECT_H # include <sys/select.h> @@ -77,14 +94,20 @@ #endif #ifdef HAVE_IFADDRS_H +# ifdef __HAIKU__ +# define _BSD_SOURCE +# endif # include <ifaddrs.h> #endif + #ifdef HAVE_SYS_IOCTL_H # include <sys/ioctl.h> #endif + #ifdef HAVE_SYS_SOCKIO_H # include <sys/sockio.h> #endif + #ifdef HAVE_NET_IF_H # include <net/if.h> #endif @@ -92,16 +115,42 @@ #ifdef HAVE_SYS_PARAM_H # include <sys/param.h> #endif + #ifdef HAVE_SYS_UCRED_H # include <sys/ucred.h> #endif + #ifdef HAVE_UCRED_H # include <ucred.h> #endif + #ifdef HAVE_NET_IF_DL_H # include <net/if_dl.h> #endif +#ifdef SOCKS5 +# include <socks.h> +#endif + +#ifndef HAVE_GETADDRINFO +# include "addrinfo.h" +#endif + +#include "internal.h" +#include "internal/array.h" +#include "internal/compilers.h" +#include "internal/error.h" +#include "internal/gc.h" +#include "internal/io.h" +#include "internal/thread.h" +#include "internal/vm.h" +#include "ruby/io.h" +#include "ruby/ruby.h" +#include "ruby/thread.h" +#include "ruby/util.h" +#include "sockport.h" +#include "ruby/fiber/scheduler.h" + #ifndef HAVE_TYPE_SOCKLEN_T typedef int socklen_t; #endif @@ -135,11 +184,6 @@ unsigned int if_nametoindex(const char *); */ #define pseudo_AF_FTIP pseudo_AF_RTIP -#ifndef HAVE_GETADDRINFO -# include "addrinfo.h" -#endif - -#include "sockport.h" #ifndef NI_MAXHOST # define NI_MAXHOST 1025 @@ -216,11 +260,6 @@ typedef union { # endif #endif -#ifdef __BEOS__ -# undef close -# define close closesocket -#endif - #define INET_CLIENT 0 #define INET_SERVER 1 #define INET_SOCKS 2 @@ -228,12 +267,18 @@ typedef union { extern int rsock_do_not_reverse_lookup; #define FMODE_NOREVLOOKUP 0x100 +/* common socket families only */ +#define FMODE_UNIX 0x00200000 +#define FMODE_INET 0x00400000 +#define FMODE_INET6 0x00800000 +#define FMODE_SOCK (FMODE_UNIX|FMODE_INET|FMODE_INET6) + extern VALUE rb_cBasicSocket; extern VALUE rb_cIPSocket; extern VALUE rb_cTCPSocket; extern VALUE rb_cTCPServer; extern VALUE rb_cUDPSocket; -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN extern VALUE rb_cUNIXSocket; extern VALUE rb_cUNIXServer; #endif @@ -242,22 +287,18 @@ extern VALUE rb_cAddrinfo; extern VALUE rb_cSockOpt; extern VALUE rb_eSocket; +extern VALUE rb_eResolution; #ifdef SOCKS extern VALUE rb_cSOCKSSocket; -# ifdef SOCKS5 -# include <socks.h> -# else -void SOCKSinit(); -int Rconnect(); +# ifndef SOCKS5 +void SOCKSinit(char *); +int Rconnect(int, const struct sockaddr *, socklen_t); # endif #endif #include "constdefs.h" -#define BLOCKING_REGION(func, arg) (long)rb_thread_blocking_region((func), (arg), RUBY_UBF_IO, 0) -#define BLOCKING_REGION_FD(func, arg) (long)rb_thread_io_blocking_region((func), (arg), (arg)->fd) - #define SockAddrStringValue(v) rsock_sockaddr_string_value(&(v)) #define SockAddrStringValuePtr(v) rsock_sockaddr_string_value_ptr(&(v)) #define SockAddrStringValueWithAddrinfo(v, rai_ret) rsock_sockaddr_string_value_with_addrinfo(&(v), &(rai_ret)) @@ -267,7 +308,7 @@ VALUE rsock_sockaddr_string_value_with_addrinfo(volatile VALUE *v, VALUE *ai_ret VALUE rb_check_sockaddr_string_type(VALUE); -NORETURN(void rsock_raise_socket_error(const char *, int)); +NORETURN(void rsock_raise_resolution_error(const char *, int)); int rsock_family_arg(VALUE domain); int rsock_socktype_arg(VALUE type); @@ -276,12 +317,19 @@ int rsock_optname_arg(int family, int level, VALUE optname); int rsock_cmsg_type_arg(int family, int level, VALUE type); int rsock_shutdown_how_arg(VALUE how); -int rsock_getfamily(int sockfd); +int rsock_getfamily(rb_io_t *fptr); -int rb_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res); +struct rb_addrinfo { + struct addrinfo *ai; + int allocated_by_malloc; +}; +void rb_freeaddrinfo(struct rb_addrinfo *ai); +VALUE rsock_freeaddrinfo(VALUE arg); int rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags); -struct addrinfo *rsock_addrinfo(VALUE host, VALUE port, int socktype, int flags); -struct addrinfo *rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack); +int rsock_fd_family(int fd); +struct rb_addrinfo *rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags, VALUE timeout); +struct rb_addrinfo *rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack, VALUE timeout); + VALUE rsock_fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len); VALUE rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len); @@ -290,23 +338,24 @@ VALUE rsock_addrinfo_inspect_sockaddr(VALUE rai); VALUE rsock_make_ipaddr(struct sockaddr *addr, socklen_t addrlen); VALUE rsock_ipaddr(struct sockaddr *sockaddr, socklen_t sockaddrlen, int norevlookup); -VALUE rsock_make_hostent(VALUE host, struct addrinfo *addr, VALUE (*ipaddr)(struct sockaddr *, socklen_t)); +VALUE rsock_make_hostent(VALUE host, struct rb_addrinfo *addr, VALUE (*ipaddr)(struct sockaddr *, socklen_t)); VALUE rsock_inspect_sockaddr(struct sockaddr *addr, socklen_t socklen, VALUE ret); socklen_t rsock_sockaddr_len(struct sockaddr *addr); VALUE rsock_sockaddr_obj(struct sockaddr *addr, socklen_t len); int rsock_revlookup_flag(VALUE revlookup, int *norevlookup); -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN VALUE rsock_unixpath_str(struct sockaddr_un *sockaddr, socklen_t len); VALUE rsock_unixaddr(struct sockaddr_un *sockaddr, socklen_t len); socklen_t rsock_unix_sockaddr_len(VALUE path); #endif int rsock_socket(int domain, int type, int proto); +int rsock_detect_cloexec(int fd); VALUE rsock_init_sock(VALUE sock, int fd); VALUE rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass); -VALUE rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv, VALUE local_host, VALUE local_serv, int type); +VALUE rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv, VALUE local_host, VALUE local_serv, int type, VALUE resolv_timeout, VALUE connect_timeout, VALUE open_timeout, VALUE fast_fallback, VALUE test_mode_settings); VALUE rsock_init_unixsock(VALUE sock, VALUE path, int server); struct rsock_send_arg { @@ -327,28 +376,34 @@ enum sock_recv_type { RECV_SOCKET /* Socket#recvfrom */ }; -VALUE rsock_s_recvfrom_nonblock(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from); +VALUE rsock_s_recvfrom_nonblock(VALUE sock, VALUE len, VALUE flg, VALUE str, + VALUE ex, enum sock_recv_type from); VALUE rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from); -int rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks); +int rsock_connect(VALUE self, const struct sockaddr *sockaddr, int len, int socks, VALUE timeout); -VALUE rsock_s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len); -VALUE rsock_s_accept_nonblock(VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len); +VALUE rsock_s_accept(VALUE klass, VALUE io, struct sockaddr *sockaddr, socklen_t *len); +VALUE rsock_s_accept_nonblock(VALUE klass, VALUE ex, rb_io_t *fptr, + struct sockaddr *sockaddr, socklen_t *len); VALUE rsock_sock_listen(VALUE sock, VALUE log); VALUE rsock_sockopt_new(int family, int level, int optname, VALUE data); #if defined(HAVE_SENDMSG) -VALUE rsock_bsock_sendmsg(int argc, VALUE *argv, VALUE sock); -VALUE rsock_bsock_sendmsg_nonblock(int argc, VALUE *argv, VALUE sock); +VALUE rsock_bsock_sendmsg(VALUE sock, VALUE data, VALUE flags, + VALUE dest_sockaddr, VALUE controls); +VALUE rsock_bsock_sendmsg_nonblock(VALUE sock, VALUE data, VALUE flags, + VALUE dest_sockaddr, VALUE controls, VALUE ex); #else #define rsock_bsock_sendmsg rb_f_notimplement #define rsock_bsock_sendmsg_nonblock rb_f_notimplement #endif #if defined(HAVE_RECVMSG) -VALUE rsock_bsock_recvmsg(int argc, VALUE *argv, VALUE sock); -VALUE rsock_bsock_recvmsg_nonblock(int argc, VALUE *argv, VALUE sock); +VALUE rsock_bsock_recvmsg(VALUE sock, VALUE dlen, VALUE clen, VALUE flags, + VALUE scm_rights); +VALUE rsock_bsock_recvmsg_nonblock(VALUE sock, VALUE dlen, VALUE clen, + VALUE flags, VALUE scm_rights, VALUE ex); ssize_t rsock_recvmsg(int socket, struct msghdr *message, int flags); #else #define rsock_bsock_recvmsg rb_f_notimplement @@ -359,6 +414,47 @@ ssize_t rsock_recvmsg(int socket, struct msghdr *message, int flags); void rsock_discard_cmsg_resource(struct msghdr *mh, int msg_peek_p); #endif +char *raddrinfo_host_str(VALUE host, char *hbuf, size_t hbuflen, int *flags_ptr); +char *raddrinfo_port_str(VALUE port, char *pbuf, size_t pbuflen, int *flags_ptr); + +#ifndef FAST_FALLBACK_INIT_INETSOCK_IMPL +# if !defined(HAVE_PTHREAD_CREATE) || !defined(HAVE_PTHREAD_DETACH) || defined(__MINGW32__) || defined(__MINGW64__) +# define FAST_FALLBACK_INIT_INETSOCK_IMPL 0 +# else +# include "ruby/thread_native.h" +# define FAST_FALLBACK_INIT_INETSOCK_IMPL 1 +# define IPV6_HOSTNAME_RESOLVED '1' +# define IPV4_HOSTNAME_RESOLVED '2' +# define SELECT_CANCELLED '3' + +struct fast_fallback_getaddrinfo_entry +{ + int family, err, refcount; + struct addrinfo hints; + struct addrinfo *ai; + struct fast_fallback_getaddrinfo_shared *shared; + int has_syserr; + long test_sleep_ms; + int test_ecode; +}; + +struct fast_fallback_getaddrinfo_shared +{ + int notify, refcount; + char *node, *service; + rb_nativethread_lock_t lock; + struct fast_fallback_getaddrinfo_entry getaddrinfo_entries[FLEX_ARY_LEN]; +}; + +int raddrinfo_pthread_create(pthread_t *th, void *(*start_routine) (void *), void *arg); +void *fork_safe_do_fast_fallback_getaddrinfo(void *ptr); +void free_fast_fallback_getaddrinfo_entry(struct fast_fallback_getaddrinfo_entry **entry); +void free_fast_fallback_getaddrinfo_shared(struct fast_fallback_getaddrinfo_shared **shared); +# endif +#endif + +NORETURN(void rsock_raise_user_specified_timeout(struct addrinfo *ai, VALUE host, VALUE port)); + void rsock_init_basicsocket(void); void rsock_init_ipsocket(void); void rsock_init_tcpsocket(void); @@ -386,4 +482,33 @@ NORETURN(void rsock_sys_fail_sockaddr(const char *, struct sockaddr *addr, sockl NORETURN(void rsock_sys_fail_raddrinfo(const char *, VALUE rai)); NORETURN(void rsock_sys_fail_raddrinfo_or_sockaddr(const char *, VALUE addr, VALUE rai)); +#if defined(__MINGW32__) || defined(_WIN32) +#define RSOCK_WAIT_BEFORE_BLOCKING +#endif + +/* + * some OSes may support MSG_DONTWAIT inconsistently depending on socket + * type, we only expect Linux to support it consistently for all socket types. + */ +#if defined(MSG_DONTWAIT) && defined(__linux__) +# define MSG_DONTWAIT_RELIABLE 1 +#else +# define MSG_DONTWAIT_RELIABLE 0 +#endif + +VALUE rsock_read_nonblock(VALUE sock, VALUE length, VALUE buf, VALUE ex); +VALUE rsock_write_nonblock(VALUE sock, VALUE buf, VALUE ex); + +void rsock_make_fd_nonblock(int fd); + +int rsock_is_dgram(rb_io_t *fptr); + +extern ID tcp_fast_fallback; + +#if !defined HAVE_INET_NTOP && ! defined _WIN32 +const char *inet_ntop(int, const void *, char *, size_t); +#elif defined __MINGW32__ +# define inet_ntop(f,a,n,l) rb_w32_inet_ntop(f,a,n,l) +#endif + #endif |
