gwenhywfar  4.99.8beta
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  GWEN_SYNCIO *sio;
56  GWEN_SYNCIO_SOCKET *xio;
57 
59  GWEN_NEW_OBJECT(GWEN_SYNCIO_SOCKET, xio);
60  GWEN_INHERIT_SETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio, xio, GWEN_SyncIo_Socket_FreeData);
61 
66 
67  xio->socketType=sockType;
68  xio->addressFamily=addressFamily;
69 
70  return sio;
71 }
72 
73 
74 
76  GWEN_SYNCIO *sio;
77  GWEN_SYNCIO_SOCKET *xio;
78 
80  GWEN_NEW_OBJECT(GWEN_SYNCIO_SOCKET, xio);
81  GWEN_INHERIT_SETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio, xio, GWEN_SyncIo_Socket_FreeData);
82 
87 
88  xio->socketType=GWEN_Socket_GetSocketType(socket);
89  xio->socket=socket;
91 
92  return sio;
93 }
94 
95 
96 
97 void GWENHYWFAR_CB GWEN_SyncIo_Socket_FreeData(void *bp, void *p) {
98  GWEN_SYNCIO_SOCKET *xio;
99 
100  xio=(GWEN_SYNCIO_SOCKET*) p;
101  free(xio->address);
102  GWEN_Socket_free(xio->socket);
103  GWEN_FREE_OBJECT(xio);
104 }
105 
106 
107 
109  GWEN_SYNCIO_SOCKET *xio;
110 
111  assert(sio);
112  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
113  assert(xio);
114 
115  return xio->address;
116 }
117 
118 
119 
120 void GWEN_SyncIo_Socket_SetAddress(GWEN_SYNCIO *sio, const char *s) {
121  GWEN_SYNCIO_SOCKET *xio;
122 
123  assert(sio);
124  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
125  assert(xio);
126 
127  free(xio->address);
128  if (s) xio->address=strdup(s);
129  else xio->address=NULL;
130 }
131 
132 
133 
135  GWEN_SYNCIO_SOCKET *xio;
136 
137  assert(sio);
138  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
139  assert(xio);
140 
141  return xio->port;
142 }
143 
144 
145 
147  GWEN_SYNCIO_SOCKET *xio;
148 
149  assert(sio);
150  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
151  assert(xio);
152 
153  xio->port=i;
154 }
155 
156 
157 
159  GWEN_SYNCIO_SOCKET *xio;
160  GWEN_SOCKET *sk;
161  GWEN_INETADDRESS *addr;
162  int rv;
163 
164  assert(sio);
165  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
166  assert(xio);
167 
169  /* already connected */
170  return 0;
171 
173  /* passive, can't connect */
174  DBG_ERROR(GWEN_LOGDOMAIN, "Passive socket, can't connect");
175  return GWEN_ERROR_INVALID;
176  }
177 
178  sk=GWEN_Socket_new(xio->socketType);
179  rv=GWEN_Socket_Open(sk);
180  if (rv<0) {
181  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
184  I18N("Error setting up socket: %d"),
185  rv);
186  GWEN_Socket_free(sk);
187  return rv;
188  }
189  addr=GWEN_InetAddr_new(xio->addressFamily);
190 
191  rv=GWEN_InetAddr_SetAddress(addr, xio->address);
192  if (rv<0) {
195  I18N("Resolving hostname \"%s\" ..."),
196  xio->address);
197  rv=GWEN_InetAddr_SetName(addr, xio->address);
198  if (rv<0) {
201  I18N("Unknown hostname \"%s\""),
202  xio->address);
203  GWEN_InetAddr_free(addr);
204  GWEN_Socket_free(sk);
205  return rv;
206  }
207  else {
208  char addrBuf[256];
209 
210  rv=GWEN_InetAddr_GetAddress(addr, addrBuf, sizeof(addrBuf)-1);
211  addrBuf[sizeof(addrBuf)-1]=0;
212  if (rv<0) {
213  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
214  }
215  else
218  I18N("IP address is \"%s\""),
219  addrBuf);
220  }
221  }
222  GWEN_InetAddr_SetPort(addr, xio->port);
223 
224  /* connect */
227  I18N("Connecting to \"%s\""),
228  xio->address);
229  rv=GWEN_Socket_Connect(sk, addr);
230  GWEN_InetAddr_free(addr);
231  if (rv<0) {
234  I18N("Error connecting to \"%s\": %s"),
235  xio->address,
236  strerror(errno));
237  GWEN_Socket_free(sk);
238  return rv;
239  }
240 
241  /* done */
242  xio->socket=sk;
244  DBG_INFO(GWEN_LOGDOMAIN, "Connected to \"%s\"", xio->address);
247  I18N("Connected to \"%s\""),
248  xio->address);
249  return 0;
250 }
251 
252 
253 
255  GWEN_SYNCIO_SOCKET *xio;
256 
257  assert(sio);
258  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
259  assert(xio);
260 
261  if (xio->socket) {
262  GWEN_Socket_Close(xio->socket);
263  GWEN_Socket_free(xio->socket);
264  xio->socket=NULL;
266  DBG_INFO(GWEN_LOGDOMAIN, "Disconnected socket");
267  }
268 
269  return 0;
270 }
271 
272 
273 
275  uint8_t *buffer,
276  uint32_t size) {
277  GWEN_SYNCIO_SOCKET *xio;
278  int rv;
279  int i;
280 
281  assert(sio);
282  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
283  assert(xio);
284 
285  if (size==0) {
286  DBG_ERROR(GWEN_LOGDOMAIN, "Read size is zero");
287  return GWEN_ERROR_INVALID;
288  }
289 
291  /* not connected */
292  DBG_ERROR(GWEN_LOGDOMAIN, "Socket not connected (%d)",
293  GWEN_SyncIo_GetStatus(sio));
295  }
296 
297  if (xio->socket==NULL) {
298  DBG_ERROR(GWEN_LOGDOMAIN, "No socket");
299  return GWEN_ERROR_INTERNAL;
300  }
301 
302  /* check whether there is data available */
303  do {
304  rv=GWEN_Socket_WaitForRead(xio->socket, 0);
305  }
306  while (rv==GWEN_ERROR_INTERRUPTED);
307 
308 
309  /* nothing to read immediately, wait for data availability */
310  if (rv==GWEN_ERROR_TIMEOUT) {
311  GWEN_SOCKET_LIST2 *sl;
312 
314  GWEN_Socket_List2_PushBack(sl, xio->socket);
315 
316  do {
318  }
319  while (rv==GWEN_ERROR_INTERRUPTED);
320 
322  if (rv<0) {
323  if (rv==GWEN_ERROR_TIMEOUT) {
324  DBG_ERROR(GWEN_LOGDOMAIN, "timeout (%d)", rv);
325  return rv;
326  }
327  else {
328  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
329  return rv;
330  }
331  }
332  }
333 
334  i=size;
335  rv=GWEN_Socket_Read(xio->socket, (char*) buffer, &i);
336  if (rv<0) {
337  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
338  return rv;
339  }
340 
341 #if 0
342  DBG_ERROR(0, "Received this:");
343  GWEN_Text_DumpString((const char*) buffer, i, stderr, 2);
344 #endif
345 
346  return i;
347 }
348 
349 
350 
352  const uint8_t *buffer,
353  uint32_t size) {
354  GWEN_SYNCIO_SOCKET *xio;
355  int rv;
356  int i;
357 
358  assert(sio);
359  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
360  assert(xio);
361 
363  /* not connected */
364  DBG_ERROR(GWEN_LOGDOMAIN, "Socket not connected");
366  }
367 
368  if (xio->socket==NULL) {
369  DBG_ERROR(GWEN_LOGDOMAIN, "No socket");
370  return GWEN_ERROR_INTERNAL;
371  }
372 
373  /* check whether the socket is writeable */
374  do {
375  rv=GWEN_Socket_WaitForWrite(xio->socket, 0);
376  }
377  while (rv==GWEN_ERROR_INTERRUPTED);
378 
379  if (rv==GWEN_ERROR_TIMEOUT) {
380  int rv;
381  GWEN_SOCKET_LIST2 *sl;
382 
384  GWEN_Socket_List2_PushBack(sl, xio->socket);
385 
386  do {
388  }
389  while (rv==GWEN_ERROR_INTERRUPTED);
390 
391  if (rv<0) {
392  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
394  return rv;
395  }
397  }
398 
399  i=size;
400  rv=GWEN_Socket_Write(xio->socket, (const char*) buffer, &i);
401  if (rv<0) {
402  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
403  return rv;
404  }
405 
406 #if 0
407  DBG_ERROR(0, "Written this:");
408  GWEN_Text_DumpString((const char*) buffer, i, stderr, 2);
409 #endif
410 
411  return i;
412 }
413 
414 
415 
416 
417 
int GWENHYWFAR_CB GWEN_SyncIo_Socket_Write(GWEN_SYNCIO *sio, const uint8_t *buffer, uint32_t size)
#define I18N(m)
Definition: error.c:42
#define GWEN_SYNCIO_SOCKET_TYPE
Definition: syncio_socket.h:33
int GWEN_Gui_WaitForSockets(GWEN_SOCKET_LIST2 *readSockets, GWEN_SOCKET_LIST2 *writeSockets, uint32_t guiid, int msecs)
Definition: gui.c:1079
struct GWEN_SOCKET_LIST2 GWEN_SOCKET_LIST2
Definition: listdoc.h:3880
#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:81
void GWEN_Text_DumpString(const char *s, unsigned int l, unsigned int insert)
Definition: text.c:1235
GWEN_SYNCIO_WRITE_FN GWEN_SyncIo_SetWriteFn(GWEN_SYNCIO *sio, GWEN_SYNCIO_WRITE_FN fn)
Definition: syncio.c:283
#define GWEN_FREE_OBJECT(varname)
Definition: memory.h:92
#define NULL
Definition: binreloc.c:290
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:235
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:153
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:193
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
void GWENHYWFAR_CB GWEN_SyncIo_Socket_FreeData(void *bp, void *p)
Definition: syncio_socket.c:97
int GWENHYWFAR_CB GWEN_SyncIo_Socket_Disconnect(GWEN_SYNCIO *sio)
#define GWEN_NEW_OBJECT(typ, varname)
Definition: memory.h:86
struct GWEN_SYNCIO GWEN_SYNCIO
Definition: syncio.h:40
#define GWENHYWFAR_CB
Definition: gwenhywfarapi.h:89
int GWEN_Gui_ProgressLog2(uint32_t id, GWEN_LOGGER_LEVEL level, const char *fmt,...)
Definition: gui.c:951
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:185
GWENHYWFAR_API int GWEN_Socket_Close(GWEN_SOCKET *sp)
struct GWEN_INETADDRESSSTRUCT GWEN_INETADDRESS
Definition: inetaddr.h:97
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:85
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:247
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:164
GWENHYWFAR_API int GWEN_InetAddr_SetAddress(GWEN_INETADDRESS *ia, const char *addr)
struct GWEN_SOCKET GWEN_SOCKET
Definition: inetsocket.h:43
GWEN_SYNCIO * GWEN_SyncIo_Socket_TakeOver(GWEN_SOCKET *socket)
Definition: syncio_socket.c:75
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:271
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_INHERIT_GETDATA(bt, t, element)
Definition: inherit.h:271
GWENHYWFAR_API int GWEN_InetAddr_SetPort(GWEN_INETADDRESS *ia, int port)