gwenhywfar  5.14.1
endpoint_multilayer.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_multilayer_p.h"
17 
18 #include <gwenhywfar/endpoint.h>
19 #include <gwenhywfar/debug.h>
20 #include <gwenhywfar/inherit.h>
21 
22 
23 #define GWEN_ENDPOINT_MULTILAYER_NAME "multilayer"
24 #define GWEN_ENDPOINT_MULTILAYER_DEFAULT_RECONNECT_TIME 5
25 #define GWEN_ENDPOINT_MULTILAYER_DEFAULT_CONNECT_TIMEOUT 10
26 
27 
28 GWEN_INHERIT(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_MULTILAYER);
29 
30 
31 /* ------------------------------------------------------------------------------------------------
32  * forward declarations
33  * ------------------------------------------------------------------------------------------------
34  */
35 
36 static void GWENHYWFAR_CB _freeData(void *bp, void *p);
37 
38 static void _addSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_UNUSED GWEN_SOCKETSET *xSet);
39 static void _checkSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet);
40 static int _startConnect(GWEN_MSG_ENDPOINT *ep);
41 static void _moveMessagesBetweenLists(GWEN_MSG_LIST *srcList, GWEN_MSG_LIST *dstList);
42 
45  GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet);
47  GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet);
48 
50  GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet);
52  GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet);
53 
54 
55 
56 /* ------------------------------------------------------------------------------------------------
57  * implementations
58  * ------------------------------------------------------------------------------------------------
59  */
60 
61 
62 
63 GWEN_MSG_ENDPOINT *GWEN_MultilayerEndpoint_new(const char *name, int groupId)
64 {
66  GWEN_ENDPOINT_MULTILAYER *xep;
67 
69  GWEN_NEW_OBJECT(GWEN_ENDPOINT_MULTILAYER, xep);
70  GWEN_INHERIT_SETDATA(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_MULTILAYER, ep, xep, _freeData);
71 
74 
75  xep->reconnectTimeInSeconds=GWEN_ENDPOINT_MULTILAYER_DEFAULT_RECONNECT_TIME;
76  xep->connectTimeoutInSeconds=GWEN_ENDPOINT_MULTILAYER_DEFAULT_CONNECT_TIMEOUT;
77 
78  return ep;
79 }
80 
81 
82 
83 void GWENHYWFAR_CB _freeData(GWEN_UNUSED void *bp, void *p)
84 {
85  GWEN_ENDPOINT_MULTILAYER *xep;
86 
87  xep=(GWEN_ENDPOINT_MULTILAYER*) p;
88  GWEN_FREE_OBJECT(xep);
89 }
90 
91 
92 
94 {
95  if (ep) {
96  GWEN_ENDPOINT_MULTILAYER *xep;
97 
98  xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_MULTILAYER, ep);
99  if (xep)
100  return xep->reconnectTimeInSeconds;
101  }
103 }
104 
105 
106 
108 {
109  if (ep) {
110  GWEN_ENDPOINT_MULTILAYER *xep;
111 
112  xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_MULTILAYER, ep);
113  if (xep)
114  xep->reconnectTimeInSeconds=i;
115  }
116 }
117 
118 
119 
121 {
122  if (ep) {
123  GWEN_ENDPOINT_MULTILAYER *xep;
124 
125  xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_MULTILAYER, ep);
126  if (xep)
127  return xep->connectTimeoutInSeconds;
128  }
130 }
131 
132 
133 
135 {
136  if (ep) {
137  GWEN_ENDPOINT_MULTILAYER *xep;
138 
139  xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_MULTILAYER, ep);
140  if (xep)
141  xep->connectTimeoutInSeconds=i;
142  }
143 }
144 
145 
146 
148 {
149  if (ep) {
150  GWEN_ENDPOINT_MULTILAYER *xep;
151 
152  xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_MULTILAYER, ep);
153  if (xep)
154  return xep->stage;
155  }
156  return 0;
157 }
158 
159 
160 
162 {
163  if (ep) {
164  GWEN_ENDPOINT_MULTILAYER *xep;
165 
166  xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_MULTILAYER, ep);
167  if (xep)
168  xep->stage=i;
169  }
170 }
171 
172 
173 
176 {
177  if (ep) {
178  GWEN_ENDPOINT_MULTILAYER *xep;
179 
180  xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_MULTILAYER, ep);
181  if (xep) {
183 
184  oldFn=xep->startConnectFn;
185  xep->startConnectFn=fn;
186  return oldFn;
187  }
188  }
189 
190  return NULL;
191 }
192 
193 
194 
197 {
198  if (ep) {
199  GWEN_ENDPOINT_MULTILAYER *xep;
200 
201  xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_MULTILAYER, ep);
202  if (xep) {
204 
205  oldFn=xep->checkSocketsFn;
206  xep->checkSocketsFn=fn;
207  return oldFn;
208  }
209  }
210 
211  return NULL;
212 }
213 
214 
215 
217 {
218  if (ep) {
220  int rv;
221 
222  /* connect, set state */
223  rv=_startConnect(ep);
224  if (rv<0 && rv!=GWEN_ERROR_IN_PROGRESS) {
225  DBG_INFO(GWEN_LOGDOMAIN, "Endpoint %s: Error connecting (%d)", GWEN_MsgEndpoint_GetName(ep), rv);
227  }
228  else {
229  DBG_INFO(GWEN_LOGDOMAIN, "Endpoint %s: Connecting.", GWEN_MsgEndpoint_GetName(ep));
231  }
232  return rv;
233  }
234  else {
235  DBG_ERROR(GWEN_LOGDOMAIN, "Endpoint %s: Not unconnected", GWEN_MsgEndpoint_GetName(ep));
236  }
237  }
238  else {
239  DBG_ERROR(GWEN_LOGDOMAIN, "No endpoint");
240  }
241  return GWEN_ERROR_GENERIC;
242 }
243 
244 
245 
247 {
248  if (ep) {
249  GWEN_MSG_ENDPOINT *epChild;
250 
251  epChild=GWEN_MsgEndpoint_Tree2_GetFirstChild(ep);
252  if (epChild) {
255  else {
257  DBG_ERROR(GWEN_LOGDOMAIN, "Error on tcp layer, disconnecting");
260  }
261  else {
263  _addSocketsWhenConnecting(ep, epChild, readSet, writeSet, xSet);
265  _addSocketsWhenConnected(ep, epChild, readSet, writeSet, xSet);
266  }
267  }
268  } /* if (epChild) */
269  } /* if (ep) */
270 }
271 
272 
273 
275 {
276  DBG_DEBUG(GWEN_LOGDOMAIN, "Checking sockets in state %d", GWEN_MsgEndpoint_GetState(ep));
277  if (ep) {
278  GWEN_MSG_ENDPOINT *epChild;
279 
280  epChild=GWEN_MsgEndpoint_Tree2_GetFirstChild(ep);
281  if (epChild) {
283  /* nothing to do here */
284  } /* if GWEN_MSG_ENDPOINT_STATE_UNCONNECTED */
285  else {
287  DBG_ERROR(GWEN_LOGDOMAIN, "Error on tcp layer, disconnecting");
290  }
291  else {
293  _checkSocketsWhenConnecting(ep, epChild, readSet, writeSet, xSet);
295  _checkSocketsWhenConnected(ep, epChild, readSet, writeSet, xSet);
296  }
297  }
298  }
299  }
300 }
301 
302 
303 
305 {
306  time_t now;
307 
308  now=time(NULL);
310  int rv;
311 
312  /* (re)connect, set state */
313  DBG_INFO(GWEN_LOGDOMAIN, "Starting to (re-)connect");
315  if (rv<0 && rv!=GWEN_ERROR_IN_PROGRESS) {
316  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
317  }
318  }
319 }
320 
321 
322 
324  GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
325 {
326  time_t now;
327 
328  now=time(NULL);
331  DBG_ERROR(GWEN_LOGDOMAIN, "Timeout on connect");
334  }
335  else
336  GWEN_MsgEndpoint_AddSockets(epChild, readSet, writeSet, xSet);
337 }
338 
339 
340 
342  GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
343 {
345  DBG_ERROR(GWEN_LOGDOMAIN, "Error on tcp layer, disconnecting");
348  }
349  else {
350  /* move to-send messages to child */
352  GWEN_MsgEndpoint_AddSockets(epChild, readSet, writeSet, xSet);
353  }
354 }
355 
356 
357 
359  GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
360 {
363  GWEN_MsgEndpoint_CheckSockets(epChild, readSet, writeSet, xSet);
365 }
366 
367 
368 
370 {
371  GWEN_MSG *msg;
372 
373  while( (msg=GWEN_Msg_List_First(srcList)) ) {
374  GWEN_Msg_List_Del(msg);
375  GWEN_Msg_List_Add(msg, dstList);
376  }
377 }
378 
379 
380 
381 
382 
384 {
385  GWEN_MSG_ENDPOINT *epChild;
386 
387  epChild=GWEN_MsgEndpoint_Tree2_GetFirstChild(ep);
388  if (epChild) {
389  GWEN_ENDPOINT_MULTILAYER *xep;
390 
391  xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_MULTILAYER, ep);
392  if (xep) {
393  if (xep->startConnectFn)
394  return xep->startConnectFn(ep, epChild);
395  }
396  }
397  return GWEN_ERROR_GENERIC;
398 }
399 
400 
401 
403  GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
404 {
405  GWEN_ENDPOINT_MULTILAYER *xep;
406 
407  GWEN_MsgEndpoint_CheckSockets(epChild, readSet, writeSet, xSet); /* let base layer work */
408 
409  xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_MULTILAYER, ep);
410  if (xep) {
411  if (xep->checkSocketsFn)
412  xep->checkSocketsFn(ep, epChild, readSet, writeSet, xSet);
413  }
414 }
415 
416 
#define GWEN_MSG_ENDPOINT_STATE_UNCONNECTED
Definition: endpoint.h:23
#define DBG_ERROR(dbg_logger, format,...)
Definition: debug.h:97
GWEN_ENDPOINT_MULTILAYER_CHECKSOCKETS_FN GWEN_MultilayerEndpoint_SetCheckSocketsFn(GWEN_MSG_ENDPOINT *ep, GWEN_ENDPOINT_MULTILAYER_CHECKSOCKETS_FN fn)
#define GWEN_MSG_ENDPOINT_STATE_CONNECTING
Definition: endpoint.h:24
int GWEN_MultilayerEndpoint_GetStage(const GWEN_MSG_ENDPOINT *ep)
static void _checkSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
struct GWEN_MSG_ENDPOINT GWEN_MSG_ENDPOINT
Object which can send and receive messages (base class).
Definition: endpoint.h:37
#define DBG_DEBUG(dbg_logger, format,...)
Definition: debug.h:214
GWEN_MSG_ENDPOINT * GWEN_MultilayerEndpoint_new(const char *name, int groupId)
void GWEN_MsgEndpoint_AddSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
Definition: endpoint.c:289
#define GWEN_FREE_OBJECT(varname)
Definition: memory.h:61
#define NULL
Definition: binreloc.c:300
static void _checkForNeedToReconnect(GWEN_MSG_ENDPOINT *ep)
GWEN_INHERIT(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_MULTILAYER)
#define GWEN_MSG_ENDPOINT_STATE_CONNECTED
Definition: endpoint.h:25
struct GWEN_SOCKETSETSTRUCT GWEN_SOCKETSET
Definition: inetsocket.h:45
#define GWEN_ENDPOINT_MULTILAYER_DEFAULT_RECONNECT_TIME
GWEN_MSG * GWEN_Msg_List_First(const GWEN_MSG_LIST *l)
#define GWEN_LOGDOMAIN
Definition: logger.h:32
static int _startConnect(GWEN_MSG_ENDPOINT *ep)
GWEN_ENDPOINT_MULTILAYER_STARTCONNECT_FN GWEN_MultilayerEndpoint_SetStartConnectFn(GWEN_MSG_ENDPOINT *ep, GWEN_ENDPOINT_MULTILAYER_STARTCONNECT_FN fn)
void GWEN_Msg_List_Del(GWEN_MSG *element)
static void _checkSocketsWhenConnected(GWEN_MSG_ENDPOINT *ep, GWEN_MSG_ENDPOINT *epChild, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
GWEN_MSG_ENDPOINT * GWEN_MsgEndpoint_new(const char *name, int groupId)
Definition: endpoint.c:31
time_t GWEN_MsgEndpoint_GetTimeOfLastStateChange(const GWEN_MSG_ENDPOINT *ep)
Definition: endpoint.c:144
int GWEN_MultilayerEndpoint_StartConnect(GWEN_MSG_ENDPOINT *ep)
int(* GWEN_ENDPOINT_MULTILAYER_STARTCONNECT_FN)(GWEN_MSG_ENDPOINT *ep, GWEN_MSG_ENDPOINT *epChild)
#define GWEN_NEW_OBJECT(typ, varname)
Definition: memory.h:55
void GWEN_MultilayerEndpoint_SetConnectTimeoutInSeconds(GWEN_MSG_ENDPOINT *ep, int i)
#define GWEN_ERROR_IN_PROGRESS
Definition: error.h:72
static void GWENHYWFAR_CB _freeData(void *bp, void *p)
#define GWENHYWFAR_CB
Definition: gwenhywfarapi.h:89
GWEN_MSG_LIST * GWEN_MsgEndpoint_GetReceivedMessageList(const GWEN_MSG_ENDPOINT *ep)
Definition: endpoint.c:207
int GWEN_MsgEndpoint_GetState(const GWEN_MSG_ENDPOINT *ep)
Definition: endpoint.c:124
#define GWEN_ERROR_GENERIC
Definition: error.h:62
int GWEN_MultilayerEndpoint_GetConnectTimeoutInSeconds(const GWEN_MSG_ENDPOINT *ep)
static void _addSocketsWhenConnecting(GWEN_MSG_ENDPOINT *ep, GWEN_MSG_ENDPOINT *epChild, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
static void _moveMessagesBetweenLists(GWEN_MSG_LIST *srcList, GWEN_MSG_LIST *dstList)
void GWEN_MsgEndpoint_Disconnect(GWEN_MSG_ENDPOINT *ep)
Definition: endpoint.c:483
struct GWEN_MSG GWEN_MSG
Definition: msg.h:24
void(* GWEN_ENDPOINT_MULTILAYER_CHECKSOCKETS_FN)(GWEN_MSG_ENDPOINT *ep, GWEN_MSG_ENDPOINT *epChild, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
void GWEN_MsgEndpoint_CheckSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
Definition: endpoint.c:297
void GWEN_MultilayerEndpoint_SetStage(GWEN_MSG_ENDPOINT *ep, int i)
#define GWEN_ENDPOINT_MULTILAYER_DEFAULT_CONNECT_TIMEOUT
static void _addSocketsWhenConnected(GWEN_MSG_ENDPOINT *ep, GWEN_MSG_ENDPOINT *epChild, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
int GWEN_MultilayerEndpoint_GetReconnectTimeInSeconds(const GWEN_MSG_ENDPOINT *ep)
void GWEN_MsgEndpoint_SetState(GWEN_MSG_ENDPOINT *ep, int m)
Definition: endpoint.c:131
#define DBG_INFO(dbg_logger, format,...)
Definition: debug.h:181
const char * GWEN_MsgEndpoint_GetName(const GWEN_MSG_ENDPOINT *ep)
Definition: endpoint.c:90
void GWEN_MultilayerEndpoint_SetReconnectTimeInSeconds(GWEN_MSG_ENDPOINT *ep, int i)
GWEN_MSG_ENDPOINT_CHECKSOCKETS_FN GWEN_MsgEndpoint_SetCheckSocketsFn(GWEN_MSG_ENDPOINT *ep, GWEN_MSG_ENDPOINT_CHECKSOCKETS_FN fn)
Definition: endpoint.c:518
static void _checkSocketsWhenConnecting(GWEN_MSG_ENDPOINT *ep, GWEN_MSG_ENDPOINT *epChild, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
#define GWEN_INHERIT_SETDATA(bt, t, element, data, fn)
Definition: inherit.h:300
static void _addSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_UNUSED GWEN_SOCKETSET *xSet)
#define GWEN_ENDPOINT_MULTILAYER_NAME
#define GWEN_UNUSED
void GWEN_Msg_List_Add(GWEN_MSG *element, GWEN_MSG_LIST *list)
GWEN_MSG_LIST * GWEN_MsgEndpoint_GetSendMessageList(const GWEN_MSG_ENDPOINT *ep)
Definition: endpoint.c:214
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