1 /*
2  * Copyright (c) 2006-2024 RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2018-06-06     chenYong     first version
9  * 2022-06-02     xianxistu    add implement about "AT server"
10  */
11 
12 #ifndef __AT_SOCKET_H__
13 #define __AT_SOCKET_H__
14 
15 #include <rtthread.h>
16 #include <rtdevice.h>
17 #include <rthw.h>
18 
19 #include <netdb.h>
20 #include <sys/socket.h>
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 #ifndef AT_SOCKET_RECV_BFSZ
27 #define AT_SOCKET_RECV_BFSZ            512
28 #endif
29 
30 #define AT_DEFAULT_RECVMBOX_SIZE       10
31 #define AT_DEFAULT_ACCEPTMBOX_SIZE     10
32 
33 /* sal socket magic word */
34 #define AT_SOCKET_MAGIC                0xA100
35 
36 #ifdef AT_USING_SOCKET_SERVER
37 #define AT_SOCKET_INFO_LEN (sizeof("SOCKET:") + 4)
38 #endif
39 
40 /* Current state of the AT socket. */
41 enum at_socket_state
42 {
43     AT_SOCKET_NONE,
44     AT_SOCKET_OPEN,
45     AT_SOCKET_LISTEN,
46     AT_SOCKET_CONNECT,
47     AT_SOCKET_CLOSED
48 };
49 
50 enum at_socket_type
51 {
52     AT_SOCKET_INVALID   = 0,
53     AT_SOCKET_TCP       = 0x10,      /* TCP IPv4 */
54     AT_SOCKET_UDP       = 0x20,      /* UDP IPv4 */
55 };
56 
57 typedef enum
58 {
59     AT_SOCKET_EVT_RECV,
60     AT_SOCKET_EVT_CLOSED,
61 #ifdef AT_USING_SOCKET_SERVER
62     AT_SOCKET_EVT_CONNECTED,
63 #endif
64 } at_socket_evt_t;
65 
66 struct at_socket;
67 struct at_device;
68 
69 typedef void (*at_evt_cb_t)(struct at_socket *socket, at_socket_evt_t event, const char *buff, size_t bfsz);
70 
71 /* A callback prototype to inform about events for AT socket */
72 typedef void (* at_socket_callback)(struct at_socket *conn, int event, uint16_t len);
73 
74 /* AT socket operations function */
75 struct at_socket_ops
76 {
77     int (*at_connect)(struct at_socket *socket, char *ip, int32_t port, enum at_socket_type type, rt_bool_t is_client);
78     int (*at_closesocket)(struct at_socket *socket);
79     int (*at_send)(struct at_socket *socket, const char *buff, size_t bfsz, enum at_socket_type type);
80     int (*at_domain_resolve)(const char *name, char ip[16]);
81     void (*at_set_event_cb)(at_socket_evt_t event, at_evt_cb_t cb);
82     int (*at_socket)(struct at_device *device, enum at_socket_type type);
83 #ifdef AT_USING_SOCKET_SERVER
84     int (*at_listen)(struct at_socket *socket, int backlog);
85 #endif
86 };
87 
88 /* AT receive package list structure */
89 struct at_recv_pkt
90 {
91     rt_slist_t list;
92     size_t bfsz_totle;
93     size_t bfsz_index;
94     char *buff;
95 };
96 typedef struct at_recv_pkt *at_recv_pkt_t;
97 
98 #ifdef AT_USING_SOCKET_SERVER
99 struct at_listen_state
100 {
101     uint16_t is_listen;
102     uint16_t port;
103 };
104 #endif
105 
106 struct at_socket
107 {
108     /* AT socket magic word */
109     uint32_t magic;
110 
111     int socket;
112 #ifdef AT_USING_SOCKET_SERVER
113     struct at_listen_state listen;
114 #endif
115 
116     /* device releated information for the socket */
117     void *device;
118     /* type of the AT socket (TCP, UDP or RAW) */
119     enum at_socket_type type;
120     /* current state of the AT socket */
121     enum at_socket_state state;
122     /* sockets operations */
123     const struct at_socket_ops *ops;
124     /* receive semaphore, received data release semaphore */
125     rt_sem_t recv_notice;
126     rt_mutex_t recv_lock;
127     rt_slist_t recvpkt_list;
128 
129     /* timeout to wait for send or received data in milliseconds */
130     int32_t recv_timeout;
131     int32_t send_timeout;
132     /* A callback function that is informed about events for this AT socket */
133     at_socket_callback callback;
134 
135     /* number of times data was received, set by event_callback() */
136     uint16_t rcvevent;
137     /* number of times data was ACKed (free send buffer), set by event_callback() */
138     uint16_t sendevent;
139     /* error happened for this socket, set by event_callback() */
140     uint16_t errevent;
141     /* Last UDP connect address */
142     struct sockaddr last_udp_adr;
143 
144 #ifdef SAL_USING_POSIX
145     rt_wqueue_t wait_head;
146 #endif
147     rt_slist_t list;
148 
149     /* user-specific data */
150     void *user_data;
151 };
152 
153 int at_socket(int domain, int type, int protocol);
154 int at_closesocket(int socket);
155 int at_shutdown(int socket, int how);
156 int at_bind(int socket, const struct sockaddr *name, socklen_t namelen);
157 #ifdef AT_USING_SOCKET_SERVER
158 int at_listen(int socket, int backlog);
159 #endif
160 int at_connect(int socket, const struct sockaddr *name, socklen_t namelen);
161 #ifdef AT_USING_SOCKET_SERVER
162 int at_accept(int socket, struct sockaddr *name, socklen_t *namelen);
163 #endif
164 int at_sendto(int socket, const void *data, size_t size, int flags, const struct sockaddr *to, socklen_t tolen);
165 int at_send(int socket, const void *data, size_t size, int flags);
166 int at_recvfrom(int socket, void *mem, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);
167 int at_recv(int socket, void *mem, size_t len, int flags);
168 int at_getsockopt(int socket, int level, int optname, void *optval, socklen_t *optlen);
169 int at_setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen);
170 struct hostent *at_gethostbyname(const char *name);
171 int at_gethostbyname_r(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop);
172 int at_getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res);
173 void at_freeaddrinfo(struct addrinfo *ai);
174 
175 struct at_socket *at_get_socket(int socket);
176 #ifdef AT_USING_SOCKET_SERVER
177 struct at_socket *at_get_base_socket(int base_socket);
178 #endif
179 
180 #ifndef RT_USING_SAL
181 
182 #define socket(domain, type, protocol)                      at_socket(domain, type, protocol)
183 #define closesocket(socket)                                 at_closesocket(socket)
184 #define shutdown(socket, how)                               at_shutdown(socket, how)
185 #define bind(socket, name, namelen)                         at_bind(socket, name, namelen)
186 #define connect(socket, name, namelen)                      at_connect(socket, name, namelen)
187 #define sendto(socket, data, size, flags, to, tolen)        at_sendto(socket, data, size, flags, to, tolen)
188 #define send(socket, data, size, flags)                     at_send(socket, data, size, flags)
189 #define recvfrom(socket, mem, len, flags, from, fromlen)    at_recvfrom(socket, mem, len, flags, from, fromlen)
190 #define getsockopt(socket, level, optname, optval, optlen)  at_getsockopt(socket, level, optname, optval, optlen)
191 #define setsockopt(socket, level, optname, optval, optlen)  at_setsockopt(socket, level, optname, optval, optlen)
192 
193 #define gethostbyname(name)                                 at_gethostbyname(name)
194 #define getaddrinfo(nodename, servname, hints, res)         at_getaddrinfo(nodename, servname, hints, res)
195 #define freeaddrinfo(ai)                                    at_freeaddrinfo(ai)
196 
197 #endif /* RT_USING_SAL */
198 
199 #ifdef __cplusplus
200 }
201 #endif
202 
203 #endif /* AT_SOCKET_H__ */
204