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
32static void GWENHYWFAR_CB _freeData(void *bp, void *p);
33
34static void _addSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet);
35static void _checkSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet);
36
37static int _startConnect(GWEN_MSG_ENDPOINT *ep);
39static GWEN_INETADDRESS *_createAndSetupAddress(const char *host, int port);
40
41
42/* ------------------------------------------------------------------------------------------------
43 * implementations
44 * ------------------------------------------------------------------------------------------------
45 */
46
47
48
49GWEN_INHERIT(GWEN_MSG_ENDPOINT, GWEN_ENDPOINT_TCPC)
50
51
52
53
54GWEN_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
109void 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
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);
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);
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);
249 return NULL;
250 }
251 return sk;
252}
253
254
255
256GWEN_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 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
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
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
int GWEN_MsgEndpoint_HaveMessageToSend(const GWEN_MSG_ENDPOINT *ep)
Definition endpoint.c:267
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_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)
#define GWEN_MSG_ENDPOINT_TCPC_NAME
static GWEN_INETADDRESS * _createAndSetupAddress(const char *host, int port)
#define GWEN_ENDPOINT_TCPC_RECONNECT_TIME
static GWEN_SOCKET * _createAndSetupSocket(void)
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)
int GWEN_TcpcEndpoint_StartConnect(GWEN_MSG_ENDPOINT *ep)
GWEN_MSG_ENDPOINT * GWEN_TcpcEndpoint_new(const char *host, int port, const char *name, int groupId)
static int _startConnect(GWEN_MSG_ENDPOINT *ep)
static void _addSockets(GWEN_MSG_ENDPOINT *ep, 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
@ GWEN_SocketTypeTCP
Definition inetsocket.h:84
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_SetBlocking(GWEN_SOCKET *sp, int fl)
GWENHYWFAR_API int GWEN_Socket_Connect(GWEN_SOCKET *sp, const GWEN_INETADDRESS *addr)
GWENHYWFAR_API int GWEN_Socket_GetSocketError(GWEN_SOCKET *sp)
#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_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_SetName(GWEN_INETADDRESS *ia, const char *name)
struct GWEN_SOCKETSETSTRUCT GWEN_SOCKETSET
Definition inetsocket.h:45
struct GWEN_SOCKET GWEN_SOCKET
Definition inetsocket.h:44
#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:32
#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