原始版本
This commit is contained in:
42
RT_Thread/components/net/sal/Kconfig
Normal file
42
RT_Thread/components/net/sal/Kconfig
Normal file
@ -0,0 +1,42 @@
|
||||
menuconfig RT_USING_SAL
|
||||
bool "SAL: socket abstraction layer"
|
||||
select RT_USING_NETDEV
|
||||
default n
|
||||
|
||||
if RT_USING_SAL
|
||||
|
||||
config SAL_INTERNET_CHECK
|
||||
bool "Enable the ability that check internet status"
|
||||
select RT_USING_SYSTEM_WORKQUEUE
|
||||
default y
|
||||
help
|
||||
The ability that check internet status is provided by RT-Thread.
|
||||
|
||||
menu "Docking with protocol stacks"
|
||||
config SAL_USING_LWIP
|
||||
bool "Docking with lwIP stack"
|
||||
default n
|
||||
|
||||
config SAL_USING_AT
|
||||
bool "Docking with AT commands stack"
|
||||
default n
|
||||
|
||||
config SAL_USING_TLS
|
||||
bool "Docking with MbedTLS protocol"
|
||||
default n
|
||||
endmenu
|
||||
|
||||
config SAL_USING_POSIX
|
||||
bool
|
||||
depends on DFS_USING_POSIX
|
||||
default y
|
||||
help
|
||||
Enable BSD socket operated by file system API
|
||||
Let BSD socket operated by file system API, such as read/write and involveed in select/poll POSIX APIs.
|
||||
|
||||
config SAL_SOCKETS_NUM
|
||||
int "the maximum number of sockets"
|
||||
depends on !SAL_USING_POSIX
|
||||
default 16
|
||||
|
||||
endif
|
||||
35
RT_Thread/components/net/sal/SConscript
Normal file
35
RT_Thread/components/net/sal/SConscript
Normal file
@ -0,0 +1,35 @@
|
||||
# RT-Thread building script for component
|
||||
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
|
||||
src = Glob('src/*.c')
|
||||
src += ['socket/net_netdb.c']
|
||||
|
||||
CPPPATH = [cwd + '/include']
|
||||
CPPPATH += [cwd + '/include/socket']
|
||||
|
||||
if GetDepend('SAL_USING_LWIP') or GetDepend('SAL_USING_AT'):
|
||||
CPPPATH += [cwd + '/impl']
|
||||
|
||||
if GetDepend('SAL_USING_LWIP'):
|
||||
src += ['impl/af_inet_lwip.c']
|
||||
|
||||
if GetDepend('SAL_USING_AT'):
|
||||
src += ['impl/af_inet_at.c']
|
||||
|
||||
if GetDepend('SAL_USING_TLS'):
|
||||
src += ['impl/proto_mbedtls.c']
|
||||
|
||||
if GetDepend('SAL_USING_POSIX'):
|
||||
CPPPATH += [cwd + '/include/dfs_net']
|
||||
src += ['socket/net_sockets.c']
|
||||
src += Glob('dfs_net/*.c')
|
||||
|
||||
if not GetDepend('HAVE_SYS_SOCKET_H'):
|
||||
CPPPATH += [cwd + '/include/socket/sys_socket']
|
||||
|
||||
group = DefineGroup('SAL', src, depend = ['RT_USING_SAL'], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
119
RT_Thread/components/net/sal/dfs_net/dfs_net.c
Normal file
119
RT_Thread/components/net/sal/dfs_net/dfs_net.c
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2015-02-17 Bernard First version
|
||||
* 2016-05-07 Bernard Rename dfs_lwip to dfs_net
|
||||
* 2018-03-09 Bernard Fix the last data issue in poll.
|
||||
* 2018-05-24 ChenYong Add socket abstraction layer
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
#include <dfs.h>
|
||||
#include <dfs_net.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
int dfs_net_getsocket(int fd)
|
||||
{
|
||||
int socket;
|
||||
struct dfs_file *file;
|
||||
|
||||
file = fd_get(fd);
|
||||
if (file == NULL) return -1;
|
||||
|
||||
if (file->vnode->type != FT_SOCKET) socket = -1;
|
||||
else socket = (int)(size_t)file->vnode->data;
|
||||
|
||||
return socket;
|
||||
}
|
||||
|
||||
static int dfs_net_ioctl(struct dfs_file* file, int cmd, void* args)
|
||||
{
|
||||
int ret;
|
||||
int socket = (int)(size_t)file->vnode->data;
|
||||
|
||||
ret = sal_ioctlsocket(socket, cmd, args);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = rt_get_errno();
|
||||
return (ret > 0) ? (-ret) : ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DFS_V2
|
||||
static ssize_t dfs_net_read(struct dfs_file* file, void *buf, size_t count, off_t *pos)
|
||||
#else
|
||||
static ssize_t dfs_net_read(struct dfs_file* file, void *buf, size_t count)
|
||||
#endif
|
||||
{
|
||||
int ret;
|
||||
int socket = (int)(size_t)file->vnode->data;
|
||||
|
||||
ret = sal_recvfrom(socket, buf, count, 0, NULL, NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = rt_get_errno();
|
||||
return (ret > 0) ? (-ret) : ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DFS_V2
|
||||
static ssize_t dfs_net_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos)
|
||||
#else
|
||||
static ssize_t dfs_net_write(struct dfs_file *file, const void *buf, size_t count)
|
||||
#endif
|
||||
{
|
||||
int ret;
|
||||
int socket = (int)(size_t)file->vnode->data;
|
||||
|
||||
ret = sal_sendto(socket, buf, count, 0, NULL, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = rt_get_errno();
|
||||
return (ret > 0) ? (-ret) : ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dfs_net_close(struct dfs_file* file)
|
||||
{
|
||||
int socket;
|
||||
int ret = 0;
|
||||
|
||||
if (file->vnode->ref_count == 1)
|
||||
{
|
||||
socket = (int)(size_t)file->vnode->data;
|
||||
ret = sal_closesocket(socket);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dfs_net_poll(struct dfs_file *file, struct rt_pollreq *req)
|
||||
{
|
||||
extern int sal_poll(struct dfs_file *file, struct rt_pollreq *req);
|
||||
|
||||
return sal_poll(file, req);
|
||||
}
|
||||
|
||||
const struct dfs_file_ops _net_fops =
|
||||
{
|
||||
.close = dfs_net_close,
|
||||
.ioctl = dfs_net_ioctl,
|
||||
.read = dfs_net_read,
|
||||
.write = dfs_net_write,
|
||||
.poll = dfs_net_poll,
|
||||
};
|
||||
|
||||
const struct dfs_file_ops *dfs_net_get_fops(void)
|
||||
{
|
||||
return &_net_fops;
|
||||
}
|
||||
38
RT_Thread/components/net/sal/impl/af_inet.h
Normal file
38
RT_Thread/components/net/sal/impl/af_inet.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-08-25 ChenYong First version
|
||||
*/
|
||||
|
||||
#ifndef __AF_INET_H__
|
||||
#define __AF_INET_H__
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef SAL_USING_LWIP
|
||||
|
||||
/* Set lwIP network interface device protocol family information */
|
||||
int sal_lwip_netdev_set_pf_info(struct netdev *netdev);
|
||||
|
||||
#endif /* SAL_USING_LWIP */
|
||||
|
||||
#ifdef SAL_USING_AT
|
||||
|
||||
/* Set AT network interface device protocol family information */
|
||||
int sal_at_netdev_set_pf_info(struct netdev *netdev);
|
||||
|
||||
#endif /* SAL_USING_AT */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __AF_INET_H__ */
|
||||
125
RT_Thread/components/net/sal/impl/af_inet_at.c
Normal file
125
RT_Thread/components/net/sal/impl/af_inet_at.c
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-06-06 ChenYong First version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
#include <netdb.h>
|
||||
#include <sal_low_lvl.h>
|
||||
|
||||
#include <at_socket.h>
|
||||
#include <af_inet.h>
|
||||
|
||||
#include <netdev.h>
|
||||
|
||||
#ifdef SAL_USING_POSIX
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
#ifdef SAL_USING_AT
|
||||
|
||||
#ifdef SAL_USING_POSIX
|
||||
static int at_poll(struct dfs_file *file, struct rt_pollreq *req)
|
||||
{
|
||||
int mask = 0;
|
||||
struct at_socket *sock;
|
||||
struct sal_socket *sal_sock;
|
||||
|
||||
sal_sock = sal_get_socket((int)file->vnode->data);
|
||||
if(!sal_sock)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
sock = at_get_socket((int)sal_sock->user_data);
|
||||
if (sock != NULL)
|
||||
{
|
||||
rt_base_t level;
|
||||
|
||||
rt_poll_add(&sock->wait_head, req);
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
if (sock->rcvevent)
|
||||
{
|
||||
mask |= POLLIN;
|
||||
}
|
||||
if (sock->sendevent)
|
||||
{
|
||||
mask |= POLLOUT;
|
||||
}
|
||||
if (sock->errevent)
|
||||
{
|
||||
mask |= POLLERR;
|
||||
}
|
||||
rt_hw_interrupt_enable(level);
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct sal_socket_ops at_socket_ops =
|
||||
{
|
||||
at_socket,
|
||||
at_closesocket,
|
||||
at_bind,
|
||||
#ifdef AT_USING_SOCKET_SERVER
|
||||
at_listen,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
at_connect,
|
||||
#ifdef AT_USING_SOCKET_SERVER
|
||||
at_accept,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
at_sendto,
|
||||
NULL,
|
||||
NULL,
|
||||
at_recvfrom,
|
||||
at_getsockopt,
|
||||
at_setsockopt,
|
||||
at_shutdown,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
#ifdef SAL_USING_POSIX
|
||||
at_poll,
|
||||
#endif /* SAL_USING_POSIX */
|
||||
};
|
||||
|
||||
static const struct sal_netdb_ops at_netdb_ops =
|
||||
{
|
||||
at_gethostbyname,
|
||||
at_gethostbyname_r,
|
||||
at_getaddrinfo,
|
||||
at_freeaddrinfo,
|
||||
};
|
||||
|
||||
static const struct sal_proto_family at_inet_family =
|
||||
{
|
||||
AF_AT,
|
||||
AF_INET,
|
||||
&at_socket_ops,
|
||||
&at_netdb_ops,
|
||||
};
|
||||
|
||||
|
||||
/* Set AT network interface device protocol family information */
|
||||
int sal_at_netdev_set_pf_info(struct netdev *netdev)
|
||||
{
|
||||
RT_ASSERT(netdev);
|
||||
|
||||
netdev->sal_user_data = (void *) &at_inet_family;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SAL_USING_AT */
|
||||
350
RT_Thread/components/net/sal/impl/af_inet_lwip.c
Normal file
350
RT_Thread/components/net/sal/impl/af_inet_lwip.c
Normal file
@ -0,0 +1,350 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-05-17 ChenYong First version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
#ifdef SAL_USING_POSIX
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
#include <lwip/sockets.h>
|
||||
#include <lwip/netdb.h>
|
||||
#include <lwip/api.h>
|
||||
#include <lwip/init.h>
|
||||
#include <lwip/netif.h>
|
||||
|
||||
#include <sal_low_lvl.h>
|
||||
#include <af_inet.h>
|
||||
|
||||
#include <netdev.h>
|
||||
|
||||
#if (LWIP_VERSION < 0x2000000) && NETDEV_IPV6
|
||||
#error "The lwIP version is not support IPV6, please disable netdev IPV6 configuration "
|
||||
#elif (LWIP_VERSION > 0x2000000) && (NETDEV_IPV6 != LWIP_IPV6)
|
||||
#error "IPV6 configuration error, Please check and synchronize netdev and lwip IPV6 configuration."
|
||||
#endif
|
||||
|
||||
#if LWIP_VERSION < 0x2000000
|
||||
#define SELWAIT_T int
|
||||
#else
|
||||
#ifndef SELWAIT_T
|
||||
#define SELWAIT_T u8_t
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SAL_USING_LWIP
|
||||
|
||||
#ifdef SAL_USING_POSIX
|
||||
|
||||
#if LWIP_VERSION >= 0x20100ff
|
||||
#include <lwip/priv/sockets_priv.h>
|
||||
#else /* LWIP_VERSION < 0x20100ff */
|
||||
/*
|
||||
* Re-define lwip socket
|
||||
*
|
||||
* NOTE: please make sure the definitions same in lwip::net_socket.c
|
||||
*/
|
||||
struct lwip_sock {
|
||||
/** sockets currently are built on netconns, each socket has one netconn */
|
||||
struct netconn *conn;
|
||||
/** data that was left from the previous read */
|
||||
void *lastdata;
|
||||
/** offset in the data that was left from the previous read */
|
||||
u16_t lastoffset;
|
||||
/** number of times data was received, set by event_callback(),
|
||||
tested by the receive and select functions */
|
||||
s16_t rcvevent;
|
||||
/** number of times data was ACKed (free send buffer), set by event_callback(),
|
||||
tested by select */
|
||||
u16_t sendevent;
|
||||
/** error happened for this socket, set by event_callback(), tested by select */
|
||||
u16_t errevent;
|
||||
/** last error that occurred on this socket */
|
||||
#if LWIP_VERSION < 0x2000000
|
||||
int err;
|
||||
#else
|
||||
u8_t err;
|
||||
#endif
|
||||
/** counter of how many threads are waiting for this socket using select */
|
||||
SELWAIT_T select_waiting;
|
||||
|
||||
rt_wqueue_t wait_head;
|
||||
};
|
||||
#endif /* LWIP_VERSION >= 0x20100ff */
|
||||
|
||||
static RT_DEFINE_SPINLOCK(_spinlock);
|
||||
|
||||
extern struct lwip_sock *lwip_tryget_socket(int s);
|
||||
|
||||
static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
|
||||
{
|
||||
int s;
|
||||
struct lwip_sock *sock;
|
||||
uint32_t event = 0;
|
||||
SYS_ARCH_DECL_PROTECT(lev);
|
||||
|
||||
LWIP_UNUSED_ARG(len);
|
||||
|
||||
/* Get socket */
|
||||
if (conn)
|
||||
{
|
||||
s = conn->socket;
|
||||
if (s < 0)
|
||||
{
|
||||
/* Data comes in right away after an accept, even though
|
||||
* the server task might not have created a new socket yet.
|
||||
* Just count down (or up) if that's the case and we
|
||||
* will use the data later. Note that only receive events
|
||||
* can happen before the new socket is set up. */
|
||||
SYS_ARCH_PROTECT(lev);
|
||||
if (conn->socket < 0)
|
||||
{
|
||||
if (evt == NETCONN_EVT_RCVPLUS)
|
||||
{
|
||||
conn->socket--;
|
||||
}
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
return;
|
||||
}
|
||||
s = conn->socket;
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
}
|
||||
|
||||
sock = lwip_tryget_socket(s);
|
||||
if (!sock)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SYS_ARCH_PROTECT(lev);
|
||||
/* Set event as required */
|
||||
switch (evt)
|
||||
{
|
||||
case NETCONN_EVT_RCVPLUS:
|
||||
sock->rcvevent++;
|
||||
break;
|
||||
case NETCONN_EVT_RCVMINUS:
|
||||
sock->rcvevent--;
|
||||
break;
|
||||
case NETCONN_EVT_SENDPLUS:
|
||||
sock->sendevent = 1;
|
||||
break;
|
||||
case NETCONN_EVT_SENDMINUS:
|
||||
sock->sendevent = 0;
|
||||
break;
|
||||
case NETCONN_EVT_ERROR:
|
||||
sock->errevent = 1;
|
||||
break;
|
||||
default:
|
||||
LWIP_ASSERT("unknown event", 0);
|
||||
break;
|
||||
}
|
||||
|
||||
#if LWIP_VERSION >= 0x20100ff
|
||||
if ((void*)(sock->lastdata.pbuf) || (sock->rcvevent > 0))
|
||||
#else
|
||||
if ((void*)(sock->lastdata) || (sock->rcvevent > 0))
|
||||
#endif
|
||||
event |= POLLIN;
|
||||
if (sock->sendevent)
|
||||
event |= POLLOUT;
|
||||
if (sock->errevent)
|
||||
event |= POLLERR;
|
||||
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
|
||||
if (event)
|
||||
{
|
||||
rt_wqueue_wakeup(&sock->wait_head, (void*)(size_t)event);
|
||||
}
|
||||
}
|
||||
#endif /* SAL_USING_POSIX */
|
||||
|
||||
static int inet_socket(int domain, int type, int protocol)
|
||||
{
|
||||
#ifdef SAL_USING_POSIX
|
||||
int socket;
|
||||
|
||||
socket = lwip_socket(domain, type, protocol);
|
||||
if (socket >= 0)
|
||||
{
|
||||
struct lwip_sock *lwsock;
|
||||
|
||||
lwsock = lwip_tryget_socket(socket);
|
||||
lwsock->conn->callback = event_callback;
|
||||
|
||||
rt_wqueue_init(&lwsock->wait_head);
|
||||
}
|
||||
|
||||
return socket;
|
||||
#else
|
||||
return lwip_socket(domain, type, protocol);
|
||||
#endif /* SAL_USING_POSIX */
|
||||
}
|
||||
|
||||
static int inet_accept(int socket, struct sockaddr *addr, socklen_t *addrlen)
|
||||
{
|
||||
#ifdef SAL_USING_POSIX
|
||||
int new_socket;
|
||||
|
||||
new_socket = lwip_accept(socket, addr, addrlen);
|
||||
if (new_socket >= 0)
|
||||
{
|
||||
struct lwip_sock *lwsock;
|
||||
|
||||
lwsock = lwip_tryget_socket(new_socket);
|
||||
|
||||
rt_wqueue_init(&lwsock->wait_head);
|
||||
}
|
||||
|
||||
return new_socket;
|
||||
#else
|
||||
return lwip_accept(socket, addr, addrlen);
|
||||
#endif /* SAL_USING_POSIX */
|
||||
}
|
||||
|
||||
static int inet_getsockname(int socket, struct sockaddr *name, socklen_t *namelen)
|
||||
{
|
||||
#if LWIP_VERSION_MAJOR < 2U
|
||||
rt_kprintf("ERROR: Your lwIP version is not supported. Please using lwIP 2.0.0+.\n");
|
||||
RT_ASSERT(LWIP_VERSION_MAJOR >= 2U);
|
||||
#endif
|
||||
|
||||
return lwip_getsockname(socket, name, namelen);
|
||||
}
|
||||
|
||||
int inet_ioctlsocket(int socket, long cmd, void *arg)
|
||||
{
|
||||
int flags;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case F_GETFL:
|
||||
case F_SETFL:
|
||||
flags = (int)(size_t)arg;
|
||||
#ifdef O_LARGEFILE
|
||||
flags &= ~O_LARGEFILE;
|
||||
#endif
|
||||
return lwip_fcntl(socket, cmd, flags);
|
||||
|
||||
default:
|
||||
return lwip_ioctl(socket, cmd, arg);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SAL_USING_POSIX
|
||||
static int inet_poll(struct dfs_file *file, struct rt_pollreq *req)
|
||||
{
|
||||
int mask = 0;
|
||||
struct lwip_sock *sock;
|
||||
struct sal_socket *sal_sock;
|
||||
|
||||
sal_sock = sal_get_socket((int)(size_t)file->vnode->data);
|
||||
if(!sal_sock)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
sock = lwip_tryget_socket((int)(size_t)sal_sock->user_data);
|
||||
if (sock != NULL)
|
||||
{
|
||||
rt_base_t level;
|
||||
|
||||
rt_poll_add(&sock->wait_head, req);
|
||||
|
||||
level = rt_spin_lock_irqsave(&_spinlock);
|
||||
|
||||
#if LWIP_VERSION >= 0x20100ff
|
||||
if ((void*)(sock->lastdata.pbuf) || sock->rcvevent)
|
||||
#else
|
||||
if ((void*)(sock->lastdata) || sock->rcvevent)
|
||||
#endif
|
||||
{
|
||||
mask |= POLLIN;
|
||||
}
|
||||
if (sock->sendevent)
|
||||
{
|
||||
mask |= POLLOUT;
|
||||
}
|
||||
if (sock->errevent)
|
||||
{
|
||||
mask |= POLLERR;
|
||||
/* clean error event */
|
||||
sock->errevent = 0;
|
||||
}
|
||||
rt_spin_unlock_irqrestore(&_spinlock, level);
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct sal_socket_ops lwip_socket_ops =
|
||||
{
|
||||
.socket = inet_socket,
|
||||
.closesocket = lwip_close,
|
||||
.bind = lwip_bind,
|
||||
.listen = lwip_listen,
|
||||
.connect = lwip_connect,
|
||||
.accept = inet_accept,
|
||||
.sendto = (int (*)(int, const void *, size_t, int, const struct sockaddr *, socklen_t))lwip_sendto,
|
||||
#if LWIP_VERSION >= 0x20102ff
|
||||
.sendmsg = (int (*)(int, const struct msghdr *, int))lwip_sendmsg,
|
||||
.recvmsg = (int (*)(int, struct msghdr *, int))lwip_recvmsg,
|
||||
#endif
|
||||
.recvfrom = (int (*)(int, void *, size_t, int, struct sockaddr *, socklen_t *))lwip_recvfrom,
|
||||
.getsockopt = lwip_getsockopt,
|
||||
//TODO fix on 1.4.1
|
||||
.setsockopt = lwip_setsockopt,
|
||||
.shutdown = lwip_shutdown,
|
||||
.getpeername = lwip_getpeername,
|
||||
.getsockname = inet_getsockname,
|
||||
.ioctlsocket = inet_ioctlsocket,
|
||||
.socketpair = RT_NULL,
|
||||
#ifdef SAL_USING_POSIX
|
||||
.poll = inet_poll,
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct sal_netdb_ops lwip_netdb_ops =
|
||||
{
|
||||
.gethostbyname = lwip_gethostbyname,
|
||||
.gethostbyname_r = lwip_gethostbyname_r,
|
||||
.getaddrinfo = lwip_getaddrinfo,
|
||||
.freeaddrinfo = lwip_freeaddrinfo,
|
||||
};
|
||||
|
||||
static const struct sal_proto_family lwip_inet_family =
|
||||
{
|
||||
.family = AF_INET,
|
||||
#if LWIP_VERSION > 0x2000000
|
||||
.sec_family = AF_INET6,
|
||||
#else
|
||||
.sec_family = AF_INET,
|
||||
#endif
|
||||
.skt_ops = &lwip_socket_ops,
|
||||
.netdb_ops = &lwip_netdb_ops,
|
||||
};
|
||||
|
||||
/* Set lwIP network interface device protocol family information */
|
||||
int sal_lwip_netdev_set_pf_info(struct netdev *netdev)
|
||||
{
|
||||
RT_ASSERT(netdev);
|
||||
|
||||
netdev->sal_user_data = (void *) &lwip_inet_family;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SAL_USING_LWIP */
|
||||
249
RT_Thread/components/net/sal/impl/proto_mbedtls.c
Normal file
249
RT_Thread/components/net/sal/impl/proto_mbedtls.c
Normal file
@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-11-12 ChenYong First version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
#ifdef RT_USING_DFS
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statfs.h>
|
||||
#endif
|
||||
|
||||
#ifdef SAL_USING_TLS
|
||||
#include <sal_tls.h>
|
||||
#endif
|
||||
#include <netdb.h>
|
||||
#include <sal_low_lvl.h>
|
||||
|
||||
#include <netdev.h>
|
||||
|
||||
#ifdef SAL_USING_TLS
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include <mbedtls/config.h>
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include <tls_certificate.h>
|
||||
#include <tls_client.h>
|
||||
|
||||
#ifndef SAL_MEBDTLS_BUFFER_LEN
|
||||
#define SAL_MEBDTLS_BUFFER_LEN 1024
|
||||
#endif
|
||||
|
||||
static void *mebdtls_socket(int socket)
|
||||
{
|
||||
MbedTLSSession *session = RT_NULL;
|
||||
char *pers = "mbedtls";
|
||||
|
||||
if (socket < 0)
|
||||
{
|
||||
return RT_NULL;
|
||||
}
|
||||
|
||||
session = (MbedTLSSession *) tls_calloc(1, sizeof(MbedTLSSession));
|
||||
if (session == RT_NULL)
|
||||
{
|
||||
return RT_NULL;
|
||||
}
|
||||
|
||||
session->buffer_len = SAL_MEBDTLS_BUFFER_LEN;
|
||||
session->buffer = tls_calloc(1, session->buffer_len);
|
||||
if (session->buffer == RT_NULL)
|
||||
{
|
||||
tls_free(session);
|
||||
session = RT_NULL;
|
||||
|
||||
return RT_NULL;
|
||||
}
|
||||
|
||||
/* initialize TLS Client sesison */
|
||||
if (mbedtls_client_init(session, (void *) pers, rt_strlen(pers)) != RT_EOK)
|
||||
{
|
||||
mbedtls_client_close(session);
|
||||
return RT_NULL;
|
||||
}
|
||||
session->server_fd.fd = socket;
|
||||
|
||||
return (void *)session;
|
||||
}
|
||||
|
||||
int mbedtls_net_send_cb(void *ctx, const unsigned char *buf, size_t len)
|
||||
{
|
||||
struct sal_socket *sock;
|
||||
int socket, ret;
|
||||
struct sal_proto_family *pf;
|
||||
|
||||
RT_ASSERT(ctx);
|
||||
RT_ASSERT(buf);
|
||||
|
||||
socket = ((mbedtls_net_context *) ctx)->fd;
|
||||
sock = sal_get_socket(socket);
|
||||
if (sock == RT_NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
pf = (struct sal_proto_family *)sock->netdev->sal_user_data;
|
||||
|
||||
/* Register scoket sendto option to TLS send data callback */
|
||||
ret = pf->skt_ops->sendto((int) sock->user_data, (void *)buf, len, 0, RT_NULL, RT_NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
#ifdef RT_USING_DFS
|
||||
if ((fcntl(socket, F_GETFL) & O_NONBLOCK) == O_NONBLOCK)
|
||||
return MBEDTLS_ERR_SSL_WANT_WRITE;
|
||||
#endif
|
||||
if (errno == ECONNRESET)
|
||||
return MBEDTLS_ERR_NET_CONN_RESET;
|
||||
if ( errno == EINTR)
|
||||
return MBEDTLS_ERR_SSL_WANT_READ;
|
||||
|
||||
return MBEDTLS_ERR_NET_SEND_FAILED ;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mbedtls_net_recv_cb( void *ctx, unsigned char *buf, size_t len)
|
||||
{
|
||||
struct sal_socket *sock;
|
||||
struct sal_proto_family *pf;
|
||||
int socket, ret;
|
||||
|
||||
RT_ASSERT(ctx);
|
||||
RT_ASSERT(buf);
|
||||
|
||||
socket = ((mbedtls_net_context *) ctx)->fd;
|
||||
sock = sal_get_socket(socket);
|
||||
if (sock == RT_NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
pf = (struct sal_proto_family *)sock->netdev->sal_user_data;
|
||||
|
||||
/* Register scoket recvfrom option to TLS recv data callback */
|
||||
ret = pf->skt_ops->recvfrom((int) sock->user_data, (void *)buf, len, 0, RT_NULL, RT_NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
#ifdef RT_USING_DFS
|
||||
if ((fcntl(socket, F_GETFL) & O_NONBLOCK) == O_NONBLOCK)
|
||||
return MBEDTLS_ERR_SSL_WANT_WRITE;
|
||||
#endif
|
||||
if (errno == ECONNRESET)
|
||||
return MBEDTLS_ERR_NET_CONN_RESET;
|
||||
if ( errno == EINTR)
|
||||
return MBEDTLS_ERR_SSL_WANT_READ;
|
||||
|
||||
return MBEDTLS_ERR_NET_RECV_FAILED ;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mbedtls_connect(void *sock)
|
||||
{
|
||||
MbedTLSSession *session = RT_NULL;
|
||||
int ret = 0;
|
||||
|
||||
RT_ASSERT(sock);
|
||||
|
||||
session = (MbedTLSSession *) sock;
|
||||
|
||||
/* Set the SSL Configure infromation */
|
||||
ret = mbedtls_client_context(session);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
/* Set the underlying BIO callbacks for write, read and read-with-timeout. */
|
||||
mbedtls_ssl_set_bio(&session->ssl, &session->server_fd, mbedtls_net_send_cb, mbedtls_net_recv_cb, RT_NULL);
|
||||
|
||||
while ((ret = mbedtls_ssl_handshake(&session->ssl)) != 0)
|
||||
{
|
||||
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
|
||||
{
|
||||
goto __exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the result of the certificate verification */
|
||||
ret = mbedtls_ssl_get_verify_result(&session->ssl);
|
||||
if (ret != 0)
|
||||
{
|
||||
rt_memset(session->buffer, 0x00, session->buffer_len);
|
||||
mbedtls_x509_crt_verify_info((char *)session->buffer, session->buffer_len, " ! ", ret);
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
__exit:
|
||||
if (session)
|
||||
{
|
||||
mbedtls_client_close(session);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mbedtls_closesocket(void *sock)
|
||||
{
|
||||
struct sal_socket *ssock;
|
||||
int socket;
|
||||
|
||||
if (sock == RT_NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
socket = ((MbedTLSSession *) sock)->server_fd.fd;
|
||||
ssock = sal_get_socket(socket);
|
||||
if (ssock == RT_NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Close TLS client session, and clean user-data in SAL socket */
|
||||
mbedtls_client_close((MbedTLSSession *) sock);
|
||||
ssock->user_data_tls = RT_NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sal_proto_tls_ops mbedtls_proto_ops=
|
||||
{
|
||||
RT_NULL,
|
||||
mebdtls_socket,
|
||||
mbedtls_connect,
|
||||
(int (*)(void *sock, const void *data, size_t size)) mbedtls_client_write,
|
||||
(int (*)(void *sock, void *mem, size_t len)) mbedtls_client_read,
|
||||
mbedtls_closesocket,
|
||||
};
|
||||
|
||||
static const struct sal_proto_tls mbedtls_proto =
|
||||
{
|
||||
"mbedtls",
|
||||
&mbedtls_proto_ops,
|
||||
};
|
||||
|
||||
int sal_mbedtls_proto_init(void)
|
||||
{
|
||||
/* register MbedTLS protocol options to SAL */
|
||||
sal_proto_tls_register(&mbedtls_proto);
|
||||
|
||||
return 0;
|
||||
}
|
||||
INIT_COMPONENT_EXPORT(sal_mbedtls_proto_init);
|
||||
|
||||
#endif /* SAL_USING_TLS */
|
||||
29
RT_Thread/components/net/sal/include/dfs_net/dfs_net.h
Normal file
29
RT_Thread/components/net/sal/include/dfs_net/dfs_net.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2015-02-17 Bernard First version
|
||||
* 2016-05-05 Bernard rename dfs_lwip to dfs_net.
|
||||
*/
|
||||
|
||||
#ifndef DFS_NET_H__
|
||||
#define DFS_NET_H__
|
||||
|
||||
#include <dfs_file.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
const struct dfs_file_ops* dfs_net_get_fops(void);
|
||||
int dfs_net_getsocket(int fd);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
122
RT_Thread/components/net/sal/include/sal_low_lvl.h
Normal file
122
RT_Thread/components/net/sal/include/sal_low_lvl.h
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-05-17 ChenYong First version
|
||||
* 2022-05-15 Meco Man rename sal.h as sal_low_lvl.h to avoid conflicts
|
||||
* with Microsoft Visual Studio header file
|
||||
*/
|
||||
|
||||
#ifndef SAL_LOW_LEVEL_H__
|
||||
#define SAL_LOW_LEVEL_H__
|
||||
|
||||
#include <rtdevice.h>
|
||||
|
||||
#ifdef SAL_USING_POSIX
|
||||
#include <dfs_file.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !defined(socklen_t) && !defined(SOCKLEN_T_DEFINED)
|
||||
typedef uint32_t socklen_t;
|
||||
#endif
|
||||
|
||||
/* SAL socket magic word */
|
||||
#define SAL_SOCKET_MAGIC 0x5A10
|
||||
|
||||
/* The maximum number of sockets structure */
|
||||
#ifndef SAL_SOCKETS_NUM
|
||||
#define SAL_SOCKETS_NUM DFS_FD_MAX
|
||||
#endif
|
||||
|
||||
/* The maximum number of protocol families */
|
||||
#ifndef SAL_PROTO_FAMILIES_NUM
|
||||
#define SAL_PROTO_FAMILIES_NUM 4
|
||||
#endif
|
||||
|
||||
/* SAL socket offset */
|
||||
#ifndef SAL_SOCKET_OFFSET
|
||||
#define SAL_SOCKET_OFFSET 0
|
||||
#endif
|
||||
|
||||
struct sockaddr;
|
||||
struct msghdr;
|
||||
struct addrinfo;
|
||||
struct sal_socket
|
||||
{
|
||||
uint32_t magic; /* SAL socket magic word */
|
||||
|
||||
int socket; /* SAL socket descriptor */
|
||||
int domain;
|
||||
int type;
|
||||
int protocol;
|
||||
|
||||
struct netdev *netdev; /* SAL network interface device */
|
||||
|
||||
void *user_data; /* user-specific data */
|
||||
#ifdef SAL_USING_TLS
|
||||
void *user_data_tls; /* user-specific TLS data */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* network interface socket opreations */
|
||||
struct sal_socket_ops
|
||||
{
|
||||
int (*socket) (int domain, int type, int protocol);
|
||||
int (*closesocket)(int s);
|
||||
int (*bind) (int s, const struct sockaddr *name, socklen_t namelen);
|
||||
int (*listen) (int s, int backlog);
|
||||
int (*connect) (int s, const struct sockaddr *name, socklen_t namelen);
|
||||
int (*accept) (int s, struct sockaddr *addr, socklen_t *addrlen);
|
||||
int (*sendto) (int s, const void *data, size_t size, int flags, const struct sockaddr *to, socklen_t tolen);
|
||||
int (*sendmsg) (int s, const struct msghdr *message, int flags);
|
||||
int (*recvmsg) (int s, struct msghdr *message, int flags);
|
||||
int (*recvfrom) (int s, void *mem, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);
|
||||
int (*getsockopt) (int s, int level, int optname, void *optval, socklen_t *optlen);
|
||||
int (*setsockopt) (int s, int level, int optname, const void *optval, socklen_t optlen);
|
||||
int (*shutdown) (int s, int how);
|
||||
int (*getpeername)(int s, struct sockaddr *name, socklen_t *namelen);
|
||||
int (*getsockname)(int s, struct sockaddr *name, socklen_t *namelen);
|
||||
int (*ioctlsocket)(int s, long cmd, void *arg);
|
||||
int (*socketpair) (int s, int type, int protocol, int *fds);
|
||||
#ifdef SAL_USING_POSIX
|
||||
int (*poll) (struct dfs_file *file, struct rt_pollreq *req);
|
||||
#endif
|
||||
};
|
||||
|
||||
/* sal network database name resolving */
|
||||
struct sal_netdb_ops
|
||||
{
|
||||
struct hostent* (*gethostbyname) (const char *name);
|
||||
int (*gethostbyname_r)(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop);
|
||||
int (*getaddrinfo) (const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res);
|
||||
void (*freeaddrinfo) (struct addrinfo *ai);
|
||||
};
|
||||
|
||||
struct sal_proto_family
|
||||
{
|
||||
int family; /* primary protocol families type */
|
||||
int sec_family; /* secondary protocol families type */
|
||||
const struct sal_socket_ops *skt_ops; /* socket opreations */
|
||||
const struct sal_netdb_ops *netdb_ops; /* network database opreations */
|
||||
};
|
||||
|
||||
/* SAL(Socket Abstraction Layer) initialize */
|
||||
int sal_init(void);
|
||||
/* Get SAL socket object by socket descriptor */
|
||||
struct sal_socket *sal_get_socket(int sock);
|
||||
|
||||
/* check SAL socket netweork interface device internet status */
|
||||
int sal_check_netdev_internet_up(struct netdev *netdev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SAL_H__ */
|
||||
77
RT_Thread/components/net/sal/include/sal_msg.h
Normal file
77
RT_Thread/components/net/sal/include/sal_msg.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-12-06 zmq810150896 The first version.
|
||||
*/
|
||||
#ifndef __SAL_MSG_H__
|
||||
#define __SAL_MSG_H__
|
||||
#include <rtthread.h>
|
||||
|
||||
/* message frame */
|
||||
struct msg_buf
|
||||
{
|
||||
void *parm; /* Parameters for message detection */
|
||||
void *buf; /* Data to be sent */
|
||||
rt_size_t length; /* Data length */
|
||||
void *control_data; /* Additional data to send the message */
|
||||
rt_size_t data_len; /* Additional data length */
|
||||
int msg_type; /* message type */
|
||||
int data_type; /* Addittional data length */
|
||||
int msg_level;
|
||||
int *fd; /* Pass the array used by fd */
|
||||
rt_slist_t msg_next; /* Next message */
|
||||
rt_slist_t msg_node; /* sendmsg is used to send multiple messages at the same time */
|
||||
};
|
||||
|
||||
/* Remaining message */
|
||||
struct last_buf
|
||||
{
|
||||
void *buf; /* Data to be sent */
|
||||
rt_size_t length; /* Data length */
|
||||
rt_size_t offset; /* Data Offset */
|
||||
struct msg_buf *msg;
|
||||
};
|
||||
|
||||
/* sock */
|
||||
struct unix_sock
|
||||
{
|
||||
rt_uint8_t len;
|
||||
int flags;
|
||||
uint8_t family; /* protocol */
|
||||
char path[108]; /* file name */
|
||||
struct unix_conn *conn; /* connecting processing */
|
||||
rt_wqueue_t wq_head; /* Waiting queue head */
|
||||
rt_atomic_t listen_num; /* Maximum listening quantity */
|
||||
rt_atomic_t conn_counter; /* connected num */
|
||||
struct rt_mutex sock_lock;
|
||||
rt_slist_t wait_conn_head;
|
||||
struct last_buf pbuf;
|
||||
};
|
||||
|
||||
struct unix_conn
|
||||
{
|
||||
int state; /* connect state */
|
||||
int type;
|
||||
int proto;
|
||||
|
||||
#ifdef SAL_USING_AF_UNIX
|
||||
rt_atomic_t msg_count;
|
||||
#endif
|
||||
rt_uint32_t send_timeout;
|
||||
rt_uint32_t recv_timeout;
|
||||
rt_wqueue_t wq_read_head;
|
||||
rt_wqueue_t wq_confirm;
|
||||
struct rt_mutex conn_lock;
|
||||
rt_slist_t msg_head; /* message head */
|
||||
rt_slist_t conn_node;
|
||||
struct unix_sock *sock;
|
||||
struct unix_sock *ser_sock;
|
||||
struct unix_conn *correl_conn; /* Information about the other party */
|
||||
int (* conn_callback)(struct unix_conn *conn); /* The callback function that establishes the connection */
|
||||
};
|
||||
|
||||
#endif
|
||||
86
RT_Thread/components/net/sal/include/sal_netdb.h
Normal file
86
RT_Thread/components/net/sal/include/sal_netdb.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-05-24 ChenYong First version
|
||||
*/
|
||||
#ifndef SAL_NETDB_H__
|
||||
#define SAL_NETDB_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include "sal_socket.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define EAI_NONAME 200
|
||||
#define EAI_SERVICE 201
|
||||
#define EAI_FAIL 202
|
||||
#define EAI_MEMORY 203
|
||||
#define EAI_FAMILY 204
|
||||
|
||||
#define HOST_NOT_FOUND 210
|
||||
#define NO_DATA 211
|
||||
#define NO_RECOVERY 212
|
||||
#define TRY_AGAIN 213
|
||||
|
||||
#define AI_PASSIVE 0x01
|
||||
#define AI_CANONNAME 0x02
|
||||
#define AI_NUMERICHOST 0x04
|
||||
#define AI_NUMERICSERV 0x08
|
||||
#define AI_V4MAPPED 0x10
|
||||
#define AI_ALL 0x20
|
||||
#define AI_ADDRCONFIG 0x40
|
||||
|
||||
/* input flags for structure addrinfo */
|
||||
#define AI_PASSIVE 0x01
|
||||
#define AI_CANONNAME 0x02
|
||||
#define AI_NUMERICHOST 0x04
|
||||
#define AI_NUMERICSERV 0x08
|
||||
#define AI_V4MAPPED 0x10
|
||||
#define AI_ALL 0x20
|
||||
#define AI_ADDRCONFIG 0x40
|
||||
|
||||
#define DNS_MAX_NAME_LENGTH 256
|
||||
|
||||
struct hostent {
|
||||
char *h_name; /* Official name of the host. */
|
||||
char **h_aliases; /* A pointer to an array of pointers to alternative host names,
|
||||
terminated by a null pointer. */
|
||||
int h_addrtype; /* Address type. */
|
||||
int h_length; /* The length, in bytes, of the address. */
|
||||
char **h_addr_list; /* A pointer to an array of pointers to network addresses (in
|
||||
network byte order) for the host, terminated by a null pointer. */
|
||||
#define h_addr h_addr_list[0] /* for backward compatibility */
|
||||
};
|
||||
|
||||
struct addrinfo {
|
||||
int ai_flags; /* Input flags. */
|
||||
int ai_family; /* Address family of socket. */
|
||||
int ai_socktype; /* Socket type. */
|
||||
int ai_protocol; /* Protocol of socket. */
|
||||
socklen_t ai_addrlen; /* Length of socket address. */
|
||||
struct sockaddr *ai_addr; /* Socket address of socket. */
|
||||
char *ai_canonname; /* Canonical name of service location. */
|
||||
struct addrinfo *ai_next; /* Pointer to next in list. */
|
||||
};
|
||||
|
||||
struct hostent *sal_gethostbyname(const char *name);
|
||||
|
||||
int sal_gethostbyname_r(const char *name, struct hostent *ret, char *buf,
|
||||
size_t buflen, struct hostent **result, int *h_errnop);
|
||||
void sal_freeaddrinfo(struct addrinfo *ai);
|
||||
int sal_getaddrinfo(const char *nodename,
|
||||
const char *servname,
|
||||
const struct addrinfo *hints,
|
||||
struct addrinfo **res);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SAL_NETDB_H__ */
|
||||
357
RT_Thread/components/net/sal/include/sal_socket.h
Normal file
357
RT_Thread/components/net/sal/include/sal_socket.h
Normal file
@ -0,0 +1,357 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-05-24 ChenYong First version
|
||||
*/
|
||||
|
||||
#ifndef SAL_SOCKET_H__
|
||||
#define SAL_SOCKET_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !defined(socklen_t) && !defined(SOCKLEN_T_DEFINED)
|
||||
typedef uint32_t socklen_t;
|
||||
#endif
|
||||
|
||||
#if !defined(sa_family_t) && !defined(SA_FAMILY_T_DEFINED)
|
||||
typedef uint8_t sa_family_t;
|
||||
#endif
|
||||
|
||||
/* If your port already typedef's in_port_t, define IN_PORT_T_DEFINED
|
||||
to prevent this code from redefining it. */
|
||||
#if !defined(in_port_t) && !defined(IN_PORT_T_DEFINED)
|
||||
typedef uint16_t in_port_t;
|
||||
#endif
|
||||
|
||||
/* Socket protocol types (TCP/UDP/RAW) */
|
||||
#define SOCK_STREAM 1
|
||||
#define SOCK_DGRAM 2
|
||||
#define SOCK_RAW 3
|
||||
#define SOCK_PACKET 10
|
||||
|
||||
#define SOCK_NONBLOCK 04000
|
||||
#define SOCK_CLOEXEC 02000000
|
||||
|
||||
#define SOCK_MAX (SOCK_CLOEXEC + 1)
|
||||
|
||||
/* Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c) */
|
||||
#define SO_REUSEADDR 0x0004 /* Allow local address reuse */
|
||||
#define SO_KEEPALIVE 0x0008 /* keep connections alive */
|
||||
#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */
|
||||
|
||||
#define SO_PASSCRED 16
|
||||
#define SO_PEERCRED 17
|
||||
|
||||
#define SO_BINDTODEVICE 25
|
||||
#define SO_ATTACH_FILTER 26
|
||||
#define SO_DETACH_FILTER 27
|
||||
|
||||
#define SO_SNDBUFFORCE 32
|
||||
#define SO_RCVBUFFORCE 33
|
||||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
/* Additional options, not kept in so_options */
|
||||
#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */
|
||||
#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */
|
||||
#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */
|
||||
#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */
|
||||
#define SO_LINGER 0x0080 /* linger on close if data present */
|
||||
#define SO_DONTLINGER ((int)(~SO_LINGER))
|
||||
#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */
|
||||
#define SO_REUSEPORT 0x0200 /* Unimplemented: allow local address & port reuse */
|
||||
#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */
|
||||
#define SO_RCVBUF 0x1002 /* receive buffer size */
|
||||
#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */
|
||||
#define SO_RCVLOWAT 0x1004 /* Unimplemented: receive low-water mark */
|
||||
#define SO_SNDTIMEO 0x1005 /* send timeout */
|
||||
#define SO_RCVTIMEO 0x1006 /* receive timeout */
|
||||
#define SO_ERROR 0x1007 /* get error status and clear */
|
||||
#define SO_TYPE 0x1008 /* get socket type */
|
||||
#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */
|
||||
#define SO_NO_CHECK 0x100a /* don't create UDP checksum */
|
||||
|
||||
/* Level number for (get/set)sockopt() to apply to socket itself */
|
||||
#define SOL_SOCKET 0xfff /* options for socket level */
|
||||
#define SOL_NETLINK 270
|
||||
|
||||
#define AF_UNSPEC 0
|
||||
#define AF_UNIX 1
|
||||
#define AF_INET 2
|
||||
#define AF_INET6 10
|
||||
#define AF_NETLINK 16
|
||||
#define AF_CAN 29 /* Controller Area Network */
|
||||
#define AF_AT 45 /* AT socket */
|
||||
#define AF_WIZ 46 /* WIZnet socket */
|
||||
#define PF_UNIX AF_UNIX
|
||||
#define PF_INET AF_INET
|
||||
#define PF_INET6 AF_INET6
|
||||
#define PF_NETLINK AF_NETLINK
|
||||
#define PF_UNSPEC AF_UNSPEC
|
||||
#define PF_CAN AF_CAN
|
||||
#define PF_AT AF_AT
|
||||
#define PF_WIZ AF_WIZ
|
||||
|
||||
#define AF_MAX (AF_WIZ + 1) /* For now.. */
|
||||
|
||||
#define IPPROTO_IP 0
|
||||
#define IPPROTO_ICMP 1
|
||||
#define IPPROTO_TCP 6
|
||||
#define IPPROTO_UDP 17
|
||||
#define IPPROTO_IPV6 41
|
||||
#define IPPROTO_ICMPV6 58
|
||||
#define IPPROTO_UDPLITE 136
|
||||
#define IPPROTO_RAW 255
|
||||
|
||||
/* Flags we can use with send and recv */
|
||||
#define MSG_PEEK 0x01 /* Peeks at an incoming message */
|
||||
#define MSG_WAITALL 0x02 /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */
|
||||
#define MSG_OOB 0x04 /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */
|
||||
#define MSG_DONTWAIT 0x08 /* Nonblocking i/o for this operation only */
|
||||
#define MSG_MORE 0x10 /* Sender will send more */
|
||||
|
||||
#define MSG_ERRQUEUE 0x2000 /* Fetch message from error queue */
|
||||
#define MSG_CONFIRM 0x0800 /* Confirm path validity */
|
||||
|
||||
/* Options for level IPPROTO_IP */
|
||||
#define IP_TOS 1
|
||||
#define IP_TTL 2
|
||||
|
||||
/* Options for level IPPROTO_TCP */
|
||||
#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */
|
||||
#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */
|
||||
#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */
|
||||
#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */
|
||||
#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */
|
||||
|
||||
/* Options and types related to multicast membership */
|
||||
#define IP_ADD_MEMBERSHIP 3
|
||||
#define IP_DROP_MEMBERSHIP 4
|
||||
/* Options and types for UDP multicast traffic handling */
|
||||
#define IP_MULTICAST_TTL 5
|
||||
#define IP_MULTICAST_IF 6
|
||||
#define IP_MULTICAST_LOOP 7
|
||||
|
||||
typedef struct ip_mreq
|
||||
{
|
||||
struct in_addr imr_multiaddr; /* IP multicast address of group */
|
||||
struct in_addr imr_interface; /* local IP address of interface */
|
||||
} ip_mreq;
|
||||
|
||||
/* The Type of Service provides an indication of the abstract parameters of the quality of service desired */
|
||||
#define IPTOS_TOS_MASK 0x1E
|
||||
#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
|
||||
#define IPTOS_LOWDELAY 0x10
|
||||
#define IPTOS_THROUGHPUT 0x08
|
||||
#define IPTOS_RELIABILITY 0x04
|
||||
#define IPTOS_LOWCOST 0x02
|
||||
#define IPTOS_MINCOST IPTOS_LOWCOST
|
||||
|
||||
/* The Network Control precedence designation is intended to be used within a network only */
|
||||
#define IPTOS_PREC_MASK 0xe0
|
||||
#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK)
|
||||
#define IPTOS_PREC_NETCONTROL 0xe0
|
||||
#define IPTOS_PREC_INTERNETCONTROL 0xc0
|
||||
#define IPTOS_PREC_CRITIC_ECP 0xa0
|
||||
#define IPTOS_PREC_FLASHOVERRIDE 0x80
|
||||
#define IPTOS_PREC_FLASH 0x60
|
||||
#define IPTOS_PREC_IMMEDIATE 0x40
|
||||
#define IPTOS_PREC_PRIORITY 0x20
|
||||
#define IPTOS_PREC_ROUTINE 0x00
|
||||
|
||||
#define SCM_RIGHTS 0x01 /* rw: access rights (array of int) */
|
||||
#define SCM_CREDENTIALS 0x02 /* rw: struct ucred */
|
||||
#define SCM_SECURITY 0x03 /* rw: security label */
|
||||
|
||||
/* Options for shatdown type */
|
||||
#ifndef SHUT_RD
|
||||
#define SHUT_RD 0
|
||||
#define SHUT_WR 1
|
||||
#define SHUT_RDWR 2
|
||||
#endif
|
||||
|
||||
struct sockaddr
|
||||
{
|
||||
uint8_t sa_len;
|
||||
sa_family_t sa_family;
|
||||
char sa_data[14];
|
||||
};
|
||||
|
||||
/* Structure describing the address of an AF_LOCAL (aka AF_UNIX) socket. */
|
||||
struct sockaddr_un
|
||||
{
|
||||
unsigned short sa_family;
|
||||
char sun_path[108]; /* Path name. */
|
||||
};
|
||||
|
||||
#if NETDEV_IPV4
|
||||
/* members are in network byte order */
|
||||
struct sockaddr_in
|
||||
{
|
||||
uint8_t sin_len;
|
||||
sa_family_t sin_family;
|
||||
in_port_t sin_port;
|
||||
struct in_addr sin_addr;
|
||||
#define SIN_ZERO_LEN 8
|
||||
char sin_zero[SIN_ZERO_LEN];
|
||||
};
|
||||
#endif /* NETDEV_IPV4 */
|
||||
|
||||
#if NETDEV_IPV6
|
||||
struct sockaddr_in6
|
||||
{
|
||||
uint8_t sin6_len; /* length of this structure */
|
||||
sa_family_t sin6_family; /* AF_INET6 */
|
||||
in_port_t sin6_port; /* Transport layer port # */
|
||||
uint32_t sin6_flowinfo; /* IPv6 flow information */
|
||||
struct in6_addr sin6_addr; /* IPv6 address */
|
||||
uint32_t sin6_scope_id; /* Set of interfaces for scope */
|
||||
};
|
||||
#endif /* NETDEV_IPV6 */
|
||||
|
||||
struct sockaddr_storage
|
||||
{
|
||||
uint8_t s2_len;
|
||||
sa_family_t ss_family;
|
||||
char s2_data1[2];
|
||||
uint32_t s2_data2[3];
|
||||
#if NETDEV_IPV6
|
||||
uint32_t s2_data3[3];
|
||||
#endif /* NETDEV_IPV6 */
|
||||
};
|
||||
|
||||
#ifdef RT_USING_MUSLLIBC
|
||||
#ifndef __DEFINED_struct_iovec
|
||||
struct iovec
|
||||
{
|
||||
void *iov_base;
|
||||
size_t iov_len;
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct msghdr
|
||||
{
|
||||
void *msg_name;
|
||||
socklen_t msg_namelen;
|
||||
struct iovec *msg_iov;
|
||||
int msg_iovlen;
|
||||
void *msg_control;
|
||||
socklen_t msg_controllen;
|
||||
int msg_flags;
|
||||
};
|
||||
|
||||
/* RFC 3542, Section 20: Ancillary Data */
|
||||
struct cmsghdr
|
||||
{
|
||||
size_t cmsg_len; /* number of bytes, including header */
|
||||
int cmsg_level; /* originating protocol */
|
||||
int cmsg_type; /* protocol-specific type */
|
||||
};
|
||||
|
||||
#define CMSG_NXTHDR(mhdr, cmsg) cmsg_nxthdr((mhdr), (cmsg))
|
||||
|
||||
#define CMSG_ALIGN(len) (((len) + sizeof(long) - 1) & ~(sizeof(long)-1))
|
||||
|
||||
#define CMSG_DATA(cmsg) ((void *)(cmsg) + sizeof(struct cmsghdr))
|
||||
#define CMSG_SPACE(len) (sizeof(struct cmsghdr) + CMSG_ALIGN(len))
|
||||
#define CMSG_LEN(len) (sizeof(struct cmsghdr) + (len))
|
||||
|
||||
#define __CMSG_FIRSTHDR(ctl, len) \
|
||||
((len) >= sizeof(struct cmsghdr) ? (struct cmsghdr *)(ctl) : (struct cmsghdr *)NULL)
|
||||
|
||||
#define CMSG_FIRSTHDR(msg) __CMSG_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
|
||||
#define CMSG_OK(mhdr, cmsg) \
|
||||
((cmsg)->cmsg_len >= sizeof(struct cmsghdr) && \
|
||||
(cmsg)->cmsg_len <= (unsigned long)((mhdr)->msg_controllen - ((char *)(cmsg) - (char *)(mhdr)->msg_control)))
|
||||
|
||||
#define for_each_cmsghdr(cmsg, msg) \
|
||||
for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg))
|
||||
|
||||
static inline struct cmsghdr *__cmsg_nxthdr(void *_ctl, size_t _size, struct cmsghdr *_cmsg)
|
||||
{
|
||||
struct cmsghdr *_ptr;
|
||||
|
||||
_ptr = (struct cmsghdr *)(((unsigned char *)_cmsg) + CMSG_ALIGN(_cmsg->cmsg_len));
|
||||
|
||||
if ((unsigned long)((char *)(_ptr + 1) - (char *)_ctl) > _size)
|
||||
{
|
||||
return (struct cmsghdr *)NULL;
|
||||
}
|
||||
|
||||
return _ptr;
|
||||
}
|
||||
|
||||
static inline struct cmsghdr *cmsg_nxthdr(struct msghdr *_msg, struct cmsghdr *_cmsg)
|
||||
{
|
||||
return __cmsg_nxthdr(_msg->msg_control, _msg->msg_controllen, _cmsg);
|
||||
}
|
||||
|
||||
#define IFNAMSIZ 16
|
||||
struct sal_ifmap
|
||||
{
|
||||
unsigned long int mem_start;
|
||||
unsigned long int mem_end;
|
||||
unsigned short int base_addr;
|
||||
unsigned char irq;
|
||||
unsigned char dma;
|
||||
unsigned char port;
|
||||
};
|
||||
|
||||
struct sal_ifreq
|
||||
{
|
||||
union
|
||||
{
|
||||
char ifrn_name[IFNAMSIZ];
|
||||
} ifr_ifrn;
|
||||
union
|
||||
{
|
||||
struct sockaddr ifru_addr;
|
||||
struct sockaddr ifru_dstaddr;
|
||||
struct sockaddr ifru_broadaddr;
|
||||
struct sockaddr ifru_netmask;
|
||||
struct sockaddr ifru_hwaddr;
|
||||
short int ifru_flags;
|
||||
int ifru_ivalue;
|
||||
int ifru_mtu;
|
||||
struct sal_ifmap ifru_map;
|
||||
char ifru_slave[IFNAMSIZ];
|
||||
char ifru_newname[IFNAMSIZ];
|
||||
char *ifru_data;
|
||||
} ifr_ifru;
|
||||
};
|
||||
|
||||
int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen);
|
||||
int sal_bind(int socket, const struct sockaddr *name, socklen_t namelen);
|
||||
int sal_shutdown(int socket, int how);
|
||||
int sal_getpeername (int socket, struct sockaddr *name, socklen_t *namelen);
|
||||
int sal_getsockname (int socket, struct sockaddr *name, socklen_t *namelen);
|
||||
int sal_getsockopt (int socket, int level, int optname, void *optval, socklen_t *optlen);
|
||||
int sal_setsockopt (int socket, int level, int optname, const void *optval, socklen_t optlen);
|
||||
int sal_connect(int socket, const struct sockaddr *name, socklen_t namelen);
|
||||
int sal_listen(int socket, int backlog);
|
||||
int sal_sendmsg(int socket, const struct msghdr *message, int flags);
|
||||
int sal_recvmsg(int socket, struct msghdr *message, int flags);
|
||||
int sal_recvfrom(int socket, void *mem, size_t len, int flags,
|
||||
struct sockaddr *from, socklen_t *fromlen);
|
||||
int sal_sendto(int socket, const void *dataptr, size_t size, int flags,
|
||||
const struct sockaddr *to, socklen_t tolen);
|
||||
int sal_socket(int domain, int type, int protocol);
|
||||
int sal_socketpair(int domain, int type, int protocol, int *fds);
|
||||
int sal_closesocket(int socket);
|
||||
int sal_ioctlsocket(int socket, long cmd, void *arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SAL_SOCKET_H__ */
|
||||
68
RT_Thread/components/net/sal/include/sal_tls.h
Normal file
68
RT_Thread/components/net/sal/include/sal_tls.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-11-10 ChenYong First version
|
||||
*/
|
||||
#ifndef __SAL_TLS_H__
|
||||
#define __SAL_TLS_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
/* Protocol level for TLS.
|
||||
* Here, the same socket protocol level for TLS as in Linux was used.
|
||||
*/
|
||||
#define SOL_TLS 282
|
||||
|
||||
/* Socket options for TLS */
|
||||
|
||||
/* Socket option to select TLS credentials to use. */
|
||||
#define TLS_CRET_LIST 1
|
||||
/* Socket option to set select ciphersuites to use. */
|
||||
#define TLS_CIPHERSUITE_LIST 2
|
||||
/* Socket option to set peer verification level for TLS connection. */
|
||||
#define TLS_PEER_VERIFY 3
|
||||
/* Socket option to set role for DTLS connection. */
|
||||
#define TLS_DTLS_ROLE 4
|
||||
|
||||
/* Protocol numbers for TLS protocols */
|
||||
#define PROTOCOL_TLS 256
|
||||
#define PROTOCOL_DTLS 257
|
||||
|
||||
|
||||
struct sal_proto_tls_ops
|
||||
{
|
||||
int (*init)(void);
|
||||
void* (*socket)(int socket);
|
||||
int (*connect)(void *sock);
|
||||
int (*send)(void *sock, const void *data, size_t size);
|
||||
int (*recv)(void *sock, void *mem, size_t len);
|
||||
int (*closesocket)(void *sock);
|
||||
|
||||
int (*set_cret_list)(void *sock, const void *cert, size_t size); /* Set TLS credentials */
|
||||
int (*set_ciphersurite)(void *sock, const void* ciphersurite, size_t size); /* Set select ciphersuites */
|
||||
int (*set_peer_verify)(void *sock, const void* peer_verify, size_t size); /* Set peer verification */
|
||||
int (*set_dtls_role)(void *sock, const void *dtls_role, size_t size); /* Set role for DTLS */
|
||||
};
|
||||
|
||||
struct sal_proto_tls
|
||||
{
|
||||
char name[RT_NAME_MAX]; /* TLS protocol name */
|
||||
const struct sal_proto_tls_ops *ops; /* SAL TLS protocol options */
|
||||
};
|
||||
|
||||
/* SAL TLS protocol register */
|
||||
int sal_proto_tls_register(const struct sal_proto_tls *pt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SAL_TLS_H__ */
|
||||
36
RT_Thread/components/net/sal/include/socket/netdb.h
Normal file
36
RT_Thread/components/net/sal/include/socket/netdb.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2015-02-17 Bernard First version
|
||||
* 2018-05-24 ChenYong Add socket abstraction layer
|
||||
*/
|
||||
|
||||
#ifndef NETDB_H__
|
||||
#define NETDB_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <sal_netdb.h>
|
||||
|
||||
struct hostent *gethostbyname(const char *name);
|
||||
|
||||
int gethostbyname_r(const char *name, struct hostent *ret, char *buf,
|
||||
size_t buflen, struct hostent **result, int *h_errnop);
|
||||
void freeaddrinfo(struct addrinfo *ai);
|
||||
int getaddrinfo(const char *nodename,
|
||||
const char *servname,
|
||||
const struct addrinfo *hints,
|
||||
struct addrinfo **res);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
20
RT_Thread/components/net/sal/include/socket/netinet/in.h
Normal file
20
RT_Thread/components/net/sal/include/socket/netinet/in.h
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2015-02-17 Bernard First version
|
||||
*/
|
||||
|
||||
#ifndef IN_H__
|
||||
#define IN_H__
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#ifndef IN6_IS_ADDR_MULTICAST
|
||||
#define IN6_IS_ADDR_MULTICAST(a) (((uint8_t *) (a))[0] == 0xff)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
16
RT_Thread/components/net/sal/include/socket/netinet/tcp.h
Normal file
16
RT_Thread/components/net/sal/include/socket/netinet/tcp.h
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2015-02-17 Bernard First version
|
||||
*/
|
||||
|
||||
#ifndef TCP_H__
|
||||
#define TCP_H__
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#endif
|
||||
16
RT_Thread/components/net/sal/include/socket/netinet/udp.h
Normal file
16
RT_Thread/components/net/sal/include/socket/netinet/udp.h
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2015-02-17 Bernard First version
|
||||
*/
|
||||
|
||||
#ifndef UDP_H__
|
||||
#define UDP_H__
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2015-02-17 Bernard First version
|
||||
* 2018-05-17 ChenYong Add socket abstraction layer
|
||||
*/
|
||||
|
||||
#ifndef SYS_SOCKET_H_
|
||||
#define SYS_SOCKET_H_
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <sal_socket.h>
|
||||
#ifdef SAL_USING_TLS
|
||||
#include <sal_tls.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef SAL_USING_POSIX
|
||||
int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
|
||||
int bind(int s, const struct sockaddr *name, socklen_t namelen);
|
||||
int shutdown(int s, int how);
|
||||
int getpeername(int s, struct sockaddr *name, socklen_t *namelen);
|
||||
int getsockname(int s, struct sockaddr *name, socklen_t *namelen);
|
||||
int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen);
|
||||
int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen);
|
||||
int connect(int s, const struct sockaddr *name, socklen_t namelen);
|
||||
int listen(int s, int backlog);
|
||||
int recv(int s, void *mem, size_t len, int flags);
|
||||
int recvfrom(int s, void *mem, size_t len, int flags,
|
||||
struct sockaddr *from, socklen_t *fromlen);
|
||||
int recvmsg(int s, struct msghdr *message, int flags);
|
||||
int sendmsg(int s, const struct msghdr *message, int flags);
|
||||
int send(int s, const void *dataptr, size_t size, int flags);
|
||||
int sendto(int s, const void *dataptr, size_t size, int flags,
|
||||
const struct sockaddr *to, socklen_t tolen);
|
||||
int socket(int domain, int type, int protocol);
|
||||
int closesocket(int s);
|
||||
int ioctlsocket(int s, long cmd, void *arg);
|
||||
int socketpair(int domain, int type, int protocol, int *fds);
|
||||
#else
|
||||
#define accept(s, addr, addrlen) sal_accept(s, addr, addrlen)
|
||||
#define bind(s, name, namelen) sal_bind(s, name, namelen)
|
||||
#define shutdown(s, how) sal_shutdown(s, how)
|
||||
#define getpeername(s, name, namelen) sal_getpeername(s, name, namelen)
|
||||
#define getsockname(s, name, namelen) sal_getsockname(s, name, namelen)
|
||||
#define getsockopt(s, level, optname, optval, optlen) sal_getsockopt(s, level, optname, optval, optlen)
|
||||
#define setsockopt(s, level, optname, optval, optlen) sal_setsockopt(s, level, optname, optval, optlen)
|
||||
#define connect(s, name, namelen) sal_connect(s, name, namelen)
|
||||
#define listen(s, backlog) sal_listen(s, backlog)
|
||||
#define recv(s, mem, len, flags) sal_recvfrom(s, mem, len, flags, NULL, NULL)
|
||||
#define recvfrom(s, mem, len, flags, from, fromlen) sal_recvfrom(s, mem, len, flags, from, fromlen)
|
||||
#define recvmsg(s, message, flags) sal_recvmsg(s, message, flags)
|
||||
#define send(s, dataptr, size, flags) sal_sendto(s, dataptr, size, flags, NULL, NULL)
|
||||
#define sendto(s, dataptr, size, flags, to, tolen) sal_sendto(s, dataptr, size, flags, to, tolen)
|
||||
#define sendmsg(s, message, flags) sal_sendmsg(s, message, flags)
|
||||
#define socket(domain, type, protocol) sal_socket(domain, type, protocol)
|
||||
#define socketpair(domain, type, protocol, fds) sal_socketpair(domain, type, protocol, fds)
|
||||
#define closesocket(s) sal_closesocket(s)
|
||||
#define ioctlsocket(s, cmd, arg) sal_ioctlsocket(s, cmd, arg)
|
||||
#endif /* SAL_USING_POSIX */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SYS_SOCKET_H_ */
|
||||
43
RT_Thread/components/net/sal/socket/net_netdb.c
Normal file
43
RT_Thread/components/net/sal/socket/net_netdb.c
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2015-02-17 Bernard First version
|
||||
* 2108-05-24 ChenYong Add socket abstraction layer
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#include <netdb.h>
|
||||
|
||||
struct hostent *gethostbyname(const char *name)
|
||||
{
|
||||
return sal_gethostbyname(name);
|
||||
}
|
||||
RTM_EXPORT(gethostbyname);
|
||||
|
||||
int gethostbyname_r(const char *name, struct hostent *ret, char *buf,
|
||||
size_t buflen, struct hostent **result, int *h_errnop)
|
||||
{
|
||||
return sal_gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
|
||||
}
|
||||
RTM_EXPORT(gethostbyname_r);
|
||||
|
||||
void freeaddrinfo(struct addrinfo *ai)
|
||||
{
|
||||
sal_freeaddrinfo(ai);
|
||||
}
|
||||
RTM_EXPORT(freeaddrinfo);
|
||||
|
||||
int getaddrinfo(const char *nodename,
|
||||
const char *servname,
|
||||
const struct addrinfo *hints,
|
||||
struct addrinfo **res)
|
||||
{
|
||||
return sal_getaddrinfo(nodename, servname, hints, res);
|
||||
}
|
||||
RTM_EXPORT(getaddrinfo);
|
||||
839
RT_Thread/components/net/sal/socket/net_sockets.c
Normal file
839
RT_Thread/components/net/sal/socket/net_sockets.c
Normal file
@ -0,0 +1,839 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2024 RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2015-02-17 Bernard First version
|
||||
* 2018-05-17 ChenYong Add socket abstraction layer
|
||||
*/
|
||||
|
||||
#include <dfs.h>
|
||||
#include <dfs_file.h>
|
||||
#include <poll.h>
|
||||
#include <dfs_net.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
/**
|
||||
* @brief Accepts an incoming connection on a listening socket.
|
||||
*
|
||||
* This function extracts the first connection request from the queue of pending connections for
|
||||
* the listening socket specified by 's' and creates a new socket for the connection.
|
||||
*
|
||||
* @param s The file descriptor of the listening socket. This socket must be created with
|
||||
* 'socket()', bound with 'bind()', and set to listen with 'listen()'.
|
||||
* @param addr A pointer to a 'sockaddr' structure that will receive the address of the connecting entity.
|
||||
* This structure is filled with the address of the client once the connection is accepted.
|
||||
* Can be 'NULL' if the address is not needed.
|
||||
* @param addrlen A pointer to a variable containing the size of 'addr'. When the function returns, this
|
||||
* variable will hold the actual size of the address returned. Can be 'NULL' if 'addr' is 'NULL'.
|
||||
*
|
||||
* @return On success, returns a new file descriptor for the accepted connection. On failure, returns '-1'
|
||||
* and sets errno to indicate the error.
|
||||
*
|
||||
* @note The original socket 's' remains open and continues to listen for additional incoming connections.
|
||||
* The returned file descriptor is used for communication with the connected client.
|
||||
*
|
||||
* @see socket() Creates a socket for accepting connections.
|
||||
* @see bind() Binds the socket to a local address.
|
||||
* @see listen() Sets the socket to listen for incoming connections.
|
||||
* @see close()/closesocket() Closes a socket when it is no longer needed.
|
||||
*/
|
||||
int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
|
||||
{
|
||||
int new_socket = -1;
|
||||
int socket = dfs_net_getsocket(s);
|
||||
|
||||
new_socket = sal_accept(socket, addr, addrlen);
|
||||
if (new_socket != -1)
|
||||
{
|
||||
/* this is a new socket, create it in file system fd */
|
||||
int fd;
|
||||
struct dfs_file *d;
|
||||
|
||||
/* allocate a fd */
|
||||
fd = fd_new();
|
||||
if (fd < 0)
|
||||
{
|
||||
rt_set_errno(-ENOMEM);
|
||||
sal_closesocket(new_socket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
d = fd_get(fd);
|
||||
if(d)
|
||||
{
|
||||
#ifdef RT_USING_DFS_V2
|
||||
d->fops = dfs_net_get_fops();
|
||||
#endif
|
||||
/* this is a socket fd */
|
||||
d->vnode = (struct dfs_vnode *)rt_malloc(sizeof(struct dfs_vnode));
|
||||
if (!d->vnode)
|
||||
{
|
||||
/* release fd */
|
||||
fd_release(fd);
|
||||
rt_set_errno(-ENOMEM);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dfs_vnode_init(d->vnode, FT_SOCKET, dfs_net_get_fops());
|
||||
d->flags = O_RDWR; /* set flags as read and write */
|
||||
|
||||
/* set socket to the data of dfs_file */
|
||||
d->vnode->data = (void *)(size_t)new_socket;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
rt_set_errno(-ENOMEM);
|
||||
sal_closesocket(new_socket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
RTM_EXPORT(accept);
|
||||
|
||||
/**
|
||||
* @brief Binds a socket to a specific local address and port.
|
||||
*
|
||||
* This function assigns a local address to a socket, defined by the 'name' parameter.
|
||||
* The address allows the socket to receive data sent to this address.
|
||||
*
|
||||
* @param s The file descriptor of the socket to bind.
|
||||
* @param name A pointer to a 'sockaddr' structure that specifies the address to bind to.
|
||||
* The structure varies based on the address family, such as 'sockaddr_in' for IPv4.
|
||||
* @param namelen The length of the 'sockaddr' structure pointed to by 'name', in bytes.
|
||||
*
|
||||
* @return Returns '0' on success. On failure, returns '-1' and sets errno to indicate the error.
|
||||
*
|
||||
* @note The socket must be created with 'socket()' before calling 'bind()'.
|
||||
* Binding is typically used for server sockets, specifying the local IP and port to listen on.
|
||||
* If the port is set to '0', the system assigns an available port automatically.
|
||||
*
|
||||
* @see socket() Creates a socket for binding.
|
||||
* @see listen() Prepares the socket to listen for incoming connections after binding.
|
||||
* @see accept() Accepts connections on a bound and listening socket.
|
||||
*/
|
||||
int bind(int s, const struct sockaddr *name, socklen_t namelen)
|
||||
{
|
||||
int socket = dfs_net_getsocket(s);
|
||||
|
||||
return sal_bind(socket, name, namelen);
|
||||
}
|
||||
RTM_EXPORT(bind);
|
||||
|
||||
/**
|
||||
* @brief Shuts down part of a full-duplex connection on a socket.
|
||||
*
|
||||
* This function disables further sends or receives on the specified socket, depending on the value
|
||||
* of the 'how' parameter. It does not close the socket, which must still be closed separately using
|
||||
* 'close()' or 'closesocket()'.
|
||||
*
|
||||
* @param s The file descriptor of the socket to shut down.
|
||||
* @param how Specifies the type of shutdown to perform. The 'how' parameter can be one of the following:
|
||||
* - 'SHUT_RD': Disables further reading on the socket. The socket will not receive data.
|
||||
* - 'SHUT_WR': Disables further writing on the socket. The socket will not send data.
|
||||
* - 'SHUT_RDWR': Disables both reading and writing on the socket. The socket will be fully shut down.
|
||||
*
|
||||
* @return Returns '0' on success. On failure, returns '-1' and sets errno to indicate the error.
|
||||
*
|
||||
* @note The 'shutdown()' function is used to gracefully close a socket in one or both directions
|
||||
* (read/write). It is commonly used in scenarios like closing the write side of a TCP connection
|
||||
* when a server has finished sending data but still expects to receive data.
|
||||
*
|
||||
* @see socket() Creates the socket used for communication.
|
||||
* @see close()/closesocket() Closes the socket after the shutdown is complete.
|
||||
* @see recv() Receives data on a socket.
|
||||
* @see send() Sends data on a socket.
|
||||
*/
|
||||
int shutdown(int s, int how)
|
||||
{
|
||||
int error = 0;
|
||||
int socket = -1;
|
||||
struct dfs_file *d;
|
||||
|
||||
socket = dfs_net_getsocket(s);
|
||||
if (socket < 0)
|
||||
{
|
||||
rt_set_errno(-ENOTSOCK);
|
||||
return -1;
|
||||
}
|
||||
|
||||
d = fd_get(s);
|
||||
if (d == NULL)
|
||||
{
|
||||
rt_set_errno(-EBADF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sal_shutdown(socket, how) == 0)
|
||||
{
|
||||
error = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_set_errno(-ENOTSOCK);
|
||||
error = -1;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
RTM_EXPORT(shutdown);
|
||||
|
||||
/**
|
||||
* @brief Retrieves the address of the peer connected to a socket.
|
||||
*
|
||||
* This function obtains the address of the peer (remote end) connected to the socket 's'.
|
||||
* It is typically used on connected sockets (e.g., TCP) to retrieve information about the peer.
|
||||
*
|
||||
* @param s The file descriptor of the connected socket.
|
||||
* @param name A pointer to a 'sockaddr' structure that will be filled with the address of the peer.
|
||||
* The structure type (e.g., 'sockaddr_in' for IPv4) depends on the address family of the socket.
|
||||
* @param namelen A pointer to a variable that initially specifies the size of the 'name' structure.
|
||||
* On return, it contains the actual size of the address returned.
|
||||
*
|
||||
* @return Returns '0' on success. On failure, returns '-1' and sets errno to indicate the error.
|
||||
*
|
||||
* @note The 'getpeername()' function is useful for retrieving information about the remote end of a connection,
|
||||
* such as the IP address and port of a peer in a TCP connection. This function is only valid for sockets
|
||||
* that are in a connected state.
|
||||
*
|
||||
* @see socket() Creates the socket used for the connection.
|
||||
* @see connect() Connects the socket to a remote address.
|
||||
* @see getsockname() Retrieves the local address of a socket.
|
||||
*/
|
||||
int getpeername(int s, struct sockaddr *name, socklen_t *namelen)
|
||||
{
|
||||
int socket = dfs_net_getsocket(s);
|
||||
|
||||
return sal_getpeername(socket, name, namelen);
|
||||
}
|
||||
RTM_EXPORT(getpeername);
|
||||
|
||||
/**
|
||||
* @brief Retrieves the local address of a socket.
|
||||
*
|
||||
* This function obtains the local address (IP address and port) associated with the socket 's'.
|
||||
* It is typically used to determine the local address and port of a bound or connected socket.
|
||||
*
|
||||
* @param s The file descriptor of the socket.
|
||||
* @param name A pointer to a 'sockaddr' structure that will be filled with the local address
|
||||
* of the socket. The structure type (e.g., 'sockaddr_in' for IPv4) depends on the
|
||||
* address family of the socket.
|
||||
* @param namelen A pointer to a variable that initially specifies the size of the 'name' structure.
|
||||
* Upon return, this variable contains the actual size of the address returned.
|
||||
*
|
||||
* @return Returns '0' on success. On failure, returns '-1' and sets errno to indicate the error.
|
||||
*
|
||||
* @note The 'getsockname()' function is useful for retrieving the local address information of a socket,
|
||||
* which can be especially useful in cases where the socket was bound with an ephemeral port (port 0),
|
||||
* allowing you to discover the actual port number assigned by the system.
|
||||
*
|
||||
* @see socket() Creates the socket for communication.
|
||||
* @see bind() Binds the socket to a specific local address.
|
||||
* @see getpeername() Retrieves the address of the peer connected to a socket.
|
||||
*/
|
||||
int getsockname(int s, struct sockaddr *name, socklen_t *namelen)
|
||||
{
|
||||
int socket = dfs_net_getsocket(s);
|
||||
|
||||
return sal_getsockname(socket, name, namelen);
|
||||
}
|
||||
RTM_EXPORT(getsockname);
|
||||
|
||||
/**
|
||||
* @brief Retrieves options for a socket.
|
||||
*
|
||||
* This function retrieves the current value for a specified option on a socket, identified
|
||||
* by the file descriptor 's'. The option is specified by the 'level' and 'optname' parameters.
|
||||
*
|
||||
* @param s The file descriptor of the socket from which to retrieve the option.
|
||||
* @param level The protocol level at which the option resides. Common levels include:
|
||||
* - 'SOL_SOCKET': To retrieve socket-level options.
|
||||
* - 'IPPROTO_IP': To retrieve IPv4 options.
|
||||
* - 'IPPROTO_TCP': To retrieve TCP options.
|
||||
* @param optname The name of the option to retrieve. Some common options include:
|
||||
* - 'SO_REUSEADDR': Checks if address reuse is enabled.
|
||||
* - 'SO_RCVBUF': Retrieves the receive buffer size.
|
||||
* - 'TCP_NODELAY': Checks if Nagle's algorithm is disabled for TCP sockets.
|
||||
* @param optval A pointer to a buffer where the value of the option will be stored.
|
||||
* The buffer must be large enough to hold the option value.
|
||||
* @param optlen A pointer to a variable that initially specifies the size of 'optval'.
|
||||
* On return, it contains the actual size of the option value returned.
|
||||
*
|
||||
* @return Returns '0' on success. On failure, returns '-1' and sets errno to indicate the error.
|
||||
*
|
||||
* @note The 'getsockopt()' function is useful for inspecting socket configuration and current settings.
|
||||
* It can provide information about options such as buffer sizes, timeouts, and protocol-specific features.
|
||||
*
|
||||
* @see socket() Creates the socket to retrieve options from.
|
||||
* @see setsockopt() Sets options for the socket.
|
||||
*/
|
||||
int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
|
||||
{
|
||||
int socket = dfs_net_getsocket(s);
|
||||
|
||||
return sal_getsockopt(socket, level, optname, optval, optlen);
|
||||
}
|
||||
RTM_EXPORT(getsockopt);
|
||||
|
||||
/**
|
||||
* @brief Sets options on a socket.
|
||||
*
|
||||
* This function sets the specified option for the socket referenced by the file descriptor 's'.
|
||||
* Socket options affect the behavior of the socket and are specified by the 'level' and 'optname' parameters.
|
||||
*
|
||||
* @param s The file descriptor of the socket on which to set the option.
|
||||
* @param level The protocol level at which the option resides. Common levels include:
|
||||
* - 'SOL_SOCKET': To configure socket-level options.
|
||||
* - 'IPPROTO_IP': To configure IPv4 options.
|
||||
* - 'IPPROTO_TCP': To configure TCP options.
|
||||
* @param optname The name of the option to set. Some common options include:
|
||||
* - 'SO_REUSEADDR': Allows reuse of local addresses.
|
||||
* - 'SO_RCVBUF': Sets the receive buffer size.
|
||||
* - 'TCP_NODELAY': Disables Nagle's algorithm for TCP sockets.
|
||||
* @param optval A pointer to the buffer containing the value to set for the specified option.
|
||||
* The type of data in this buffer depends on the option being set.
|
||||
* @param optlen The size, in bytes, of the option value pointed to by 'optval'.
|
||||
*
|
||||
* @return Returns '0' on success. On failure, returns '-1' and sets errno to indicate the error.
|
||||
*
|
||||
* @note The 'setsockopt()' function is useful for configuring various socket behaviors, such as
|
||||
* setting timeouts, buffer sizes, and enabling or disabling certain protocol features.
|
||||
* The changes may affect socket performance and resource usage.
|
||||
*
|
||||
* @see socket() Creates the socket to configure.
|
||||
* @see getsockopt() Retrieves options set on the socket.
|
||||
* @see bind() Binds the socket to a local address.
|
||||
*/
|
||||
int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
|
||||
{
|
||||
int socket = dfs_net_getsocket(s);
|
||||
|
||||
return sal_setsockopt(socket, level, optname, optval, optlen);
|
||||
}
|
||||
RTM_EXPORT(setsockopt);
|
||||
|
||||
/**
|
||||
* @brief Initiates a connection on a socket.
|
||||
*
|
||||
* This function connects the socket specified by 's' to the server address specified by 'name'.
|
||||
* The socket must have been created with 'socket()' and, for some types of sockets, may need
|
||||
* to be bound to a local address with 'bind()' before calling 'connect()'.
|
||||
*
|
||||
* @param s The file descriptor of the socket to connect.
|
||||
* @param name A pointer to a 'sockaddr' structure that specifies the address of the server to connect to.
|
||||
* The specific structure (e.g., 'sockaddr_in' for IPv4) depends on the address family.
|
||||
* @param namelen The length, in bytes, of the address structure pointed to by 'name'.
|
||||
*
|
||||
* @return Returns '0' on success. On failure, returns '-1' and sets errno to indicate the error.
|
||||
*
|
||||
* @note 'connect()' is typically used by client sockets to establish a connection with a server.
|
||||
* For connection-oriented protocols (e.g., TCP), this initiates the connection handshake.
|
||||
* For connectionless protocols (e.g., UDP), it defines a fixed peer address.
|
||||
*
|
||||
* @see socket() Creates the socket to be connected.
|
||||
* @see bind() Binds the socket to a local address (optional for client sockets).
|
||||
* @see accept() Used by server sockets to accept incoming connections.
|
||||
* @see close()/closesocket() Closes the socket when done.
|
||||
*/
|
||||
int connect(int s, const struct sockaddr *name, socklen_t namelen)
|
||||
{
|
||||
int socket = dfs_net_getsocket(s);
|
||||
return sal_connect(socket, name, namelen);
|
||||
}
|
||||
RTM_EXPORT(connect);
|
||||
|
||||
/**
|
||||
* @brief Marks a socket as a passive socket, ready to accept incoming connections.
|
||||
*
|
||||
* This function prepares a socket to accept incoming connection requests. The socket
|
||||
* must first be created with 'socket()' and bound to a local address with 'bind()'.
|
||||
*
|
||||
* @param s The file descriptor of the socket to set to listening mode.
|
||||
* @param backlog The maximum number of pending connections that can be queued for acceptance.
|
||||
* If more incoming connections arrive than the backlog limit, they may be rejected
|
||||
* or ignored until the server accepts some of the pending connections.
|
||||
*
|
||||
* @return Returns '0' on success. On failure, returns '-1' and sets errno to indicate the error.
|
||||
*
|
||||
* @note After calling 'listen()', the socket can be used with 'accept()' to handle connection requests.
|
||||
* The backlog size affects how many connections can wait to be accepted before being rejected.
|
||||
*
|
||||
* @see socket() Creates the socket.
|
||||
* @see bind() Binds the socket to a specific address.
|
||||
* @see accept() Accepts a pending connection request on the listening socket.
|
||||
*/
|
||||
int listen(int s, int backlog)
|
||||
{
|
||||
int socket = dfs_net_getsocket(s);
|
||||
|
||||
return sal_listen(socket, backlog);
|
||||
}
|
||||
RTM_EXPORT(listen);
|
||||
|
||||
/**
|
||||
* @brief Receives data from a connected socket.
|
||||
*
|
||||
* This function reads data from a connected socket and stores it in the specified buffer.
|
||||
* It is typically used with connection-oriented protocols (e.g., TCP).
|
||||
*
|
||||
* @param s The file descriptor of the connected socket to receive data from.
|
||||
* @param mem A pointer to the buffer where the received data will be stored.
|
||||
* @param len The maximum number of bytes to read into the buffer.
|
||||
* @param flags Specifies the behavior of the receive operation. Common flags include:
|
||||
* - '0': Default operation.
|
||||
* - 'MSG_DONTWAIT': Non-blocking operation.
|
||||
* - 'MSG_PEEK': Peeks at the incoming data without removing it from the queue.
|
||||
*
|
||||
* @return Returns the number of bytes received on success. On failure, returns '-1' and sets errno to indicate the error.
|
||||
* A return value of '0' indicates that the connection has been closed by the remote peer.
|
||||
*
|
||||
* @note The 'recv()' function may not receive all the requested bytes in a single call.
|
||||
* Multiple calls to 'recv()' may be needed to read the complete data.
|
||||
*
|
||||
* @see socket() Creates the socket to be used for receiving data.
|
||||
* @see connect() Connects the socket to a remote address (for connection-oriented protocols).
|
||||
* @see recvfrom() Receives data from a specific address, typically used with connectionless sockets.
|
||||
* @see send() Sends data on a connected socket.
|
||||
*/
|
||||
int recv(int s, void *mem, size_t len, int flags)
|
||||
{
|
||||
int socket = dfs_net_getsocket(s);
|
||||
|
||||
return sal_recvfrom(socket, mem, len, flags, NULL, NULL);
|
||||
}
|
||||
RTM_EXPORT(recv);
|
||||
|
||||
/**
|
||||
* @brief Sends a message on a socket.
|
||||
*
|
||||
* The 'sendmsg()' function sends data on the socket 's' using the structured data in the 'msghdr'
|
||||
* structure. This function is commonly used for sending complex messages with multiple buffers,
|
||||
* control information, or for working with datagram sockets.
|
||||
*
|
||||
* @param s The file descriptor of the socket to send the message on.
|
||||
* @param message A pointer to an 'msghdr' structure, which contains the data, address, and control information:
|
||||
* - 'msg_name': Optional destination address (used for connectionless sockets).
|
||||
* - 'msg_namelen': Size of the destination address.
|
||||
* - 'msg_iov': An array of 'iovec' structures that point to the data buffers to be sent.
|
||||
* - 'msg_iovlen': The number of elements in the 'msg_iov' array.
|
||||
* - 'msg_control': Optional ancillary data, such as file descriptors for UNIX domain sockets.
|
||||
* - 'msg_controllen': The size of the ancillary data buffer.
|
||||
* - 'msg_flags': Flags related to the message.
|
||||
* @param flags Specifies how the message should be sent. Common flags include:
|
||||
* - 'MSG_DONTWAIT': Sends the message in non-blocking mode.
|
||||
* - 'MSG_EOR': Indicates the end of a record (for record-oriented sockets).
|
||||
*
|
||||
* @return Returns the number of bytes sent on success. On failure, returns '-1' and sets errno to indicate the error.
|
||||
*
|
||||
* @note The 'sendmsg()' function is useful for sending messages with multiple buffers or ancillary data,
|
||||
* allowing flexible communication options such as attaching file descriptors. This function can be
|
||||
* used with both connection-oriented and connectionless sockets.
|
||||
*
|
||||
* @see recvmsg() Receives a message from a socket.
|
||||
* @see send() Sends data on a socket.
|
||||
* @see socket() Creates the socket to use with 'sendmsg()'.
|
||||
*/
|
||||
int sendmsg(int s, const struct msghdr *message, int flags)
|
||||
{
|
||||
int socket = dfs_net_getsocket(s);
|
||||
|
||||
return sal_sendmsg(socket, message, flags);
|
||||
}
|
||||
RTM_EXPORT(sendmsg);
|
||||
|
||||
/**
|
||||
* @brief Receives a message from a socket.
|
||||
*
|
||||
* The 'recvmsg()' function receives data from the socket 's' into the buffers described by
|
||||
* the 'msghdr' structure. This function allows for complex data structures, including multiple
|
||||
* data buffers and optional control information.
|
||||
*
|
||||
* @param s The file descriptor of the socket to receive data from.
|
||||
* @param message A pointer to an 'msghdr' structure, which will be filled with the received data and
|
||||
* information. The structure contains:
|
||||
* - 'msg_name': A buffer for the source address (used for connectionless sockets).
|
||||
* - 'msg_namelen': Specifies the size of the 'msg_name' buffer.
|
||||
* - 'msg_iov': An array of 'iovec' structures that point to the buffers to store received data.
|
||||
* - 'msg_iovlen': The number of elements in the 'msg_iov' array.
|
||||
* - 'msg_control': A buffer for ancillary data, such as received file descriptors.
|
||||
* - 'msg_controllen': The size of the ancillary data buffer.
|
||||
* - 'msg_flags': Flags set by the 'recvmsg()' call to indicate the message status.
|
||||
* @param flags Specifies how the message should be received. Common flags include:
|
||||
* - 'MSG_DONTWAIT': Receives the message in non-blocking mode.
|
||||
* - 'MSG_PEEK': Peeks at the incoming message without removing it from the queue.
|
||||
* - 'MSG_WAITALL': Waits for the full amount of data to be received.
|
||||
*
|
||||
* @return Returns the number of bytes received on success. On failure, returns '-1' and sets errno to indicate the error.
|
||||
*
|
||||
* @note The 'recvmsg()' function is useful for receiving messages with multiple buffers or ancillary data.
|
||||
* It can be used with both connection-oriented and connectionless sockets, making it versatile for
|
||||
* different communication needs.
|
||||
*
|
||||
* @see sendmsg() Sends a message on a socket.
|
||||
* @see recv() Receives data on a socket.
|
||||
* @see socket() Creates the socket used with 'recvmsg()'.
|
||||
*/
|
||||
int recvmsg(int s, struct msghdr *message, int flags)
|
||||
{
|
||||
int socket = dfs_net_getsocket(s);
|
||||
|
||||
return sal_recvmsg(socket, message, flags);
|
||||
}
|
||||
RTM_EXPORT(recvmsg);
|
||||
|
||||
/**
|
||||
* @brief Receives data from a specific address using an unconnected socket.
|
||||
*
|
||||
* This function reads data from a socket and stores it in the specified buffer. It is commonly used
|
||||
* with connectionless protocols (e.g., UDP) to receive data from a specific source address.
|
||||
*
|
||||
* @param s The file descriptor of the socket to receive data from.
|
||||
* @param mem A pointer to the buffer where the received data will be stored.
|
||||
* @param len The maximum number of bytes to read into the buffer.
|
||||
* @param flags Specifies the behavior of the receive operation. Common flags include:
|
||||
* - '0': Default operation.
|
||||
* - 'MSG_DONTWAIT': Non-blocking operation.
|
||||
* - 'MSG_PEEK': Peeks at the incoming data without removing it from the queue.
|
||||
* @param from A pointer to a 'sockaddr' structure that will be filled with the address of the
|
||||
* sending entity. This is the source address from which the data was received.
|
||||
* @param fromlen A pointer to a variable that initially contains the size of the 'from' structure.
|
||||
* Upon return, this variable will hold the actual size of the address returned.
|
||||
*
|
||||
* @return Returns the number of bytes received on success. On failure, returns '-1' and sets errno to indicate the error.
|
||||
* A return value of '0' indicates that the connection has been closed by the remote peer.
|
||||
*
|
||||
* @note The 'recvfrom()' function is useful for receiving data from an arbitrary source address,
|
||||
* which makes it especially suited for connectionless protocols where the peer's address may vary.
|
||||
* The 'from' parameter is filled with the sender's address, which can be useful for identifying
|
||||
* the origin of the data.
|
||||
*
|
||||
* @see socket() Creates the socket used for receiving data.
|
||||
* @see sendto() Sends data to a specific address, typically used with connectionless sockets.
|
||||
* @see recv() Receives data on a connected socket.
|
||||
*/
|
||||
int recvfrom(int s, void *mem, size_t len, int flags,
|
||||
struct sockaddr *from, socklen_t *fromlen)
|
||||
{
|
||||
int socket = dfs_net_getsocket(s);
|
||||
|
||||
return sal_recvfrom(socket, mem, len, flags, from, fromlen);
|
||||
}
|
||||
RTM_EXPORT(recvfrom);
|
||||
|
||||
/**
|
||||
* @brief Sends data on a connected socket.
|
||||
*
|
||||
* This function sends data to a connected socket, specified by the file descriptor 's'.
|
||||
* It is typically used with connection-oriented protocols (e.g., TCP).
|
||||
*
|
||||
* @param s The file descriptor of the socket to send data on.
|
||||
* The socket must be connected to a remote peer.
|
||||
* @param dataptr A pointer to the buffer containing the data to send.
|
||||
* @param size The size, in bytes, of the data to be sent from the buffer.
|
||||
* @param flags Specifies the behavior of the send operation. Common flags include:
|
||||
* - '0': Default operation.
|
||||
* - 'MSG_DONTWAIT': Non-blocking operation.
|
||||
* - 'MSG_NOSIGNAL': Prevents the sending of 'SIGPIPE' on errors.
|
||||
*
|
||||
* @return Returns the number of bytes sent on success. On failure, returns '-1' and sets errno to indicate the error.
|
||||
* If the connection is closed by the remote peer, the return value may be '0'.
|
||||
*
|
||||
* @note The 'send()' function does not guarantee that all data will be sent in a single call.
|
||||
* If fewer bytes are sent than requested, the remaining data should be sent in subsequent calls.
|
||||
*
|
||||
* @see socket() Creates the socket to be used for sending data.
|
||||
* @see connect() Connects the socket to a remote address (for connection-oriented protocols).
|
||||
* @see sendto() Sends data to a specific address, typically used with connectionless sockets.
|
||||
* @see recv() Receives data from a connected socket.
|
||||
*/
|
||||
int send(int s, const void *dataptr, size_t size, int flags)
|
||||
{
|
||||
int socket = dfs_net_getsocket(s);
|
||||
|
||||
return sal_sendto(socket, dataptr, size, flags, NULL, 0);
|
||||
}
|
||||
RTM_EXPORT(send);
|
||||
|
||||
/**
|
||||
* @brief Sends data to a specific address using an unconnected socket.
|
||||
*
|
||||
* This function is typically used with connectionless protocols (e.g., UDP) to send data
|
||||
* to a specific destination address, as specified by 'to'.
|
||||
*
|
||||
* @param s The file descriptor of the socket to send data on.
|
||||
* @param dataptr A pointer to the buffer containing the data to be sent.
|
||||
* @param size The size, in bytes, of the data to be sent from the buffer.
|
||||
* @param flags Specifies the behavior of the send operation. Common flags include:
|
||||
* - '0': Default operation.
|
||||
* - 'MSG_DONTWAIT': Non-blocking operation.
|
||||
* - 'MSG_NOSIGNAL': Prevents the sending of 'SIGPIPE' on errors.
|
||||
* @param to A pointer to a 'sockaddr' structure that specifies the destination address.
|
||||
* The structure type (e.g., 'sockaddr_in' for IPv4) depends on the address family.
|
||||
* @param tolen The length, in bytes, of the address structure pointed to by 'to'.
|
||||
*
|
||||
* @return Returns the number of bytes sent on success. On failure, returns '-1' and sets errno to indicate the error.
|
||||
*
|
||||
* @note Unlike 'send()', 'sendto()' can specify a target address for each message, allowing it to be used
|
||||
* for both connected and unconnected sockets. In connectionless protocols, 'sendto()' is commonly
|
||||
* used without prior calls to 'connect()'.
|
||||
*
|
||||
* @see socket() Creates the socket used for sending data.
|
||||
* @see recvfrom() Receives data from a specific address, typically used with connectionless sockets.
|
||||
* @see connect() Optional for connection-oriented protocols.
|
||||
* @see send() Sends data on a connected socket.
|
||||
*/
|
||||
int sendto(int s, const void *dataptr, size_t size, int flags,
|
||||
const struct sockaddr *to, socklen_t tolen)
|
||||
{
|
||||
int socket = dfs_net_getsocket(s);
|
||||
|
||||
return sal_sendto(socket, dataptr, size, flags, to, tolen);
|
||||
}
|
||||
RTM_EXPORT(sendto);
|
||||
|
||||
/**
|
||||
* @brief Creates a network socket.
|
||||
*
|
||||
* This function creates a socket and returns a file descriptor that can be used for network communication.
|
||||
*
|
||||
* @param domain The communication protocol family (address family) that defines the socket's protocol.
|
||||
* Common values include:
|
||||
* - 'AF_INET': IPv4
|
||||
* - 'AF_INET6': IPv6
|
||||
* - 'AF_UNIX': Local communication (inter-process communication on the same machine)
|
||||
* - 'AF_AT': AT socket
|
||||
* - 'AF_WIZ': WIZnet
|
||||
* @param type The type of socket, which determines the characteristics of data transmission.
|
||||
* Common values include:
|
||||
* - 'SOCK_STREAM': Connection-oriented byte stream communication (e.g., TCP)
|
||||
* - 'SOCK_DGRAM': Connectionless datagram communication (e.g., UDP)
|
||||
* - 'SOCK_RAW': Provides raw network protocol access
|
||||
* @param protocol Specifies the protocol to be used with the socket. It is usually set to '0',
|
||||
* which allows the system to choose the default protocol:
|
||||
* - For 'SOCK_STREAM', the default is TCP.
|
||||
* - For 'SOCK_DGRAM', the default is UDP.
|
||||
*
|
||||
* @return On success, returns a file descriptor (a non-negative integer) representing the socket.
|
||||
* On failure, returns '-1' and sets errno to indicate the error.
|
||||
*
|
||||
* @note The created socket can be used for binding, listening, receiving, and sending data.
|
||||
*
|
||||
* @see bind() Used to bind the socket to a local address.
|
||||
* @see listen() Used to set the socket to listen for incoming connections.
|
||||
* @see accept() Used to accept incoming connection requests.
|
||||
* @see connect() Used to connect to a remote host.
|
||||
*/
|
||||
int socket(int domain, int type, int protocol)
|
||||
{
|
||||
/* create a BSD socket */
|
||||
int fd;
|
||||
int socket;
|
||||
struct dfs_file *d;
|
||||
|
||||
/* allocate a fd */
|
||||
fd = fd_new();
|
||||
if (fd < 0)
|
||||
{
|
||||
rt_set_errno(-ENOMEM);
|
||||
|
||||
return -1;
|
||||
}
|
||||
d = fd_get(fd);
|
||||
|
||||
#ifdef RT_USING_DFS_V2
|
||||
d->fops = dfs_net_get_fops();
|
||||
#endif
|
||||
|
||||
d->vnode = (struct dfs_vnode *)rt_malloc(sizeof(struct dfs_vnode));
|
||||
if (!d->vnode)
|
||||
{
|
||||
/* release fd */
|
||||
fd_release(fd);
|
||||
rt_set_errno(-ENOMEM);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* create socket and then put it to the dfs_file */
|
||||
socket = sal_socket(domain, type, protocol);
|
||||
if (socket >= 0)
|
||||
{
|
||||
dfs_vnode_init(d->vnode, FT_SOCKET, dfs_net_get_fops());
|
||||
d->flags = O_RDWR; /* set flags as read and write */
|
||||
|
||||
/* set socket to the data of dfs_file */
|
||||
d->vnode->data = (void *)(size_t)socket;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* release fd */
|
||||
fd_release(fd);
|
||||
rt_set_errno(-ENOMEM);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
RTM_EXPORT(socket);
|
||||
|
||||
/**
|
||||
* @brief Closes a socket.
|
||||
*
|
||||
* This function closes the socket specified by the file descriptor 's'. Once closed, the socket
|
||||
* can no longer be used for communication. Any pending data that has not been transmitted may be lost.
|
||||
*
|
||||
* @param s The file descriptor of the socket to close.
|
||||
*
|
||||
* @return Returns '0' on success. On failure, returns '-1' and sets errno to indicate the error.
|
||||
*
|
||||
* @note After calling 'closesocket()', the socket descriptor becomes invalid. The socket cannot
|
||||
* be used for further communication or operations. It is important to close sockets when they are no longer needed
|
||||
* to release system resources.
|
||||
*
|
||||
* @see socket() Creates a socket.
|
||||
* @see shutdown() Shuts down the socket for reading and/or writing, without closing it.
|
||||
* @see recv() Receives data from a socket.
|
||||
* @see send() Sends data on a socket.
|
||||
*/
|
||||
int closesocket(int s)
|
||||
{
|
||||
int error = 0;
|
||||
int socket = -1;
|
||||
struct dfs_file *d;
|
||||
|
||||
socket = dfs_net_getsocket(s);
|
||||
if (socket < 0)
|
||||
{
|
||||
rt_set_errno(-ENOTSOCK);
|
||||
return -1;
|
||||
}
|
||||
|
||||
d = fd_get(s);
|
||||
if (d == RT_NULL)
|
||||
{
|
||||
rt_set_errno(-EBADF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!d->vnode)
|
||||
{
|
||||
rt_set_errno(-EBADF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sal_closesocket(socket) == 0)
|
||||
{
|
||||
error = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_set_errno(-ENOTSOCK);
|
||||
error = -1;
|
||||
}
|
||||
|
||||
/* socket has been closed, delete it from file system fd */
|
||||
fd_release(s);
|
||||
|
||||
return error;
|
||||
}
|
||||
RTM_EXPORT(closesocket);
|
||||
|
||||
/**
|
||||
* @brief Creates a pair of connected sockets.
|
||||
*
|
||||
* The 'socketpair()' function creates two connected sockets, which can be used for bidirectional
|
||||
* communication between processes or threads on the same machine. This is commonly used for inter-process
|
||||
* communication (IPC) in UNIX-like operating systems.
|
||||
*
|
||||
* @param domain The communication domain (or protocol family). Typically, 'AF_UNIX' (or 'AF_LOCAL')
|
||||
* is used to create sockets for local communication.
|
||||
* @param type The type of socket to be created. Common values include:
|
||||
* - 'SOCK_STREAM': Provides reliable, connection-oriented communication.
|
||||
* - 'SOCK_DGRAM': Provides connectionless, unreliable communication.
|
||||
* @param protocol The protocol to be used with the sockets. Normally set to '0' to use the default protocol
|
||||
* for the specified 'domain' and 'type'.
|
||||
* @param fds An array of two integers where the file descriptors for the two connected sockets will be stored.
|
||||
* After a successful call, 'fds[0]' and 'fds[1]' represent the two ends of the socket pair.
|
||||
*
|
||||
* @return Returns '0' on success. On failure, returns '-1' and sets 'errno' to indicate the error.
|
||||
*
|
||||
* @note The 'socketpair()' function is commonly used to create a communication channel between two processes
|
||||
* (parent and child after 'fork()') or two threads. Data written to one socket is available for reading
|
||||
* from the other. It is primarily supported on UNIX-like systems and may not be available on Windows.
|
||||
*
|
||||
* @see socket() Creates a single socket for network communication.
|
||||
* @see pipe() Creates an unidirectional communication channel between processes.
|
||||
*/
|
||||
int socketpair(int domain, int type, int protocol, int *fds)
|
||||
{
|
||||
rt_err_t ret = 0;
|
||||
int sock_fds[2];
|
||||
|
||||
fds[0] = socket(domain, type, protocol);
|
||||
if (fds[0] < 0)
|
||||
{
|
||||
fds[0] = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
fds[1] = socket(domain, type, protocol);
|
||||
if (fds[1] < 0)
|
||||
{
|
||||
closesocket(fds[0]);
|
||||
fds[0] = 0;
|
||||
fds[1] = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
sock_fds[0] = dfs_net_getsocket(fds[0]);
|
||||
sock_fds[1] = dfs_net_getsocket(fds[1]);
|
||||
|
||||
ret = sal_socketpair(domain, type, protocol, sock_fds);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
closesocket(fds[0]);
|
||||
closesocket(fds[1]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
RTM_EXPORT(socketpair);
|
||||
|
||||
/**
|
||||
* @brief Controls socket I/O modes.
|
||||
*
|
||||
* The 'ioctlsocket()' function manipulates the I/O mode of the socket specified by the file descriptor 's'.
|
||||
* It is primarily used to enable or disable non-blocking mode on a socket or to perform other socket-specific
|
||||
* operations.
|
||||
*
|
||||
* @param s The file descriptor of the socket to control.
|
||||
* @param cmd The command that specifies the operation to perform. Some common commands include:
|
||||
* - 'FIONBIO': Enables or disables non-blocking mode. Setting 'arg' to a non-zero value
|
||||
* enables non-blocking mode; setting it to zero disables it.
|
||||
* - 'FIONREAD': Retrieves the number of bytes available to read, storing the result in 'arg'.
|
||||
* @param arg A pointer to an argument for the command. The type and meaning of this argument depend on the
|
||||
* specified command ('cmd'). For example, in non-blocking mode ('FIONBIO'), it points to a 'long'
|
||||
* that is either non-zero (to enable) or zero (to disable) non-blocking mode.
|
||||
*
|
||||
* @return Returns '0' on success. On failure, returns '-1' and sets errno (or 'WSAGetLastError()' on Windows) to indicate the error.
|
||||
*
|
||||
* @note This function is specific to Windows environments and is a part of the Winsock API. It performs
|
||||
* similar functionality to the 'fcntl()' function on UNIX-like systems.
|
||||
* The 'ioctlsocket()' function allows for various socket manipulations that affect how the socket
|
||||
* operates in certain conditions, such as setting it to non-blocking mode.
|
||||
*
|
||||
* @see socket() Creates a socket to use with 'ioctlsocket()'.
|
||||
* @see fcntl() Performs similar operations on UNIX-like systems.
|
||||
*/
|
||||
int ioctlsocket(int s, long cmd, void *arg)
|
||||
{
|
||||
int socket = dfs_net_getsocket(s);
|
||||
|
||||
return sal_ioctlsocket(socket, cmd, arg);
|
||||
}
|
||||
RTM_EXPORT(ioctlsocket);
|
||||
1626
RT_Thread/components/net/sal/src/sal_socket.c
Normal file
1626
RT_Thread/components/net/sal/src/sal_socket.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user