00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00170 return 0;
00171
00172 if (GWEN_SyncIo_GetFlags(sio) & GWEN_SYNCIO_FLAGS_PASSIVE) {
00173
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
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
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
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
00303 do {
00304 rv=GWEN_Socket_WaitForRead(xio->socket, 0);
00305 } while (rv==GWEN_ERROR_INTERRUPTED);
00306
00307
00308
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
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
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