gwenhywfar 4.0.3

syncio_socket.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  begin       : Tue Apr 27 2010
00003  copyright   : (C) 2010 by Martin Preuss
00004  email       : martin@libchipcard.de
00005 
00006  ***************************************************************************
00007  *                                                                         *
00008  *   This library is free software; you can redistribute it and/or         *
00009  *   modify it under the terms of the GNU Lesser General Public            *
00010  *   License as published by the Free Software Foundation; either          *
00011  *   version 2.1 of the License, or (at your option) any later version.    *
00012  *                                                                         *
00013  *   This library is distributed in the hope that it will be useful,       *
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00016  *   Lesser General Public License for more details.                       *
00017  *                                                                         *
00018  *   You should have received a copy of the GNU Lesser General Public      *
00019  *   License along with this library; if not, write to the Free Software   *
00020  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
00021  *   MA  02111-1307  USA                                                   *
00022  *                                                                         *
00023  ***************************************************************************/
00024 
00025 #ifdef HAVE_CONFIG_H
00026 # include <config.h>
00027 #endif
00028 
00029 #define DISABLE_DEBUGLOG
00030 
00031 
00032 
00033 #include "syncio_socket_p.h"
00034 #include "i18n_l.h"
00035 
00036 #include <gwenhywfar/misc.h>
00037 #include <gwenhywfar/debug.h>
00038 #include <gwenhywfar/gui.h>
00039 #include <gwenhywfar/text.h>
00040 
00041 #include <assert.h>
00042 #include <errno.h>
00043 #include <string.h>
00044 
00045 
00046 #define GWEN_SYNCIO_SOCKET_READ_TIMEOUT  60000
00047 #define GWEN_SYNCIO_SOCKET_WRITE_TIMEOUT 60000
00048 
00049 
00050 GWEN_INHERIT(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET)
00051 
00052 
00053 
00054 GWEN_SYNCIO *GWEN_SyncIo_Socket_new(GWEN_SOCKETTYPE sockType, GWEN_AddressFamily addressFamily) {
00055   GWEN_SYNCIO *sio;
00056   GWEN_SYNCIO_SOCKET *xio;
00057 
00058   sio=GWEN_SyncIo_new(GWEN_SYNCIO_SOCKET_TYPE, NULL);
00059   GWEN_NEW_OBJECT(GWEN_SYNCIO_SOCKET, xio);
00060   GWEN_INHERIT_SETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio, xio, GWEN_SyncIo_Socket_FreeData);
00061 
00062   GWEN_SyncIo_SetConnectFn(sio, GWEN_SyncIo_Socket_Connect);
00063   GWEN_SyncIo_SetDisconnectFn(sio, GWEN_SyncIo_Socket_Disconnect);
00064   GWEN_SyncIo_SetReadFn(sio, GWEN_SyncIo_Socket_Read);
00065   GWEN_SyncIo_SetWriteFn(sio, GWEN_SyncIo_Socket_Write);
00066 
00067   xio->socketType=sockType;
00068   xio->addressFamily=addressFamily;
00069 
00070   return sio;
00071 }
00072 
00073 
00074 
00075 GWEN_SYNCIO *GWEN_SyncIo_Socket_TakeOver(GWEN_SOCKET *socket) {
00076   GWEN_SYNCIO *sio;
00077   GWEN_SYNCIO_SOCKET *xio;
00078 
00079   sio=GWEN_SyncIo_new(GWEN_SYNCIO_SOCKET_TYPE, NULL);
00080   GWEN_NEW_OBJECT(GWEN_SYNCIO_SOCKET, xio);
00081   GWEN_INHERIT_SETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio, xio, GWEN_SyncIo_Socket_FreeData);
00082 
00083   GWEN_SyncIo_SetConnectFn(sio, GWEN_SyncIo_Socket_Connect);
00084   GWEN_SyncIo_SetDisconnectFn(sio, GWEN_SyncIo_Socket_Disconnect);
00085   GWEN_SyncIo_SetReadFn(sio, GWEN_SyncIo_Socket_Read);
00086   GWEN_SyncIo_SetWriteFn(sio, GWEN_SyncIo_Socket_Write);
00087 
00088   xio->socketType=GWEN_Socket_GetSocketType(socket);
00089   xio->socket=socket;
00090   GWEN_SyncIo_SetStatus(sio, GWEN_SyncIo_Status_Connected);
00091 
00092   return sio;
00093 }
00094 
00095 
00096 
00097 void GWENHYWFAR_CB GWEN_SyncIo_Socket_FreeData(void *bp, void *p) {
00098   GWEN_SYNCIO_SOCKET *xio;
00099 
00100   xio=(GWEN_SYNCIO_SOCKET*) p;
00101   free(xio->address);
00102   GWEN_Socket_free(xio->socket);
00103   GWEN_FREE_OBJECT(xio);
00104 }
00105 
00106 
00107 
00108 const char *GWEN_SyncIo_Socket_GetAddress(const GWEN_SYNCIO *sio) {
00109   GWEN_SYNCIO_SOCKET *xio;
00110 
00111   assert(sio);
00112   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
00113   assert(xio);
00114 
00115   return xio->address;
00116 }
00117 
00118 
00119 
00120 void GWEN_SyncIo_Socket_SetAddress(GWEN_SYNCIO *sio, const char *s) {
00121   GWEN_SYNCIO_SOCKET *xio;
00122 
00123   assert(sio);
00124   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
00125   assert(xio);
00126 
00127   free(xio->address);
00128   if (s) xio->address=strdup(s);
00129   else xio->address=NULL;
00130 }
00131 
00132 
00133 
00134 int GWEN_SyncIo_Socket_GetPort(const GWEN_SYNCIO *sio) {
00135   GWEN_SYNCIO_SOCKET *xio;
00136 
00137   assert(sio);
00138   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
00139   assert(xio);
00140 
00141   return xio->port;
00142 }
00143 
00144 
00145 
00146 void GWEN_SyncIo_Socket_SetPort(GWEN_SYNCIO *sio, int i) {
00147   GWEN_SYNCIO_SOCKET *xio;
00148 
00149   assert(sio);
00150   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
00151   assert(xio);
00152 
00153   xio->port=i;
00154 }
00155 
00156 
00157 
00158 int GWENHYWFAR_CB GWEN_SyncIo_Socket_Connect(GWEN_SYNCIO *sio) {
00159   GWEN_SYNCIO_SOCKET *xio;
00160   GWEN_SOCKET *sk;
00161   GWEN_INETADDRESS *addr;
00162   int rv;
00163 
00164   assert(sio);
00165   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
00166   assert(xio);
00167 
00168   if (GWEN_SyncIo_GetStatus(sio)==GWEN_SyncIo_Status_Connected)
00169     /* already connected */
00170     return 0;
00171 
00172   if (GWEN_SyncIo_GetFlags(sio) & GWEN_SYNCIO_FLAGS_PASSIVE) {
00173     /* passive, can't connect */
00174     DBG_ERROR(GWEN_LOGDOMAIN, "Passive socket, can't connect");
00175     return GWEN_ERROR_INVALID;
00176   }
00177 
00178   sk=GWEN_Socket_new(xio->socketType);
00179   rv=GWEN_Socket_Open(sk);
00180   if (rv<0) {
00181     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00182     GWEN_Gui_ProgressLog2(0,
00183                           GWEN_LoggerLevel_Error,
00184                           I18N("Error setting up socket: %d"),
00185                           rv);
00186     GWEN_Socket_free(sk);
00187     return rv;
00188   }
00189   addr=GWEN_InetAddr_new(xio->addressFamily);
00190 
00191   rv=GWEN_InetAddr_SetAddress(addr, xio->address);
00192   if (rv<0) {
00193     GWEN_Gui_ProgressLog2(0,
00194                           GWEN_LoggerLevel_Info,
00195                           I18N("Resolving hostname \"%s\" ..."),
00196                           xio->address);
00197     rv=GWEN_InetAddr_SetName(addr, xio->address);
00198     if (rv<0) {
00199       GWEN_Gui_ProgressLog2(0,
00200                             GWEN_LoggerLevel_Error,
00201                             I18N("Unknown hostname \"%s\""),
00202                             xio->address);
00203       GWEN_InetAddr_free(addr);
00204       GWEN_Socket_free(sk);
00205       return rv;
00206     }
00207     else {
00208       char addrBuf[256];
00209 
00210       rv=GWEN_InetAddr_GetAddress(addr, addrBuf, sizeof(addrBuf)-1);
00211       addrBuf[sizeof(addrBuf)-1]=0;
00212       if (rv<0) {
00213         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00214       }
00215       else
00216         GWEN_Gui_ProgressLog2(0,
00217                               GWEN_LoggerLevel_Info,
00218                               I18N("IP address is \"%s\""),
00219                               addrBuf);
00220     }
00221   }
00222   GWEN_InetAddr_SetPort(addr, xio->port);
00223 
00224   /* connect */
00225   GWEN_Gui_ProgressLog2(0,
00226                         GWEN_LoggerLevel_Info,
00227                         I18N("Connecting to \"%s\""),
00228                         xio->address);
00229   rv=GWEN_Socket_Connect(sk, addr);
00230   if (rv<0) {
00231     GWEN_Gui_ProgressLog2(0,
00232                           GWEN_LoggerLevel_Error,
00233                           I18N("Error connecting to \"%s\": %s"),
00234                           xio->address,
00235                           strerror(errno));
00236     GWEN_InetAddr_free(addr);
00237     GWEN_Socket_free(sk);
00238     return rv;
00239   }
00240 
00241   /* done */
00242   xio->socket=sk;
00243   GWEN_SyncIo_SetStatus(sio, GWEN_SyncIo_Status_Connected);
00244   DBG_INFO(GWEN_LOGDOMAIN, "Connected to \"%s\"", xio->address);
00245   GWEN_Gui_ProgressLog2(0,
00246                         GWEN_LoggerLevel_Notice,
00247                         I18N("Connected to \"%s\""),
00248                         xio->address);
00249   return 0;
00250 }
00251 
00252 
00253 
00254 int GWENHYWFAR_CB GWEN_SyncIo_Socket_Disconnect(GWEN_SYNCIO *sio) {
00255   GWEN_SYNCIO_SOCKET *xio;
00256 
00257   assert(sio);
00258   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
00259   assert(xio);
00260 
00261   if (xio->socket) {
00262     GWEN_Socket_Close(xio->socket);
00263     GWEN_Socket_free(xio->socket);
00264     xio->socket=NULL;
00265     GWEN_SyncIo_SetStatus(sio, GWEN_SyncIo_Status_Disconnected);
00266     DBG_INFO(GWEN_LOGDOMAIN, "Disconnected socket");
00267   }
00268 
00269   return 0;
00270 }
00271 
00272 
00273 
00274 int GWENHYWFAR_CB GWEN_SyncIo_Socket_Read(GWEN_SYNCIO *sio,
00275                                           uint8_t *buffer,
00276                                           uint32_t size) {
00277   GWEN_SYNCIO_SOCKET *xio;
00278   int rv;
00279   int i;
00280 
00281   assert(sio);
00282   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
00283   assert(xio);
00284 
00285   if (size==0) {
00286     DBG_ERROR(GWEN_LOGDOMAIN, "Read size is zero");
00287     return GWEN_ERROR_INVALID;
00288   }
00289 
00290   if (GWEN_SyncIo_GetStatus(sio)!=GWEN_SyncIo_Status_Connected) {
00291     /* not connected */
00292     DBG_ERROR(GWEN_LOGDOMAIN, "Socket not connected (%d)",
00293               GWEN_SyncIo_GetStatus(sio));
00294     return GWEN_ERROR_NOT_CONNECTED;
00295   }
00296 
00297   if (xio->socket==NULL) {
00298     DBG_ERROR(GWEN_LOGDOMAIN, "No socket");
00299     return GWEN_ERROR_INTERNAL;
00300   }
00301 
00302   /* check whether there is data available */
00303   do {
00304     rv=GWEN_Socket_WaitForRead(xio->socket, 0);
00305   } while (rv==GWEN_ERROR_INTERRUPTED);
00306 
00307 
00308   /* nothing to read immediately, wait for data availability */
00309   if (rv==GWEN_ERROR_TIMEOUT) {
00310     GWEN_SOCKET_LIST2 *sl;
00311 
00312     sl=GWEN_Socket_List2_new();
00313     GWEN_Socket_List2_PushBack(sl, xio->socket);
00314 
00315     do {
00316       rv=GWEN_Gui_WaitForSockets(sl, NULL, 0, GWEN_SYNCIO_SOCKET_READ_TIMEOUT);
00317     } while (rv==GWEN_ERROR_INTERRUPTED);
00318 
00319     GWEN_Socket_List2_free(sl);
00320     if (rv<0) {
00321       if (rv==GWEN_ERROR_TIMEOUT) {
00322         DBG_ERROR(GWEN_LOGDOMAIN, "timeout (%d)", rv);
00323         return rv;
00324       }
00325       else {
00326         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00327         return rv;
00328       }
00329     }
00330   }
00331 
00332   i=size;
00333   rv=GWEN_Socket_Read(xio->socket, (char*) buffer, &i);
00334   if (rv<0) {
00335     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00336     return rv;
00337   }
00338 
00339 #if 0
00340   DBG_ERROR(0, "Received this:");
00341   GWEN_Text_DumpString((const char*) buffer, i, stderr, 2);
00342 #endif
00343 
00344   return i;
00345 }
00346 
00347 
00348 
00349 int GWENHYWFAR_CB GWEN_SyncIo_Socket_Write(GWEN_SYNCIO *sio,
00350                                            const uint8_t *buffer,
00351                                            uint32_t size) {
00352   GWEN_SYNCIO_SOCKET *xio;
00353   int rv;
00354   int i;
00355 
00356   assert(sio);
00357   xio=GWEN_INHERIT_GETDATA(GWEN_SYNCIO, GWEN_SYNCIO_SOCKET, sio);
00358   assert(xio);
00359 
00360   if (GWEN_SyncIo_GetStatus(sio)!=GWEN_SyncIo_Status_Connected) {
00361     /* not connected */
00362     DBG_ERROR(GWEN_LOGDOMAIN, "Socket not connected");
00363     return GWEN_ERROR_NOT_CONNECTED;
00364   }
00365 
00366   if (xio->socket==NULL) {
00367     DBG_ERROR(GWEN_LOGDOMAIN, "No socket");
00368     return GWEN_ERROR_INTERNAL;
00369   }
00370 
00371   /* check whether the socket is writeable */
00372   do {
00373     rv=GWEN_Socket_WaitForWrite(xio->socket, 0);
00374   } while (rv==GWEN_ERROR_INTERRUPTED);
00375 
00376   if (rv==GWEN_ERROR_TIMEOUT) {
00377     int rv;
00378     GWEN_SOCKET_LIST2 *sl;
00379 
00380     sl=GWEN_Socket_List2_new();
00381     GWEN_Socket_List2_PushBack(sl, xio->socket);
00382 
00383     do {
00384       rv=GWEN_Gui_WaitForSockets(NULL, sl, 0, GWEN_SYNCIO_SOCKET_WRITE_TIMEOUT);
00385     } while (rv==GWEN_ERROR_INTERRUPTED);
00386 
00387     if (rv<0) {
00388       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00389       GWEN_Socket_List2_free(sl);
00390       return rv;
00391     }
00392     GWEN_Socket_List2_free(sl);
00393   }
00394 
00395   i=size;
00396   rv=GWEN_Socket_Write(xio->socket, (const char*) buffer, &i);
00397   if (rv<0) {
00398     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00399     return rv;
00400   }
00401 
00402 #if 0
00403   DBG_ERROR(0, "Written this:");
00404   GWEN_Text_DumpString((const char*) buffer, i, stderr, 2);
00405 #endif
00406 
00407   return i;
00408 }
00409 
00410 
00411 
00412 
00413