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
28GWEN_INHERIT(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_MULTILAYER);
29
30
31/* ------------------------------------------------------------------------------------------------
32 * forward declarations
33 * ------------------------------------------------------------------------------------------------
34 */
35
36static void GWENHYWFAR_CB _freeData(void *bp, void *p);
37
38static void _addSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_UNUSED GWEN_SOCKETSET *xSet);
39static void _checkSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet);
40static int _startConnect(GWEN_MSG_ENDPOINT *ep);
41static 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
63GWEN_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
83void GWENHYWFAR_CB _freeData(GWEN_UNUSED void *bp, void *p)
84{
85 GWEN_ENDPOINT_MULTILAYER *xep;
86
87 xep=(GWEN_ENDPOINT_MULTILAYER*) p;
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
366
367
368
370{
371 GWEN_MSG *msg;
372
373 while( (msg=GWEN_Msg_List_First(srcList)) ) {
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 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
#define DBG_DEBUG(dbg_logger, format,...)
Definition debug.h:214
GWEN_MSG_ENDPOINT * GWEN_MsgEndpoint_new(const char *name, int groupId)
Definition endpoint.c:31
GWEN_MSG_LIST * GWEN_MsgEndpoint_GetReceivedMessageList(const GWEN_MSG_ENDPOINT *ep)
Definition endpoint.c:207
void GWEN_MsgEndpoint_AddSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
Definition endpoint.c:289
time_t GWEN_MsgEndpoint_GetTimeOfLastStateChange(const GWEN_MSG_ENDPOINT *ep)
Definition endpoint.c:144
void GWEN_MsgEndpoint_SetState(GWEN_MSG_ENDPOINT *ep, int m)
Definition endpoint.c:131
void GWEN_MsgEndpoint_CheckSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
Definition endpoint.c:297
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
void GWEN_MsgEndpoint_Disconnect(GWEN_MSG_ENDPOINT *ep)
Definition endpoint.c:483
const char * GWEN_MsgEndpoint_GetName(const GWEN_MSG_ENDPOINT *ep)
Definition endpoint.c:90
GWEN_MSG_ENDPOINT_CHECKSOCKETS_FN GWEN_MsgEndpoint_SetCheckSocketsFn(GWEN_MSG_ENDPOINT *ep, GWEN_MSG_ENDPOINT_CHECKSOCKETS_FN fn)
Definition endpoint.c:518
GWEN_MSG_LIST * GWEN_MsgEndpoint_GetSendMessageList(const GWEN_MSG_ENDPOINT *ep)
Definition endpoint.c:214
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_CONNECTING
Definition endpoint.h:24
#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)
int GWEN_MultilayerEndpoint_GetStage(const GWEN_MSG_ENDPOINT *ep)
void GWEN_MultilayerEndpoint_SetStage(GWEN_MSG_ENDPOINT *ep, int i)
static void _moveMessagesBetweenLists(GWEN_MSG_LIST *srcList, GWEN_MSG_LIST *dstList)
#define GWEN_ENDPOINT_MULTILAYER_DEFAULT_CONNECT_TIMEOUT
#define GWEN_ENDPOINT_MULTILAYER_NAME
void GWEN_MultilayerEndpoint_SetConnectTimeoutInSeconds(GWEN_MSG_ENDPOINT *ep, int i)
GWEN_ENDPOINT_MULTILAYER_STARTCONNECT_FN GWEN_MultilayerEndpoint_SetStartConnectFn(GWEN_MSG_ENDPOINT *ep, GWEN_ENDPOINT_MULTILAYER_STARTCONNECT_FN fn)
GWEN_MSG_ENDPOINT * GWEN_MultilayerEndpoint_new(const char *name, int groupId)
static void GWENHYWFAR_CB _freeData(void *bp, void *p)
void GWEN_MultilayerEndpoint_SetReconnectTimeInSeconds(GWEN_MSG_ENDPOINT *ep, int i)
int GWEN_MultilayerEndpoint_GetConnectTimeoutInSeconds(const GWEN_MSG_ENDPOINT *ep)
int GWEN_MultilayerEndpoint_StartConnect(GWEN_MSG_ENDPOINT *ep)
static void _checkSocketsWhenConnecting(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)
static void _addSocketsWhenConnected(GWEN_MSG_ENDPOINT *ep, GWEN_MSG_ENDPOINT *epChild, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
static int _startConnect(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 _checkSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
static void _checkForNeedToReconnect(GWEN_MSG_ENDPOINT *ep)
#define GWEN_ENDPOINT_MULTILAYER_DEFAULT_RECONNECT_TIME
static void _checkSocketsWhenConnected(GWEN_MSG_ENDPOINT *ep, GWEN_MSG_ENDPOINT *epChild, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
GWEN_ENDPOINT_MULTILAYER_CHECKSOCKETS_FN GWEN_MultilayerEndpoint_SetCheckSocketsFn(GWEN_MSG_ENDPOINT *ep, GWEN_ENDPOINT_MULTILAYER_CHECKSOCKETS_FN fn)
static void _addSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_UNUSED GWEN_SOCKETSET *xSet)
int(* GWEN_ENDPOINT_MULTILAYER_STARTCONNECT_FN)(GWEN_MSG_ENDPOINT *ep, GWEN_MSG_ENDPOINT *epChild)
void(* GWEN_ENDPOINT_MULTILAYER_CHECKSOCKETS_FN)(GWEN_MSG_ENDPOINT *ep, GWEN_MSG_ENDPOINT *epChild, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
#define GWEN_ERROR_GENERIC
Definition error.h:62
#define GWEN_ERROR_IN_PROGRESS
Definition error.h:72
#define GWEN_UNUSED
#define GWENHYWFAR_CB
struct GWEN_SOCKETSETSTRUCT GWEN_SOCKETSET
Definition inetsocket.h:45
#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
GWEN_MSG * GWEN_Msg_List_First(const GWEN_MSG_LIST *l)
void GWEN_Msg_List_Del(GWEN_MSG *element)
void GWEN_Msg_List_Add(GWEN_MSG *element, GWEN_MSG_LIST *list)
#define GWEN_LOGDOMAIN
Definition logger.h:32
#define GWEN_FREE_OBJECT(varname)
Definition memory.h:61
#define GWEN_NEW_OBJECT(typ, varname)
Definition memory.h:55
struct GWEN_MSG GWEN_MSG
Definition msg.h:24
static void GWENHYWFAR_CB _freeData(GWEN_UNUSED void *bp, void *p)
Definition nogui.c:222