gwenhywfar  4.6.0beta
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  if (rv<0) {
233  I18N("Error connecting to \"%s\": %s"),
234  xio->address,
235  strerror(errno));
236  GWEN_InetAddr_free(addr);
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  } while (rv==GWEN_ERROR_INTERRUPTED);
306 
307 
308  /* nothing to read immediately, wait for data availability */
309  if (rv==GWEN_ERROR_TIMEOUT) {
310  GWEN_SOCKET_LIST2 *sl;
311 
312  sl=GWEN_Socket_List2_new();
313  GWEN_Socket_List2_PushBack(sl, xio->socket);
314 
315  do {
317  } while (rv==GWEN_ERROR_INTERRUPTED);
318 
319  GWEN_Socket_List2_free(sl);
320  if (rv<0) {
321  if (rv==GWEN_ERROR_TIMEOUT) {
322  DBG_ERROR(GWEN_LOGDOMAIN, "timeout (%d)", rv);
323  return rv;
324  }
325  else {
326  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
327  return rv;
328  }
329  }
330  }
331 
332  i=size;
333  rv=GWEN_Socket_Read(xio->socket, (char*) buffer, &i);
334  if (rv<0) {
335  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
336  return rv;
337  }
338 
339 #if 0
340  DBG_ERROR(0, "Received this:");
341  GWEN_Text_DumpString((const char*) buffer, i, stderr, 2);
342 #endif
343 
344  return i;
345 }
346 
347 
348 
350  const uint8_t *buffer,
351  uint32_t size) {
352  GWEN_SYNCIO_SOCKET *xio;
353  int rv;
354  int i;
355 
356  assert(sio);
357  xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
358  assert(xio);
359 
361  /* not connected */
362  DBG_ERROR(GWEN_LOGDOMAIN, "Socket not connected");
364  }
365 
366  if (xio->socket==NULL) {
367  DBG_ERROR(GWEN_LOGDOMAIN, "No socket");
368  return GWEN_ERROR_INTERNAL;
369  }
370 
371  /* check whether the socket is writeable */
372  do {
373  rv=GWEN_Socket_WaitForWrite(xio->socket, 0);
374  } while (rv==GWEN_ERROR_INTERRUPTED);
375 
376  if (rv==GWEN_ERROR_TIMEOUT) {
377  int rv;
378  GWEN_SOCKET_LIST2 *sl;
379 
380  sl=GWEN_Socket_List2_new();
381  GWEN_Socket_List2_PushBack(sl, xio->socket);
382 
383  do {
385  } while (rv==GWEN_ERROR_INTERRUPTED);
386 
387  if (rv<0) {
388  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
389  GWEN_Socket_List2_free(sl);
390  return rv;
391  }
392  GWEN_Socket_List2_free(sl);
393  }
394 
395  i=size;
396  rv=GWEN_Socket_Write(xio->socket, (const char*) buffer, &i);
397  if (rv<0) {
398  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
399  return rv;
400  }
401 
402 #if 0
403  DBG_ERROR(0, "Written this:");
404  GWEN_Text_DumpString((const char*) buffer, i, stderr, 2);
405 #endif
406 
407  return i;
408 }
409 
410 
411 
412 
413