gwenhywfar  5.14.1
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 
33 static void GWENHYWFAR_CB _freeData(void *bp, void *p);
34 
35 static void _addSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet);
36 static void _checkSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet);
37 
38 static int _startListen(GWEN_MSG_ENDPOINT *ep);
40 static GWEN_INETADDRESS *_createAndSetupAddress(const char *host, int port);
41 
42 
43 
44 /* ------------------------------------------------------------------------------------------------
45  * implementations
46  * ------------------------------------------------------------------------------------------------
47  */
48 
49 
50 
51 GWEN_INHERIT(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_TCPD)
52 
53 
54 
55 
56 
57 GWEN_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 
78 void 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);
84  GWEN_FREE_OBJECT(xep);
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);
244  GWEN_Socket_free(sk);
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);
255  GWEN_Socket_free(sk);
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);
278  GWEN_Socket_free(sk);
279  return NULL;
280  }
281 
282  rv=GWEN_Socket_SetReuseAddress(sk, 1);
283  if (rv<0) {
284  DBG_INFO(GWEN_LOGDOMAIN, "Error setting up address reuse on socket: %d", rv);
285  GWEN_Socket_free(sk);
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);
292  GWEN_Socket_free(sk);
293  return NULL;
294  }
295  return sk;
296 }
297 
298 
299 
300 GWEN_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 GWEN_MSG_ENDPOINT_STATE_UNCONNECTED
Definition: endpoint.h:23
GWEN_SOCKET * GWEN_MsgEndpoint_GetSocket(const GWEN_MSG_ENDPOINT *ep)
Definition: endpoint.c:104
#define DBG_ERROR(dbg_logger, format,...)
Definition: debug.h:97
GWEN_MSG_ENDPOINT * GWEN_TcpdEndpoint_new(const char *host, int port, const char *name, int groupId)
Definition: endpoint_tcpd.c:57
struct GWEN_MSG_ENDPOINT GWEN_MSG_ENDPOINT
Object which can send and receive messages (base class).
Definition: endpoint.h:37
int GWEN_TcpdEndpoint_StartListening(GWEN_MSG_ENDPOINT *ep)
GWENHYWFAR_API int GWEN_Socket_Accept(GWEN_SOCKET *sp, GWEN_INETADDRESS **addr, GWEN_SOCKET **newsock)
#define GWEN_FREE_OBJECT(varname)
Definition: memory.h:61
#define NULL
Definition: binreloc.c:300
GWENHYWFAR_API void GWEN_InetAddr_free(GWEN_INETADDRESS *ia)
GWENHYWFAR_API GWEN_INETADDRESS * GWEN_InetAddr_new(GWEN_AddressFamily af)
#define GWEN_MSG_ENDPOINT_STATE_CONNECTED
Definition: endpoint.h:25
struct GWEN_SOCKETSETSTRUCT GWEN_SOCKETSET
Definition: inetsocket.h:45
static void _checkSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
GWENHYWFAR_API int GWEN_Socket_Open(GWEN_SOCKET *sp)
#define GWEN_LOGDOMAIN
Definition: logger.h:32
GWENHYWFAR_API int GWEN_Socket_SetBlocking(GWEN_SOCKET *sp, int fl)
GWENHYWFAR_API int GWEN_Socket_SetReuseAddress(GWEN_SOCKET *sp, int fl)
GWEN_MSG_ENDPOINT * GWEN_MsgEndpoint_new(const char *name, int groupId)
Definition: endpoint.c:31
static GWEN_SOCKET * _createAndSetupSocket(void)
void GWEN_MsgEndpoint_SetSocket(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKET *sk)
Definition: endpoint.c:111
#define GWEN_NEW_OBJECT(typ, varname)
Definition: memory.h:55
#define GWEN_ERROR_IN_PROGRESS
Definition: error.h:72
#define GWENHYWFAR_CB
Definition: gwenhywfarapi.h:89
int GWEN_MsgEndpoint_GetState(const GWEN_MSG_ENDPOINT *ep)
Definition: endpoint.c:124
#define GWEN_ERROR_GENERIC
Definition: error.h:62
struct GWEN_INETADDRESSSTRUCT GWEN_INETADDRESS
Definition: inetaddr.h:95
GWENHYWFAR_API int GWEN_SocketSet_AddSocket(GWEN_SOCKETSET *ssp, const GWEN_SOCKET *sp)
GWENHYWFAR_API int GWEN_InetAddr_SetName(GWEN_INETADDRESS *ia, const char *name)
static void _addSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
GWENHYWFAR_API GWEN_SOCKET * GWEN_Socket_new(GWEN_SOCKETTYPE socketType)
GWENHYWFAR_API int GWEN_InetAddr_GetPort(const GWEN_INETADDRESS *ia)
static GWEN_INETADDRESS * _createAndSetupAddress(const char *host, int port)
GWENHYWFAR_API int GWEN_InetAddr_SetAddress(GWEN_INETADDRESS *ia, const char *addr)
void GWEN_TcpdEndpoint_SetAcceptFn(GWEN_MSG_ENDPOINT *ep, GWEN_ENDPOINT_TCPD_ACCEPT_FN f, void *data)
Definition: endpoint_tcpd.c:90
#define GWEN_MSG_ENDPOINT_TCPD_BACKLOG
Definition: endpoint_tcpd.c:23
GWENHYWFAR_API int GWEN_Socket_Bind(GWEN_SOCKET *sp, const GWEN_INETADDRESS *addr)
static void GWENHYWFAR_CB _freeData(void *bp, void *p)
void GWEN_MsgEndpoint_ChildrenCheckSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
Definition: endpoint.c:321
struct GWEN_SOCKET GWEN_SOCKET
Definition: inetsocket.h:44
GWENHYWFAR_API int GWEN_Socket_Listen(GWEN_SOCKET *sp, int backlog)
GWENHYWFAR_API int GWEN_SocketSet_HasSocket(GWEN_SOCKETSET *ssp, const GWEN_SOCKET *sp)
#define GWEN_INHERIT(bt, t)
Definition: inherit.h:264
void GWEN_MsgEndpoint_SetState(GWEN_MSG_ENDPOINT *ep, int m)
Definition: endpoint.c:131
#define DBG_INFO(dbg_logger, format,...)
Definition: debug.h:181
GWEN_MSG_ENDPOINT *(* GWEN_ENDPOINT_TCPD_ACCEPT_FN)(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKET *sk, const GWEN_INETADDRESS *addr, void *data)
Definition: endpoint_tcpd.h:24
const char * GWEN_MsgEndpoint_GetName(const GWEN_MSG_ENDPOINT *ep)
Definition: endpoint.c:90
void GWEN_MsgEndpoint_ChildrenAddSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
Definition: endpoint.c:305
GWEN_MSG_ENDPOINT_CHECKSOCKETS_FN GWEN_MsgEndpoint_SetCheckSocketsFn(GWEN_MSG_ENDPOINT *ep, GWEN_MSG_ENDPOINT_CHECKSOCKETS_FN fn)
Definition: endpoint.c:518
#define GWEN_MSG_ENDPOINT_TCPD_NAME
Definition: endpoint_tcpd.c:22
#define GWEN_INHERIT_SETDATA(bt, t, element, data, fn)
Definition: inherit.h:300
static int _startListen(GWEN_MSG_ENDPOINT *ep)
GWENHYWFAR_API int GWEN_InetAddr_GetAddress(const GWEN_INETADDRESS *ia, char *buffer, unsigned int bsize)
GWENHYWFAR_API void GWEN_Socket_free(GWEN_SOCKET *sp)
#define GWEN_UNUSED
GWEN_MSG_ENDPOINT_ADDSOCKETS_FN GWEN_MsgEndpoint_SetAddSocketsFn(GWEN_MSG_ENDPOINT *ep, GWEN_MSG_ENDPOINT_ADDSOCKETS_FN fn)
Definition: endpoint.c:504
#define GWEN_INHERIT_GETDATA(bt, t, element)
Definition: inherit.h:279
GWENHYWFAR_API int GWEN_InetAddr_SetPort(GWEN_INETADDRESS *ia, int port)