gwenhywfar  5.14.1
endpoint_tcpc.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_tcpc_p.h"
17 
18 #include <gwenhywfar/debug.h>
19 
20 
21 
22 #define GWEN_MSG_ENDPOINT_TCPC_NAME "tcpclient"
23 #define GWEN_ENDPOINT_TCPC_RECONNECT_TIME 5
24 
25 
26 
27 /* ------------------------------------------------------------------------------------------------
28  * forward declarations
29  * ------------------------------------------------------------------------------------------------
30  */
31 
32 static void GWENHYWFAR_CB _freeData(void *bp, void *p);
33 
34 static void _addSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet);
35 static void _checkSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet);
36 
37 static int _startConnect(GWEN_MSG_ENDPOINT *ep);
39 static GWEN_INETADDRESS *_createAndSetupAddress(const char *host, int port);
40 
41 
42 /* ------------------------------------------------------------------------------------------------
43  * implementations
44  * ------------------------------------------------------------------------------------------------
45  */
46 
47 
48 
49 GWEN_INHERIT(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_TCPC)
50 
51 
52 
53 
54 GWEN_MSG_ENDPOINT *GWEN_TcpcEndpoint_new(const char *host, int port, const char *name, int groupId)
55 {
57  GWEN_ENDPOINT_TCPC *xep;
58 
61 
62  GWEN_NEW_OBJECT(GWEN_ENDPOINT_TCPC, xep);
63  GWEN_INHERIT_SETDATA(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_TCPC, ep, xep, _freeData);
64  xep->host=host?strdup(host):NULL;
65  xep->port=port;
66 
69 
70  return ep;
71 }
72 
73 
74 
76 {
77  if (ep) {
79  int rv;
80 
81  /* connect, set state */
82  rv=_startConnect(ep);
83  if (rv==GWEN_ERROR_IN_PROGRESS) {
84  DBG_INFO(GWEN_LOGDOMAIN, "Endpoint %s: Connect in progress", GWEN_MsgEndpoint_GetName(ep));
86  }
87  else if (rv==0) {
88  DBG_INFO(GWEN_LOGDOMAIN, "Endpoint %s: Connected.", GWEN_MsgEndpoint_GetName(ep));
90  }
91  else {
92  DBG_INFO(GWEN_LOGDOMAIN, "Endpoint %s: Error on connect (%d)", GWEN_MsgEndpoint_GetName(ep), rv);
93  }
94  return rv;
95  }
96  else {
97  DBG_ERROR(GWEN_LOGDOMAIN, "Endpoint %s: Not unconnected", GWEN_MsgEndpoint_GetName(ep));
98  }
99  }
100  else {
101  DBG_ERROR(GWEN_LOGDOMAIN, "No endpoint");
102  }
103  return GWEN_ERROR_GENERIC;
104 }
105 
106 
107 
108 
109 void GWENHYWFAR_CB _freeData(GWEN_UNUSED void *bp, void *p)
110 {
111  GWEN_ENDPOINT_TCPC *xep;
112 
113  xep=(GWEN_ENDPOINT_TCPC*) p;
114  free(xep->host);
115  GWEN_FREE_OBJECT(xep);
116 }
117 
118 
119 
121 {
122  if (ep) {
124  time_t now;
125 
126  now=time(NULL);
128  int rv;
129 
130  /* (re)connect, set state */
131  DBG_INFO(GWEN_LOGDOMAIN, "Starting to (re-)connect");
133  if (rv<0 && rv!=GWEN_ERROR_IN_PROGRESS) {
134  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
135  }
136  }
137  }
138 
141  }
142 
147  }
148  } /* if (ep) */
149 }
150 
151 
152 
154  GWEN_UNUSED GWEN_SOCKETSET *readSet,
155  GWEN_SOCKETSET *writeSet,
157 {
158  if (ep) {
159  GWEN_SOCKET *sk;
160 
162  if (sk) {
164  if (GWEN_SocketSet_HasSocket(writeSet, sk)) {
165  int rv;
166 
168  if (rv==GWEN_ERROR_IN_PROGRESS) {
169  DBG_DEBUG(GWEN_LOGDOMAIN, "Connect still in progress");
170  }
171  else if (rv==0) {
172  DBG_INFO(GWEN_LOGDOMAIN, "Connected.");
174  }
175  else {
176  DBG_INFO(GWEN_LOGDOMAIN, "Error on connect(%d)", rv);
177  }
178  }
179  }
180  } /* if (sk) */
181  else {
182  DBG_INFO(GWEN_LOGDOMAIN, "Endpoint \"%s\": No socket", GWEN_MsgEndpoint_GetName(ep));
183  }
184  } /* if (ep) */
185 }
186 
187 
188 
190 {
191  GWEN_ENDPOINT_TCPC *xep;
192 
193  DBG_INFO(GWEN_LOGDOMAIN, "Starting to connect");
194  xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_TCPC, ep);
195  if (xep) {
196  GWEN_INETADDRESS *addr;
197  GWEN_SOCKET *sk;
198  int rv;
199 
200  addr=_createAndSetupAddress(xep->host, xep->port);
201  if (addr==NULL) {
202  DBG_INFO(GWEN_LOGDOMAIN, "here");
203  return GWEN_ERROR_GENERIC;
204  }
205 
207  if (sk==NULL) {
208  DBG_INFO(GWEN_LOGDOMAIN, "here");
209  GWEN_InetAddr_free(addr);
210  return GWEN_ERROR_GENERIC;
211  }
212 
213  rv=GWEN_Socket_Connect(sk, addr);
214  if (rv<0) {
215  if (rv!=GWEN_ERROR_IN_PROGRESS) {
216  DBG_INFO(GWEN_LOGDOMAIN, "Error on connect(\"%s\", %d): %d", xep->host, xep->port, rv);
217  GWEN_Socket_free(sk);
218  GWEN_InetAddr_free(addr);
219  return rv;
220  }
221  }
223  GWEN_InetAddr_free(addr);
224  return rv;
225  }
226  return GWEN_ERROR_GENERIC;
227 }
228 
229 
230 
232 {
233  GWEN_SOCKET *sk;
234  int rv;
235 
237 
238  rv=GWEN_Socket_Open(sk);
239  if (rv<0) {
240  DBG_INFO(GWEN_LOGDOMAIN, "Error opening socket: %d", rv);
241  GWEN_Socket_free(sk);
242  return NULL;
243  }
244 
245  rv=GWEN_Socket_SetBlocking(sk, 0);
246  if (rv<0) {
247  DBG_INFO(GWEN_LOGDOMAIN, "Error setting socket nonblocking: %d", rv);
248  GWEN_Socket_free(sk);
249  return NULL;
250  }
251  return sk;
252 }
253 
254 
255 
256 GWEN_INETADDRESS *_createAndSetupAddress(const char *host, int port)
257 {
258  GWEN_INETADDRESS *addr;
259  int rv;
260 
262  rv=GWEN_InetAddr_SetAddress(addr, host);
263  if (rv<0)
264  rv=GWEN_InetAddr_SetName(addr, host);
265  if (rv<0) {
266  DBG_INFO(GWEN_LOGDOMAIN, "Error setting host \"%s\": %d", host, rv);
267  GWEN_InetAddr_free(addr);
268  return NULL;
269  }
270  rv=GWEN_InetAddr_SetPort(addr, port);
271  if (rv<0) {
272  DBG_INFO(GWEN_LOGDOMAIN, "Error setting port \"%d\": %d", port, rv);
273  GWEN_InetAddr_free(addr);
274  return NULL;
275  }
276 
277  return addr;
278 }
279 
280 
281 
282 
283 
#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
#define GWEN_MSG_ENDPOINT_STATE_CONNECTING
Definition: endpoint.h:24
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
static void _checkSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet)
static void GWENHYWFAR_CB _freeData(void *bp, void *p)
#define GWEN_MSG_ENDPOINT_TCPC_NAME
Definition: endpoint_tcpc.c:22
#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
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)
GWEN_MSG_ENDPOINT * GWEN_TcpcEndpoint_new(const char *host, int port, const char *name, int groupId)
Definition: endpoint_tcpc.c:54
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
void GWEN_MsgEndpoint_SetSocket(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKET *sk)
Definition: endpoint.c:111
#define GWEN_ENDPOINT_TCPC_RECONNECT_TIME
Definition: endpoint_tcpc.c:23
#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_HaveMessageToSend(const GWEN_MSG_ENDPOINT *ep)
Definition: endpoint.c:267
GWENHYWFAR_API int GWEN_Socket_Connect(GWEN_SOCKET *sp, const GWEN_INETADDRESS *addr)
static GWEN_SOCKET * _createAndSetupSocket(void)
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_Socket_GetSocketError(GWEN_SOCKET *sp)
int GWEN_TcpcEndpoint_StartConnect(GWEN_MSG_ENDPOINT *ep)
Definition: endpoint_tcpc.c:75
GWENHYWFAR_API int GWEN_InetAddr_SetAddress(GWEN_INETADDRESS *ia, const char *addr)
static GWEN_INETADDRESS * _createAndSetupAddress(const char *host, int port)
struct GWEN_SOCKET GWEN_SOCKET
Definition: inetsocket.h:44
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
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
#define GWEN_INHERIT_SETDATA(bt, t, element, data, fn)
Definition: inherit.h:300
GWENHYWFAR_API void GWEN_Socket_free(GWEN_SOCKET *sp)
#define GWEN_UNUSED
static int _startConnect(GWEN_MSG_ENDPOINT *ep)
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)