gwenhywfar 5.12.0
endpoint_tcpd.c
Go to the documentation of this file.
1/****************************************************************************
2 * This file is part of the project Gwenhywfar.
3 * Gwenhywfar (c) by 2023 Martin Preuss, all rights reserved.
4 *
5 * The license for this file can be found in the file COPYING which you
6 * should have received along with this file.
7 ****************************************************************************/
8
9#ifdef HAVE_CONFIG_H
10# include <config.h>
11#endif
12
13/*#define DISABLE_DEBUGLOG*/
14
15
16#include "./endpoint_tcpd_p.h"
17
18#include <gwenhywfar/debug.h>
19
20
21
22#define GWEN_MSG_ENDPOINT_TCPD_NAME "tcpcserver"
23#define GWEN_MSG_ENDPOINT_TCPD_BACKLOG 10
24
25
26
27
28/* ------------------------------------------------------------------------------------------------
29 * forward declarations
30 * ------------------------------------------------------------------------------------------------
31 */
32
33static void GWENHYWFAR_CB _freeData(void *bp, void *p);
34
35static void _addSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet);
36static void _checkSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet);
37
38static int _startListen(GWEN_MSG_ENDPOINT *ep);
40static GWEN_INETADDRESS *_createAndSetupAddress(const char *host, int port);
41
42
43
44/* ------------------------------------------------------------------------------------------------
45 * implementations
46 * ------------------------------------------------------------------------------------------------
47 */
48
49
50
51GWEN_INHERIT(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_TCPD)
52
53
54
55
56
57GWEN_MSG_ENDPOINT *GWEN_TcpdEndpoint_new(const char *host, int port, const char *name, int groupId)
58{
60 GWEN_ENDPOINT_TCPD *xep;
61
64
65 GWEN_NEW_OBJECT(GWEN_ENDPOINT_TCPD, xep);
66 GWEN_INHERIT_SETDATA(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_TCPD, ep, xep, _freeData);
67 xep->host=host?strdup(host):NULL;
68 xep->port=port;
69
72
73 return ep;
74}
75
76
77
78void GWENHYWFAR_CB _freeData(GWEN_UNUSED void *bp, void *p)
79{
80 GWEN_ENDPOINT_TCPD *xep;
81
82 xep=(GWEN_ENDPOINT_TCPD*) p;
83 free(xep->host);
85}
86
87
88
89
91{
92 if (ep) {
93 GWEN_ENDPOINT_TCPD *xep;
94
95 xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_TCPD, ep);
96 if (xep) {
97 xep->acceptFn=f;
98 xep->acceptData=data;
99 }
100 }
101}
102
103
104
106{
107 if (ep) {
109 int rv;
110
111 /* connect, set state */
112 rv=_startListen(ep);
113 if (rv<0) {
114 DBG_INFO(GWEN_LOGDOMAIN, "Endpoint %s: Error on listen (%d)", GWEN_MsgEndpoint_GetName(ep), rv);
115 return rv;
116 }
117 DBG_INFO(GWEN_LOGDOMAIN, "Endpoint %s: Now listening", GWEN_MsgEndpoint_GetName(ep));
119 }
120 else {
121 DBG_ERROR(GWEN_LOGDOMAIN, "Endpoint %s: Not unconnected", GWEN_MsgEndpoint_GetName(ep));
122 }
123 }
124 else {
125 DBG_ERROR(GWEN_LOGDOMAIN, "No endpoint");
126 }
127 return GWEN_ERROR_GENERIC;
128}
129
130
131
133{
134
136 int rv;
137
138 DBG_INFO(GWEN_LOGDOMAIN, "Endpoint %s: Starting to listen", GWEN_MsgEndpoint_GetName(ep));
139 rv=_startListen(ep);
140 if (rv<0) {
141 DBG_INFO(GWEN_LOGDOMAIN, "Endpoint %s: Error on listen (%d)", GWEN_MsgEndpoint_GetName(ep), rv);
142 }
143 else {
144 DBG_INFO(GWEN_LOGDOMAIN, "Endpoint %s: Now listening", GWEN_MsgEndpoint_GetName(ep));
146 }
147 }
148
151 }
152
153 GWEN_MsgEndpoint_ChildrenAddSockets(ep, readSet, writeSet, xSet);
154}
155
156
157
159{
160 if (ep) {
161 GWEN_ENDPOINT_TCPD *xep;
162
163 xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_TCPD, ep);
164 if (xep) {
165 GWEN_SOCKET *sk;
166
168 if (sk && GWEN_SocketSet_HasSocket(readSet, sk)) {
169 GWEN_INETADDRESS *incomingAddress=NULL;
170 GWEN_SOCKET *incomingSocket=NULL;
171 int rv;
172
173 /* accept incoming connection */
174 rv=GWEN_Socket_Accept(sk, &incomingAddress, &incomingSocket);
175 if (rv<0) {
176 DBG_INFO(GWEN_LOGDOMAIN, "Endpoint %s: Error on accept (%d)", GWEN_MsgEndpoint_GetName(ep), rv);
177 }
178 else {
179 char addrBuffer[16];
180
181 GWEN_InetAddr_GetAddress(incomingAddress, addrBuffer, sizeof(addrBuffer));
183 "Endpoint %s: Incoming connection from %s:%d",
185 addrBuffer,
186 GWEN_InetAddr_GetPort(incomingAddress));
187 if (xep->acceptFn) {
188 GWEN_MSG_ENDPOINT *incomingEp;
189
190 incomingEp=xep->acceptFn(ep, incomingSocket, incomingAddress, xep->acceptData);
191 if (incomingEp) {
192 DBG_INFO(GWEN_LOGDOMAIN, "Endpoint %s: Incoming connection accepted, adding", GWEN_MsgEndpoint_GetName(ep));
194 GWEN_MsgEndpoint_Tree2_AddChild(ep, incomingEp);
195 }
196 else {
197 DBG_INFO(GWEN_LOGDOMAIN, "Endpoint %s: Error accepting incoming connection", GWEN_MsgEndpoint_GetName(ep));
198 GWEN_Socket_free(incomingSocket);
199 }
200 }
201 else {
202 DBG_INFO(GWEN_LOGDOMAIN, "Endpoint %s: function \"acceptFn\" not set", GWEN_MsgEndpoint_GetName(ep));
203 GWEN_Socket_free(incomingSocket);
204 }
205 }
206 GWEN_InetAddr_free(incomingAddress);
207 }
208 }
209 }
210
211 GWEN_MsgEndpoint_ChildrenCheckSockets(ep, readSet, writeSet, xSet);
212}
213
214
215
217{
218 GWEN_ENDPOINT_TCPD *xep;
219
220 DBG_INFO(GWEN_LOGDOMAIN, "Starting to listen");
221 xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_TCPD, ep);
222 if (xep) {
223 GWEN_INETADDRESS *addr;
224 GWEN_SOCKET *sk;
225 int rv;
226
227 addr=_createAndSetupAddress(xep->host, xep->port);
228 if (addr==NULL) {
229 DBG_INFO(GWEN_LOGDOMAIN, "here");
230 return GWEN_ERROR_GENERIC;
231 }
232
234 if (sk==NULL) {
235 DBG_INFO(GWEN_LOGDOMAIN, "here");
236 GWEN_InetAddr_free(addr);
237 return GWEN_ERROR_GENERIC;
238 }
239
240 rv=GWEN_Socket_Bind(sk, addr);
241 if (rv<0) {
242 if (rv!=GWEN_ERROR_IN_PROGRESS) {
243 DBG_INFO(GWEN_LOGDOMAIN, "Error on bind(\"%s\", %d): %d", xep->host, xep->port, rv);
245 GWEN_InetAddr_free(addr);
246 return rv;
247 }
248 }
249 GWEN_InetAddr_free(addr);
250
252 if (rv<0) {
253 if (rv!=GWEN_ERROR_IN_PROGRESS) {
254 DBG_INFO(GWEN_LOGDOMAIN, "Error on listen(\"%s\", %d): %d", xep->host, xep->port, rv);
256 return rv;
257 }
258 }
259
261 return rv;
262 }
263 return GWEN_ERROR_GENERIC;
264}
265
266
267
269{
270 GWEN_SOCKET *sk;
271 int rv;
272
274
275 rv=GWEN_Socket_Open(sk);
276 if (rv<0) {
277 DBG_INFO(GWEN_LOGDOMAIN, "Error opening socket: %d", rv);
279 return NULL;
280 }
281
283 if (rv<0) {
284 DBG_INFO(GWEN_LOGDOMAIN, "Error setting up address reuse on socket: %d", rv);
286 return NULL;
287 }
288
289 rv=GWEN_Socket_SetBlocking(sk, 0);
290 if (rv<0) {
291 DBG_INFO(GWEN_LOGDOMAIN, "Error setting socket nonblocking: %d", rv);
293 return NULL;
294 }
295 return sk;
296}
297
298
299
300GWEN_INETADDRESS *_createAndSetupAddress(const char *host, int port)
301{
302 GWEN_INETADDRESS *addr;
303 int rv;
304
306 rv=GWEN_InetAddr_SetAddress(addr, host);
307 if (rv<0)
308 rv=GWEN_InetAddr_SetName(addr, host);
309 if (rv<0) {
310 DBG_INFO(GWEN_LOGDOMAIN, "Error setting host \"%s\": %d", host, rv);
311 GWEN_InetAddr_free(addr);
312 return NULL;
313 }
314 rv=GWEN_InetAddr_SetPort(addr, port);
315 if (rv<0) {
316 DBG_INFO(GWEN_LOGDOMAIN, "Error setting port \"%d\": %d", port, rv);
317 GWEN_InetAddr_free(addr);
318 return NULL;
319 }
320
321 return addr;
322}
323
324
325
326
327
328
329
330
331
332
333
334
#define NULL
Definition binreloc.c:300
#define DBG_INFO(dbg_logger, format,...)
Definition debug.h:181
#define DBG_ERROR(dbg_logger, format,...)
Definition debug.h:97
GWEN_MSG_ENDPOINT * GWEN_MsgEndpoint_new(const char *name, int groupId)
Definition endpoint.c:31
void GWEN_MsgEndpoint_ChildrenCheckSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
Definition endpoint.c:321
void GWEN_MsgEndpoint_ChildrenAddSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
Definition endpoint.c:305
void GWEN_MsgEndpoint_SetState(GWEN_MSG_ENDPOINT *ep, int m)
Definition endpoint.c:131
GWEN_SOCKET * GWEN_MsgEndpoint_GetSocket(const GWEN_MSG_ENDPOINT *ep)
Definition endpoint.c:104
int GWEN_MsgEndpoint_GetState(const GWEN_MSG_ENDPOINT *ep)
Definition endpoint.c:124
GWEN_MSG_ENDPOINT_ADDSOCKETS_FN GWEN_MsgEndpoint_SetAddSocketsFn(GWEN_MSG_ENDPOINT *ep, GWEN_MSG_ENDPOINT_ADDSOCKETS_FN fn)
Definition endpoint.c:504
const char * GWEN_MsgEndpoint_GetName(const GWEN_MSG_ENDPOINT *ep)
Definition endpoint.c:90
void GWEN_MsgEndpoint_SetSocket(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKET *sk)
Definition endpoint.c:111
GWEN_MSG_ENDPOINT_CHECKSOCKETS_FN GWEN_MsgEndpoint_SetCheckSocketsFn(GWEN_MSG_ENDPOINT *ep, GWEN_MSG_ENDPOINT_CHECKSOCKETS_FN fn)
Definition endpoint.c:518
struct GWEN_MSG_ENDPOINT GWEN_MSG_ENDPOINT
Object which can send and receive messages (base class).
Definition endpoint.h:37
#define GWEN_MSG_ENDPOINT_STATE_UNCONNECTED
Definition endpoint.h:23
#define GWEN_MSG_ENDPOINT_STATE_CONNECTED
Definition endpoint.h:25
static void _addSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_UNUSED GWEN_SOCKETSET *xSet)
static void _checkSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
GWEN_MSG_ENDPOINT * GWEN_TcpdEndpoint_new(const char *host, int port, const char *name, int groupId)
static GWEN_INETADDRESS * _createAndSetupAddress(const char *host, int port)
void GWEN_TcpdEndpoint_SetAcceptFn(GWEN_MSG_ENDPOINT *ep, GWEN_ENDPOINT_TCPD_ACCEPT_FN f, void *data)
static GWEN_SOCKET * _createAndSetupSocket(void)
static int _startListen(GWEN_MSG_ENDPOINT *ep)
static void GWENHYWFAR_CB _freeData(void *bp, void *p)
int GWEN_TcpdEndpoint_StartListening(GWEN_MSG_ENDPOINT *ep)
static void _checkSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
static void _addSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
#define GWEN_MSG_ENDPOINT_TCPD_NAME
#define GWEN_MSG_ENDPOINT_TCPD_BACKLOG
GWEN_MSG_ENDPOINT *(* GWEN_ENDPOINT_TCPD_ACCEPT_FN)(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKET *sk, const GWEN_INETADDRESS *addr, void *data)
#define GWEN_ERROR_GENERIC
Definition error.h:62
#define GWEN_ERROR_IN_PROGRESS
Definition error.h:72
@ GWEN_SocketTypeTCP
Definition inetsocket.h:80
GWENHYWFAR_API void GWEN_Socket_free(GWEN_SOCKET *sp)
GWENHYWFAR_API int GWEN_Socket_Open(GWEN_SOCKET *sp)
GWENHYWFAR_API GWEN_SOCKET * GWEN_Socket_new(GWEN_SOCKETTYPE socketType)
GWENHYWFAR_API int GWEN_SocketSet_HasSocket(GWEN_SOCKETSET *ssp, const GWEN_SOCKET *sp)
GWENHYWFAR_API int GWEN_SocketSet_AddSocket(GWEN_SOCKETSET *ssp, const GWEN_SOCKET *sp)
GWENHYWFAR_API int GWEN_Socket_Accept(GWEN_SOCKET *sp, GWEN_INETADDRESS **addr, GWEN_SOCKET **newsock)
GWENHYWFAR_API int GWEN_Socket_Bind(GWEN_SOCKET *sp, const GWEN_INETADDRESS *addr)
GWENHYWFAR_API int GWEN_Socket_SetBlocking(GWEN_SOCKET *sp, int fl)
GWENHYWFAR_API int GWEN_Socket_SetReuseAddress(GWEN_SOCKET *sp, int fl)
GWENHYWFAR_API int GWEN_Socket_Listen(GWEN_SOCKET *sp, int backlog)
#define GWEN_UNUSED
#define GWENHYWFAR_CB
GWENHYWFAR_API void GWEN_InetAddr_free(GWEN_INETADDRESS *ia)
struct GWEN_INETADDRESSSTRUCT GWEN_INETADDRESS
Definition inetaddr.h:95
GWENHYWFAR_API int GWEN_InetAddr_GetAddress(const GWEN_INETADDRESS *ia, char *buffer, unsigned int bsize)
GWENHYWFAR_API int GWEN_InetAddr_SetPort(GWEN_INETADDRESS *ia, int port)
GWENHYWFAR_API GWEN_INETADDRESS * GWEN_InetAddr_new(GWEN_AddressFamily af)
@ GWEN_AddressFamilyIP
Definition inetaddr.h:85
GWENHYWFAR_API int GWEN_InetAddr_SetAddress(GWEN_INETADDRESS *ia, const char *addr)
GWENHYWFAR_API int GWEN_InetAddr_GetPort(const GWEN_INETADDRESS *ia)
GWENHYWFAR_API int GWEN_InetAddr_SetName(GWEN_INETADDRESS *ia, const char *name)
struct GWEN_SOCKETSETSTRUCT GWEN_SOCKETSET
Definition inetsocket.h:41
struct GWEN_SOCKET GWEN_SOCKET
Definition inetsocket.h:40
#define GWEN_INHERIT_SETDATA(bt, t, element, data, fn)
Definition inherit.h:300
#define GWEN_INHERIT(bt, t)
Definition inherit.h:264
#define GWEN_INHERIT_GETDATA(bt, t, element)
Definition inherit.h:279
#define GWEN_LOGDOMAIN
Definition logger.h:35
#define GWEN_FREE_OBJECT(varname)
Definition memory.h:61
#define GWEN_NEW_OBJECT(typ, varname)
Definition memory.h:55
static void GWENHYWFAR_CB _freeData(GWEN_UNUSED void *bp, void *p)
Definition nogui.c:222