gwenhywfar  5.10.1
syncio_socket.c
Go to the documentation of this file.
1 /***************************************************************************
2  begin : Tue Apr 27 2010
3  copyright : (C) 2010 by Martin Preuss
4  email : martin@libchipcard.de
5 
6  ***************************************************************************
7  * *
8  * This library is free software; you can redistribute it and/or *
9  * modify it under the terms of the GNU Lesser General Public *
10  * License as published by the Free Software Foundation; either *
11  * version 2.1 of the License, or (at your option) any later version. *
12  * *
13  * This library is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16  * Lesser General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU Lesser General Public *
19  * License along with this library; if not, write to the Free Software *
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21  * MA 02111-1307 USA *
22  * *
23  ***************************************************************************/
24 
25 #ifdef HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #define DISABLE_DEBUGLOG
30 
31 
32 
33 #include "syncio_socket_p.h"
34 #include "i18n_l.h"
35 
36 #include <gwenhywfar/misc.h>
37 #include <gwenhywfar/debug.h>
38 #include <gwenhywfar/gui.h>
39 #include <gwenhywfar/text.h>
40 
41 #include <assert.h>
42 #include <errno.h>
43 #include <string.h>
44 
45 
46 #define GWEN_SYNCIO_SOCKET_READ_TIMEOUT 60000
47 #define GWEN_SYNCIO_SOCKET_WRITE_TIMEOUT 60000
48 
49 
50 GWEN_INHERIT(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET)
51 
52 
53 
55 {
56  GWEN_SYNCIO *sio;
57  GWEN_SYNCIO_SOCKET *xio;
58 
60  GWEN_NEW_OBJECT(GWEN_SYNCIO_SOCKET, xio);
61  GWEN_INHERIT_SETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio, xio, GWEN_SyncIo_Socket_FreeData);
62 
67 
68  xio->socketType=sockType;
69  xio->addressFamily=addressFamily;
70 
71  return sio;
72 }
73 
74 
75 
77 {
78  GWEN_SYNCIO *sio;
79  GWEN_SYNCIO_SOCKET *xio;
80 
82  GWEN_NEW_OBJECT(GWEN_SYNCIO_SOCKET, xio);
83  GWEN_INHERIT_SETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio, xio, GWEN_SyncIo_Socket_FreeData);
84 
89 
90  xio->socketType=GWEN_Socket_GetSocketType(socket);
91  xio->socket=socket;
93 
94  return sio;
95 }
96 
97 
98 
100 {
101  GWEN_SYNCIO_SOCKET *xio;
102 
103  xio=(GWEN_SYNCIO_SOCKET *) p;
104  free(xio->address);
105  GWEN_Socket_free(xio->socket);
106  GWEN_FREE_OBJECT(xio);
107 }
108 
109 
110 
112 {
113  GWEN_SYNCIO_SOCKET *xio;
114 
115  assert(sio);
116  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
117  assert(xio);
118 
119  return xio->address;
120 }
121 
122 
123 
125 {
126  GWEN_SYNCIO_SOCKET *xio;
127 
128  assert(sio);
129  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
130  assert(xio);
131 
132  free(xio->address);
133  if (s)
134  xio->address=strdup(s);
135  else
136  xio->address=NULL;
137 }
138 
139 
140 
142 {
143  GWEN_SYNCIO_SOCKET *xio;
144 
145  assert(sio);
146  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
147  assert(xio);
148 
149  return xio->port;
150 }
151 
152 
153 
155 {
156  GWEN_SYNCIO_SOCKET *xio;
157 
158  assert(sio);
159  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
160  assert(xio);
161 
162  xio->port=i;
163 }
164 
165 
166 
168 {
169  GWEN_SYNCIO_SOCKET *xio;
170  GWEN_SOCKET *sk;
171  GWEN_INETADDRESS *addr;
172  int rv;
173 
174  assert(sio);
175  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
176  assert(xio);
177 
179  /* already connected */
180  return 0;
181 
183  /* passive, can't connect */
184  DBG_ERROR(GWEN_LOGDOMAIN, "Passive socket, can't connect");
185  return GWEN_ERROR_INVALID;
186  }
187 
188  sk=GWEN_Socket_new(xio->socketType);
189  rv=GWEN_Socket_Open(sk);
190  if (rv<0) {
191  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
194  I18N("Error setting up socket: %d"),
195  rv);
196  GWEN_Socket_free(sk);
197  return rv;
198  }
199  addr=GWEN_InetAddr_new(xio->addressFamily);
200 
201  rv=GWEN_InetAddr_SetAddress(addr, xio->address);
202  if (rv<0) {
205  I18N("Resolving hostname \"%s\" ..."),
206  xio->address);
207  rv=GWEN_InetAddr_SetName(addr, xio->address);
208  if (rv<0) {
211  I18N("Unknown hostname \"%s\""),
212  xio->address);
213  GWEN_InetAddr_free(addr);
214  GWEN_Socket_free(sk);
215  return rv;
216  }
217  else {
218  char addrBuf[256];
219 
220  rv=GWEN_InetAddr_GetAddress(addr, addrBuf, sizeof(addrBuf)-1);
221  addrBuf[sizeof(addrBuf)-1]=0;
222  if (rv<0) {
223  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
224  }
225  else
228  I18N("IP address is \"%s\""),
229  addrBuf);
230  }
231  }
232  GWEN_InetAddr_SetPort(addr, xio->port);
233 
234  /* connect */
237  I18N("Connecting to \"%s\""),
238  xio->address);
239  rv=GWEN_Socket_Connect(sk, addr);
240  GWEN_InetAddr_free(addr);
241  if (rv<0) {
244  I18N("Error connecting to \"%s\": %s"),
245  xio->address,
246  strerror(errno));
247  GWEN_Socket_free(sk);
248  return rv;
249  }
250 
251  /* done */
252  xio->socket=sk;
254  DBG_INFO(GWEN_LOGDOMAIN, "Connected to \"%s\"", xio->address);
257  I18N("Connected to \"%s\""),
258  xio->address);
259  return 0;
260 }
261 
262 
263 
265 {
266  GWEN_SYNCIO_SOCKET *xio;
267 
268  assert(sio);
269  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
270  assert(xio);
271 
272  if (xio->socket) {
273  GWEN_Socket_Close(xio->socket);
274  GWEN_Socket_free(xio->socket);
275  xio->socket=NULL;
277  DBG_INFO(GWEN_LOGDOMAIN, "Disconnected socket");
278  }
279 
280  return 0;
281 }
282 
283 
284 
286  uint8_t *buffer,
287  uint32_t size)
288 {
289  GWEN_SYNCIO_SOCKET *xio;
290  int rv;
291  int i;
292 
293  assert(sio);
294  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
295  assert(xio);
296 
297  if (size==0) {
298  DBG_ERROR(GWEN_LOGDOMAIN, "Read size is zero");
299  return GWEN_ERROR_INVALID;
300  }
301 
303  /* not connected */
304  DBG_ERROR(GWEN_LOGDOMAIN, "Socket not connected (%d)",
305  GWEN_SyncIo_GetStatus(sio));
307  }
308 
309  if (xio->socket==NULL) {
310  DBG_ERROR(GWEN_LOGDOMAIN, "No socket");
311  return GWEN_ERROR_INTERNAL;
312  }
313 
314  /* check whether there is data available */
315  do {
316  rv=GWEN_Socket_WaitForRead(xio->socket, 0);
317  }
318  while (rv==GWEN_ERROR_INTERRUPTED);
319 
320 
321  /* nothing to read immediately, wait for data availability */
322  if (rv==GWEN_ERROR_TIMEOUT) {
323  GWEN_SOCKET_LIST2 *sl;
324 
326  GWEN_Socket_List2_PushBack(sl, xio->socket);
327 
328  do {
330  }
331  while (rv==GWEN_ERROR_INTERRUPTED);
332 
334  if (rv<0) {
335  if (rv==GWEN_ERROR_TIMEOUT) {
336  DBG_ERROR(GWEN_LOGDOMAIN, "timeout (%d)", rv);
337  return rv;
338  }
339  else {
340  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
341  return rv;
342  }
343  }
344  }
345 
346  i=size;
347  rv=GWEN_Socket_Read(xio->socket, (char *) buffer, &i);
348  if (rv<0) {
349  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
350  return rv;
351  }
352 
353 #if 0
354  DBG_ERROR(0, "Received this:");
355  GWEN_Text_DumpString((const char *) buffer, i, stderr, 2);
356 #endif
357 
358  return i;
359 }
360 
361 
362 
364  const uint8_t *buffer,
365  uint32_t size)
366 {
367  GWEN_SYNCIO_SOCKET *xio;
368  int rv;
369  int i;
370 
371  assert(sio);
372  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
373  assert(xio);
374 
376  /* not connected */
377  DBG_ERROR(GWEN_LOGDOMAIN, "Socket not connected");
379  }
380 
381  if (xio->socket==NULL) {
382  DBG_ERROR(GWEN_LOGDOMAIN, "No socket");
383  return GWEN_ERROR_INTERNAL;
384  }
385 
386  /* check whether the socket is writeable */
387  do {
388  rv=GWEN_Socket_WaitForWrite(xio->socket, 0);
389  }
390  while (rv==GWEN_ERROR_INTERRUPTED);
391 
392  if (rv==GWEN_ERROR_TIMEOUT) {
393  GWEN_SOCKET_LIST2 *sl;
394 
396  GWEN_Socket_List2_PushBack(sl, xio->socket);
397 
398  do {
400  }
401  while (rv==GWEN_ERROR_INTERRUPTED);
402 
403  if (rv<0) {
404  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
406  return rv;
407  }
409  }
410 
411  i=size;
412  rv=GWEN_Socket_Write(xio->socket, (const char *) buffer, &i);
413  if (rv<0) {
414  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
415  return rv;
416  }
417 
418 #if 0
419  DBG_ERROR(0, "Written this:");
420  GWEN_Text_DumpString((const char *) buffer, i, stderr, 2);
421 #endif
422 
423  return i;
424 }
425 
426 
427 
428 
429 
int GWENHYWFAR_CB GWEN_SyncIo_Socket_Write(GWEN_SYNCIO *sio, const uint8_t *buffer, uint32_t size)
void GWENHYWFAR_CB GWEN_SyncIo_Socket_FreeData(GWEN_UNUSED void *bp, void *p)
Definition: syncio_socket.c:99
#define I18N(m)
Definition: error.c:42
#define GWEN_SYNCIO_SOCKET_TYPE
Definition: syncio_socket.h:33
GWENHYWFAR_API int GWEN_Gui_WaitForSockets(GWEN_SOCKET_LIST2 *readSockets, GWEN_SOCKET_LIST2 *writeSockets, uint32_t guiid, int msecs)
Definition: gui_virtual.c:667
struct GWEN_SOCKET_LIST2 GWEN_SOCKET_LIST2
Definition: listdoc.h:4030
#define GWEN_ERROR_INVALID
Definition: error.h:67
GWENHYWFAR_API int GWEN_Socket_Write(GWEN_SOCKET *sp, const char *buffer, int *bsize)
GWEN_SOCKETTYPE
Definition: inetsocket.h:79
void GWEN_Text_DumpString(const char *s, unsigned int l, unsigned int insert)
Definition: text.c:1283
GWEN_SYNCIO_WRITE_FN GWEN_SyncIo_SetWriteFn(GWEN_SYNCIO *sio, GWEN_SYNCIO_WRITE_FN fn)
Definition: syncio.c:304
#define GWEN_FREE_OBJECT(varname)
Definition: memory.h:61
#define NULL
Definition: binreloc.c:300
GWENHYWFAR_API void GWEN_InetAddr_free(GWEN_INETADDRESS *ia)
GWEN_SYNCIO_CONNECT_FN GWEN_SyncIo_SetConnectFn(GWEN_SYNCIO *sio, GWEN_SYNCIO_CONNECT_FN fn)
Definition: syncio.c:252
void GWEN_SyncIo_Socket_SetAddress(GWEN_SYNCIO *sio, const char *s)
GWENHYWFAR_API GWEN_INETADDRESS * GWEN_InetAddr_new(GWEN_AddressFamily af)
void GWEN_Socket_List2_free(GWEN_SOCKET_LIST2 *l)
uint32_t GWEN_SyncIo_GetFlags(const GWEN_SYNCIO *sio)
Definition: syncio.c:161
GWENHYWFAR_API int GWEN_Socket_WaitForWrite(GWEN_SOCKET *sp, int timeout)
GWENHYWFAR_API int GWEN_Socket_Open(GWEN_SOCKET *sp)
#define GWEN_LOGDOMAIN
Definition: logger.h:35
void GWEN_SyncIo_SetStatus(GWEN_SYNCIO *sio, GWEN_SYNCIO_STATUS st)
Definition: syncio.c:206
int GWEN_SyncIo_Socket_GetPort(const GWEN_SYNCIO *sio)
GWENHYWFAR_API int GWEN_Socket_Read(GWEN_SOCKET *sp, char *buffer, int *bsize)
#define GWEN_ERROR_INTERRUPTED
Definition: error.h:74
int GWENHYWFAR_CB GWEN_SyncIo_Socket_Read(GWEN_SYNCIO *sio, uint8_t *buffer, uint32_t size)
int GWENHYWFAR_CB GWEN_SyncIo_Socket_Connect(GWEN_SYNCIO *sio)
#define GWEN_ERROR_NOT_CONNECTED
Definition: error.h:120
int GWENHYWFAR_CB GWEN_SyncIo_Socket_Disconnect(GWEN_SYNCIO *sio)
#define GWEN_NEW_OBJECT(typ, varname)
Definition: memory.h:55
struct GWEN_SYNCIO GWEN_SYNCIO
Definition: syncio.h:40
#define GWENHYWFAR_CB
Definition: gwenhywfarapi.h:89
GWENHYWFAR_API int GWEN_Gui_ProgressLog2(uint32_t id, GWEN_LOGGER_LEVEL level, const char *text,...)
Definition: gui_virtual.c:458
GWENHYWFAR_API int GWEN_Socket_Connect(GWEN_SOCKET *sp, const GWEN_INETADDRESS *addr)
#define GWEN_SYNCIO_SOCKET_WRITE_TIMEOUT
Definition: syncio_socket.c:47
#define GWEN_SYNCIO_SOCKET_READ_TIMEOUT
Definition: syncio_socket.c:46
#define GWEN_SYNCIO_FLAGS_PASSIVE
Definition: syncio.h:57
GWENHYWFAR_API GWEN_SOCKETTYPE GWEN_Socket_GetSocketType(GWEN_SOCKET *sp)
GWEN_SYNCIO_STATUS GWEN_SyncIo_GetStatus(const GWEN_SYNCIO *sio)
Definition: syncio.c:197
GWENHYWFAR_API int GWEN_Socket_Close(GWEN_SOCKET *sp)
struct GWEN_INETADDRESSSTRUCT GWEN_INETADDRESS
Definition: inetaddr.h:95
void GWEN_SyncIo_Socket_SetPort(GWEN_SYNCIO *sio, int i)
GWENHYWFAR_API int GWEN_InetAddr_SetName(GWEN_INETADDRESS *ia, const char *name)
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
GWEN_SOCKET_LIST2 * GWEN_Socket_List2_new()
void GWEN_Socket_List2_PushBack(GWEN_SOCKET_LIST2 *l, GWEN_SOCKET *p)
GWENHYWFAR_API GWEN_SOCKET * GWEN_Socket_new(GWEN_SOCKETTYPE socketType)
GWEN_AddressFamily
Definition: inetaddr.h:83
GWEN_SYNCIO * GWEN_SyncIo_new(const char *typeName, GWEN_SYNCIO *baseIo)
Definition: syncio.c:51
GWEN_SYNCIO_DISCONNECT_FN GWEN_SyncIo_SetDisconnectFn(GWEN_SYNCIO *sio, GWEN_SYNCIO_DISCONNECT_FN fn)
Definition: syncio.c:265
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:181
GWENHYWFAR_API int GWEN_InetAddr_SetAddress(GWEN_INETADDRESS *ia, const char *addr)
struct GWEN_SOCKET GWEN_SOCKET
Definition: inetsocket.h:40
GWEN_SYNCIO * GWEN_SyncIo_Socket_TakeOver(GWEN_SOCKET *socket)
Definition: syncio_socket.c:76
GWEN_SYNCIO * GWEN_SyncIo_Socket_new(GWEN_SOCKETTYPE sockType, GWEN_AddressFamily addressFamily)
Definition: syncio_socket.c:54
#define GWEN_ERROR_TIMEOUT
Definition: error.h:71
#define GWEN_INHERIT(bt, t)
Definition: inherit.h:264
GWEN_SYNCIO_READ_FN GWEN_SyncIo_SetReadFn(GWEN_SYNCIO *sio, GWEN_SYNCIO_READ_FN fn)
Definition: syncio.c:291
const char * GWEN_SyncIo_Socket_GetAddress(const GWEN_SYNCIO *sio)
#define GWEN_ERROR_INTERNAL
Definition: error.h:125
GWENHYWFAR_API int GWEN_Socket_WaitForRead(GWEN_SOCKET *sp, int timeout)
#define GWEN_INHERIT_SETDATA(bt, t, element, data, fn)
Definition: inherit.h:292
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
#define GWEN_INHERIT_GETDATA(bt, t, element)
Definition: inherit.h:271
GWENHYWFAR_API int GWEN_InetAddr_SetPort(GWEN_INETADDRESS *ia, int port)