gwenhywfar
4.3.1
|
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