2016-01-26 16:07:52 +00:00
/*
2020-02-20 15:35:16 +00:00
Copyright ( c ) 2016 - 2020 Chung , Hyung - Hwan . All rights reserved .
2016-01-26 16:07:52 +00:00
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions
are met :
1. Redistributions of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
2. Redistributions in binary form must reproduce the above copyright
notice , this list of conditions and the following disclaimer in the
documentation and / or other materials provided with the distribution .
THIS SOFTWARE IS PROVIDED BY THE AUTHOR " AS IS " AND ANY EXPRESS OR
2022-06-11 05:32:01 +00:00
IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
2016-01-26 16:07:52 +00:00
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
2021-07-22 07:30:20 +00:00
# include <hio-sck.h>
# include "hio-prv.h"
2016-02-02 15:40:09 +00:00
2022-06-22 06:44:28 +00:00
# include <sys/types.h>
2016-01-26 16:02:20 +00:00
# include <sys/socket.h>
# include <fcntl.h>
2016-01-28 16:44:47 +00:00
# include <unistd.h>
2016-01-26 16:02:20 +00:00
# include <errno.h>
2020-07-29 10:04:14 +00:00
# include <string.h> /* strerror */
2016-03-30 16:31:56 +00:00
2016-01-28 16:44:47 +00:00
# include <netinet/in.h>
# include <arpa/inet.h>
2020-11-15 04:02:47 +00:00
# include <net/if.h>
2020-07-24 17:29:52 +00:00
# include <netinet/if_ether.h>
2016-04-25 16:15:36 +00:00
2021-08-08 04:10:29 +00:00
# if defined(HAVE_NETINET_SCTP_H)
# include <netinet / sctp.h>
2021-08-13 15:33:53 +00:00
# if defined(IPPROTO_SCTP)
# define ENABLE_SCTP
# endif
2021-08-08 04:10:29 +00:00
# endif
2016-04-25 16:15:36 +00:00
# if defined(HAVE_NETPACKET_PACKET_H)
# include <netpacket / packet.h>
# endif
# if defined(HAVE_NET_IF_DL_H)
# include <net / if_dl.h>
# endif
2020-07-19 06:23:43 +00:00
# if defined(HAVE_SYS_SENDFILE_H)
# include <sys / sendfile.h>
# endif
2016-01-26 16:02:20 +00:00
2020-11-16 15:40:20 +00:00
# if defined(HAVE_SYS_IOCTL_H)
# include <sys / ioctl.h>
# endif
2020-11-16 16:55:22 +00:00
# if defined(HAVE_NET_BPF_H)
# include <net / bpf.h>
# endif
2020-11-16 15:40:20 +00:00
2016-04-18 14:21:23 +00:00
# if defined(__linux__)
# include <limits.h>
# if defined(HAVE_LINUX_NETFILTER_IPV4_H)
# include <linux / netfilter_ipv4.h> /* SO_ORIGINAL_DST */
# endif
# if !defined(SO_ORIGINAL_DST)
# define SO_ORIGINAL_DST 80
# endif
# if !defined(IP_TRANSPARENT)
# define IP_TRANSPARENT 19
# endif
# if !defined(SO_REUSEPORT)
# define SO_REUSEPORT 15
# endif
# endif
2016-04-17 17:00:58 +00:00
# if defined(HAVE_OPENSSL_SSL_H) && defined(HAVE_SSL)
# include <openssl / ssl.h>
# if defined(HAVE_OPENSSL_ERR_H)
# include <openssl / err.h>
# endif
# if defined(HAVE_OPENSSL_ENGINE_H)
# include <openssl / engine.h>
# endif
# define USE_SSL
# endif
2016-03-29 15:02:01 +00:00
/* ========================================================================= */
2016-01-26 16:02:20 +00:00
2021-07-22 07:30:20 +00:00
static hio_syshnd_t open_async_socket ( hio_t * hio , int domain , int type , int proto )
2019-01-11 07:35:43 +00:00
{
2021-07-22 07:30:20 +00:00
hio_syshnd_t sck = HIO_SYSHND_INVALID ;
2016-01-26 16:02:20 +00:00
2019-01-11 07:35:43 +00:00
# if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC)
2020-07-24 17:29:52 +00:00
type | = SOCK_NONBLOCK | SOCK_CLOEXEC ;
2019-01-11 07:35:43 +00:00
open_socket :
# endif
sck = socket ( domain , type , proto ) ;
2021-07-22 07:30:20 +00:00
if ( sck = = HIO_SYSHND_INVALID )
2016-04-06 13:49:47 +00:00
{
2019-01-11 07:35:43 +00:00
# if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC)
if ( errno = = EINVAL & & ( type & ( SOCK_NONBLOCK | SOCK_CLOEXEC ) ) )
2016-04-06 13:49:47 +00:00
{
2019-01-11 07:35:43 +00:00
type & = ~ ( SOCK_NONBLOCK | SOCK_CLOEXEC ) ;
goto open_socket ;
2016-04-06 13:49:47 +00:00
}
2019-01-11 07:35:43 +00:00
# endif
goto oops ;
2016-04-06 13:49:47 +00:00
}
2019-01-11 07:35:43 +00:00
else
2016-01-26 16:02:20 +00:00
{
2019-01-11 07:35:43 +00:00
# if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC)
if ( type & ( SOCK_NONBLOCK | SOCK_CLOEXEC ) ) goto done ;
# endif
2016-01-26 16:02:20 +00:00
}
2016-03-23 13:54:15 +00:00
2021-07-22 07:30:20 +00:00
if ( hio_makesyshndasync ( hio , sck ) < = - 1 | |
hio_makesyshndcloexec ( hio , sck ) < = - 1 ) goto oops ;
2016-01-26 16:02:20 +00:00
2019-01-11 07:35:43 +00:00
done :
2016-01-26 16:02:20 +00:00
return sck ;
2019-01-11 07:35:43 +00:00
oops :
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( hio , 0 , errno ) ;
if ( sck ! = HIO_SYSHND_INVALID ) close ( sck ) ;
return HIO_SYSHND_INVALID ;
2020-07-24 17:29:52 +00:00
}
2021-07-22 07:30:20 +00:00
static hio_syshnd_t open_async_qx ( hio_t * hio , hio_syshnd_t * side_chan )
2020-07-24 17:29:52 +00:00
{
int fd [ 2 ] ;
int type = SOCK_DGRAM ;
# if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC)
type | = SOCK_NONBLOCK | SOCK_CLOEXEC ;
open_socket :
# endif
if ( socketpair ( AF_UNIX , type , 0 , fd ) < = - 1 )
{
# if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC)
if ( errno = = EINVAL & & ( type & ( SOCK_NONBLOCK | SOCK_CLOEXEC ) ) )
{
type & = ~ ( SOCK_NONBLOCK | SOCK_CLOEXEC ) ;
goto open_socket ;
}
# endif
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( hio , 0 , errno ) ;
return HIO_SYSHND_INVALID ;
2020-07-24 17:29:52 +00:00
}
else
{
# if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC)
if ( type & ( SOCK_NONBLOCK | SOCK_CLOEXEC ) ) goto done ;
# endif
}
2021-07-22 07:30:20 +00:00
if ( hio_makesyshndasync ( hio , fd [ 0 ] ) < = - 1 | |
hio_makesyshndasync ( hio , fd [ 1 ] ) < = - 1 | |
hio_makesyshndcloexec ( hio , fd [ 0 ] ) < = - 1 | |
hio_makesyshndcloexec ( hio , fd [ 1 ] ) < = - 1 )
2020-07-24 17:29:52 +00:00
{
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( hio , 0 , errno ) ;
2020-07-24 17:29:52 +00:00
close ( fd [ 0 ] ) ;
close ( fd [ 1 ] ) ;
2021-07-22 07:30:20 +00:00
return HIO_SYSHND_INVALID ;
2020-07-24 17:29:52 +00:00
}
done :
* side_chan = fd [ 1 ] ; /* write end of the pipe */
return fd [ 0 ] ; /* read end of the pipe */
2016-01-26 16:02:20 +00:00
}
2021-07-22 07:30:20 +00:00
static hio_syshnd_t open_async_bpf ( hio_t * hio )
2020-11-16 15:40:20 +00:00
{
2021-07-22 07:30:20 +00:00
hio_syshnd_t fd = HIO_SYSHND_INVALID ;
2021-08-09 08:24:21 +00:00
#if 0
2020-11-16 15:40:20 +00:00
int tmp ;
unsigned int bufsize ;
2021-08-09 08:24:21 +00:00
# endif
2020-11-16 15:40:20 +00:00
fd = open ( " /dev/bpf " , O_RDWR ) ;
2021-07-22 07:30:20 +00:00
if ( fd = = HIO_SYSHND_INVALID ) goto oops ;
2020-11-16 15:40:20 +00:00
2020-11-16 16:55:22 +00:00
#if 0
2021-08-08 04:10:29 +00:00
if ( ioctl ( fd , BIOCIMMEDIATE , & tmp ) < = - 1 ) goto oops ;
if ( ioctl ( fd , BIOCGBLEN , & bufsize ) < = - 1 ) goto oops ;
2020-11-16 16:55:22 +00:00
# endif
2020-11-16 15:40:20 +00:00
return fd ;
oops :
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( hio , 0 , errno ) ;
if ( fd ! = HIO_SYSHND_INVALID ) close ( fd ) ;
return HIO_SYSHND_INVALID ;
2020-11-16 15:40:20 +00:00
}
2016-04-02 15:25:35 +00:00
/* ========================================================================= */
2021-07-22 07:30:20 +00:00
static hio_devaddr_t * skad_to_devaddr ( hio_dev_sck_t * dev , const hio_skad_t * sckaddr , hio_devaddr_t * devaddr )
2016-03-30 16:31:56 +00:00
{
2016-04-18 14:21:23 +00:00
if ( sckaddr )
2016-03-30 16:31:56 +00:00
{
2016-04-18 14:21:23 +00:00
devaddr - > ptr = ( void * ) sckaddr ;
2021-08-17 07:00:22 +00:00
devaddr - > len = hio_skad_get_size ( sckaddr ) ;
2016-04-18 14:21:23 +00:00
return devaddr ;
2016-03-30 16:31:56 +00:00
}
2021-07-22 07:30:20 +00:00
return HIO_NULL ;
2016-03-30 16:31:56 +00:00
}
2021-07-22 07:30:20 +00:00
static HIO_INLINE hio_skad_t * devaddr_to_skad ( hio_dev_sck_t * dev , const hio_devaddr_t * devaddr , hio_skad_t * sckaddr )
2016-03-30 16:31:56 +00:00
{
2021-07-22 07:30:20 +00:00
return ( hio_skad_t * ) devaddr - > ptr ;
2016-03-30 16:31:56 +00:00
}
2016-04-02 15:25:35 +00:00
2016-03-29 15:02:01 +00:00
/* ========================================================================= */
2016-03-30 07:06:54 +00:00
2021-08-08 07:03:52 +00:00
# define IS_STREAM(sck) ((sck)->dev_cap & HIO_DEV_CAP_STREAM)
2016-03-30 07:06:54 +00:00
2016-03-29 15:02:01 +00:00
struct sck_type_map_t
{
int domain ;
int type ;
int proto ;
2021-08-08 04:10:29 +00:00
unsigned int connectable : 1 ;
unsigned int listenable : 1 ;
hio_bitmask_t extra_dev_cap ;
2016-03-30 07:06:54 +00:00
} ;
2020-11-16 15:40:20 +00:00
# define __AF_BPF 999998
2020-07-24 17:29:52 +00:00
2016-03-30 07:06:54 +00:00
static struct sck_type_map_t sck_type_map [ ] =
2016-03-29 15:02:01 +00:00
{
2021-07-22 07:30:20 +00:00
/* HIO_DEV_SCK_QX */
2021-08-08 04:10:29 +00:00
{ HIO_AF_QX , 0 , 0 , 0 , 0 , 0 } ,
2021-08-06 03:23:48 +00:00
# if defined(AF_UNIX)
2021-08-08 04:10:29 +00:00
{ AF_UNIX , SOCK_STREAM , 0 , 1 , 1 , HIO_DEV_CAP_STREAM } ,
2021-08-06 03:23:48 +00:00
# else
2021-08-08 04:10:29 +00:00
{ - 1 , 0 , 0 , 0 , 0 , 0 } ,
2021-08-06 03:23:48 +00:00
# endif
2020-07-24 17:29:52 +00:00
2021-07-22 07:30:20 +00:00
/* HIO_DEV_SCK_TCP4 */
2021-08-08 04:10:29 +00:00
{ AF_INET , SOCK_STREAM , 0 , 1 , 1 , HIO_DEV_CAP_STREAM } ,
2016-04-25 14:07:28 +00:00
2021-07-22 07:30:20 +00:00
/* HIO_DEV_SCK_TCP6 */
2021-08-08 04:10:29 +00:00
{ AF_INET6 , SOCK_STREAM , 0 , 1 , 1 , HIO_DEV_CAP_STREAM } ,
2016-04-25 14:07:28 +00:00
2021-08-08 04:10:29 +00:00
/* HIO_DEV_SCK_UPD4 */ /* TODO: the socket api allows connect() on UDP sockets. should i mark it connectable? */
{ AF_INET , SOCK_DGRAM , 0 , 0 , 0 , 0 } ,
2016-04-25 14:07:28 +00:00
2021-07-22 07:30:20 +00:00
/* HIO_DEV_SCK_UDP6 */
2021-08-08 04:10:29 +00:00
{ AF_INET6 , SOCK_DGRAM , 0 , 0 , 0 , 0 } ,
2021-08-06 04:34:13 +00:00
2021-08-13 15:33:53 +00:00
# if defined(ENABLE_SCTP)
2021-08-06 04:34:13 +00:00
/* HIO_DEV_SCK_SCTP4 */
2021-08-08 04:10:29 +00:00
{ AF_INET , SOCK_STREAM , IPPROTO_SCTP , 1 , 1 , HIO_DEV_CAP_STREAM } ,
2021-08-06 04:34:13 +00:00
/* HIO_DEV_SCK_SCTP6 */
2021-08-08 04:10:29 +00:00
{ AF_INET6 , SOCK_STREAM , IPPROTO_SCTP , 1 , 1 , HIO_DEV_CAP_STREAM } ,
2021-08-06 04:34:13 +00:00
/* HIO_DEV_SCK_SCTP4_SP - not implemented */
2021-08-09 08:24:21 +00:00
/*{ AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP, 1, 1, 0 },*/
{ - 1 , 0 , 0 , 0 , 0 , 0 } ,
2021-08-06 04:34:13 +00:00
/* HIO_DEV_SCK_SCTP6_SP - not implemented */
2021-08-09 08:24:21 +00:00
/*{ AF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, 1, 1, 0 },*/
{ - 1 , 0 , 0 , 0 , 0 , 0 } ,
2021-08-06 04:34:13 +00:00
# else
2021-08-08 04:10:29 +00:00
{ - 1 , 0 , 0 , 0 , 0 , 0 } ,
{ - 1 , 0 , 0 , 0 , 0 , 0 } ,
{ - 1 , 0 , 0 , 0 , 0 , 0 } ,
{ - 1 , 0 , 0 , 0 , 0 , 0 } ,
2021-08-06 04:34:13 +00:00
# endif
2016-03-29 15:02:01 +00:00
2021-07-22 07:30:20 +00:00
/* HIO_DEV_SCK_ICMP4 - IP protocol field is 1 byte only. no byte order conversion is needed */
2021-08-08 04:10:29 +00:00
{ AF_INET , SOCK_RAW , IPPROTO_ICMP , 0 , 0 , 0 } ,
2020-11-16 15:40:20 +00:00
2021-07-22 07:30:20 +00:00
/* HIO_DEV_SCK_ICMP6 - IP protocol field is 1 byte only. no byte order conversion is needed */
2021-08-08 04:10:29 +00:00
{ AF_INET6 , SOCK_RAW , IPPROTO_ICMP , 0 , 0 , 0 } ,
2021-08-06 04:34:13 +00:00
2016-04-25 16:15:36 +00:00
2021-07-22 07:30:20 +00:00
# if defined(AF_PACKET) && (HIO_SIZEOF_STRUCT_SOCKADDR_LL > 0)
/* HIO_DEV_SCK_ARP - Ethernet type is 2 bytes long. Protocol must be specified in the network byte order */
2021-08-08 04:10:29 +00:00
{ AF_PACKET , SOCK_RAW , HIO_CONST_HTON16 ( HIO_ETHHDR_PROTO_ARP ) , 0 , 0 , 0 } ,
2016-04-25 14:07:28 +00:00
2021-07-22 07:30:20 +00:00
/* HIO_DEV_SCK_ARP_DGRAM - link-level header removed*/
2021-08-08 04:10:29 +00:00
{ AF_PACKET , SOCK_DGRAM , HIO_CONST_HTON16 ( HIO_ETHHDR_PROTO_ARP ) , 0 , 0 , 0 } ,
2016-04-25 14:07:28 +00:00
2021-07-22 07:30:20 +00:00
# elif defined(AF_LINK) && (HIO_SIZEOF_STRUCT_SOCKADDR_DL > 0)
/* HIO_DEV_SCK_ARP */
2021-08-08 04:10:29 +00:00
{ AF_LINK , SOCK_RAW , HIO_CONST_HTON16 ( HIO_ETHHDR_PROTO_ARP ) , 0 , 0 , 0 } ,
2016-04-25 16:15:36 +00:00
2021-07-22 07:30:20 +00:00
/* HIO_DEV_SCK_ARP_DGRAM */
2021-08-08 04:10:29 +00:00
{ AF_LINK , SOCK_DGRAM , HIO_CONST_HTON16 ( HIO_ETHHDR_PROTO_ARP ) , 0 , 0 , 0 } ,
2016-04-25 16:15:36 +00:00
# else
2021-08-08 04:10:29 +00:00
{ - 1 , 0 , 0 , 0 , 0 , 0 } ,
{ - 1 , 0 , 0 , 0 , 0 , 0 } ,
2016-04-25 16:15:36 +00:00
# endif
2021-07-22 07:30:20 +00:00
# if defined(AF_PACKET) && (HIO_SIZEOF_STRUCT_SOCKADDR_LL > 0)
/* HIO_DEV_SCK_PACKET */
2021-08-08 04:10:29 +00:00
{ AF_PACKET , SOCK_RAW , HIO_CONST_HTON16 ( ETH_P_ALL ) , 0 , 0 , 0 } ,
2021-07-22 07:30:20 +00:00
# elif defined(AF_LINK) && (HIO_SIZEOF_STRUCT_SOCKADDR_DL > 0)
/* HIO_DEV_SCK_PACKET */
2021-08-08 04:10:29 +00:00
{ AF_LINK , SOCK_RAW , HIO_CONST_HTON16 ( 0 ) , 0 , 0 , 0 } ,
2020-07-24 17:29:52 +00:00
# else
2021-08-08 04:10:29 +00:00
{ - 1 , 0 , 0 , 0 , 0 , 0 } ,
2020-07-24 17:29:52 +00:00
# endif
2020-11-16 15:40:20 +00:00
2021-07-22 07:30:20 +00:00
/* HIO_DEV_SCK_BPF - arp */
2021-08-08 04:10:29 +00:00
{ __AF_BPF , 0 , 0 , 0 , 0 , 0 } /* not implemented yet */
2016-03-29 15:02:01 +00:00
} ;
2016-03-30 07:06:54 +00:00
/* ======================================================================== */
2021-07-22 07:30:20 +00:00
static void connect_timedout ( hio_t * hio , const hio_ntime_t * now , hio_tmrjob_t * job )
2016-03-29 15:02:01 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) job - > ctx ;
2016-03-29 15:02:01 +00:00
2021-08-08 07:03:52 +00:00
HIO_ASSERT ( hio , IS_STREAM ( rdev ) ) ;
2016-03-29 15:02:01 +00:00
2021-07-22 07:30:20 +00:00
if ( rdev - > state & HIO_DEV_SCK_CONNECTING )
2016-03-29 15:02:01 +00:00
{
2021-07-22 07:30:20 +00:00
/* the state check for HIO_DEV_TCP_CONNECTING is actually redundant
2016-03-30 07:06:54 +00:00
* as it must not be fired after it gets connected . the timer job
* doesn ' t need to be deleted when it gets connected for this check
* here . this libarary , however , deletes the job when it gets
* connected . */
2021-07-22 07:30:20 +00:00
HIO_DEBUG1 ( hio , " SCK(%p) - connect timed out. halting \n " , rdev ) ;
hio_dev_sck_halt ( rdev ) ;
2016-03-29 15:02:01 +00:00
}
2016-03-30 07:06:54 +00:00
}
2021-07-22 07:30:20 +00:00
static void ssl_accept_timedout ( hio_t * hio , const hio_ntime_t * now , hio_tmrjob_t * job )
2016-04-20 15:59:11 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) job - > ctx ;
2016-04-20 15:59:11 +00:00
2021-08-08 07:03:52 +00:00
HIO_ASSERT ( hio , IS_STREAM ( rdev ) ) ;
2016-04-20 15:59:11 +00:00
2021-07-22 07:30:20 +00:00
if ( rdev - > state & HIO_DEV_SCK_ACCEPTING_SSL )
2016-04-20 15:59:11 +00:00
{
2021-07-22 07:30:20 +00:00
HIO_DEBUG1 ( hio , " SCK(%p) - ssl-accept timed out. halting \n " , rdev ) ;
hio_dev_sck_halt ( rdev ) ;
2016-04-20 15:59:11 +00:00
}
}
2021-07-22 07:30:20 +00:00
static void ssl_connect_timedout ( hio_t * hio , const hio_ntime_t * now , hio_tmrjob_t * job )
2016-04-21 15:07:58 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) job - > ctx ;
2016-04-21 15:07:58 +00:00
2021-08-08 07:03:52 +00:00
HIO_ASSERT ( hio , IS_STREAM ( rdev ) ) ;
2016-04-21 15:07:58 +00:00
2021-07-22 07:30:20 +00:00
if ( rdev - > state & HIO_DEV_SCK_CONNECTING_SSL )
2016-04-21 15:07:58 +00:00
{
2021-07-22 07:30:20 +00:00
HIO_DEBUG1 ( hio , " SCK(%p) - ssl-connect timed out. halting \n " , rdev ) ;
hio_dev_sck_halt ( rdev ) ;
2016-04-21 15:07:58 +00:00
}
}
2021-07-22 07:30:20 +00:00
static HIO_INLINE int schedule_timer_job_at ( hio_dev_sck_t * dev , const hio_ntime_t * fire_at , hio_tmrjob_handler_t handler )
2016-04-21 15:07:58 +00:00
{
2021-07-22 07:30:20 +00:00
return hio_schedtmrjobat ( dev - > hio , fire_at , handler , & dev - > tmrjob_index , dev ) ;
2016-04-21 15:07:58 +00:00
}
2016-04-22 06:31:12 +00:00
2021-07-22 07:30:20 +00:00
static HIO_INLINE int schedule_timer_job_after ( hio_dev_sck_t * dev , const hio_ntime_t * fire_after , hio_tmrjob_handler_t handler )
2016-04-22 06:31:12 +00:00
{
2021-07-22 07:30:20 +00:00
return hio_schedtmrjobafter ( dev - > hio , fire_after , handler , & dev - > tmrjob_index , dev ) ;
2016-04-22 06:31:12 +00:00
}
2016-03-30 07:06:54 +00:00
/* ======================================================================== */
2019-01-28 08:13:06 +00:00
# if defined(USE_SSL)
2021-07-22 07:30:20 +00:00
static void set_ssl_error ( hio_t * hio , int sslerr )
2019-01-28 08:13:06 +00:00
{
2021-07-22 07:30:20 +00:00
hio_bch_t emsg [ 128 ] ;
ERR_error_string_n ( sslerr , emsg , HIO_COUNTOF ( emsg ) ) ;
hio_seterrbfmt ( hio , HIO_ESYSERR , " %hs " , emsg ) ;
2019-01-28 08:13:06 +00:00
}
# endif
2016-03-30 07:06:54 +00:00
2021-07-22 07:30:20 +00:00
static int dev_sck_make ( hio_dev_t * dev , void * ctx )
2016-03-30 07:06:54 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
hio_dev_sck_make_t * arg = ( hio_dev_sck_make_t * ) ctx ;
hio_syshnd_t hnd = HIO_SYSHND_INVALID ;
hio_syshnd_t side_chan = HIO_SYSHND_INVALID ;
2016-03-30 07:06:54 +00:00
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( hio , arg - > type > = 0 & & arg - > type < HIO_COUNTOF ( sck_type_map ) ) ;
2016-03-29 15:02:01 +00:00
2020-07-26 17:26:38 +00:00
/* initialize some fields first where 0 is not somthing initial or invalid. */
2021-07-22 07:30:20 +00:00
rdev - > hnd = HIO_SYSHND_INVALID ;
rdev - > side_chan = HIO_SYSHND_INVALID ;
rdev - > tmrjob_index = HIO_TMRIDX_INVALID ;
2020-07-26 09:21:05 +00:00
2016-04-26 05:54:48 +00:00
if ( sck_type_map [ arg - > type ] . domain < = - 1 )
{
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_ENOIMPL ) ; /* TODO: better error info? */
2020-07-26 17:26:38 +00:00
goto oops ;
2016-04-26 05:54:48 +00:00
}
2021-08-06 03:23:48 +00:00
if ( HIO_UNLIKELY ( sck_type_map [ arg - > type ] . domain = = HIO_AF_QX ) )
2020-07-24 17:29:52 +00:00
{
2021-07-22 07:30:20 +00:00
hnd = open_async_qx ( hio , & side_chan ) ;
if ( hnd = = HIO_SYSHND_INVALID ) goto oops ;
2020-07-24 17:29:52 +00:00
}
else
{
2021-07-22 07:30:20 +00:00
hnd = open_async_socket ( hio , sck_type_map [ arg - > type ] . domain , sck_type_map [ arg - > type ] . type , sck_type_map [ arg - > type ] . proto ) ;
if ( hnd = = HIO_SYSHND_INVALID ) goto oops ;
2021-08-08 04:10:29 +00:00
2021-08-13 15:33:53 +00:00
# if defined(ENABLE_SCTP)
2021-08-08 04:10:29 +00:00
if ( sck_type_map [ arg - > type ] . type = = SOCK_SEQPACKET & &
sck_type_map [ arg - > type ] . proto = = IPPROTO_SCTP )
{
struct sctp_event_subscribe sctp_ev_s ;
HIO_MEMSET ( & sctp_ev_s , 0 , HIO_SIZEOF ( sctp_ev_s ) ) ;
sctp_ev_s . sctp_data_io_event = 1 ;
setsockopt ( hnd , IPPROTO_SCTP , SCTP_EVENTS , & sctp_ev_s , HIO_SIZEOF ( sctp_ev_s ) ) ;
}
# endif
2020-07-24 17:29:52 +00:00
}
2016-03-29 15:02:01 +00:00
2020-07-24 17:29:52 +00:00
rdev - > hnd = hnd ;
rdev - > side_chan = side_chan ;
2021-07-22 07:30:20 +00:00
rdev - > dev_cap = HIO_DEV_CAP_IN | HIO_DEV_CAP_OUT | sck_type_map [ arg - > type ] . extra_dev_cap ;
2016-03-29 15:02:01 +00:00
rdev - > on_write = arg - > on_write ;
rdev - > on_read = arg - > on_read ;
2019-01-11 07:35:43 +00:00
rdev - > on_connect = arg - > on_connect ;
2016-04-25 14:07:28 +00:00
rdev - > on_disconnect = arg - > on_disconnect ;
2020-07-26 09:21:05 +00:00
rdev - > on_raw_accept = arg - > on_raw_accept ;
2016-03-30 07:06:54 +00:00
rdev - > type = arg - > type ;
2016-04-02 15:25:35 +00:00
2021-07-22 07:30:20 +00:00
if ( arg - > options & HIO_DEV_SCK_MAKE_LENIENT ) rdev - > state | = HIO_DEV_SCK_LENIENT ;
2020-07-29 10:04:14 +00:00
2016-03-29 15:02:01 +00:00
return 0 ;
oops :
2022-02-14 15:08:28 +00:00
if ( hnd ! = HIO_SYSHND_INVALID ) close ( hnd ) ;
if ( side_chan ! = HIO_SYSHND_INVALID ) close ( side_chan ) ;
2016-03-29 15:02:01 +00:00
return - 1 ;
}
2021-07-22 07:30:20 +00:00
static int dev_sck_make_client ( hio_dev_t * dev , void * ctx )
2016-03-30 07:06:54 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
hio_syshnd_t * clisckhnd = ( hio_syshnd_t * ) ctx ;
2016-03-30 07:06:54 +00:00
2019-01-11 07:35:43 +00:00
/* create a socket device that is made of a socket connection
* on a listening socket .
* nothing special is done here except setting the socket handle .
2016-04-18 14:21:23 +00:00
* most of the initialization is done by the listening socket device
* after a client socket has been created . */
2020-05-24 02:04:07 +00:00
rdev - > hnd = * clisckhnd ;
2021-07-22 07:30:20 +00:00
rdev - > tmrjob_index = HIO_TMRIDX_INVALID ;
rdev - > side_chan = HIO_SYSHND_INVALID ;
2016-04-20 15:59:11 +00:00
2021-07-22 07:30:20 +00:00
if ( hio_makesyshndasync ( hio , rdev - > hnd ) < = - 1 | |
hio_makesyshndcloexec ( hio , rdev - > hnd ) < = - 1 ) goto oops ;
2020-07-29 10:04:14 +00:00
2016-03-30 07:06:54 +00:00
return 0 ;
2020-07-29 10:04:14 +00:00
oops :
2021-07-22 07:30:20 +00:00
if ( rdev - > hnd ! = HIO_SYSHND_INVALID )
2020-07-29 10:04:14 +00:00
{
close ( rdev - > hnd ) ;
2021-07-22 07:30:20 +00:00
rdev - > hnd = HIO_SYSHND_INVALID ;
2020-07-29 10:04:14 +00:00
}
return - 1 ;
}
static void dev_sck_fail_before_make_client ( void * ctx )
{
2021-07-22 07:30:20 +00:00
hio_syshnd_t * clisckhnd = ( hio_syshnd_t * ) ctx ;
2020-07-29 10:04:14 +00:00
close ( * clisckhnd ) ;
2016-03-30 07:06:54 +00:00
}
2021-07-22 07:30:20 +00:00
static int dev_sck_kill ( hio_dev_t * dev , int force )
2016-03-29 15:02:01 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
2016-03-30 07:06:54 +00:00
2022-09-13 14:33:49 +00:00
HIO_DEBUG1 ( hio , " SCK(%p) - being killed \n " , rdev ) ;
2021-08-09 08:24:21 +00:00
#if 0
2021-08-08 07:03:52 +00:00
if ( IS_STREAM ( rdev ) )
2016-03-30 07:06:54 +00:00
{
2021-07-22 07:30:20 +00:00
/*if (HIO_DEV_SCK_GET_PROGRESS(rdev))
2016-04-25 14:07:28 +00:00
{ */
2021-07-22 07:30:20 +00:00
/* for HIO_DEV_SCK_CONNECTING, HIO_DEV_SCK_CONNECTING_SSL, and HIO_DEV_SCK_ACCEPTING_SSL
2020-05-12 17:53:19 +00:00
* on_disconnect ( ) is called without corresponding on_connect ( ) .
* it is the same if connect or accept has not been called . */
2016-03-30 07:06:54 +00:00
if ( rdev - > on_disconnect ) rdev - > on_disconnect ( rdev ) ;
2016-04-25 14:07:28 +00:00
/*}*/
2016-03-30 07:06:54 +00:00
}
else
{
2021-08-09 08:24:21 +00:00
/* non-stream, but lisenable or connectable can have the progress bits on */
/*HIO_ASSERT (hio, (rdev->state & HIO_DEV_SCK_ALL_PROGRESS_BITS) == 0);*/
2016-04-25 14:07:28 +00:00
if ( rdev - > on_disconnect ) rdev - > on_disconnect ( rdev ) ;
2016-03-30 07:06:54 +00:00
}
2021-08-09 08:24:21 +00:00
# else
if ( rdev - > on_disconnect ) rdev - > on_disconnect ( rdev ) ;
# endif
if ( rdev - > tmrjob_index ! = HIO_TMRIDX_INVALID )
{
hio_deltmrjob ( hio , rdev - > tmrjob_index ) ;
HIO_ASSERT ( hio , rdev - > tmrjob_index = = HIO_TMRIDX_INVALID ) ;
}
2016-03-30 07:06:54 +00:00
2016-04-18 14:21:23 +00:00
# if defined(USE_SSL)
if ( rdev - > ssl )
2016-03-29 15:02:01 +00:00
{
2016-04-18 14:21:23 +00:00
SSL_shutdown ( ( SSL * ) rdev - > ssl ) ; /* is this needed? */
SSL_free ( ( SSL * ) rdev - > ssl ) ;
2021-07-22 07:30:20 +00:00
rdev - > ssl = HIO_NULL ;
2016-03-29 15:02:01 +00:00
}
2021-07-22 07:30:20 +00:00
if ( ! ( rdev - > state & ( HIO_DEV_SCK_ACCEPTED | HIO_DEV_SCK_ACCEPTING_SSL ) ) & & rdev - > ssl_ctx )
2016-04-17 17:00:58 +00:00
{
2016-04-20 15:59:11 +00:00
SSL_CTX_free ( ( SSL_CTX * ) rdev - > ssl_ctx ) ;
2021-07-22 07:30:20 +00:00
rdev - > ssl_ctx = HIO_NULL ;
2016-04-17 17:00:58 +00:00
}
# endif
2021-07-22 07:30:20 +00:00
if ( rdev - > hnd ! = HIO_SYSHND_INVALID )
2016-04-18 14:21:23 +00:00
{
2020-07-29 17:58:15 +00:00
close ( rdev - > hnd ) ;
2021-07-22 07:30:20 +00:00
rdev - > hnd = HIO_SYSHND_INVALID ;
2016-04-18 14:21:23 +00:00
}
2021-07-22 07:30:20 +00:00
if ( rdev - > side_chan ! = HIO_SYSHND_INVALID )
2020-07-24 17:29:52 +00:00
{
2020-07-26 09:21:05 +00:00
close ( rdev - > side_chan ) ;
2021-07-22 07:30:20 +00:00
rdev - > side_chan = HIO_SYSHND_INVALID ;
2020-07-24 17:29:52 +00:00
}
2016-04-16 16:05:57 +00:00
return 0 ;
2016-03-29 15:02:01 +00:00
}
2021-07-22 07:30:20 +00:00
static hio_syshnd_t dev_sck_getsyshnd ( hio_dev_t * dev )
2016-03-29 15:02:01 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
return ( hio_syshnd_t ) rdev - > hnd ;
2016-03-29 15:02:01 +00:00
}
2020-07-19 06:23:43 +00:00
/* ------------------------------------------------------------------------------ */
2016-03-29 15:02:01 +00:00
2021-08-08 07:03:52 +00:00
static int dev_sck_read_stream ( hio_dev_t * dev , void * buf , hio_iolen_t * len , hio_devaddr_t * srcaddr )
2016-03-30 07:06:54 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
2016-03-30 07:06:54 +00:00
2016-04-18 14:21:23 +00:00
# if defined(USE_SSL)
if ( rdev - > ssl )
2016-03-30 07:06:54 +00:00
{
2016-04-18 14:21:23 +00:00
int x ;
2019-01-28 08:13:06 +00:00
x = SSL_read ( ( SSL * ) rdev - > ssl , buf , * len ) ;
2016-04-18 14:21:23 +00:00
if ( x < = - 1 )
{
2019-01-23 09:37:23 +00:00
int err = SSL_get_error ( ( SSL * ) rdev - > ssl , x ) ;
2016-04-18 14:21:23 +00:00
if ( err = = SSL_ERROR_WANT_READ | | err = = SSL_ERROR_WANT_WRITE ) return 0 ;
2021-07-22 07:30:20 +00:00
set_ssl_error ( hio , err ) ;
2016-04-18 14:21:23 +00:00
return - 1 ;
}
* len = x ;
2016-03-30 07:06:54 +00:00
}
2016-04-18 14:21:23 +00:00
else
{
# endif
ssize_t x ;
2016-03-30 07:06:54 +00:00
2020-05-12 17:53:19 +00:00
x = recv ( rdev - > hnd , buf , * len , 0 ) ;
2021-08-08 04:10:29 +00:00
if ( x < = - 1 )
2016-04-18 14:21:23 +00:00
{
if ( errno = = EINPROGRESS | | errno = = EWOULDBLOCK | | errno = = EAGAIN ) return 0 ; /* no data available */
if ( errno = = EINTR ) return 0 ;
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( hio , 0 , errno ) ;
2016-04-18 14:21:23 +00:00
return - 1 ;
}
* len = x ;
# if defined(USE_SSL)
}
# endif
2016-03-30 07:06:54 +00:00
return 1 ;
}
2021-07-22 07:30:20 +00:00
static int dev_sck_read_stateless ( hio_dev_t * dev , void * buf , hio_iolen_t * len , hio_devaddr_t * srcaddr )
2016-03-29 15:02:01 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
hio_scklen_t srcaddrlen ;
2016-03-30 07:06:54 +00:00
ssize_t x ;
2016-03-29 15:02:01 +00:00
2021-07-22 07:30:20 +00:00
srcaddrlen = HIO_SIZEOF ( rdev - > remoteaddr ) ;
2020-05-12 17:53:19 +00:00
x = recvfrom ( rdev - > hnd , buf , * len , 0 , ( struct sockaddr * ) & rdev - > remoteaddr , & srcaddrlen ) ;
2016-03-29 15:02:01 +00:00
if ( x < = - 1 )
{
2020-07-28 10:21:10 +00:00
int eno = errno ;
if ( eno = = EINPROGRESS | | eno = = EWOULDBLOCK | | eno = = EAGAIN ) return 0 ; /* no data available */
if ( eno = = EINTR ) return 0 ;
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( hio , 0 , eno ) ;
2020-07-28 10:21:10 +00:00
2021-07-22 07:30:20 +00:00
HIO_DEBUG2 ( hio , " SCK(%p) - recvfrom failure - %hs " , rdev , strerror ( eno ) ) ;
2016-03-29 15:02:01 +00:00
return - 1 ;
}
2016-04-18 14:21:23 +00:00
srcaddr - > ptr = & rdev - > remoteaddr ;
srcaddr - > len = srcaddrlen ;
2016-03-30 16:31:56 +00:00
2016-03-29 15:02:01 +00:00
* len = x ;
return 1 ;
}
2021-07-22 07:30:20 +00:00
static int dev_sck_read_bpf ( hio_dev_t * dev , void * buf , hio_iolen_t * len , hio_devaddr_t * srcaddr )
2020-11-16 15:40:20 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
2021-08-09 08:24:21 +00:00
/*hio_dev_sck_t* rdev = (hio_dev_sck_t*)dev;*/
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( hio , 0 , HIO_ENOIMPL ) ;
2020-11-16 15:40:20 +00:00
return - 1 ;
}
2021-08-08 04:10:29 +00:00
2021-08-13 15:33:53 +00:00
# if defined(ENABLE_SCTP)
2021-08-09 08:24:21 +00:00
static int recvmsg_sctp (
int s , void * ptr , hio_oow_t len , struct sockaddr * srcaddr , hio_scklen_t * srcaddrlen ,
struct sctp_sndrcvinfo * sinfo , int * msg_flags )
{
int n ;
struct iovec iov ;
struct msghdr msg ;
struct cmsghdr * cmsg ;
hio_uint8_t cmsg_buf [ CMSG_SPACE ( HIO_SIZEOF ( * sinfo ) ) ] ;
iov . iov_base = ptr ;
iov . iov_len = len ;
HIO_MEMSET ( & msg , 0 , HIO_SIZEOF ( msg ) ) ;
msg . msg_name = srcaddr ;
msg . msg_namelen = * srcaddrlen ;
msg . msg_iov = & iov ;
msg . msg_iovlen = 1 ;
msg . msg_control = cmsg_buf ;
msg . msg_controllen = HIO_SIZEOF ( cmsg_buf ) ;
n = recvmsg ( s , & msg , 0 ) ;
if ( n < = - 1 ) return n ;
* srcaddrlen = msg . msg_namelen ;
if ( msg_flags ) * msg_flags = msg . msg_flags ;
for ( cmsg = CMSG_FIRSTHDR ( & msg ) ; cmsg ; cmsg = CMSG_NXTHDR ( & msg , cmsg ) )
{
if ( cmsg - > cmsg_level = = IPPROTO_SCTP & & cmsg - > cmsg_type = = SCTP_SNDRCV )
{
HIO_MEMCPY ( sinfo , CMSG_DATA ( cmsg ) , HIO_SIZEOF ( * sinfo ) ) ;
break ;
}
}
return n ;
}
static int sendmsg_sctp (
int s , const hio_iovec_t * iov , hio_oow_t iovcnt , struct sockaddr * dstaddr , hio_scklen_t dstaddrlen ,
hio_uint32_t ppid , hio_uint32_t flags , hio_uint16_t stream_no , hio_uint32_t ttl , hio_uint32_t context )
{
struct sctp_sndrcvinfo * sinfo ;
struct msghdr msg ;
struct cmsghdr * cmsg ;
hio_uint8_t cmsg_buf [ CMSG_SPACE ( HIO_SIZEOF ( * sinfo ) ) ] ;
msg . msg_name = dstaddr ;
msg . msg_namelen = dstaddrlen ;
msg . msg_iov = ( struct iovec * ) iov ;
msg . msg_iovlen = iovcnt ;
msg . msg_control = cmsg_buf ;
msg . msg_controllen = HIO_SIZEOF ( cmsg_buf ) ;
msg . msg_flags = 0 ;
cmsg = CMSG_FIRSTHDR ( & msg ) ;
cmsg - > cmsg_level = IPPROTO_SCTP ;
cmsg - > cmsg_type = SCTP_SNDRCV ;
cmsg - > cmsg_len = CMSG_LEN ( HIO_SIZEOF ( * sinfo ) ) ;
msg . msg_controllen = cmsg - > cmsg_len ;
sinfo = ( struct sctp_sndrcvinfo * ) CMSG_DATA ( cmsg ) ;
HIO_MEMSET ( sinfo , 0 , HIO_SIZEOF ( * sinfo ) ) ;
sinfo - > sinfo_ppid = ppid ;
sinfo - > sinfo_flags = flags ;
sinfo - > sinfo_stream = stream_no ;
sinfo - > sinfo_timetolive = ttl ;
sinfo - > sinfo_context = context ;
return sendmsg ( s , & msg , 0 ) ;
}
2021-08-08 04:10:29 +00:00
static int dev_sck_read_sctp_sp ( hio_dev_t * dev , void * buf , hio_iolen_t * len , hio_devaddr_t * srcaddr )
{
2021-08-09 08:24:21 +00:00
/* NOTE: sctp support is far away from complete */
2021-08-08 04:10:29 +00:00
hio_t * hio = dev - > hio ;
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
hio_scklen_t srcaddrlen ;
ssize_t x ;
int msg_flags ;
struct sctp_sndrcvinfo sri ;
srcaddrlen = HIO_SIZEOF ( rdev - > remoteaddr ) ;
2021-08-09 08:24:21 +00:00
2021-08-08 04:10:29 +00:00
/* msg_flags -> flags such as MSG_NOTIFICATION or MSG_EOR */
2021-08-09 08:24:21 +00:00
x = recvmsg_sctp ( rdev - > hnd , buf , * len , ( struct sockaddr * ) & rdev - > remoteaddr , & srcaddrlen , & sri , & msg_flags ) ;
2021-08-08 04:10:29 +00:00
if ( x < = - 1 )
{
int eno = errno ;
if ( eno = = EINPROGRESS | | eno = = EWOULDBLOCK | | eno = = EAGAIN ) return 0 ; /* no data available */
if ( eno = = EINTR ) return 0 ;
hio_seterrwithsyserr ( hio , 0 , eno ) ;
HIO_DEBUG2 ( hio , " SCK(%p) - recvfrom failure - %hs " , rdev , strerror ( eno ) ) ;
return - 1 ;
}
2021-08-09 08:24:21 +00:00
/*
if ( msg_flags & MSG_EOR ) end of message ? ?
else push to buffer ? ? ?
*/
hio_skad_set_chan ( & rdev - > remoteaddr , sri . sinfo_stream ) ;
/* TODO: how to store sri.sinfo_ppid or sri.sinfo_context? */
2021-08-08 04:10:29 +00:00
srcaddr - > ptr = & rdev - > remoteaddr ;
srcaddr - > len = srcaddrlen ;
* len = x ;
return 1 ;
}
# endif
2020-07-19 06:23:43 +00:00
/* ------------------------------------------------------------------------------ */
2016-03-30 07:06:54 +00:00
2021-08-08 07:03:52 +00:00
static int dev_sck_write_stream ( hio_dev_t * dev , const void * data , hio_iolen_t * len , const hio_devaddr_t * dstaddr )
2016-03-30 07:06:54 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
2016-03-30 07:06:54 +00:00
2016-04-18 14:21:23 +00:00
# if defined(USE_SSL)
if ( rdev - > ssl )
2016-03-30 07:06:54 +00:00
{
2016-04-18 14:21:23 +00:00
int x ;
if ( * len < = 0 )
2016-03-30 07:06:54 +00:00
{
2016-04-18 14:21:23 +00:00
/* it's a writing finish indicator. close the writing end of
* the socket , probably leaving it in the half - closed state */
2021-08-08 04:10:29 +00:00
if ( ( x = SSL_shutdown ( ( SSL * ) rdev - > ssl ) ) < = - 1 )
2016-04-18 14:21:23 +00:00
{
2021-07-22 07:30:20 +00:00
set_ssl_error ( hio , SSL_get_error ( ( SSL * ) rdev - > ssl , x ) ) ;
2016-04-18 14:21:23 +00:00
return - 1 ;
}
return 1 ;
}
2019-01-28 08:13:06 +00:00
x = SSL_write ( ( SSL * ) rdev - > ssl , data , * len ) ;
2016-04-18 14:21:23 +00:00
if ( x < = - 1 )
{
int err = SSL_get_error ( ( SSL * ) rdev - > ssl , x ) ;
if ( err = = SSL_ERROR_WANT_READ | | err = = SSL_ERROR_WANT_WRITE ) return 0 ;
2021-07-22 07:30:20 +00:00
set_ssl_error ( hio , err ) ;
2016-03-30 07:06:54 +00:00
return - 1 ;
}
2016-04-18 14:21:23 +00:00
* len = x ;
2016-03-30 07:06:54 +00:00
}
2016-04-18 14:21:23 +00:00
else
2016-03-30 07:06:54 +00:00
{
2016-04-18 14:21:23 +00:00
# endif
ssize_t x ;
int flags = 0 ;
2016-03-30 07:06:54 +00:00
2016-04-18 14:21:23 +00:00
if ( * len < = 0 )
{
2020-05-07 04:32:32 +00:00
/* the write handler for a stream device must handle a zero-length
* writing request specially . it ' s a writing finish indicator . close
* the writing end of the socket , probably leaving it in the half - closed state */
2021-08-08 04:10:29 +00:00
if ( shutdown ( rdev - > hnd , SHUT_WR ) < = - 1 )
2016-04-18 14:21:23 +00:00
{
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( hio , 0 , errno ) ;
2016-04-18 14:21:23 +00:00
return - 1 ;
}
2020-05-07 04:32:32 +00:00
/* it must return a non-zero positive value. if it returns 0, this request
* gets enqueued by the core . we must aovid it */
2016-04-18 14:21:23 +00:00
return 1 ;
}
/* TODO: flags MSG_DONTROUTE, MSG_DONTWAIT, MSG_MORE, MSG_OOB, MSG_NOSIGNAL */
# if defined(MSG_NOSIGNAL)
flags | = MSG_NOSIGNAL ;
# endif
2020-05-12 17:53:19 +00:00
x = send ( rdev - > hnd , data , * len , flags ) ;
2021-08-08 04:10:29 +00:00
if ( x < = - 1 )
2016-04-18 14:21:23 +00:00
{
if ( errno = = EINPROGRESS | | errno = = EWOULDBLOCK | | errno = = EAGAIN ) return 0 ; /* no data can be written */
if ( errno = = EINTR ) return 0 ;
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( hio , 0 , errno ) ;
2016-04-18 14:21:23 +00:00
return - 1 ;
}
* len = x ;
# if defined(USE_SSL)
}
# endif
2016-03-30 07:06:54 +00:00
return 1 ;
}
2020-02-22 18:24:49 +00:00
2021-08-08 07:03:52 +00:00
static int dev_sck_writev_stream ( hio_dev_t * dev , const hio_iovec_t * iov , hio_iolen_t * iovcnt , const hio_devaddr_t * dstaddr )
2020-02-22 18:24:49 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
2020-02-22 18:24:49 +00:00
2020-02-23 16:11:32 +00:00
# if defined(USE_SSL)
2020-02-22 18:24:49 +00:00
if ( rdev - > ssl )
{
int x ;
2021-07-22 07:30:20 +00:00
hio_iolen_t i , nwritten ;
2020-02-22 18:24:49 +00:00
if ( * iovcnt < = 0 )
{
/* it's a writing finish indicator. close the writing end of
* the socket , probably leaving it in the half - closed state */
2021-08-08 04:10:29 +00:00
if ( ( x = SSL_shutdown ( ( SSL * ) rdev - > ssl ) ) < = - 1 )
2020-02-22 18:24:49 +00:00
{
2021-07-22 07:30:20 +00:00
set_ssl_error ( hio , SSL_get_error ( ( SSL * ) rdev - > ssl , x ) ) ;
2020-02-22 18:24:49 +00:00
return - 1 ;
}
return 1 ;
}
2020-02-23 16:11:32 +00:00
nwritten = 0 ;
for ( i = 0 ; i < * iovcnt ; i + + )
2020-02-22 18:24:49 +00:00
{
2020-02-23 16:11:32 +00:00
/* no SSL_writev. invoke multiple calls to SSL_write().
2021-08-08 07:03:52 +00:00
* since the write function is for the stream connection ,
2020-02-23 16:11:32 +00:00
* mutiple calls shouldn ' t really matter */
x = SSL_write ( ( SSL * ) rdev - > ssl , iov [ i ] . iov_ptr , iov [ i ] . iov_len ) ;
if ( x < = - 1 )
{
int err = SSL_get_error ( ( SSL * ) rdev - > ssl , x ) ;
if ( err = = SSL_ERROR_WANT_READ | | err = = SSL_ERROR_WANT_WRITE ) return 0 ;
2021-07-22 07:30:20 +00:00
set_ssl_error ( hio , err ) ;
2020-02-23 16:11:32 +00:00
return - 1 ;
}
nwritten + = x ;
2020-02-22 18:24:49 +00:00
}
2020-02-23 16:11:32 +00:00
* iovcnt = nwritten ;
2020-02-22 18:24:49 +00:00
}
else
{
# endif
ssize_t x ;
int flags = 0 ;
struct msghdr msg ;
if ( * iovcnt < = 0 )
{
/* it's a writing finish indicator. close the writing end of
* the socket , probably leaving it in the half - closed state */
2021-08-08 04:10:29 +00:00
if ( shutdown ( rdev - > hnd , SHUT_WR ) < = - 1 )
2020-02-22 18:24:49 +00:00
{
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( hio , 0 , errno ) ;
2020-02-22 18:24:49 +00:00
return - 1 ;
}
return 1 ;
}
/* TODO: flags MSG_DONTROUTE, MSG_DONTWAIT, MSG_MORE, MSG_OOB, MSG_NOSIGNAL */
# if defined(MSG_NOSIGNAL)
flags | = MSG_NOSIGNAL ;
# endif
2020-07-20 14:08:25 +00:00
# if defined(MSG_DONTWAIT)
flags | = MSG_DONTWAIT ;
# endif
2020-02-22 18:24:49 +00:00
# if defined(HAVE_SENDMSG)
2021-07-22 07:30:20 +00:00
HIO_MEMSET ( & msg , 0 , HIO_SIZEOF ( msg ) ) ;
2020-02-22 18:24:49 +00:00
msg . msg_iov = ( struct iovec * ) iov ;
msg . msg_iovlen = * iovcnt ;
2020-05-12 17:53:19 +00:00
x = sendmsg ( rdev - > hnd , & msg , flags ) ;
2020-02-22 18:24:49 +00:00
# else
2020-05-12 17:53:19 +00:00
x = writev ( rdev - > hnd , ( const struct iovec * ) iov , * iovcnt ) ;
2020-02-22 18:24:49 +00:00
# endif
2021-08-08 04:10:29 +00:00
if ( x < = - 1 )
2020-02-22 18:24:49 +00:00
{
if ( errno = = EINPROGRESS | | errno = = EWOULDBLOCK | | errno = = EAGAIN ) return 0 ; /* no data can be written */
if ( errno = = EINTR ) return 0 ;
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( hio , 0 , errno ) ;
2020-02-22 18:24:49 +00:00
return - 1 ;
}
* iovcnt = x ;
2020-02-23 16:11:32 +00:00
# if defined(USE_SSL)
2020-02-22 18:24:49 +00:00
}
# endif
return 1 ;
}
2020-07-19 06:23:43 +00:00
/* ------------------------------------------------------------------------------ */
2021-07-22 07:30:20 +00:00
static int dev_sck_write_stateless ( hio_dev_t * dev , const void * data , hio_iolen_t * len , const hio_devaddr_t * dstaddr )
2016-03-29 15:02:01 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
2016-03-29 15:02:01 +00:00
ssize_t x ;
2020-05-12 17:53:19 +00:00
x = sendto ( rdev - > hnd , data , * len , 0 , dstaddr - > ptr , dstaddr - > len ) ;
2016-03-29 15:02:01 +00:00
if ( x < = - 1 )
{
2016-04-18 14:21:23 +00:00
if ( errno = = EINPROGRESS | | errno = = EWOULDBLOCK | | errno = = EAGAIN ) return 0 ; /* no data can be written */
2016-03-29 15:02:01 +00:00
if ( errno = = EINTR ) return 0 ;
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( hio , 0 , errno ) ;
2016-03-29 15:02:01 +00:00
return - 1 ;
}
* len = x ;
return 1 ;
}
2021-07-22 07:30:20 +00:00
static int dev_sck_writev_stateless ( hio_dev_t * dev , const hio_iovec_t * iov , hio_iolen_t * iovcnt , const hio_devaddr_t * dstaddr )
2020-02-22 18:24:49 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
2020-02-22 18:24:49 +00:00
struct msghdr msg ;
ssize_t x ;
2020-07-20 14:08:25 +00:00
int flags = 0 ;
2020-05-07 04:32:32 +00:00
2021-07-22 07:30:20 +00:00
HIO_MEMSET ( & msg , 0 , HIO_SIZEOF ( msg ) ) ;
if ( HIO_LIKELY ( dstaddr ) )
2020-02-22 18:24:49 +00:00
{
msg . msg_name = dstaddr - > ptr ;
msg . msg_namelen = dstaddr - > len ;
}
msg . msg_iov = ( struct iovec * ) iov ;
msg . msg_iovlen = * iovcnt ;
2020-07-20 14:08:25 +00:00
# if defined(MSG_NOSIGNAL)
flags | = MSG_NOSIGNAL ;
# endif
# if defined(MSG_DONTWAIT)
flags | = MSG_DONTWAIT ;
# endif
x = sendmsg ( rdev - > hnd , & msg , flags ) ;
2020-02-22 18:24:49 +00:00
if ( x < = - 1 )
{
if ( errno = = EINPROGRESS | | errno = = EWOULDBLOCK | | errno = = EAGAIN ) return 0 ; /* no data can be written */
if ( errno = = EINTR ) return 0 ;
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( hio , 0 , errno ) ;
2020-02-22 18:24:49 +00:00
return - 1 ;
}
* iovcnt = x ;
return 1 ;
}
2020-11-16 15:40:20 +00:00
/* ------------------------------------------------------------------------------ */
2021-07-22 07:30:20 +00:00
static int dev_sck_write_bpf ( hio_dev_t * dev , const void * data , hio_iolen_t * len , const hio_devaddr_t * dstaddr )
2020-11-16 15:40:20 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
2021-08-09 08:24:21 +00:00
/*hio_dev_sck_t* rdev = (hio_dev_sck_t*)dev;*/
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( hio , 0 , HIO_ENOIMPL ) ;
2020-11-16 15:40:20 +00:00
return - 1 ;
}
2021-07-22 07:30:20 +00:00
static int dev_sck_writev_bpf ( hio_dev_t * dev , const hio_iovec_t * iov , hio_iolen_t * iovcnt , const hio_devaddr_t * dstaddr )
2020-11-16 15:40:20 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
2021-08-09 08:24:21 +00:00
/*hio_dev_sck_t* rdev = (hio_dev_sck_t*)dev;*/
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( hio , 0 , HIO_ENOIMPL ) ;
2020-11-16 15:40:20 +00:00
return - 1 ;
}
2021-08-08 04:10:29 +00:00
/* ------------------------------------------------------------------------------ */
2021-08-13 15:33:53 +00:00
# if defined(ENABLE_SCTP)
2021-08-08 04:10:29 +00:00
static int dev_sck_write_sctp_sp ( hio_dev_t * dev , const void * data , hio_iolen_t * len , const hio_devaddr_t * dstaddr )
{
2021-08-09 08:24:21 +00:00
/* NOTE: sctp support is far away from complete */
2021-08-08 04:10:29 +00:00
hio_t * hio = dev - > hio ;
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
ssize_t x ;
2021-08-09 08:24:21 +00:00
hio_iovec_t iov ;
iov . iov_ptr = ( void * ) data ;
iov . iov_len = * len ;
x = sendmsg_sctp ( rdev - > hnd ,
& iov , 1 , dstaddr - > ptr , dstaddr - > len ,
0 , /* ppid - opaque */
0 , /* flags (e.g. SCTP_UNORDERED, SCTP_EOF, SCT_ABORT, ...) */
2021-08-17 07:00:22 +00:00
hio_skad_get_chan ( dstaddr - > ptr ) , /* stream number */
2021-08-08 04:10:29 +00:00
0 , /* ttl */
0 /* context*/ ) ;
if ( x < = - 1 )
{
if ( errno = = EINPROGRESS | | errno = = EWOULDBLOCK | | errno = = EAGAIN ) return 0 ; /* no data can be written */
if ( errno = = EINTR ) return 0 ;
hio_seterrwithsyserr ( hio , 0 , errno ) ;
return - 1 ;
}
* len = x ;
return 1 ;
}
static int dev_sck_writev_sctp_sp ( hio_dev_t * dev , const hio_iovec_t * iov , hio_iolen_t * iovcnt , const hio_devaddr_t * dstaddr )
{
hio_t * hio = dev - > hio ;
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
2021-08-09 08:24:21 +00:00
ssize_t x ;
x = sendmsg_sctp ( rdev - > hnd ,
iov , * iovcnt , dstaddr - > ptr , dstaddr - > len ,
0 , /* ppid - opaque */
0 , /* flags (e.g. SCTP_UNORDERED, SCTP_EOF, SCT_ABORT, ...) */
2021-08-17 07:00:22 +00:00
hio_skad_get_chan ( dstaddr - > ptr ) , /* stream number */
2021-08-09 08:24:21 +00:00
0 , /* ttl */
0 /* context*/ ) ;
if ( x < = - 1 )
{
if ( errno = = EINPROGRESS | | errno = = EWOULDBLOCK | | errno = = EAGAIN ) return 0 ; /* no data can be written */
if ( errno = = EINTR ) return 0 ;
hio_seterrwithsyserr ( hio , 0 , errno ) ;
return - 1 ;
}
* iovcnt = x ;
return 1 ;
2021-08-08 04:10:29 +00:00
}
# endif
2020-11-16 15:40:20 +00:00
2020-07-19 06:23:43 +00:00
/* ------------------------------------------------------------------------------ */
2021-08-08 07:03:52 +00:00
static int dev_sck_sendfile_stream ( hio_dev_t * dev , hio_syshnd_t in_fd , hio_foff_t foff , hio_iolen_t * len )
2020-07-19 06:23:43 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
2020-07-19 06:23:43 +00:00
#if 0 && defined(USE_SSL)
/* TODO: ssl needs to read from the file... and send... */
if ( rdev - > ssl )
{
int x ;
if ( * len < = 0 )
{
/* it's a writing finish indicator. close the writing end of
* the socket , probably leaving it in the half - closed state */
2021-08-08 04:10:29 +00:00
if ( ( x = SSL_shutdown ( ( SSL * ) rdev - > ssl ) ) < = - 1 )
2020-07-19 06:23:43 +00:00
{
2021-07-22 07:30:20 +00:00
set_ssl_error ( hio , SSL_get_error ( ( SSL * ) rdev - > ssl , x ) ) ;
2020-07-19 06:23:43 +00:00
return - 1 ;
}
return 1 ;
}
x = SSL_write ( ( SSL * ) rdev - > ssl , data , * len ) ;
if ( x < = - 1 )
{
int err = SSL_get_error ( ( SSL * ) rdev - > ssl , x ) ;
if ( err = = SSL_ERROR_WANT_READ | | err = = SSL_ERROR_WANT_WRITE ) return 0 ;
2021-07-22 07:30:20 +00:00
set_ssl_error ( hio , err ) ;
2020-07-19 06:23:43 +00:00
return - 1 ;
}
* len = x ;
}
else
{
# endif
ssize_t x ;
if ( * len < = 0 )
{
/* the write handler for a stream device must handle a zero-length
* writing request specially . it ' s a writing finish indicator . close
* the writing end of the socket , probably leaving it in the half - closed state */
2021-08-08 04:10:29 +00:00
if ( shutdown ( rdev - > hnd , SHUT_WR ) < = - 1 )
2020-07-19 06:23:43 +00:00
{
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( hio , 0 , errno ) ;
2020-07-19 06:23:43 +00:00
return - 1 ;
}
/* it must return a non-zero positive value. if it returns 0, this request
* gets enqueued by the core . we must aovid it */
return 1 ;
}
# if defined(HAVE_SENDFILE)
/* TODO: cater for other systems */
x = sendfile ( rdev - > hnd , in_fd , & foff , * len ) ;
2021-08-08 04:10:29 +00:00
if ( x < = - 1 )
2020-07-19 06:23:43 +00:00
{
if ( errno = = EINPROGRESS | | errno = = EWOULDBLOCK | | errno = = EAGAIN ) return 0 ; /* no data can be written */
if ( errno = = EINTR ) return 0 ;
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( hio , 0 , errno ) ;
2020-07-19 06:23:43 +00:00
return - 1 ;
}
* len = x ;
# else
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_ENOIMPL ) ;
2020-07-19 06:23:43 +00:00
return - 1 ;
# endif
#if 0 && defined(USE_SSL)
}
# endif
return 1 ;
}
/* ------------------------------------------------------------------------------ */
2016-04-21 13:26:14 +00:00
# if defined(USE_SSL)
2016-04-22 06:31:12 +00:00
2021-07-22 07:30:20 +00:00
static int do_ssl ( hio_dev_sck_t * dev , int ( * ssl_func ) ( SSL * ) )
2016-04-21 13:26:14 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
2019-01-28 08:13:06 +00:00
int ret , watcher_cmd , watcher_events ;
2016-04-21 13:26:14 +00:00
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( hio , dev - > ssl_ctx ) ;
2016-04-21 13:26:14 +00:00
if ( ! dev - > ssl )
{
SSL * ssl ;
2019-01-28 08:13:06 +00:00
ssl = SSL_new ( dev - > ssl_ctx ) ;
2016-04-21 13:26:14 +00:00
if ( ! ssl )
{
2021-07-22 07:30:20 +00:00
set_ssl_error ( hio , ERR_get_error ( ) ) ;
2016-04-21 13:26:14 +00:00
return - 1 ;
}
2020-05-12 17:53:19 +00:00
if ( SSL_set_fd ( ssl , dev - > hnd ) = = 0 )
2016-04-21 13:26:14 +00:00
{
2021-07-22 07:30:20 +00:00
set_ssl_error ( hio , ERR_get_error ( ) ) ;
2016-04-21 13:26:14 +00:00
return - 1 ;
}
SSL_set_read_ahead ( ssl , 0 ) ;
2016-04-22 06:31:12 +00:00
2016-04-21 13:26:14 +00:00
dev - > ssl = ssl ;
}
2021-07-22 07:30:20 +00:00
watcher_cmd = HIO_DEV_WATCH_RENEW ;
watcher_events = HIO_DEV_EVENT_IN ;
2016-04-22 06:31:12 +00:00
2019-01-28 08:13:06 +00:00
ret = ssl_func ( ( SSL * ) dev - > ssl ) ;
2016-04-21 13:26:14 +00:00
if ( ret < = 0 )
{
2019-01-28 08:13:06 +00:00
int err = SSL_get_error ( dev - > ssl , ret ) ;
2016-04-22 06:31:12 +00:00
if ( err = = SSL_ERROR_WANT_READ )
2016-04-21 13:26:14 +00:00
{
/* handshaking isn't complete */
2016-04-22 06:31:12 +00:00
ret = 0 ;
2016-04-21 13:26:14 +00:00
}
2016-04-22 06:31:12 +00:00
else if ( err = = SSL_ERROR_WANT_WRITE )
2016-04-21 13:26:14 +00:00
{
2016-04-22 06:31:12 +00:00
/* handshaking isn't complete */
2021-07-22 07:30:20 +00:00
watcher_cmd = HIO_DEV_WATCH_UPDATE ;
watcher_events = HIO_DEV_EVENT_IN | HIO_DEV_EVENT_OUT ;
2016-04-22 06:31:12 +00:00
ret = 0 ;
2016-04-21 13:26:14 +00:00
}
2016-04-22 06:31:12 +00:00
else
2016-04-21 13:26:14 +00:00
{
2021-07-22 07:30:20 +00:00
set_ssl_error ( hio , err ) ;
2016-04-22 06:31:12 +00:00
ret = - 1 ;
2016-04-21 13:26:14 +00:00
}
}
2016-04-22 06:31:12 +00:00
else
2016-04-21 13:26:14 +00:00
{
2016-04-22 06:31:12 +00:00
ret = 1 ; /* accepted */
}
2016-04-21 13:26:14 +00:00
2021-07-22 07:30:20 +00:00
if ( hio_dev_watch ( ( hio_dev_t * ) dev , watcher_cmd , watcher_events ) < = - 1 )
2016-04-22 06:31:12 +00:00
{
2021-07-22 07:30:20 +00:00
hio_stop ( hio , HIO_STOPREQ_WATCHER_ERROR ) ;
2016-04-22 06:31:12 +00:00
ret = - 1 ;
2016-04-21 13:26:14 +00:00
}
2016-04-24 17:30:43 +00:00
2016-04-22 06:31:12 +00:00
return ret ;
}
2021-07-22 07:30:20 +00:00
static HIO_INLINE int connect_ssl ( hio_dev_sck_t * dev )
2016-04-22 06:31:12 +00:00
{
2020-05-12 17:53:19 +00:00
return do_ssl ( dev , SSL_connect ) ;
2016-04-22 06:31:12 +00:00
}
2016-04-21 13:26:14 +00:00
2021-07-22 07:30:20 +00:00
static HIO_INLINE int accept_ssl ( hio_dev_sck_t * dev )
2016-04-22 06:31:12 +00:00
{
2020-05-12 17:53:19 +00:00
return do_ssl ( dev , SSL_accept ) ;
2016-04-21 13:26:14 +00:00
}
# endif
2021-07-22 07:30:20 +00:00
static int dev_sck_ioctl ( hio_dev_t * dev , int cmd , void * arg )
2016-03-29 15:02:01 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
2016-03-30 07:06:54 +00:00
switch ( cmd )
{
2021-07-22 07:30:20 +00:00
case HIO_DEV_SCK_BIND :
2016-03-30 07:06:54 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dev_sck_bind_t * bnd = ( hio_dev_sck_bind_t * ) arg ;
2016-03-30 07:06:54 +00:00
int x ;
2016-04-17 17:00:58 +00:00
# if defined(USE_SSL)
2021-07-22 07:30:20 +00:00
SSL_CTX * ssl_ctx = HIO_NULL ;
2016-04-17 17:00:58 +00:00
# endif
2021-07-22 07:30:20 +00:00
if ( HIO_DEV_SCK_GET_PROGRESS ( rdev ) )
2016-04-21 15:07:58 +00:00
{
/* can't bind again */
2021-07-22 07:30:20 +00:00
hio_seterrbfmt ( hio , HIO_EPERM , " operation in progress. not allowed to bind again " ) ;
2016-04-21 15:07:58 +00:00
return - 1 ;
}
2016-03-30 07:06:54 +00:00
2021-08-17 07:00:22 +00:00
if ( hio_skad_get_family ( & bnd - > localaddr ) = = HIO_AF_INET6 ) /* getsockopt(rdev->hnd, SO_DOMAIN, ...) may return the domain but it's kernel specific as well */
2020-07-26 09:21:05 +00:00
{
2022-06-17 05:35:30 +00:00
# if defined(IPV6_V6ONLY)
2021-07-22 07:30:20 +00:00
/* TODO: should i make it into bnd->options? HIO_DEV_SCK_BIND_IPV6ONLY? applicable to ipv6 though. */
2020-07-26 09:21:05 +00:00
int v = 1 ;
2021-08-08 04:10:29 +00:00
if ( setsockopt ( rdev - > hnd , IPPROTO_IPV6 , IPV6_V6ONLY , & v , HIO_SIZEOF ( v ) ) < = - 1 )
2020-07-26 09:21:05 +00:00
{
2021-08-06 04:34:13 +00:00
if ( ! ( bnd - > options & HIO_DEV_SCK_BIND_IGNERR ) )
{
hio_seterrbfmtwithsyserr ( hio , 0 , errno , " unable to set IPV6_V6ONLY " ) ;
return - 1 ;
}
2020-07-26 09:21:05 +00:00
}
2022-06-17 05:35:30 +00:00
# endif
2020-07-26 09:21:05 +00:00
}
2021-07-22 07:30:20 +00:00
if ( bnd - > options & HIO_DEV_SCK_BIND_BROADCAST )
2016-04-02 15:52:12 +00:00
{
int v = 1 ;
2021-08-08 04:10:29 +00:00
if ( setsockopt ( rdev - > hnd , SOL_SOCKET , SO_BROADCAST , & v , HIO_SIZEOF ( v ) ) < = - 1 )
2016-04-02 15:52:12 +00:00
{
2021-08-06 04:34:13 +00:00
/* not affected by HIO_DEV_SCK_BIND_IGNERR */
2021-07-22 07:30:20 +00:00
hio_seterrbfmtwithsyserr ( hio , 0 , errno , " unable to set SO_BROADCAST " ) ;
2016-04-02 15:52:12 +00:00
return - 1 ;
}
}
2021-07-22 07:30:20 +00:00
if ( bnd - > options & HIO_DEV_SCK_BIND_REUSEADDR )
2016-04-02 15:52:12 +00:00
{
2016-04-18 14:21:23 +00:00
# if defined(SO_REUSEADDR)
2016-04-02 15:52:12 +00:00
int v = 1 ;
2021-08-08 04:10:29 +00:00
if ( setsockopt ( rdev - > hnd , SOL_SOCKET , SO_REUSEADDR , & v , HIO_SIZEOF ( v ) ) < = - 1 )
2016-04-02 15:52:12 +00:00
{
2021-07-22 07:30:20 +00:00
if ( ! ( bnd - > options & HIO_DEV_SCK_BIND_IGNERR ) )
2020-05-24 01:18:32 +00:00
{
2021-07-22 07:30:20 +00:00
hio_seterrbfmtwithsyserr ( hio , 0 , errno , " unable to set SO_REUSEADDR " ) ;
2020-05-24 01:18:32 +00:00
return - 1 ;
}
2016-04-02 15:52:12 +00:00
}
2019-04-12 02:45:35 +00:00
/* ignore it if not available
2016-04-18 14:21:23 +00:00
# else
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_ENOIMPL ) ;
2016-04-18 14:21:23 +00:00
return - 1 ;
2019-04-12 02:45:35 +00:00
*/
2016-04-18 14:21:23 +00:00
# endif
2016-04-02 15:52:12 +00:00
}
2021-07-22 07:30:20 +00:00
if ( bnd - > options & HIO_DEV_SCK_BIND_REUSEPORT )
2016-04-17 17:00:58 +00:00
{
2016-04-18 14:21:23 +00:00
# if defined(SO_REUSEPORT)
int v = 1 ;
2021-08-08 04:10:29 +00:00
if ( setsockopt ( rdev - > hnd , SOL_SOCKET , SO_REUSEPORT , & v , HIO_SIZEOF ( v ) ) < = - 1 )
2016-04-18 14:21:23 +00:00
{
2021-07-22 07:30:20 +00:00
if ( ! ( bnd - > options & HIO_DEV_SCK_BIND_IGNERR ) )
2020-05-24 01:18:32 +00:00
{
2021-07-22 07:30:20 +00:00
hio_seterrbfmtwithsyserr ( hio , 0 , errno , " unable to set SO_REUSEPORT " ) ;
2020-05-24 01:18:32 +00:00
return - 1 ;
}
2016-04-18 14:21:23 +00:00
}
2019-04-12 02:45:35 +00:00
/* ignore it if not available
2016-04-18 14:21:23 +00:00
# else
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_ENOIMPL ) ;
2016-04-18 14:21:23 +00:00
return - 1 ;
2019-04-12 02:45:35 +00:00
*/
2016-04-18 14:21:23 +00:00
# endif
}
2016-04-17 17:00:58 +00:00
2021-07-22 07:30:20 +00:00
if ( bnd - > options & HIO_DEV_SCK_BIND_TRANSPARENT )
2016-04-18 14:21:23 +00:00
{
# if defined(IP_TRANSPARENT)
int v = 1 ;
2021-08-08 04:10:29 +00:00
if ( setsockopt ( rdev - > hnd , SOL_IP , IP_TRANSPARENT , & v , HIO_SIZEOF ( v ) ) < = - 1 )
2016-04-18 14:21:23 +00:00
{
2021-07-22 07:30:20 +00:00
hio_seterrbfmtwithsyserr ( hio , 0 , errno , " unable to set IP_TRANSPARENT " ) ;
2016-04-18 14:21:23 +00:00
return - 1 ;
}
2019-04-12 02:45:35 +00:00
/* ignore it if not available
2016-04-18 14:21:23 +00:00
# else
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_ENOIMPL ) ;
2016-04-18 14:21:23 +00:00
return - 1 ;
2019-04-12 02:45:35 +00:00
*/
2016-04-18 14:21:23 +00:00
# endif
}
2016-04-21 15:07:58 +00:00
if ( rdev - > ssl_ctx )
{
2019-01-27 02:09:22 +00:00
# if defined(USE_SSL)
2016-04-21 15:07:58 +00:00
SSL_CTX_free ( rdev - > ssl_ctx ) ;
2019-01-27 02:09:22 +00:00
# endif
2021-07-22 07:30:20 +00:00
rdev - > ssl_ctx = HIO_NULL ;
2016-04-21 15:07:58 +00:00
if ( rdev - > ssl )
{
2019-01-27 02:09:22 +00:00
# if defined(USE_SSL)
2016-04-21 15:07:58 +00:00
SSL_free ( rdev - > ssl ) ;
2019-01-27 02:09:22 +00:00
# endif
2021-07-22 07:30:20 +00:00
rdev - > ssl = HIO_NULL ;
2016-04-21 15:07:58 +00:00
}
}
2021-07-22 07:30:20 +00:00
if ( bnd - > options & HIO_DEV_SCK_BIND_SSL )
2016-04-18 14:21:23 +00:00
{
# if defined(USE_SSL)
2016-04-20 15:59:11 +00:00
if ( ! bnd - > ssl_certfile | | ! bnd - > ssl_keyfile )
2016-04-18 14:21:23 +00:00
{
2021-07-22 07:30:20 +00:00
hio_seterrbfmt ( hio , HIO_EINVAL , " SSL certficate/key file not set " ) ;
2016-04-18 14:21:23 +00:00
return - 1 ;
}
2019-01-23 09:37:23 +00:00
ssl_ctx = SSL_CTX_new ( SSLv23_server_method ( ) ) ;
2016-04-18 14:21:23 +00:00
if ( ! ssl_ctx )
2016-04-17 17:00:58 +00:00
{
2021-07-22 07:30:20 +00:00
set_ssl_error ( hio , ERR_get_error ( ) ) ;
2016-04-17 17:00:58 +00:00
return - 1 ;
}
2019-01-23 09:37:23 +00:00
if ( SSL_CTX_use_certificate_file ( ssl_ctx , bnd - > ssl_certfile , SSL_FILETYPE_PEM ) = = 0 | |
SSL_CTX_use_PrivateKey_file ( ssl_ctx , bnd - > ssl_keyfile , SSL_FILETYPE_PEM ) = = 0 | |
SSL_CTX_check_private_key ( ssl_ctx ) = = 0 /*||
2020-05-12 17:53:19 +00:00
SSL_CTX_use_certificate_chain_file ( ssl_ctx , bnd - > chainfile ) = = 0 */ )
2016-04-17 17:00:58 +00:00
{
2021-07-22 07:30:20 +00:00
set_ssl_error ( hio , ERR_get_error ( ) ) ;
2016-04-18 14:21:23 +00:00
SSL_CTX_free ( ssl_ctx ) ;
2016-04-17 17:00:58 +00:00
return - 1 ;
}
2016-04-18 14:21:23 +00:00
SSL_CTX_set_read_ahead ( ssl_ctx , 0 ) ;
2016-04-24 17:30:43 +00:00
SSL_CTX_set_mode ( ssl_ctx , SSL_CTX_get_mode ( ssl_ctx ) |
/*SSL_MODE_ENABLE_PARTIAL_WRITE |*/
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER ) ;
2016-04-22 06:31:12 +00:00
SSL_CTX_set_options ( ssl_ctx , SSL_OP_NO_SSLv2 ) ; /* no outdated SSLv2 by default */
2016-04-18 14:21:23 +00:00
# else
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_ENOIMPL ) ;
2016-04-17 17:00:58 +00:00
return - 1 ;
2016-04-18 14:21:23 +00:00
# endif
2016-04-17 17:00:58 +00:00
}
2021-08-17 07:00:22 +00:00
x = bind ( rdev - > hnd , ( struct sockaddr * ) & bnd - > localaddr , hio_skad_get_size ( & bnd - > localaddr ) ) ;
2021-08-08 04:10:29 +00:00
if ( x < = - 1 )
2016-03-30 07:06:54 +00:00
{
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( hio , 0 , errno ) ;
2016-04-18 14:21:23 +00:00
# if defined(USE_SSL)
if ( ssl_ctx ) SSL_CTX_free ( ssl_ctx ) ;
# endif
2016-03-30 07:06:54 +00:00
return - 1 ;
}
2016-04-18 14:21:23 +00:00
rdev - > localaddr = bnd - > localaddr ;
2016-04-17 17:00:58 +00:00
# if defined(USE_SSL)
2016-04-20 15:59:11 +00:00
rdev - > ssl_ctx = ssl_ctx ;
2016-04-17 17:00:58 +00:00
# endif
2016-04-18 14:21:23 +00:00
2016-03-30 07:06:54 +00:00
return 0 ;
}
2021-07-22 07:30:20 +00:00
case HIO_DEV_SCK_CONNECT :
2016-03-30 07:06:54 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dev_sck_connect_t * conn = ( hio_dev_sck_connect_t * ) arg ;
2016-04-18 14:21:23 +00:00
struct sockaddr * sa = ( struct sockaddr * ) & conn - > remoteaddr ;
2021-07-22 07:30:20 +00:00
hio_scklen_t sl ;
2016-03-30 07:06:54 +00:00
int x ;
2016-04-20 15:59:11 +00:00
# if defined(USE_SSL)
2021-07-22 07:30:20 +00:00
SSL_CTX * ssl_ctx = HIO_NULL ;
2016-04-20 15:59:11 +00:00
# endif
2016-04-21 15:07:58 +00:00
2021-07-22 07:30:20 +00:00
if ( HIO_DEV_SCK_GET_PROGRESS ( rdev ) )
2016-04-21 15:07:58 +00:00
{
/* can't connect again */
2021-07-22 07:30:20 +00:00
hio_seterrbfmt ( hio , HIO_EPERM , " operation in progress. disallowed to connect again " ) ;
2016-04-21 15:07:58 +00:00
return - 1 ;
}
2021-08-08 04:10:29 +00:00
if ( ! sck_type_map [ rdev - > type ] . connectable )
2016-03-30 07:06:54 +00:00
{
2021-08-09 08:24:21 +00:00
hio_seterrbfmt ( hio , HIO_EPERM , " unconnectable socket device " ) ;
2016-03-30 07:06:54 +00:00
return - 1 ;
}
2021-07-22 07:30:20 +00:00
if ( sa - > sa_family = = AF_INET ) sl = HIO_SIZEOF ( struct sockaddr_in ) ;
else if ( sa - > sa_family = = AF_INET6 ) sl = HIO_SIZEOF ( struct sockaddr_in6 ) ;
2016-03-30 07:06:54 +00:00
else
{
2021-07-22 07:30:20 +00:00
hio_seterrbfmt ( hio , HIO_EINVAL , " unknown address family %d " , sa - > sa_family ) ;
2016-03-30 07:06:54 +00:00
return - 1 ;
}
2016-04-21 13:26:14 +00:00
# if defined(USE_SSL)
2016-04-21 15:07:58 +00:00
if ( rdev - > ssl_ctx )
{
if ( rdev - > ssl )
{
SSL_free ( rdev - > ssl ) ;
2021-07-22 07:30:20 +00:00
rdev - > ssl = HIO_NULL ;
2016-04-21 15:07:58 +00:00
}
SSL_CTX_free ( rdev - > ssl_ctx ) ;
2021-07-22 07:30:20 +00:00
rdev - > ssl_ctx = HIO_NULL ;
2016-04-21 15:07:58 +00:00
}
2021-07-22 07:30:20 +00:00
if ( conn - > options & HIO_DEV_SCK_CONNECT_SSL )
2016-04-20 15:59:11 +00:00
{
ssl_ctx = SSL_CTX_new ( SSLv23_client_method ( ) ) ;
if ( ! ssl_ctx )
{
2021-07-22 07:30:20 +00:00
set_ssl_error ( hio , ERR_get_error ( ) ) ;
2016-04-20 15:59:11 +00:00
return - 1 ;
}
2016-04-22 06:31:12 +00:00
SSL_CTX_set_read_ahead ( ssl_ctx , 0 ) ;
2016-04-24 17:30:43 +00:00
SSL_CTX_set_mode ( ssl_ctx , SSL_CTX_get_mode ( ssl_ctx ) |
/* SSL_MODE_ENABLE_PARTIAL_WRITE | */
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER ) ;
2016-04-20 15:59:11 +00:00
}
2016-04-21 13:26:14 +00:00
# endif
2020-02-25 07:09:20 +00:00
/* the socket is already non-blocking */
2016-04-21 13:26:14 +00:00
/*{
2020-05-12 17:53:19 +00:00
int flags = fcntl ( rdev - > hnd , F_GETFL ) ;
fcntl ( rdev - > hnd , F_SETFL , flags & ~ O_NONBLOCK ) ;
2016-04-21 13:26:14 +00:00
} */
2020-05-12 17:53:19 +00:00
x = connect ( rdev - > hnd , sa , sl ) ;
2016-04-21 13:26:14 +00:00
/*{
2020-05-12 17:53:19 +00:00
int flags = fcntl ( rdev - > hnd , F_GETFL ) ;
fcntl ( rdev - > hnd , F_SETFL , flags | O_NONBLOCK ) ;
2016-04-21 13:26:14 +00:00
} */
2020-02-25 07:09:20 +00:00
if ( x < = - 1 )
2016-03-30 07:06:54 +00:00
{
2016-04-18 14:21:23 +00:00
if ( errno = = EINPROGRESS | | errno = = EWOULDBLOCK | | errno = = EAGAIN )
2016-03-30 07:06:54 +00:00
{
2021-07-22 07:30:20 +00:00
if ( hio_dev_watch ( ( hio_dev_t * ) rdev , HIO_DEV_WATCH_UPDATE , HIO_DEV_EVENT_IN | HIO_DEV_EVENT_OUT ) < = - 1 )
2016-04-21 13:26:14 +00:00
{
/* watcher update failure. it's critical */
2021-07-22 07:30:20 +00:00
hio_stop ( hio , HIO_STOPREQ_WATCHER_ERROR ) ;
2022-09-06 00:57:37 +00:00
goto oops_connect_watcher_error ;
2016-04-21 13:26:14 +00:00
}
else
2016-03-30 07:06:54 +00:00
{
2021-07-22 07:30:20 +00:00
HIO_INIT_NTIME ( & rdev - > tmout , 0 , 0 ) ; /* just in case */
2016-04-22 06:31:12 +00:00
2021-07-22 07:30:20 +00:00
if ( HIO_IS_POS_NTIME ( & conn - > connect_tmout ) )
2016-03-30 07:06:54 +00:00
{
2019-01-23 09:37:23 +00:00
if ( schedule_timer_job_after ( rdev , & conn - > connect_tmout , connect_timedout ) < = - 1 )
2016-04-22 06:31:12 +00:00
{
goto oops_connect ;
}
else
{
/* update rdev->tmout to the deadline of the connect timeout job */
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( hio , rdev - > tmrjob_index ! = HIO_TMRIDX_INVALID ) ;
hio_gettmrjobdeadline ( hio , rdev - > tmrjob_index , & rdev - > tmout ) ;
2016-04-22 06:31:12 +00:00
}
2016-03-30 07:06:54 +00:00
}
2016-04-18 14:21:23 +00:00
rdev - > remoteaddr = conn - > remoteaddr ;
2016-04-20 15:59:11 +00:00
# if defined(USE_SSL)
rdev - > ssl_ctx = ssl_ctx ;
# endif
2021-07-22 07:30:20 +00:00
HIO_DEV_SCK_SET_PROGRESS ( rdev , HIO_DEV_SCK_CONNECTING ) ;
2016-03-30 07:06:54 +00:00
return 0 ;
}
}
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( hio , 0 , errno ) ;
2016-04-21 13:26:14 +00:00
oops_connect :
2021-07-22 07:30:20 +00:00
if ( hio_dev_watch ( ( hio_dev_t * ) rdev , HIO_DEV_WATCH_UPDATE , HIO_DEV_EVENT_IN ) < = - 1 )
2016-04-21 13:26:14 +00:00
{
/* watcher update failure. it's critical */
2021-07-22 07:30:20 +00:00
hio_stop ( hio , HIO_STOPREQ_WATCHER_ERROR ) ;
2016-04-21 13:26:14 +00:00
}
2022-09-06 00:57:37 +00:00
oops_connect_watcher_error :
2016-04-20 15:59:11 +00:00
# if defined(USE_SSL)
if ( ssl_ctx ) SSL_CTX_free ( ssl_ctx ) ;
# endif
2016-03-30 07:06:54 +00:00
return - 1 ;
}
2016-04-21 13:26:14 +00:00
else
{
/* connected immediately */
2016-04-20 15:59:11 +00:00
2020-02-25 07:09:20 +00:00
/* don't call on_connect() callback even though the connection has been established.
* i don ' t want on_connect ( ) to be called within the this function . */
2021-07-22 07:30:20 +00:00
if ( hio_dev_watch ( ( hio_dev_t * ) rdev , HIO_DEV_WATCH_UPDATE , HIO_DEV_EVENT_IN | HIO_DEV_EVENT_OUT ) < = - 1 )
2016-04-21 13:26:14 +00:00
{
2020-02-25 07:09:20 +00:00
/* watcher update failure. it's critical */
2021-07-22 07:30:20 +00:00
hio_stop ( hio , HIO_STOPREQ_WATCHER_ERROR ) ;
2020-02-25 07:09:20 +00:00
goto oops_connect ;
}
2016-04-22 06:31:12 +00:00
2020-02-25 07:09:20 +00:00
/* as i know it's connected already,
* i don ' t schedule a connection timeout job */
2016-04-21 15:07:58 +00:00
2020-02-25 07:09:20 +00:00
rdev - > remoteaddr = conn - > remoteaddr ;
2016-04-21 13:26:14 +00:00
# if defined(USE_SSL)
2020-02-25 07:09:20 +00:00
rdev - > ssl_ctx = ssl_ctx ;
2016-04-21 13:26:14 +00:00
# endif
2020-06-11 17:20:09 +00:00
/* set progress CONNECTING so that the ready handler invokes on_connect() */
2021-07-22 07:30:20 +00:00
HIO_DEV_SCK_SET_PROGRESS ( rdev , HIO_DEV_SCK_CONNECTING ) ;
2016-04-21 13:26:14 +00:00
return 0 ;
}
2016-03-30 07:06:54 +00:00
}
2021-07-22 07:30:20 +00:00
case HIO_DEV_SCK_LISTEN :
2016-03-30 07:06:54 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dev_sck_listen_t * lstn = ( hio_dev_sck_listen_t * ) arg ;
2016-03-30 07:06:54 +00:00
int x ;
2021-07-22 07:30:20 +00:00
if ( HIO_DEV_SCK_GET_PROGRESS ( rdev ) )
2016-04-21 15:07:58 +00:00
{
/* can't listen again */
2021-07-22 07:30:20 +00:00
hio_seterrbfmt ( hio , HIO_EPERM , " operation in progress. disallowed to listen again " ) ;
2016-04-21 15:07:58 +00:00
return - 1 ;
}
2021-08-08 04:10:29 +00:00
if ( ! sck_type_map [ rdev - > type ] . listenable )
2016-03-30 07:06:54 +00:00
{
2021-08-09 08:24:21 +00:00
hio_seterrbfmt ( hio , HIO_EPERM , " unlistenable socket device " ) ;
2016-03-30 07:06:54 +00:00
return - 1 ;
}
2020-05-12 17:53:19 +00:00
x = listen ( rdev - > hnd , lstn - > backlogs ) ;
2021-08-08 04:10:29 +00:00
if ( x < = - 1 )
2016-03-30 07:06:54 +00:00
{
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( hio , 0 , errno ) ;
2016-03-30 07:06:54 +00:00
return - 1 ;
}
2021-07-25 17:52:05 +00:00
if ( rdev - > dev_cap & HIO_DEV_CAP_WATCH_REREG_REQUIRED )
{
/* On NetBSD, the listening socket added before listen()
* doesn ' t generate an event even if a new connection is ready
* to be accepted . */
/* TODO: need to keep the old watch flags before STOP and
* use the flags witn START */
2021-08-09 08:24:21 +00:00
if ( hio_dev_watch ( ( hio_dev_t * ) rdev , HIO_DEV_WATCH_STOP , 0 ) < = - 1 | |
hio_dev_watch ( ( hio_dev_t * ) rdev , HIO_DEV_WATCH_START , 0 ) < = - 1 )
2021-07-25 17:52:05 +00:00
{
hio_stop ( hio , HIO_STOPREQ_WATCHER_ERROR ) ;
return - 1 ;
}
}
2020-05-07 10:10:33 +00:00
rdev - > tmout = lstn - > accept_tmout ;
2021-07-22 07:30:20 +00:00
HIO_DEV_SCK_SET_PROGRESS ( rdev , HIO_DEV_SCK_LISTENING ) ;
2016-03-30 07:06:54 +00:00
return 0 ;
}
}
2016-03-29 15:02:01 +00:00
return 0 ;
}
2021-07-22 07:30:20 +00:00
static hio_dev_mth_t dev_mth_sck_stateless =
2016-03-29 15:02:01 +00:00
{
dev_sck_make ,
dev_sck_kill ,
2021-07-22 07:30:20 +00:00
HIO_NULL ,
2016-03-29 15:02:01 +00:00
dev_sck_getsyshnd ,
2021-07-26 15:19:31 +00:00
HIO_NULL ,
2021-08-08 07:37:33 +00:00
dev_sck_ioctl , /* ioctl */
2016-03-29 15:02:01 +00:00
2016-03-30 07:06:54 +00:00
dev_sck_read_stateless ,
dev_sck_write_stateless ,
2020-02-22 18:24:49 +00:00
dev_sck_writev_stateless ,
2021-07-22 07:30:20 +00:00
HIO_NULL , /* sendfile */
2016-03-29 15:02:01 +00:00
} ;
2021-08-08 07:03:52 +00:00
static hio_dev_mth_t dev_mth_sck_stream =
2016-03-30 07:06:54 +00:00
{
dev_sck_make ,
dev_sck_kill ,
2021-07-22 07:30:20 +00:00
HIO_NULL ,
2016-03-30 07:06:54 +00:00
dev_sck_getsyshnd ,
2021-07-26 15:19:31 +00:00
HIO_NULL ,
2021-08-08 07:37:33 +00:00
dev_sck_ioctl , /* ioctl */
2016-03-30 07:06:54 +00:00
2021-08-08 07:03:52 +00:00
dev_sck_read_stream ,
dev_sck_write_stream ,
dev_sck_writev_stream ,
dev_sck_sendfile_stream ,
2016-03-30 07:06:54 +00:00
} ;
2021-08-13 15:33:53 +00:00
# if defined(ENABLE_SCTP)
2021-08-09 08:24:21 +00:00
static hio_dev_mth_t dev_mth_sck_sctp_sp =
{
dev_sck_make ,
dev_sck_kill ,
HIO_NULL ,
dev_sck_getsyshnd ,
HIO_NULL ,
dev_sck_ioctl , /* ioctl */
dev_sck_read_sctp_sp ,
dev_sck_write_sctp_sp ,
dev_sck_writev_sctp_sp ,
HIO_NULL , /* sendfile */
} ;
2021-08-13 15:33:53 +00:00
# endif
2021-08-09 08:24:21 +00:00
2021-08-08 07:03:52 +00:00
static hio_dev_mth_t dev_mth_clisck_stateless =
2016-03-30 07:06:54 +00:00
{
dev_sck_make_client ,
dev_sck_kill ,
2020-07-29 10:04:14 +00:00
dev_sck_fail_before_make_client ,
2016-03-30 07:06:54 +00:00
dev_sck_getsyshnd ,
2021-07-26 15:19:31 +00:00
HIO_NULL ,
2021-08-08 07:37:33 +00:00
dev_sck_ioctl ,
2016-03-30 07:06:54 +00:00
2021-08-08 07:03:52 +00:00
dev_sck_read_stateless ,
dev_sck_write_stateless ,
dev_sck_writev_stateless ,
HIO_NULL ,
} ;
static hio_dev_mth_t dev_mth_clisck_stream =
{
dev_sck_make_client ,
dev_sck_kill ,
dev_sck_fail_before_make_client ,
dev_sck_getsyshnd ,
HIO_NULL ,
2021-08-08 07:37:33 +00:00
dev_sck_ioctl ,
2021-08-08 07:03:52 +00:00
dev_sck_read_stream ,
dev_sck_write_stream ,
dev_sck_writev_stream ,
2021-08-08 07:37:33 +00:00
dev_sck_sendfile_stream
2016-03-30 07:06:54 +00:00
} ;
2020-07-24 17:29:52 +00:00
2021-08-13 15:33:53 +00:00
# if defined(ENABLE_SCTP)
2021-08-09 08:24:21 +00:00
static hio_dev_mth_t dev_mth_clisck_sctp_sp =
{
dev_sck_make_client ,
dev_sck_kill ,
dev_sck_fail_before_make_client ,
dev_sck_getsyshnd ,
HIO_NULL ,
dev_sck_ioctl ,
dev_sck_read_sctp_sp ,
dev_sck_write_sctp_sp ,
dev_sck_writev_sctp_sp ,
HIO_NULL ,
} ;
2021-08-13 15:33:53 +00:00
# endif
2021-08-09 08:24:21 +00:00
2021-07-22 07:30:20 +00:00
static hio_dev_mth_t dev_mth_sck_bpf =
2020-11-16 15:40:20 +00:00
{
dev_sck_make ,
dev_sck_kill ,
2021-07-22 07:30:20 +00:00
HIO_NULL ,
2020-11-16 15:40:20 +00:00
dev_sck_getsyshnd ,
2021-07-26 15:19:31 +00:00
HIO_NULL ,
2021-08-08 07:37:33 +00:00
dev_sck_ioctl , /* ioctl */
2020-11-16 15:40:20 +00:00
dev_sck_read_bpf ,
dev_sck_write_bpf ,
dev_sck_writev_bpf ,
2021-07-22 07:30:20 +00:00
HIO_NULL , /* sendfile */
2020-11-16 15:40:20 +00:00
} ;
2016-03-29 15:02:01 +00:00
/* ========================================================================= */
2021-07-22 07:30:20 +00:00
static int harvest_outgoing_connection ( hio_dev_sck_t * rdev )
2016-04-21 13:26:14 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = rdev - > hio ;
2016-04-21 13:26:14 +00:00
int errcode ;
2021-07-22 07:30:20 +00:00
hio_scklen_t len ;
2016-04-21 13:26:14 +00:00
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( hio , ! ( rdev - > state & HIO_DEV_SCK_CONNECTED ) ) ;
2016-04-21 13:26:14 +00:00
2021-07-22 07:30:20 +00:00
len = HIO_SIZEOF ( errcode ) ;
2021-08-08 04:10:29 +00:00
if ( getsockopt ( rdev - > hnd , SOL_SOCKET , SO_ERROR , ( char * ) & errcode , & len ) < = - 1 )
2016-04-21 13:26:14 +00:00
{
2021-07-22 07:30:20 +00:00
hio_seterrbfmtwithsyserr ( hio , 0 , errno , " unable to get SO_ERROR " ) ;
2016-04-21 13:26:14 +00:00
return - 1 ;
}
else if ( errcode = = 0 )
{
2021-07-22 07:30:20 +00:00
hio_skad_t localaddr ;
hio_scklen_t addrlen ;
2016-04-21 13:26:14 +00:00
/* connected */
2021-07-22 07:30:20 +00:00
if ( rdev - > tmrjob_index ! = HIO_TMRIDX_INVALID )
2016-04-21 13:26:14 +00:00
{
2021-07-22 07:30:20 +00:00
hio_deltmrjob ( hio , rdev - > tmrjob_index ) ;
HIO_ASSERT ( hio , rdev - > tmrjob_index = = HIO_TMRIDX_INVALID ) ;
2016-04-21 13:26:14 +00:00
}
2021-07-22 07:30:20 +00:00
addrlen = HIO_SIZEOF ( localaddr ) ;
2020-05-12 17:53:19 +00:00
if ( getsockname ( rdev - > hnd , ( struct sockaddr * ) & localaddr , & addrlen ) = = 0 ) rdev - > localaddr = localaddr ;
2016-04-21 13:26:14 +00:00
2021-07-22 07:30:20 +00:00
if ( hio_dev_watch ( ( hio_dev_t * ) rdev , HIO_DEV_WATCH_RENEW , HIO_DEV_EVENT_IN ) < = - 1 )
2016-04-21 13:26:14 +00:00
{
/* watcher update failure. it's critical */
2021-07-22 07:30:20 +00:00
hio_stop ( hio , HIO_STOPREQ_WATCHER_ERROR ) ;
2016-04-21 13:26:14 +00:00
return - 1 ;
}
# if defined(USE_SSL)
if ( rdev - > ssl_ctx )
{
int x ;
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( hio , ! rdev - > ssl ) ; /* must not be SSL-connected yet */
2016-04-21 13:26:14 +00:00
2020-06-24 03:00:46 +00:00
x = connect_ssl ( rdev ) ;
2016-04-21 13:26:14 +00:00
if ( x < = - 1 ) return - 1 ;
if ( x = = 0 )
{
2016-04-21 15:07:58 +00:00
/* underlying socket connected but not SSL-connected */
2021-07-22 07:30:20 +00:00
HIO_DEV_SCK_SET_PROGRESS ( rdev , HIO_DEV_SCK_CONNECTING_SSL ) ;
2016-04-21 15:07:58 +00:00
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( hio , rdev - > tmrjob_index = = HIO_TMRIDX_INVALID ) ;
2016-04-21 15:07:58 +00:00
2016-04-22 06:31:12 +00:00
/* rdev->tmout has been set to the deadline of the connect task
* when the CONNECT IOCTL command has been executed . use the
2016-04-24 17:30:43 +00:00
* same deadline here */
2021-07-22 07:30:20 +00:00
if ( HIO_IS_POS_NTIME ( & rdev - > tmout ) & &
2019-01-16 10:42:20 +00:00
schedule_timer_job_at ( rdev , & rdev - > tmout , ssl_connect_timedout ) < = - 1 )
2016-04-21 15:07:58 +00:00
{
2021-07-22 07:30:20 +00:00
HIO_DEBUG1 ( hio , " SCK(%p) - ssl-connect timeout scheduling failed. halting \n " , rdev ) ;
hio_dev_sck_halt ( rdev ) ;
2016-04-21 15:07:58 +00:00
}
2016-04-21 13:26:14 +00:00
return 0 ;
}
else
{
goto ssl_connected ;
}
}
else
{
ssl_connected :
# endif
2021-07-22 07:30:20 +00:00
HIO_DEV_SCK_SET_PROGRESS ( rdev , HIO_DEV_SCK_CONNECTED ) ;
2019-01-16 10:42:20 +00:00
if ( rdev - > on_connect ) rdev - > on_connect ( rdev ) ;
2016-04-21 13:26:14 +00:00
# if defined(USE_SSL)
}
# endif
return 0 ;
}
else if ( errcode = = EINPROGRESS | | errcode = = EWOULDBLOCK )
{
/* still in progress */
return 0 ;
}
else
{
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( hio , 0 , errcode ) ;
2016-04-21 13:26:14 +00:00
return - 1 ;
}
}
2021-07-22 07:30:20 +00:00
static int make_accepted_client_connection ( hio_dev_sck_t * rdev , hio_syshnd_t clisck , hio_skad_t * remoteaddr , hio_dev_sck_type_t clisck_type )
2016-04-21 13:26:14 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = rdev - > hio ;
hio_dev_sck_t * clidev ;
hio_scklen_t addrlen ;
2021-08-08 07:03:52 +00:00
hio_dev_mth_t * dev_mth ;
2019-01-11 07:35:43 +00:00
2020-07-24 17:29:52 +00:00
if ( rdev - > on_raw_accept )
2016-04-21 13:26:14 +00:00
{
2020-07-24 17:29:52 +00:00
/* this is a special optional callback. If you don't want a client socket device
* to be created upon accept , you may implement the on_raw_accept ( ) handler .
2021-07-16 02:30:25 +00:00
* the socket handle is delegated to the callback . */
2020-07-26 09:21:05 +00:00
rdev - > on_raw_accept ( rdev , clisck , remoteaddr ) ;
2020-07-24 17:29:52 +00:00
return 0 ;
2016-04-21 13:26:14 +00:00
}
2021-08-08 07:22:50 +00:00
/* rdev->dev_size:
* use rdev - > dev_size when instantiating a client sck device
* instead of HIO_SIZEOF ( hio_dev_sck_t ) . therefore , the
* extension area as big as that of the master socket device
* is created in the client sck device
* dev_mth :
* choose the client socket method base on the master socket
* device capability . currently , stream or non - stream is supported .
*/
2021-08-13 15:33:53 +00:00
# if defined(ENABLE_SCTP)
2021-08-09 08:24:21 +00:00
dev_mth = ( sck_type_map [ clisck_type ] . extra_dev_cap & HIO_DEV_CAP_STREAM ) ? & dev_mth_clisck_stream :
( sck_type_map [ clisck_type ] . proto = = IPPROTO_SCTP ) ? & dev_mth_clisck_sctp_sp : & dev_mth_clisck_stateless ;
2021-08-13 15:33:53 +00:00
# else
dev_mth = ( sck_type_map [ clisck_type ] . extra_dev_cap & HIO_DEV_CAP_STREAM ) ? & dev_mth_clisck_stream : & dev_mth_clisck_stateless ;
# endif
2021-08-08 07:03:52 +00:00
clidev = ( hio_dev_sck_t * ) hio_dev_make ( hio , rdev - > dev_size , dev_mth , rdev - > dev_evcb , & clisck ) ;
2021-07-22 07:30:20 +00:00
if ( HIO_UNLIKELY ( ! clidev ) )
2016-04-21 13:26:14 +00:00
{
2021-07-22 07:30:20 +00:00
/* [NOTE] 'clisck' is closed by callback methods called by hio_dev_make() upon failure */
HIO_DEBUG3 ( hio , " SCK(%p) - unable to make a new accepted device for %d - %js \n " , rdev , ( int ) clisck , hio_geterrmsg ( hio ) ) ;
2016-04-21 13:26:14 +00:00
return - 1 ;
}
2020-07-26 09:21:05 +00:00
clidev - > type = clisck_type ;
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( hio , clidev - > hnd = = clisck ) ;
2016-04-21 13:26:14 +00:00
2021-08-08 04:10:29 +00:00
clidev - > dev_cap | = HIO_DEV_CAP_IN | HIO_DEV_CAP_OUT | sck_type_map [ clisck_type ] . extra_dev_cap ;
2020-07-24 17:29:52 +00:00
clidev - > remoteaddr = * remoteaddr ;
2016-04-21 13:26:14 +00:00
2021-07-22 07:30:20 +00:00
addrlen = HIO_SIZEOF ( clidev - > localaddr ) ;
2021-08-08 04:10:29 +00:00
if ( getsockname ( clisck , ( struct sockaddr * ) & clidev - > localaddr , & addrlen ) < = - 1 ) clidev - > localaddr = rdev - > localaddr ;
2016-04-21 13:26:14 +00:00
# if defined(SO_ORIGINAL_DST)
/* if REDIRECT is used, SO_ORIGINAL_DST returns the original
* destination address . When REDIRECT is not used , it returnes
* the address of the local socket . In this case , it should
* be same as the result of getsockname ( ) . */
2021-07-22 07:30:20 +00:00
addrlen = HIO_SIZEOF ( clidev - > orgdstaddr ) ;
2021-08-08 04:10:29 +00:00
if ( getsockopt ( clisck , SOL_IP , SO_ORIGINAL_DST , & clidev - > orgdstaddr , & addrlen ) < = - 1 ) clidev - > orgdstaddr = rdev - > localaddr ;
2016-04-21 13:26:14 +00:00
# else
clidev - > orgdstaddr = rdev - > localaddr ;
# endif
2021-07-22 07:30:20 +00:00
if ( ! hio_equal_skads ( & clidev - > orgdstaddr , & clidev - > localaddr , 0 ) )
2016-04-21 13:26:14 +00:00
{
2021-07-22 07:30:20 +00:00
clidev - > state | = HIO_DEV_SCK_INTERCEPTED ;
2016-04-21 13:26:14 +00:00
}
2021-08-17 07:00:22 +00:00
else if ( hio_skad_get_port ( & clidev - > localaddr ) ! = hio_skad_get_port ( & rdev - > localaddr ) )
2016-04-21 13:26:14 +00:00
{
/* When TPROXY is used, getsockname() and SO_ORIGNAL_DST return
* the same addresses . however , the port number may be different
* as a typical TPROXY rule is set to change the port number .
* However , this check is fragile if the server port number is
* set to 0.
*
* Take note that the above assumption gets wrong if the TPROXY
* rule doesn ' t change the port number . so it won ' t be able
* to handle such a TPROXYed packet without port transformation . */
2021-07-22 07:30:20 +00:00
clidev - > state | = HIO_DEV_SCK_INTERCEPTED ;
2016-04-21 13:26:14 +00:00
}
#if 0
2019-01-11 07:35:43 +00:00
else if ( ( clidev - > initial_ifindex = resolve_ifindex ( fd , clidev - > localaddr ) ) < = - 1 )
2016-04-21 13:26:14 +00:00
{
/* the local_address is not one of a local address.
* it ' s probably proxied . */
2021-07-22 07:30:20 +00:00
clidev - > state | = HIO_DEV_SCK_INTERCEPTED ;
2016-04-21 13:26:14 +00:00
}
# endif
/* inherit some event handlers from the parent.
* you can still change them inside the on_connect handler */
clidev - > on_connect = rdev - > on_connect ;
clidev - > on_disconnect = rdev - > on_disconnect ;
2021-07-22 07:30:20 +00:00
clidev - > on_raw_accept = HIO_NULL ; /* don't inherit this */
2016-04-21 13:26:14 +00:00
clidev - > on_write = rdev - > on_write ;
clidev - > on_read = rdev - > on_read ;
2020-05-05 15:12:08 +00:00
/* inherit the contents of the extension area */
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( hio , rdev - > dev_size = = clidev - > dev_size ) ;
HIO_MEMCPY ( hio_dev_sck_getxtn ( clidev ) , hio_dev_sck_getxtn ( rdev ) , rdev - > dev_size - HIO_SIZEOF ( hio_dev_sck_t ) ) ;
2020-05-05 15:12:08 +00:00
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( hio , clidev - > tmrjob_index = = HIO_TMRIDX_INVALID ) ;
2016-04-21 13:26:14 +00:00
if ( rdev - > ssl_ctx )
{
2021-07-22 07:30:20 +00:00
HIO_DEV_SCK_SET_PROGRESS ( clidev , HIO_DEV_SCK_ACCEPTING_SSL ) ;
HIO_ASSERT ( hio , clidev - > state & HIO_DEV_SCK_ACCEPTING_SSL ) ;
2016-04-21 13:26:14 +00:00
/* actual SSL acceptance must be completed in the client device */
/* let the client device know the SSL context to use */
clidev - > ssl_ctx = rdev - > ssl_ctx ;
2021-07-22 07:30:20 +00:00
if ( HIO_IS_POS_NTIME ( & rdev - > tmout ) & &
2020-05-05 15:12:08 +00:00
schedule_timer_job_after ( clidev , & rdev - > tmout , ssl_accept_timedout ) < = - 1 )
2016-04-21 13:26:14 +00:00
{
2016-04-21 15:07:58 +00:00
/* timer job scheduling failed. halt the device */
2021-07-22 07:30:20 +00:00
HIO_DEBUG1 ( hio , " SCK(%p) - ssl-accept timeout scheduling failed. halting \n " , rdev ) ;
hio_dev_sck_halt ( clidev ) ;
2016-04-21 13:26:14 +00:00
}
}
else
{
2021-07-22 07:30:20 +00:00
HIO_DEV_SCK_SET_PROGRESS ( clidev , HIO_DEV_SCK_ACCEPTED ) ;
/*if (clidev->on_connect(clidev) <= -1) hio_dev_sck_halt (clidev);*/
2019-01-16 10:42:20 +00:00
if ( clidev - > on_connect ) clidev - > on_connect ( clidev ) ;
2016-04-21 13:26:14 +00:00
}
return 0 ;
}
2021-07-22 07:30:20 +00:00
static int accept_incoming_connection ( hio_dev_sck_t * rdev )
2020-07-24 17:29:52 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = rdev - > hio ;
hio_syshnd_t clisck ;
hio_skad_t remoteaddr ;
hio_scklen_t addrlen ;
2020-07-24 17:29:52 +00:00
int flags ;
/* this is a server(lisening) socket */
2021-07-25 17:52:05 +00:00
# if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) && defined(HAVE_PACCEPT)
flags = SOCK_NONBLOCK | SOCK_CLOEXEC ;
addrlen = HIO_SIZEOF ( remoteaddr ) ;
clisck = paccept ( rdev - > hnd , ( struct sockaddr * ) & remoteaddr , & addrlen , HIO_NULL , flags ) ;
if ( clisck < = - 1 )
{
if ( errno ! = ENOSYS ) goto accept_error ;
/* go on for the normal 3-parameter accept */
}
else
{
goto accept_done ;
}
# elif defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) && defined(HAVE_ACCEPT4)
2020-07-24 17:29:52 +00:00
flags = SOCK_NONBLOCK | SOCK_CLOEXEC ;
2021-07-22 07:30:20 +00:00
addrlen = HIO_SIZEOF ( remoteaddr ) ;
2020-07-24 17:29:52 +00:00
clisck = accept4 ( rdev - > hnd , ( struct sockaddr * ) & remoteaddr , & addrlen , flags ) ;
if ( clisck < = - 1 )
{
2020-08-01 15:56:53 +00:00
if ( errno ! = ENOSYS ) goto accept_error ;
2020-07-24 17:29:52 +00:00
/* go on for the normal 3-parameter accept */
}
else
{
goto accept_done ;
}
# endif
2020-08-01 15:56:53 +00:00
2021-07-22 07:30:20 +00:00
addrlen = HIO_SIZEOF ( remoteaddr ) ;
2020-07-24 17:29:52 +00:00
clisck = accept ( rdev - > hnd , ( struct sockaddr * ) & remoteaddr , & addrlen ) ;
if ( clisck < = - 1 )
{
2020-08-01 15:56:53 +00:00
# if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) && defined(HAVE_ACCEPT4)
accept_error :
# endif
2020-07-24 17:29:52 +00:00
if ( errno = = EINPROGRESS | | errno = = EWOULDBLOCK | | errno = = EAGAIN ) return 0 ;
if ( errno = = EINTR ) return 0 ; /* if interrupted by a signal, treat it as if it's EINPROGRESS */
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( hio , 0 , errno ) ;
2020-07-24 17:29:52 +00:00
return - 1 ;
}
2020-08-01 15:56:53 +00:00
# if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) && defined(HAVE_ACCEPT4)
2020-07-24 17:29:52 +00:00
accept_done :
2020-08-01 15:56:53 +00:00
# endif
2020-07-28 10:21:10 +00:00
return make_accepted_client_connection ( rdev , clisck , & remoteaddr , rdev - > type ) ;
2020-07-24 17:29:52 +00:00
}
2021-08-08 07:03:52 +00:00
static int dev_evcb_sck_ready_stream ( hio_dev_t * dev , int events )
2016-03-29 15:02:01 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
2016-03-30 07:06:54 +00:00
2021-07-22 07:30:20 +00:00
if ( events & HIO_DEV_EVENT_ERR )
2016-03-30 07:06:54 +00:00
{
int errcode ;
2021-07-22 07:30:20 +00:00
hio_scklen_t len ;
2016-03-30 07:06:54 +00:00
2021-07-22 07:30:20 +00:00
len = HIO_SIZEOF ( errcode ) ;
2021-08-08 04:10:29 +00:00
if ( getsockopt ( rdev - > hnd , SOL_SOCKET , SO_ERROR , ( char * ) & errcode , & len ) < = - 1 )
2016-03-30 07:06:54 +00:00
{
/* the error number is set to the socket error code.
* errno resulting from getsockopt ( ) doesn ' t reflect the actual
* socket error . so errno is not used to set the error number .
2021-07-22 07:30:20 +00:00
* instead , the generic device error HIO_EDEVERRR is used */
hio_seterrbfmt ( hio , HIO_EDEVERR , " device error - unable to get SO_ERROR " ) ;
2016-03-30 07:06:54 +00:00
}
else
{
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( hio , 0 , errcode ) ;
2016-03-30 07:06:54 +00:00
}
return - 1 ;
}
2016-03-29 15:02:01 +00:00
2016-03-30 07:06:54 +00:00
/* this socket can connect */
2021-07-22 07:30:20 +00:00
switch ( HIO_DEV_SCK_GET_PROGRESS ( rdev ) )
2016-03-30 07:06:54 +00:00
{
2021-07-22 07:30:20 +00:00
case HIO_DEV_SCK_CONNECTING :
if ( events & HIO_DEV_EVENT_HUP )
2016-03-30 07:06:54 +00:00
{
2016-04-21 13:26:14 +00:00
/* device hang-up */
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_EDEVHUP ) ;
2016-03-30 07:06:54 +00:00
return - 1 ;
}
2021-07-22 07:30:20 +00:00
else if ( events & ( HIO_DEV_EVENT_PRI | HIO_DEV_EVENT_IN ) )
2016-03-30 07:06:54 +00:00
{
2016-04-21 13:26:14 +00:00
/* invalid event masks. generic device error */
2021-07-22 07:30:20 +00:00
hio_seterrbfmt ( hio , HIO_EDEVERR , " device error - invalid event mask " ) ;
2016-04-21 13:26:14 +00:00
return - 1 ;
2016-03-30 07:06:54 +00:00
}
2021-07-22 07:30:20 +00:00
else if ( events & HIO_DEV_EVENT_OUT )
2016-03-30 07:06:54 +00:00
{
2016-04-21 13:26:14 +00:00
/* when connected, the socket becomes writable */
2019-01-28 08:13:06 +00:00
return harvest_outgoing_connection ( rdev ) ;
2016-03-30 07:06:54 +00:00
}
else
{
2016-04-21 13:26:14 +00:00
return 0 ; /* success but don't invoke on_read() */
2016-03-30 07:06:54 +00:00
}
2021-07-22 07:30:20 +00:00
case HIO_DEV_SCK_CONNECTING_SSL :
2016-04-21 13:26:14 +00:00
# if defined(USE_SSL)
2021-07-22 07:30:20 +00:00
if ( events & HIO_DEV_EVENT_HUP )
2016-03-30 07:06:54 +00:00
{
2016-04-21 13:26:14 +00:00
/* device hang-up */
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_EDEVHUP ) ;
2016-03-30 07:06:54 +00:00
return - 1 ;
}
2021-07-22 07:30:20 +00:00
else if ( events & HIO_DEV_EVENT_PRI )
2016-03-30 07:06:54 +00:00
{
2016-04-21 13:26:14 +00:00
/* invalid event masks. generic device error */
2021-07-22 07:30:20 +00:00
hio_seterrbfmt ( hio , HIO_EDEVERR , " device error - invalid event mask " ) ;
2016-03-30 07:06:54 +00:00
return - 1 ;
}
2021-07-22 07:30:20 +00:00
else if ( events & ( HIO_DEV_EVENT_IN | HIO_DEV_EVENT_OUT ) )
2016-04-21 13:26:14 +00:00
{
int x ;
2016-03-30 07:06:54 +00:00
2019-01-28 08:13:06 +00:00
x = connect_ssl ( rdev ) ;
2016-04-21 13:26:14 +00:00
if ( x < = - 1 ) return - 1 ;
if ( x = = 0 ) return 0 ; /* not SSL-Connected */
2016-04-18 14:21:23 +00:00
2021-07-22 07:30:20 +00:00
if ( rdev - > tmrjob_index ! = HIO_TMRIDX_INVALID )
2016-04-21 13:26:14 +00:00
{
2021-07-22 07:30:20 +00:00
hio_deltmrjob ( rdev - > hio , rdev - > tmrjob_index ) ;
rdev - > tmrjob_index = HIO_TMRIDX_INVALID ;
2016-04-21 13:26:14 +00:00
}
2021-07-22 07:30:20 +00:00
HIO_DEV_SCK_SET_PROGRESS ( rdev , HIO_DEV_SCK_CONNECTED ) ;
2019-01-16 10:42:20 +00:00
if ( rdev - > on_connect ) rdev - > on_connect ( rdev ) ;
2016-04-21 13:26:14 +00:00
return 0 ;
}
2016-04-18 14:21:23 +00:00
else
2016-04-21 13:26:14 +00:00
{
return 0 ; /* success. no actual I/O yet */
}
2016-04-18 14:21:23 +00:00
# else
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_EINTERN ) ;
2016-04-21 13:26:14 +00:00
return - 1 ;
2016-04-18 14:21:23 +00:00
# endif
2021-07-22 07:30:20 +00:00
case HIO_DEV_SCK_LISTENING :
2016-04-21 13:26:14 +00:00
2021-07-22 07:30:20 +00:00
if ( events & HIO_DEV_EVENT_HUP )
2016-04-18 14:21:23 +00:00
{
2016-04-21 13:26:14 +00:00
/* device hang-up */
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_EDEVHUP ) ;
2016-04-21 13:26:14 +00:00
return - 1 ;
2016-04-18 14:21:23 +00:00
}
2021-07-22 07:30:20 +00:00
else if ( events & ( HIO_DEV_EVENT_PRI | HIO_DEV_EVENT_OUT ) )
2016-04-18 14:21:23 +00:00
{
2021-07-22 07:30:20 +00:00
hio_seterrbfmt ( hio , HIO_EDEVERR , " device error - invalid event mask " ) ;
2016-04-21 13:26:14 +00:00
return - 1 ;
2016-04-18 14:21:23 +00:00
}
2021-07-22 07:30:20 +00:00
else if ( events & HIO_DEV_EVENT_IN )
2016-04-18 14:21:23 +00:00
{
2021-07-22 07:30:20 +00:00
if ( rdev - > state & HIO_DEV_SCK_LENIENT )
2020-05-07 04:32:32 +00:00
{
accept_incoming_connection ( rdev ) ;
return 0 ; /* return ok to the core regardless of accept()'s result */
}
else
{
/* [NOTE] if the accept operation fails, the core also kills this listening device. */
return accept_incoming_connection ( rdev ) ;
}
2016-04-18 14:21:23 +00:00
}
else
{
2016-04-21 13:26:14 +00:00
return 0 ; /* success but don't invoke on_read() */
2016-04-18 14:21:23 +00:00
}
2016-03-30 07:06:54 +00:00
2021-07-22 07:30:20 +00:00
case HIO_DEV_SCK_ACCEPTING_SSL :
2016-04-21 13:26:14 +00:00
# if defined(USE_SSL)
2021-07-22 07:30:20 +00:00
if ( events & HIO_DEV_EVENT_HUP )
2016-04-18 14:21:23 +00:00
{
2016-04-21 13:26:14 +00:00
/* device hang-up */
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_EDEVHUP ) ;
2016-04-18 14:21:23 +00:00
return - 1 ;
}
2021-07-22 07:30:20 +00:00
else if ( events & HIO_DEV_EVENT_PRI )
2016-04-18 14:21:23 +00:00
{
2016-04-21 13:26:14 +00:00
/* invalid event masks. generic device error */
2021-07-22 07:30:20 +00:00
hio_seterrbfmt ( hio , HIO_EDEVERR , " device error - invalid event mask " ) ;
2016-04-18 14:21:23 +00:00
return - 1 ;
}
2021-07-22 07:30:20 +00:00
else if ( events & ( HIO_DEV_EVENT_IN | HIO_DEV_EVENT_OUT ) )
2016-04-21 13:26:14 +00:00
{
int x ;
2020-05-12 17:53:19 +00:00
2019-01-28 08:13:06 +00:00
x = accept_ssl ( rdev ) ;
2016-04-21 13:26:14 +00:00
if ( x < = - 1 ) return - 1 ;
2020-05-12 17:53:19 +00:00
if ( x = = 0 ) return 0 ; /* not SSL-accepted yet */
2016-04-18 14:21:23 +00:00
2021-07-22 07:30:20 +00:00
if ( rdev - > tmrjob_index ! = HIO_TMRIDX_INVALID )
2016-04-21 13:26:14 +00:00
{
2021-07-22 07:30:20 +00:00
hio_deltmrjob ( rdev - > hio , rdev - > tmrjob_index ) ;
rdev - > tmrjob_index = HIO_TMRIDX_INVALID ;
2016-04-21 13:26:14 +00:00
}
2021-07-22 07:30:20 +00:00
HIO_DEV_SCK_SET_PROGRESS ( rdev , HIO_DEV_SCK_ACCEPTED ) ;
2019-01-16 10:42:20 +00:00
if ( rdev - > on_connect ) rdev - > on_connect ( rdev ) ;
2016-04-18 14:21:23 +00:00
return 0 ;
}
2016-04-21 13:26:14 +00:00
else
{
return 0 ; /* no reading or writing yet */
}
# else
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_EINTERN ) ;
2016-04-18 14:21:23 +00:00
return - 1 ;
2016-04-21 13:26:14 +00:00
# endif
2016-04-20 15:59:11 +00:00
2016-04-18 14:21:23 +00:00
2016-04-21 13:26:14 +00:00
default :
2021-07-22 07:30:20 +00:00
if ( events & HIO_DEV_EVENT_HUP )
2016-04-21 13:26:14 +00:00
{
2021-07-22 07:30:20 +00:00
if ( events & ( HIO_DEV_EVENT_PRI | HIO_DEV_EVENT_IN | HIO_DEV_EVENT_OUT ) )
2016-04-21 13:26:14 +00:00
{
/* probably half-open? */
return 1 ;
}
2016-04-18 14:21:23 +00:00
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_EDEVHUP ) ;
2016-04-21 13:26:14 +00:00
return - 1 ;
}
2016-03-30 07:06:54 +00:00
2016-04-21 13:26:14 +00:00
return 1 ; /* the device is ok. carry on reading or writing */
2016-03-30 07:06:54 +00:00
}
2016-03-29 15:02:01 +00:00
}
2021-07-22 07:30:20 +00:00
static int dev_evcb_sck_ready_stateless ( hio_dev_t * dev , int events )
2016-03-29 15:02:01 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
2016-03-30 07:06:54 +00:00
2021-07-22 07:30:20 +00:00
if ( events & HIO_DEV_EVENT_ERR )
2016-03-30 07:06:54 +00:00
{
int errcode ;
2021-07-22 07:30:20 +00:00
hio_scklen_t len ;
2016-03-30 07:06:54 +00:00
2021-07-22 07:30:20 +00:00
len = HIO_SIZEOF ( errcode ) ;
2021-08-08 04:10:29 +00:00
if ( getsockopt ( rdev - > hnd , SOL_SOCKET , SO_ERROR , ( char * ) & errcode , & len ) < = - 1 )
2016-03-30 07:06:54 +00:00
{
/* the error number is set to the socket error code.
* errno resulting from getsockopt ( ) doesn ' t reflect the actual
* socket error . so errno is not used to set the error number .
2021-07-22 07:30:20 +00:00
* instead , the generic device error HIO_EDEVERRR is used */
hio_seterrbfmt ( hio , HIO_EDEVERR , " device error - unable to get SO_ERROR " ) ;
2016-03-30 07:06:54 +00:00
}
else
{
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( rdev - > hio , 0 , errcode ) ;
2016-03-30 07:06:54 +00:00
}
return - 1 ;
}
2021-07-22 07:30:20 +00:00
else if ( events & HIO_DEV_EVENT_HUP )
2016-03-30 07:06:54 +00:00
{
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_EDEVHUP ) ;
2016-03-30 07:06:54 +00:00
return - 1 ;
}
2016-03-29 15:02:01 +00:00
2016-03-30 07:06:54 +00:00
return 1 ; /* the device is ok. carry on reading or writing */
2016-03-29 15:02:01 +00:00
}
2021-08-08 07:03:52 +00:00
static int dev_evcb_sck_on_read_stream ( hio_dev_t * dev , const void * data , hio_iolen_t dlen , const hio_devaddr_t * srcaddr )
2016-03-30 16:31:56 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
return rdev - > on_read ( rdev , data , dlen , HIO_NULL ) ;
2016-03-30 16:31:56 +00:00
}
2021-08-08 07:03:52 +00:00
static int dev_evcb_sck_on_write_stream ( hio_dev_t * dev , hio_iolen_t wrlen , void * wrctx , const hio_devaddr_t * dstaddr )
2016-03-29 15:02:01 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
return rdev - > on_write ( rdev , wrlen , wrctx , HIO_NULL ) ;
2016-03-30 07:06:54 +00:00
}
2016-03-29 15:02:01 +00:00
2021-07-22 07:30:20 +00:00
static int dev_evcb_sck_on_read_stateless ( hio_dev_t * dev , const void * data , hio_iolen_t dlen , const hio_devaddr_t * srcaddr )
2016-03-30 07:06:54 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
2019-01-28 08:13:06 +00:00
return rdev - > on_read ( rdev , data , dlen , srcaddr - > ptr ) ;
2016-03-30 16:31:56 +00:00
}
2021-07-22 07:30:20 +00:00
static int dev_evcb_sck_on_write_stateless ( hio_dev_t * dev , hio_iolen_t wrlen , void * wrctx , const hio_devaddr_t * dstaddr )
2016-03-30 16:31:56 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
2019-01-28 08:13:06 +00:00
return rdev - > on_write ( rdev , wrlen , wrctx , dstaddr - > ptr ) ;
2016-03-29 15:02:01 +00:00
}
2020-07-24 17:29:52 +00:00
/* ========================================================================= */
2021-08-08 07:03:52 +00:00
static hio_dev_evcb_t dev_sck_event_callbacks_stream =
2016-03-29 15:02:01 +00:00
{
2021-08-08 07:03:52 +00:00
dev_evcb_sck_ready_stream ,
dev_evcb_sck_on_read_stream ,
dev_evcb_sck_on_write_stream
2016-03-29 15:02:01 +00:00
} ;
2021-07-22 07:30:20 +00:00
static hio_dev_evcb_t dev_sck_event_callbacks_stateless =
2016-03-30 07:06:54 +00:00
{
dev_evcb_sck_ready_stateless ,
2016-03-30 16:31:56 +00:00
dev_evcb_sck_on_read_stateless ,
dev_evcb_sck_on_write_stateless
2016-03-30 07:06:54 +00:00
} ;
2021-08-09 08:24:21 +00:00
static hio_dev_evcb_t dev_sck_event_callbacks_sctp_sp =
{
dev_evcb_sck_ready_stateless ,
dev_evcb_sck_on_read_stateless ,
dev_evcb_sck_on_write_stateless
} ;
2020-07-24 17:29:52 +00:00
/* ========================================================================= */
2021-07-22 07:30:20 +00:00
static int dev_evcb_sck_ready_qx ( hio_dev_t * dev , int events )
2020-07-24 17:29:52 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
2020-07-24 17:29:52 +00:00
2021-07-22 07:30:20 +00:00
if ( events & HIO_DEV_EVENT_ERR )
2020-07-24 17:29:52 +00:00
{
int errcode ;
2021-07-22 07:30:20 +00:00
hio_scklen_t len ;
2020-07-24 17:29:52 +00:00
2021-07-22 07:30:20 +00:00
len = HIO_SIZEOF ( errcode ) ;
2021-08-08 04:10:29 +00:00
if ( getsockopt ( rdev - > hnd , SOL_SOCKET , SO_ERROR , ( char * ) & errcode , & len ) < = - 1 )
2020-07-24 17:29:52 +00:00
{
/* the error number is set to the socket error code.
* errno resulting from getsockopt ( ) doesn ' t reflect the actual
* socket error . so errno is not used to set the error number .
2021-07-22 07:30:20 +00:00
* instead , the generic device error HIO_EDEVERRR is used */
hio_seterrbfmt ( hio , HIO_EDEVERR , " device error - unable to get SO_ERROR " ) ;
2020-07-24 17:29:52 +00:00
}
else
{
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( rdev - > hio , 0 , errcode ) ;
2020-07-24 17:29:52 +00:00
}
return - 1 ;
}
2021-07-22 07:30:20 +00:00
else if ( events & HIO_DEV_EVENT_HUP )
2020-07-24 17:29:52 +00:00
{
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_EDEVHUP ) ;
2020-07-24 17:29:52 +00:00
return - 1 ;
}
return 1 ; /* the device is ok. carry on reading or writing */
}
2021-07-22 07:30:20 +00:00
static int dev_evcb_sck_on_read_qx ( hio_dev_t * dev , const void * data , hio_iolen_t dlen , const hio_devaddr_t * srcaddr )
2020-07-24 17:29:52 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
2020-07-24 17:29:52 +00:00
2021-07-22 07:30:20 +00:00
if ( rdev - > type = = HIO_DEV_SCK_QX )
2020-07-24 17:29:52 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dev_sck_qxmsg_t * qxmsg ;
2020-07-24 17:29:52 +00:00
2021-07-22 07:30:20 +00:00
if ( dlen ! = HIO_SIZEOF ( * qxmsg ) )
2020-07-24 17:29:52 +00:00
{
2021-07-22 07:30:20 +00:00
hio_seterrbfmt ( hio , HIO_EINVAL , " wrong qx packet size " ) ;
2020-07-28 10:21:10 +00:00
return 0 ;
2020-07-24 17:29:52 +00:00
}
2020-07-26 09:21:05 +00:00
2021-07-22 07:30:20 +00:00
qxmsg = ( hio_dev_sck_qxmsg_t * ) data ;
if ( qxmsg - > cmd = = HIO_DEV_SCK_QXMSG_NEWCONN )
2020-07-26 09:21:05 +00:00
{
2020-07-29 10:04:14 +00:00
if ( make_accepted_client_connection ( rdev , qxmsg - > syshnd , & qxmsg - > remoteaddr , qxmsg - > scktype ) < = - 1 )
2020-07-26 09:21:05 +00:00
{
2021-07-25 17:52:05 +00:00
/*printf ("unable to accept new client connection %d\n", qxmsg->syshnd);*/
2021-07-22 07:30:20 +00:00
return ( rdev - > state & HIO_DEV_SCK_LENIENT ) ? 0 : - 1 ;
2020-07-26 09:21:05 +00:00
}
}
else
{
2021-07-22 07:30:20 +00:00
hio_seterrbfmt ( hio , HIO_EINVAL , " wrong qx command code " ) ;
2020-07-28 10:21:10 +00:00
return 0 ;
2020-07-26 09:21:05 +00:00
}
return 0 ;
2020-07-24 17:29:52 +00:00
}
2020-07-26 09:21:05 +00:00
/* this is not for a qx socket */
2021-07-22 07:30:20 +00:00
return rdev - > on_read ( rdev , data , dlen , HIO_NULL ) ;
2020-07-24 17:29:52 +00:00
}
2021-07-22 07:30:20 +00:00
static int dev_evcb_sck_on_write_qx ( hio_dev_t * dev , hio_iolen_t wrlen , void * wrctx , const hio_devaddr_t * dstaddr )
2020-07-24 17:29:52 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dev_sck_t * rdev = ( hio_dev_sck_t * ) dev ;
2020-07-26 09:21:05 +00:00
2021-07-22 07:30:20 +00:00
if ( rdev - > type = = HIO_DEV_SCK_QX )
2020-07-26 09:21:05 +00:00
{
/* this should not be called */
return 0 ;
}
2021-07-22 07:30:20 +00:00
return rdev - > on_write ( rdev , wrlen , wrctx , HIO_NULL ) ;
2020-07-24 17:29:52 +00:00
}
2021-07-22 07:30:20 +00:00
static hio_dev_evcb_t dev_sck_event_callbacks_qx =
2020-07-24 17:29:52 +00:00
{
dev_evcb_sck_ready_qx ,
dev_evcb_sck_on_read_qx ,
dev_evcb_sck_on_write_qx
} ;
2016-03-30 07:06:54 +00:00
/* ========================================================================= */
2021-07-22 07:30:20 +00:00
static int dev_evcb_sck_ready_bpf ( hio_dev_t * dev , int events )
2020-11-16 15:40:20 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
2021-08-09 08:24:21 +00:00
/*hio_dev_sck_t* rdev = (hio_dev_sck_t*)dev;*/
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_ENOIMPL ) ;
2020-11-16 15:40:20 +00:00
return - 1 ;
}
2021-07-22 07:30:20 +00:00
static int dev_evcb_sck_on_read_bpf ( hio_dev_t * dev , const void * data , hio_iolen_t dlen , const hio_devaddr_t * srcaddr )
2020-11-16 15:40:20 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
2021-08-09 08:24:21 +00:00
/*hio_dev_sck_t* rdev = (hio_dev_sck_t*)dev;*/
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_ENOIMPL ) ;
2020-11-16 15:40:20 +00:00
return - 1 ;
}
2021-07-22 07:30:20 +00:00
static int dev_evcb_sck_on_write_bpf ( hio_dev_t * dev , hio_iolen_t wrlen , void * wrctx , const hio_devaddr_t * dstaddr )
2020-11-16 15:40:20 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
2021-08-09 08:24:21 +00:00
/*hio_dev_sck_t* rdev = (hio_dev_sck_t*)dev;*/
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_ENOIMPL ) ;
2020-11-16 15:40:20 +00:00
return - 1 ;
}
2021-07-22 07:30:20 +00:00
static hio_dev_evcb_t dev_sck_event_callbacks_bpf =
2020-11-16 15:40:20 +00:00
{
dev_evcb_sck_ready_bpf ,
dev_evcb_sck_on_read_bpf ,
dev_evcb_sck_on_write_bpf
} ;
/* ========================================================================= */
2021-07-22 07:30:20 +00:00
hio_dev_sck_t * hio_dev_sck_make ( hio_t * hio , hio_oow_t xtnsize , const hio_dev_sck_make_t * info )
2016-03-30 07:06:54 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dev_sck_t * rdev ;
2016-03-30 07:06:54 +00:00
2021-07-22 07:30:20 +00:00
if ( info - > type < 0 & & info - > type > = HIO_COUNTOF ( sck_type_map ) )
2016-03-30 07:06:54 +00:00
{
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_EINVAL ) ;
return HIO_NULL ;
2016-03-30 07:06:54 +00:00
}
2021-07-22 07:30:20 +00:00
if ( info - > type = = HIO_DEV_SCK_QX )
2020-07-24 17:29:52 +00:00
{
2021-07-22 07:30:20 +00:00
rdev = ( hio_dev_sck_t * ) hio_dev_make (
hio , HIO_SIZEOF ( hio_dev_sck_t ) + xtnsize ,
2020-11-16 15:40:20 +00:00
& dev_mth_sck_stateless , & dev_sck_event_callbacks_qx , ( void * ) info ) ;
}
2021-07-22 07:30:20 +00:00
else if ( info - > type = = HIO_DEV_SCK_BPF )
2020-11-16 15:40:20 +00:00
{
2021-07-22 07:30:20 +00:00
rdev = ( hio_dev_sck_t * ) hio_dev_make (
hio , HIO_SIZEOF ( hio_dev_sck_t ) + xtnsize ,
2020-11-16 15:40:20 +00:00
& dev_mth_sck_bpf , & dev_sck_event_callbacks_bpf , ( void * ) info ) ;
2020-07-24 17:29:52 +00:00
}
2021-08-08 07:03:52 +00:00
else if ( sck_type_map [ info - > type ] . extra_dev_cap & HIO_DEV_CAP_STREAM ) /* can't use the IS_STREAM() macro yet */
2016-03-30 07:06:54 +00:00
{
2021-07-22 07:30:20 +00:00
rdev = ( hio_dev_sck_t * ) hio_dev_make (
hio , HIO_SIZEOF ( hio_dev_sck_t ) + xtnsize ,
2021-08-08 07:03:52 +00:00
& dev_mth_sck_stream , & dev_sck_event_callbacks_stream , ( void * ) info ) ;
2016-03-30 07:06:54 +00:00
}
2021-08-13 15:33:53 +00:00
# if defined(ENABLE_SCTP)
2021-08-09 08:24:21 +00:00
else if ( sck_type_map [ info - > type ] . proto = = IPPROTO_SCTP )
{
rdev = ( hio_dev_sck_t * ) hio_dev_make (
hio , HIO_SIZEOF ( hio_dev_sck_t ) + xtnsize ,
& dev_mth_sck_sctp_sp , & dev_sck_event_callbacks_sctp_sp , ( void * ) info ) ;
}
2021-08-13 15:33:53 +00:00
# endif
2016-03-30 07:06:54 +00:00
else
{
2021-07-22 07:30:20 +00:00
rdev = ( hio_dev_sck_t * ) hio_dev_make (
hio , HIO_SIZEOF ( hio_dev_sck_t ) + xtnsize ,
2020-11-16 15:40:20 +00:00
& dev_mth_sck_stateless , & dev_sck_event_callbacks_stateless , ( void * ) info ) ;
2016-03-30 07:06:54 +00:00
}
return rdev ;
}
2021-07-22 07:30:20 +00:00
int hio_dev_sck_bind ( hio_dev_sck_t * dev , hio_dev_sck_bind_t * info )
2016-03-30 07:06:54 +00:00
{
2021-07-22 07:30:20 +00:00
return hio_dev_ioctl ( ( hio_dev_t * ) dev , HIO_DEV_SCK_BIND , info ) ;
2016-03-30 07:06:54 +00:00
}
2021-07-22 07:30:20 +00:00
int hio_dev_sck_connect ( hio_dev_sck_t * dev , hio_dev_sck_connect_t * info )
2016-03-30 07:06:54 +00:00
{
2021-07-22 07:30:20 +00:00
return hio_dev_ioctl ( ( hio_dev_t * ) dev , HIO_DEV_SCK_CONNECT , info ) ;
2016-03-30 07:06:54 +00:00
}
2016-03-29 15:02:01 +00:00
2021-07-22 07:30:20 +00:00
int hio_dev_sck_listen ( hio_dev_sck_t * dev , hio_dev_sck_listen_t * info )
2016-03-29 15:02:01 +00:00
{
2021-07-22 07:30:20 +00:00
return hio_dev_ioctl ( ( hio_dev_t * ) dev , HIO_DEV_SCK_LISTEN , info ) ;
2016-03-29 15:02:01 +00:00
}
2021-07-22 07:30:20 +00:00
int hio_dev_sck_write ( hio_dev_sck_t * dev , const void * data , hio_iolen_t dlen , void * wrctx , const hio_skad_t * dstaddr )
2016-03-29 15:02:01 +00:00
{
2021-07-22 07:30:20 +00:00
hio_devaddr_t devaddr ;
return hio_dev_write ( ( hio_dev_t * ) dev , data , dlen , wrctx , skad_to_devaddr ( dev , dstaddr , & devaddr ) ) ;
2016-03-29 15:02:01 +00:00
}
2021-07-22 07:30:20 +00:00
int hio_dev_sck_writev ( hio_dev_sck_t * dev , hio_iovec_t * iov , hio_iolen_t iovcnt , void * wrctx , const hio_skad_t * dstaddr )
2020-02-22 18:24:49 +00:00
{
2021-07-22 07:30:20 +00:00
hio_devaddr_t devaddr ;
return hio_dev_writev ( ( hio_dev_t * ) dev , iov , iovcnt , wrctx , skad_to_devaddr ( dev , dstaddr , & devaddr ) ) ;
2020-02-22 18:24:49 +00:00
}
2021-07-22 07:30:20 +00:00
int hio_dev_sck_timedwrite ( hio_dev_sck_t * dev , const void * data , hio_iolen_t dlen , const hio_ntime_t * tmout , void * wrctx , const hio_skad_t * dstaddr )
2016-03-29 15:02:01 +00:00
{
2021-07-22 07:30:20 +00:00
hio_devaddr_t devaddr ;
return hio_dev_timedwrite ( ( hio_dev_t * ) dev , data , dlen , tmout , wrctx , skad_to_devaddr ( dev , dstaddr , & devaddr ) ) ;
2016-03-29 15:02:01 +00:00
}
2016-04-25 14:07:28 +00:00
2021-07-22 07:30:20 +00:00
int hio_dev_sck_timedwritev ( hio_dev_sck_t * dev , hio_iovec_t * iov , hio_iolen_t iovcnt , const hio_ntime_t * tmout , void * wrctx , const hio_skad_t * dstaddr )
2020-02-21 16:58:41 +00:00
{
2021-07-22 07:30:20 +00:00
hio_devaddr_t devaddr ;
return hio_dev_timedwritev ( ( hio_dev_t * ) dev , iov , iovcnt , tmout , wrctx , skad_to_devaddr ( dev , dstaddr , & devaddr ) ) ;
2020-02-21 16:58:41 +00:00
}
2020-02-23 16:11:32 +00:00
/* ========================================================================= */
2021-07-22 07:30:20 +00:00
int hio_dev_sck_setsockopt ( hio_dev_sck_t * dev , int level , int optname , void * optval , hio_scklen_t optlen )
2020-02-23 16:11:32 +00:00
{
2021-08-16 16:02:04 +00:00
int n ;
n = setsockopt ( dev - > hnd , level , optname , optval , optlen ) ;
if ( n < = - 1 ) hio_seterrwithsyserr ( dev - > hio , 0 , errno ) ;
return n ;
2020-02-23 16:11:32 +00:00
}
2021-07-22 07:30:20 +00:00
int hio_dev_sck_getsockopt ( hio_dev_sck_t * dev , int level , int optname , void * optval , hio_scklen_t * optlen )
2020-02-23 16:11:32 +00:00
{
2021-08-16 16:02:04 +00:00
int n ;
n = getsockopt ( dev - > hnd , level , optname , optval , optlen ) ;
if ( n < = - 1 ) hio_seterrwithsyserr ( dev - > hio , 0 , errno ) ;
return n ;
2020-02-23 16:11:32 +00:00
}
2021-07-22 07:30:20 +00:00
int hio_dev_sck_getsockaddr ( hio_dev_sck_t * dev , hio_skad_t * skad )
2021-07-16 02:30:25 +00:00
{
2021-07-22 07:30:20 +00:00
hio_scklen_t addrlen = HIO_SIZEOF ( * skad ) ;
2021-08-06 03:23:48 +00:00
if ( dev - > type = = HIO_DEV_SCK_QX )
{
hio_skad_init_for_qx ( skad ) ;
}
else if ( getsockname ( dev - > hnd , ( struct sockaddr * ) skad , & addrlen ) < = - 1 )
2021-07-16 02:30:25 +00:00
{
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( dev - > hio , 0 , errno ) ;
2021-07-16 02:30:25 +00:00
return - 1 ;
}
return 0 ;
}
2021-07-22 07:30:20 +00:00
int hio_dev_sck_getpeeraddr ( hio_dev_sck_t * dev , hio_skad_t * skad )
2021-07-16 02:30:25 +00:00
{
2021-07-22 07:30:20 +00:00
hio_scklen_t addrlen = HIO_SIZEOF ( * skad ) ;
2021-08-06 03:23:48 +00:00
if ( dev - > type = = HIO_DEV_SCK_QX )
{
hio_skad_init_for_qx ( skad ) ;
}
else if ( getpeername ( dev - > hnd , ( struct sockaddr * ) skad , & addrlen ) < = - 1 )
2021-07-16 02:30:25 +00:00
{
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( dev - > hio , 0 , errno ) ;
2021-07-16 02:30:25 +00:00
return - 1 ;
}
return 0 ;
}
2021-08-17 07:00:22 +00:00
static int update_mcast_group ( hio_dev_sck_t * dev , int join , const hio_skad_t * mcast_skad , int ifindex )
2021-08-16 16:02:04 +00:00
{
int f ;
2021-08-17 07:00:22 +00:00
f = hio_skad_get_family ( mcast_skad ) ;
2021-08-16 16:02:04 +00:00
switch ( f )
{
case HIO_AF_INET :
{
2021-08-17 07:00:22 +00:00
/* TODO: if ip_mreqn doesn't exist, get the ip address of the index and set to imr_address */
2021-08-17 17:49:09 +00:00
# if defined(HAVE_STRUCT_IP_MREQN)
2021-08-16 16:02:04 +00:00
struct ip_mreqn mreq ;
2021-08-17 17:49:09 +00:00
# else
struct ip_mreq mreq ;
# endif
2021-08-16 16:02:04 +00:00
HIO_MEMSET ( & mreq , 0 , HIO_SIZEOF ( mreq ) ) ;
2021-08-17 07:00:22 +00:00
hio_skad_get_ipad_bytes ( mcast_skad , & mreq . imr_multiaddr , HIO_SIZEOF ( mreq . imr_multiaddr ) ) ;
2021-08-17 17:49:09 +00:00
/*mreq.imr_address = TODO: fill it will the ifindex's ip address */
# if defined(HAVE_STRUCT_IP_MREQN)
2021-08-16 16:02:04 +00:00
mreq . imr_ifindex = ifindex ;
2021-08-17 17:49:09 +00:00
# endif
2021-08-17 07:00:22 +00:00
if ( hio_dev_sck_setsockopt ( dev , IPPROTO_IP , ( join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP ) , & mreq , HIO_SIZEOF ( mreq ) ) < = - 1 ) return - 1 ;
2021-08-16 16:02:04 +00:00
return 0 ;
}
case HIO_AF_INET6 :
{
struct ipv6_mreq mreq ;
HIO_MEMSET ( & mreq , 0 , HIO_SIZEOF ( mreq ) ) ;
2021-08-17 07:00:22 +00:00
hio_skad_get_ipad_bytes ( mcast_skad , & mreq . ipv6mr_multiaddr , HIO_SIZEOF ( mreq . ipv6mr_multiaddr ) ) ;
mreq . ipv6mr_interface = ifindex ;
if ( hio_dev_sck_setsockopt ( dev , IPPROTO_IPV6 , ( join ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP ) , & mreq , HIO_SIZEOF ( mreq ) ) < = - 1 ) return - 1 ;
2021-08-16 16:02:04 +00:00
return 0 ;
}
}
hio_seterrbfmt ( hio_dev_sck_gethio ( dev ) , HIO_EINVAL , " invalid multicast address family " ) ;
return - 1 ;
}
2021-08-17 07:00:22 +00:00
int hio_dev_sck_joinmcastgroup ( hio_dev_sck_t * dev , const hio_skad_t * mcast_skad , int ifindex )
{
return update_mcast_group ( dev , 1 , mcast_skad , ifindex ) ;
}
int hio_dev_sck_leavemcastgroup ( hio_dev_sck_t * dev , const hio_skad_t * mcast_skad , int ifindex )
{
return update_mcast_group ( dev , 0 , mcast_skad , ifindex ) ;
}
2021-08-16 16:02:04 +00:00
/* ========================================================================= */
2021-07-22 07:30:20 +00:00
int hio_dev_sck_shutdown ( hio_dev_sck_t * dev , int how )
2020-05-19 09:11:39 +00:00
{
2021-07-22 07:30:20 +00:00
switch ( how & ( HIO_DEV_SCK_SHUTDOWN_READ | HIO_DEV_SCK_SHUTDOWN_WRITE ) )
2020-05-19 09:11:39 +00:00
{
2021-07-22 07:30:20 +00:00
case ( HIO_DEV_SCK_SHUTDOWN_READ | HIO_DEV_SCK_SHUTDOWN_WRITE ) :
2020-05-19 09:11:39 +00:00
how = SHUT_RDWR ;
break ;
2021-07-22 07:30:20 +00:00
case HIO_DEV_SCK_SHUTDOWN_READ :
2020-05-19 09:11:39 +00:00
how = SHUT_RD ;
break ;
2021-07-22 07:30:20 +00:00
case HIO_DEV_SCK_SHUTDOWN_WRITE :
2020-05-19 09:11:39 +00:00
how = SHUT_WR ;
break ;
default :
2021-07-22 07:30:20 +00:00
hio_seterrnum ( dev - > hio , HIO_EINVAL ) ;
2020-05-19 09:11:39 +00:00
return - 1 ;
}
2021-07-16 02:30:25 +00:00
if ( shutdown ( dev - > hnd , how ) < = - 1 )
{
2021-07-22 07:30:20 +00:00
hio_seterrwithsyserr ( dev - > hio , 0 , errno ) ;
2021-07-16 02:30:25 +00:00
return - 1 ;
}
return 0 ;
2020-05-19 09:11:39 +00:00
}
2021-07-22 07:30:20 +00:00
int hio_dev_sck_sendfileok ( hio_dev_sck_t * dev )
2020-07-19 18:55:35 +00:00
{
# if defined(USE_SSL)
2022-06-22 13:14:35 +00:00
# if defined(HAVE_SENDFILE)
/* unable to use sendfile over ssl */
2020-07-19 18:55:35 +00:00
return ! ( dev - > ssl ) ;
2022-06-22 13:14:35 +00:00
# else
/* no send file implementation */
return 0 ;
# endif
2020-07-19 18:55:35 +00:00
# else
2022-06-22 13:14:35 +00:00
# if defined(HAVE_SENDFILE)
2020-07-19 18:55:35 +00:00
return 1 ;
2022-06-22 13:14:35 +00:00
# else
return 0 ;
# endif
2020-07-19 18:55:35 +00:00
# endif
}
2021-07-22 07:30:20 +00:00
int hio_dev_sck_writetosidechan ( hio_dev_sck_t * dev , const void * dptr , hio_oow_t dlen )
2020-07-24 17:29:52 +00:00
{
2021-08-10 10:32:36 +00:00
if ( write ( dev - > side_chan , dptr , dlen ) < = - 1 )
{
/* this doesn't set the error information on the main socket. if you may check errno, though */
/* TODO: make hio_seterrbfmt() thread safe and set the error information properly. still the caller may be in the thread-unsafe context */
return - 1 ;
}
2020-07-24 17:29:52 +00:00
return 0 ;
}
2016-04-25 14:07:28 +00:00
/* ========================================================================= */
2021-07-22 07:30:20 +00:00
hio_uint16_t hio_checksum_ip ( const void * hdr , hio_oow_t len )
2016-04-25 14:07:28 +00:00
{
2021-07-22 07:30:20 +00:00
hio_uint32_t sum = 0 ;
hio_uint16_t * ptr = ( hio_uint16_t * ) hdr ;
2016-04-25 14:07:28 +00:00
while ( len > 1 )
{
sum + = * ptr + + ;
if ( sum & 0x80000000 )
sum = ( sum & 0xFFFF ) + ( sum > > 16 ) ;
len - = 2 ;
}
while ( sum > > 16 ) sum = ( sum & 0xFFFF ) + ( sum > > 16 ) ;
2021-07-22 07:30:20 +00:00
return ( hio_uint16_t ) ~ sum ;
2016-04-25 14:07:28 +00:00
}
2019-04-12 03:13:07 +00:00