io_socket.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  $RCSfile$
00003                              -------------------
00004     cvs         : $Id: crypttoken.h 1113 2007-01-10 09:14:16Z martin $
00005     begin       : Wed Mar 16 2005
00006     copyright   : (C) 2005 by Martin Preuss
00007     email       : martin@libchipcard.de
00008 
00009  ***************************************************************************
00010  *          Please see toplevel file COPYING for license details           *
00011  ***************************************************************************/
00012 
00013 #ifdef HAVE_CONFIG_H
00014 # include <config.h>
00015 #endif
00016 
00017 
00018 #include "io_socket_p.h"
00019 #include <gwenhywfar/iolayer_be.h>
00020 #include <gwenhywfar/iorequest_be.h>
00021 
00022 #include "i18n_l.h"
00023 #include <gwenhywfar/misc.h>
00024 #include <gwenhywfar/debug.h>
00025 #include <gwenhywfar/gui.h>
00026 
00027 #include <gwenhywfar/text.h> /* debug */
00028 
00029 #include <assert.h>
00030 #include <errno.h>
00031 #include <string.h>
00032 #include <unistd.h>
00033 #include <fcntl.h>
00034 
00035 
00036 //#define HACK_FOR_DAVID
00037 
00038 
00039 GWEN_INHERIT(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET)
00040 
00041 
00042 
00043 int GWEN_Proxy_Connect(GWEN_SOCKET *sp, const GWEN_INETADDRESS *addr) {
00044   int err;
00045   int tport;
00046   int len;
00047   int idx=0;
00048   int ok=0;
00049   int first=1;
00050   char *proxy;
00051   char *port;
00052   GWEN_INETADDRESS *in;
00053   char taddr[64];
00054   char wrk[1024];
00055 
00056   if (GWEN_Socket_GetSocketType(sp)!=GWEN_SocketTypeTCP)
00057     return GWEN_Socket_Connect(sp, addr);
00058 
00059   tport=GWEN_InetAddr_GetPort(addr);
00060   GWEN_InetAddr_GetAddress(addr, taddr, sizeof(taddr));
00061   snprintf(wrk, sizeof(wrk)-1, "CONNECT %s:%d\n", taddr, tport);
00062   wrk[sizeof(wrk)-1]=0;
00063   len=strlen(wrk);
00064 
00065   port=proxy=strdup(getenv("GWEN_PROXY"));
00066   assert(port);
00067 
00068   while (*port) {
00069     if (*port==':') {
00070       *port++=0;
00071       break;
00072     }
00073     else
00074       port++;
00075   }
00076 
00077   if (!*port) {
00078     free(proxy);
00079     return GWEN_ERROR_BAD_ADDRESS;
00080   }
00081 
00082   in=GWEN_InetAddr_new(GWEN_AddressFamilyIP);
00083   assert(in);
00084 
00085   err=GWEN_InetAddr_SetPort(in, atoi(port));
00086   if (err) {
00087     free(proxy);
00088     GWEN_InetAddr_free(in);
00089     return err;
00090   }
00091 
00092   err=GWEN_InetAddr_SetAddress(in, proxy);
00093   if (err) {
00094     if (err==GWEN_ERROR_BAD_ADDRESS) {
00095       err=GWEN_InetAddr_SetName(in, proxy);
00096       if (err) {
00097         free(proxy);
00098         GWEN_InetAddr_free(in);
00099         return err;
00100       }
00101     }
00102     else {
00103       free(proxy);
00104       GWEN_InetAddr_free(in);
00105       return err;
00106     }
00107   }
00108 
00109   free(proxy);
00110 
00111   /* this is the part I don't like very much but for now it is
00112    * necessary. Later this should be implemented non-blocking because the
00113    * code leading to the calling of this function expects the whole call
00114    * to be non-blocking... */
00115   err=GWEN_Socket_SetBlocking(sp, 1);
00116   if (err) {
00117     GWEN_InetAddr_free(in);
00118     return err;
00119   }
00120 
00121   tport=GWEN_InetAddr_GetPort(in);
00122   GWEN_InetAddr_GetAddress(in, taddr, sizeof(taddr));
00123   DBG_INFO(GWEN_LOGDOMAIN, "Connecting to proxy %s (port %d)", taddr, tport);
00124 
00125   /* connect to proxy */
00126   err=GWEN_Socket_Connect(sp, in);
00127   GWEN_InetAddr_free(in);
00128   if (err) {
00129     if (err==GWEN_ERROR_IN_PROGRESS) {
00130       err=GWEN_Socket_WaitForWrite(sp, 10000);
00131       if (err)
00132         return err;
00133     }
00134     else
00135       return err;
00136   }
00137 
00138   /* write connect command */
00139   err=GWEN_Socket_Write(sp, wrk, &len);
00140   if (err)
00141     return err;
00142 
00143   while (1) {
00144     err=GWEN_Socket_WaitForRead(sp, first?40000:1000);
00145     if (err)
00146       return err;
00147 
00148     first=0;
00149     len=1;
00150     err=GWEN_Socket_Read(sp, wrk+idx, &len);
00151     if (err)
00152       return err;
00153 
00154     if(wrk[idx]=='\r')
00155       continue;
00156 
00157     if(wrk[idx]=='\n') {
00158       if (!idx) {
00159         if (ok)
00160           return 0;
00161         else
00162           return GWEN_ERROR_IO;
00163       }
00164 
00165       if(!ok) {
00166         wrk[idx]=0;
00167         if (strncmp(wrk, "HTTP/1.0 200", 12)==0 ||
00168             strncmp(wrk, "HTTP/1.1 200", 12)==0)
00169           ok=1;
00170         else
00171           return GWEN_ERROR_IO;
00172       }
00173 
00174       idx=0;
00175     }
00176     else if (++idx==sizeof(wrk))
00177       return GWEN_ERROR_IO;
00178   }
00179 }
00180 
00181 
00182 
00183 GWEN_IO_LAYER *GWEN_Io_LayerSocket_new(GWEN_SOCKET *sk) {
00184   GWEN_IO_LAYER *io;
00185   GWEN_IO_LAYER_SOCKET *xio;
00186 
00187   io=GWEN_Io_Layer_new(GWEN_IO_LAYER_SOCKET_TYPE, NULL);
00188   assert(io);
00189   GWEN_NEW_OBJECT(GWEN_IO_LAYER_SOCKET, xio);
00190   assert(xio);
00191   GWEN_INHERIT_SETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io, xio, GWEN_Io_LayerSocket_freeData);
00192 
00193   GWEN_Io_Layer_SetWorkOnRequestsFn(io, GWEN_Io_LayerSocket_WorkOnRequests);
00194   GWEN_Io_Layer_SetAddRequestFn(io, GWEN_Io_LayerSocket_AddRequest);
00195   GWEN_Io_Layer_SetDelRequestFn(io, GWEN_Io_LayerSocket_DelRequest);
00196   GWEN_Io_Layer_SetHasWaitingRequestsFn(io, GWEN_Io_LayerSocket_HasWaitingRequests);
00197   GWEN_Io_Layer_SetAddWaitingSocketsFn(io, GWEN_Io_LayerSocket_AddWaitingSockets);
00198   GWEN_Io_Layer_SetListenFn(io, GWEN_Io_LayerSocket_Listen);
00199 
00200   xio->socket=sk;
00201 
00202   GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusUnconnected);
00203 
00204 
00205   return io;
00206 }
00207 
00208 
00209 
00210 GWENHYWFAR_CB
00211 void GWEN_Io_LayerSocket_freeData(void *bp, void *p) {
00212   GWEN_IO_LAYER *io;
00213   GWEN_IO_LAYER_SOCKET *xio;
00214   uint32_t lflags;
00215 
00216   io=(GWEN_IO_LAYER*) bp;
00217   assert(io);
00218   xio=(GWEN_IO_LAYER_SOCKET*) p;
00219   assert(xio);
00220 
00221   GWEN_Io_LayerSocket_AbortRequests(io, GWEN_ERROR_ABORTED);
00222   lflags=GWEN_Io_Layer_GetFlags(io);
00223 
00224   /* close socket (if it not already is) */
00225   if (!(lflags & GWEN_IO_LAYER_FLAGS_DONTCLOSE))
00226     GWEN_Socket_Close(xio->socket);
00227 
00228   /* free ressource (if requested) */
00229   if (lflags & GWEN_IO_LAYER_FLAGS_TAKEOVER) {
00230     GWEN_Socket_free(xio->socket);
00231     xio->socket=(GWEN_SOCKET*) -1;
00232   }
00233 
00234   /* done */
00235   GWEN_FREE_OBJECT(xio);
00236 }
00237 
00238 
00239 
00240 GWEN_INETADDRESS *GWEN_Io_LayerSocket_GetLocalAddr(const GWEN_IO_LAYER *io) {
00241   GWEN_IO_LAYER_SOCKET *xio;
00242 
00243   assert(io);
00244   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
00245   assert(xio);
00246 
00247   return xio->localAddr;
00248 }
00249 
00250 
00251 
00252 void GWEN_Io_LayerSocket_SetLocalAddr(GWEN_IO_LAYER *io, const GWEN_INETADDRESS *addr) {
00253   GWEN_IO_LAYER_SOCKET *xio;
00254 
00255   assert(io);
00256   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
00257   assert(xio);
00258 
00259   GWEN_InetAddr_free(xio->localAddr);
00260   if (addr) xio->localAddr=GWEN_InetAddr_dup(addr);
00261   else xio->localAddr=NULL;
00262 }
00263 
00264 
00265 
00266 GWEN_INETADDRESS *GWEN_Io_LayerSocket_GetPeerAddr(const GWEN_IO_LAYER *io) {
00267   GWEN_IO_LAYER_SOCKET *xio;
00268 
00269   assert(io);
00270   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
00271   assert(xio);
00272 
00273   return xio->peerAddr;
00274 }
00275 
00276 
00277 
00278 void GWEN_Io_LayerSocket_SetPeerAddr(GWEN_IO_LAYER *io, const GWEN_INETADDRESS *addr) {
00279   GWEN_IO_LAYER_SOCKET *xio;
00280 
00281   assert(io);
00282   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
00283   assert(xio);
00284 
00285   GWEN_InetAddr_free(xio->peerAddr);
00286   if (addr) xio->peerAddr=GWEN_InetAddr_dup(addr);
00287   else xio->peerAddr=NULL;
00288 }
00289 
00290 
00291 
00292 GWEN_SOCKET *GWEN_Io_LayerSocket_GetSocket(const GWEN_IO_LAYER *io) {
00293   GWEN_IO_LAYER_SOCKET *xio;
00294 
00295   assert(io);
00296   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
00297   assert(xio);
00298 
00299   return xio->socket;
00300 }
00301 
00302 
00303 
00304 void GWEN_Io_LayerSocket_AbortRequests(GWEN_IO_LAYER *io, int errorCode) {
00305   GWEN_IO_LAYER_SOCKET *xio;
00306 
00307   assert(io);
00308   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
00309   assert(xio);
00310 
00311   if (xio->connectRequest) {
00312     GWEN_IO_REQUEST *r;
00313 
00314     r=xio->connectRequest;
00315     xio->connectRequest=NULL;
00316     GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, errorCode);
00317     GWEN_Io_Request_free(r);
00318   }
00319   if (xio->readRequest) {
00320     GWEN_IO_REQUEST *r;
00321 
00322     r=xio->readRequest;
00323     xio->readRequest=NULL;
00324     GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, errorCode);
00325     GWEN_Io_Request_free(r);
00326   }
00327   if (xio->writeRequest) {
00328     GWEN_IO_REQUEST *r;
00329 
00330    r=xio->writeRequest;
00331    xio->writeRequest=NULL;
00332    GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, errorCode);
00333    GWEN_Io_Request_free(r);
00334   }
00335 }
00336 
00337 
00338 
00339 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerSocket_CheckForIncoming(GWEN_IO_LAYER *io) {
00340   GWEN_IO_LAYER_SOCKET *xio;
00341   int doneSomething=0;
00342 
00343   assert(io);
00344   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
00345   assert(xio);
00346 
00347   if (GWEN_Io_Layer_GetStatus(io)==GWEN_Io_Layer_StatusListening) {
00348     int rv;
00349     GWEN_SOCKET *newS=NULL;
00350     GWEN_INETADDRESS *iaddr=NULL;
00351 
00352     /* accept new connection (if there is any) */
00353     rv=GWEN_Socket_Accept(xio->socket, &iaddr, &newS);
00354     if (rv<0) {
00355       if (rv!=GWEN_ERROR_TIMEOUT && rv!=GWEN_ERROR_INTERRUPTED) {
00356         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00357         GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
00358         doneSomething=1;
00359       }
00360       /* still no incoming connection */
00361     }
00362     else {
00363       char addrBuffer[128];
00364       int port;
00365       GWEN_IO_LAYER *newIo;
00366 
00367       /* get peer address for logging */
00368       GWEN_InetAddr_GetAddress(iaddr, addrBuffer, sizeof(addrBuffer));
00369       port=GWEN_InetAddr_GetPort(iaddr);
00370       DBG_INFO(GWEN_LOGDOMAIN, "Incoming connection from %s (port %d)", addrBuffer, port);
00371 
00372       rv=GWEN_Socket_SetBlocking(newS, 0);
00373       if (rv) {
00374         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00375         GWEN_Socket_Close(newS);
00376         GWEN_Socket_free(newS);
00377         GWEN_InetAddr_free(iaddr);
00378       }
00379       else {
00380         /* got a connection, set it up */
00381         newIo=GWEN_Io_LayerSocket_new(newS);
00382         GWEN_Io_LayerSocket_SetLocalAddr(newIo, xio->localAddr);
00383         GWEN_Io_LayerSocket_SetPeerAddr(newIo, iaddr);
00384         GWEN_InetAddr_free(iaddr);
00385         GWEN_Io_Layer_AddFlags(newIo,
00386                                GWEN_IO_LAYER_FLAGS_PASSIVE |
00387                                GWEN_IO_LAYER_FLAGS_TAKEOVER); /* take over new socket */
00388         GWEN_Io_Layer_SetStatus(newIo, GWEN_Io_Layer_StatusConnected);
00389 
00390         GWEN_Io_Layer_AddIncomingLayer(io, newIo);
00391       }
00392       doneSomething=1;
00393     }
00394   }
00395 
00396   return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
00397 }
00398 
00399 
00400 
00401 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerSocket_WorkOnRequests(GWEN_IO_LAYER *io) {
00402   GWEN_IO_LAYER_SOCKET *xio;
00403   int doneSomething=0;
00404 
00405   assert(io);
00406   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
00407   assert(xio);
00408 
00409   DBG_VERBOUS(GWEN_LOGDOMAIN, "LayerSocket: Working");
00410 
00411   /* work on connect request */
00412   if (xio->connectRequest) {
00413     int rv;
00414     GWEN_IO_REQUEST *r;
00415 
00416     r=xio->connectRequest;
00417     rv=GWEN_Socket_GetSocketError(xio->socket);
00418     if (rv<0) {
00419       if (rv!=GWEN_ERROR_TIMEOUT && rv!=GWEN_ERROR_INTERRUPTED) {
00420         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00421         GWEN_Io_LayerSocket_AbortRequests(io, GWEN_ERROR_ABORTED);
00422         GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
00423         doneSomething=1;
00424       }
00425       /* still not connected */
00426     }
00427     else {
00428       char addrBuffer[128];
00429       int port;
00430 
00431       /* get address for logging */
00432       GWEN_InetAddr_GetAddress(xio->peerAddr, addrBuffer, sizeof(addrBuffer));
00433       port=GWEN_InetAddr_GetPort(xio->peerAddr);
00434       /* connected */
00435       xio->connectRequest=NULL;
00436       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00437       GWEN_Io_Request_free(r);
00438       GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusConnected);
00439       DBG_INFO(GWEN_LOGDOMAIN, "Now connected to %s (port %d)", addrBuffer, port);
00440       doneSomething=1;
00441     }
00442   }
00443 
00444   /* work on read request */
00445   if (xio->readRequest) {
00446     ssize_t rv;
00447     int bytesRead;
00448     GWEN_IO_REQUEST *r;
00449 
00450     r=xio->readRequest;
00451     bytesRead=GWEN_Io_Request_GetBufferSize(r)-GWEN_Io_Request_GetBufferPos(r);
00452     rv=GWEN_Socket_Read(xio->socket,
00453                         (char*) GWEN_Io_Request_GetBufferPtr(r)+
00454                         GWEN_Io_Request_GetBufferPos(r),
00455                         &bytesRead);
00456     if (rv<0) {
00457       if (rv!=GWEN_ERROR_TIMEOUT && rv!=GWEN_ERROR_INTERRUPTED) {
00458         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int)rv);
00459         xio->readRequest=NULL;
00460         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_IO);
00461         GWEN_Io_Request_free(r);
00462         doneSomething=1;
00463       }
00464       /* nothing to read, nothing done, so we don't set doneSomething=1 here ! */
00465     }
00466     else {
00467       if (bytesRead==0) {
00468         /* end of stream reached */
00469         DBG_INFO(GWEN_LOGDOMAIN, "End of stream reached");
00470         xio->readRequest=NULL;
00471         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_EOF);
00472         GWEN_Io_Request_free(r);
00473         doneSomething=1;
00474       }
00475       else {
00476         uint32_t newPos;
00477 
00478         /* some data returned */
00479         newPos=GWEN_Io_Request_GetBufferPos(r)+bytesRead;
00480         GWEN_Io_Request_SetBufferPos(r, newPos);
00481 
00482         if (newPos>=GWEN_Io_Request_GetBufferSize(r) ||
00483             !(GWEN_Io_Request_GetFlags(r) & GWEN_IO_REQUEST_FLAGS_READALL)) {
00484           xio->readRequest=NULL;
00485           GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00486           GWEN_Io_Request_free(r);
00487           DBG_VERBOUS(GWEN_LOGDOMAIN, "Read request finished (read %d bytes)", newPos);
00488         }
00489         else {
00490           DBG_VERBOUS(GWEN_LOGDOMAIN, "Read request waiting (got %d bytes)", newPos);
00491         }
00492         doneSomething=1;
00493       }
00494     }
00495   }
00496 
00497   /* work on write request */
00498   if (xio->writeRequest) {
00499     int bytesWritten;
00500     GWEN_IO_REQUEST *r;
00501     int rv;
00502 
00503     r=xio->writeRequest;
00504     bytesWritten=GWEN_Io_Request_GetBufferSize(r)-GWEN_Io_Request_GetBufferPos(r);
00505     rv=GWEN_Socket_Write(xio->socket,
00506                          (const char*)GWEN_Io_Request_GetBufferPtr(r)+
00507                          GWEN_Io_Request_GetBufferPos(r),
00508                          &bytesWritten);
00509     if (rv<0) {
00510       if (rv!=GWEN_ERROR_TIMEOUT && rv!=GWEN_ERROR_INTERRUPTED) {
00511         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00512         xio->writeRequest=NULL;
00513         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_IO);
00514         GWEN_Io_Request_free(r);
00515         doneSomething=1;
00516       }
00517       /* nothing to read, nothing done, so we don't set doneSomething=1 here ! */
00518     }
00519     else {
00520       uint32_t newPos;
00521 
00522       /* some data returned */
00523       newPos=GWEN_Io_Request_GetBufferPos(r)+bytesWritten;
00524       GWEN_Io_Request_SetBufferPos(r, newPos);
00525 
00526       if (newPos>=GWEN_Io_Request_GetBufferSize(r) ||
00527           !(GWEN_Io_Request_GetFlags(r) & GWEN_IO_REQUEST_FLAGS_WRITEALL)) {
00528         /* request complete */
00529         xio->writeRequest=NULL;
00530         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00531         GWEN_Io_Request_free(r);
00532         DBG_INFO(GWEN_LOGDOMAIN, "Write request finished (%d bytes written)", newPos);
00533       }
00534       doneSomething=1;
00535     }
00536   }
00537 
00538   /* possibly check for incoming layers */
00539   if (GWEN_Io_LayerSocket_CheckForIncoming(io)!=GWEN_Io_Layer_WorkResultBlocking)
00540     doneSomething=1;
00541 
00542 
00543   return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
00544 }
00545 
00546 
00547 
00548 int GWEN_Io_LayerSocket_AddRequest(GWEN_IO_LAYER *io, GWEN_IO_REQUEST *r) {
00549   GWEN_IO_LAYER_SOCKET *xio;
00550   GWEN_IO_LAYER_STATUS st;
00551   uint32_t lflags;
00552 
00553   assert(io);
00554   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
00555   assert(xio);
00556 
00557   st=GWEN_Io_Layer_GetStatus(io);
00558   lflags=GWEN_Io_Layer_GetFlags(io);
00559 
00560   switch(GWEN_Io_Request_GetType(r)) {
00561   case GWEN_Io_Request_TypeConnect:
00562     /* check status */
00563     if (st==GWEN_Io_Layer_StatusConnected &&
00564         (lflags & GWEN_IO_LAYER_FLAGS_PASSIVE)) {
00565       DBG_INFO(GWEN_LOGDOMAIN, "Socket already connected");
00566       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00567       return 0;
00568     }
00569     if (st!=GWEN_Io_Layer_StatusUnconnected &&
00570         st!=GWEN_Io_Layer_StatusDisconnected) {
00571       DBG_INFO(GWEN_LOGDOMAIN, "Socket is open");
00572       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_INVALID);
00573       return GWEN_ERROR_NOT_OPEN;
00574     }
00575 
00576     /* check whether we already have a read request */
00577     if (xio->connectRequest) {
00578       DBG_INFO(GWEN_LOGDOMAIN, "There already is a connect request");
00579       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_IN_PROGRESS);
00580       return GWEN_ERROR_IN_PROGRESS;
00581     }
00582     else {
00583       char addrBuffer[128];
00584       int port;
00585       int rv;
00586 
00587       /* get address for logging */
00588       GWEN_InetAddr_GetAddress(xio->peerAddr, addrBuffer, sizeof(addrBuffer));
00589       port=GWEN_InetAddr_GetPort(xio->peerAddr);
00590       DBG_INFO(GWEN_LOGDOMAIN, "Starting to connect to %s (port %d)", addrBuffer, port);
00591 
00592       /* not a passive io layer */
00593       GWEN_Io_Layer_SubFlags(io, GWEN_IO_LAYER_FLAGS_PASSIVE);
00594 
00595       /* open socket */
00596       rv=GWEN_Socket_Open(xio->socket);
00597       if (rv) {
00598         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00599         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, rv);
00600         return rv;
00601       }
00602 
00603 #ifndef HACK_FOR_DAVID
00604       /* set nonblocking */
00605       rv=GWEN_Socket_SetBlocking(xio->socket, 0);
00606       if (rv) {
00607         GWEN_Socket_Close(xio->socket);
00608         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00609         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, rv);
00610         return rv;
00611       }
00612 #endif
00613 
00614       /* actually start to connect */
00615       if (getenv("GWEN_PROXY"))
00616         rv=GWEN_Proxy_Connect(xio->socket, xio->peerAddr);
00617       else
00618         rv=GWEN_Socket_Connect(xio->socket, xio->peerAddr);
00619       /* not yet finished or real error ? */
00620       if (rv) {
00621         if (rv!=GWEN_ERROR_IN_PROGRESS) {
00622           /* real error, so return that error */
00623           DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00624           GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, rv);
00625         }
00626         else {
00627           /* enqueue request */
00628           xio->connectRequest=r;
00629           GWEN_Io_Request_Attach(xio->connectRequest);
00630           GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusConnecting);
00631         }
00632       }
00633       else {
00634 #ifdef HACK_FOR_DAVID
00635         /* set nonblocking */
00636         rv=GWEN_Socket_SetBlocking(xio->socket, 0);
00637         if (rv) {
00638           GWEN_Socket_Close(xio->socket);
00639           DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00640           GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, rv);
00641           return rv;
00642         }
00643 #endif
00644 
00645         /* connected */
00646         DBG_INFO(GWEN_LOGDOMAIN, "Immediately connected to %s (port %d)", addrBuffer, port);
00647         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00648         GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusConnected);
00649       }
00650     }
00651     break;
00652 
00653   case GWEN_Io_Request_TypeDisconnect:
00654     /* check status */
00655     if (st!=GWEN_Io_Layer_StatusConnected) {
00656       DBG_INFO(GWEN_LOGDOMAIN, "Io layer not connected");
00657       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
00658       return GWEN_ERROR_NOT_OPEN;
00659     }
00660     else {
00661       if ((xio->readRequest==NULL && xio->writeRequest==NULL) ||
00662           (GWEN_Io_Request_GetFlags(r) & GWEN_IO_REQUEST_FLAGS_FORCE)) {
00663         /* close files if not forbidden */
00664         if (!(lflags & GWEN_IO_LAYER_FLAGS_DONTCLOSE))
00665           GWEN_Socket_Close(xio->socket);
00666         GWEN_Io_LayerSocket_AbortRequests(io, GWEN_ERROR_ABORTED);
00667 
00668         /* closed */
00669         GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
00670         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00671       }
00672       else {
00673         /* still some pending operations, try again */
00674         return GWEN_ERROR_TRY_AGAIN;
00675       }
00676     }
00677     break;
00678 
00679   case GWEN_Io_Request_TypeRead:
00680     /* check status */
00681     if (st!=GWEN_Io_Layer_StatusConnected) {
00682       DBG_INFO(GWEN_LOGDOMAIN, "Socket is not open");
00683       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
00684       return GWEN_ERROR_NOT_OPEN;
00685     }
00686 
00687     /* check whether we already have a read request */
00688     if (xio->readRequest) {
00689       DBG_INFO(GWEN_LOGDOMAIN, "There already is a read request");
00690       return GWEN_ERROR_TRY_AGAIN;
00691     }
00692 
00693     /* enqueue request */
00694     xio->readRequest=r;
00695     GWEN_Io_Request_Attach(xio->readRequest);
00696     break;
00697 
00698   case GWEN_Io_Request_TypeWrite:
00699     /* check status */
00700     if (st!=GWEN_Io_Layer_StatusConnected) {
00701       DBG_INFO(GWEN_LOGDOMAIN, "File is not open");
00702       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
00703       return GWEN_ERROR_NOT_OPEN;
00704     }
00705 
00706     /* check whether we already have a write request */
00707     if (xio->writeRequest) {
00708       DBG_INFO(GWEN_LOGDOMAIN, "There already is a write request");
00709       return GWEN_ERROR_TRY_AGAIN;
00710     }
00711 
00712     /* enqueue request */
00713     xio->writeRequest=r;
00714     GWEN_Io_Request_Attach(xio->writeRequest);
00715     break;
00716 
00717   default:
00718     DBG_INFO(GWEN_LOGDOMAIN, "This request type is not supported (%d)", GWEN_Io_Request_GetType(r));
00719     GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_SUPPORTED);
00720     return GWEN_ERROR_NOT_SUPPORTED;
00721   }
00722 
00723   return 0;
00724 }
00725 
00726 
00727 
00728 int GWEN_Io_LayerSocket_DelRequest(GWEN_IO_LAYER *io, GWEN_IO_REQUEST *r) {
00729   GWEN_IO_LAYER_SOCKET *xio;
00730 
00731   assert(io);
00732   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
00733   assert(xio);
00734 
00735   switch(GWEN_Io_Request_GetType(r)) {
00736   case GWEN_Io_Request_TypeRead:
00737     if (xio->readRequest==r) {
00738       DBG_DEBUG(GWEN_LOGDOMAIN, "Aborted read request");
00739       xio->readRequest=NULL;
00740       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_ABORTED);
00741       GWEN_Io_Request_free(r);
00742     }
00743     else {
00744       /* not my request */
00745       DBG_INFO(GWEN_LOGDOMAIN, "Read request not registered with this io layer");
00746       return GWEN_ERROR_INVALID;
00747     }
00748     break;
00749 
00750   case GWEN_Io_Request_TypeWrite:
00751     if (xio->writeRequest==r) {
00752       DBG_DEBUG(GWEN_LOGDOMAIN, "Aborted write request");
00753       xio->writeRequest=NULL;
00754       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_ABORTED);
00755       GWEN_Io_Request_free(r);
00756     }
00757     else {
00758       /* not my request */
00759       DBG_INFO(GWEN_LOGDOMAIN, "Write request not registered with this io layer");
00760       return GWEN_ERROR_INVALID;
00761     }
00762     break;
00763 
00764   case GWEN_Io_Request_TypeConnect:
00765     if (xio->connectRequest==r) {
00766       DBG_DEBUG(GWEN_LOGDOMAIN, "Aborted connect request");
00767       if (!(GWEN_Io_Layer_GetFlags(io) & GWEN_IO_LAYER_FLAGS_DONTCLOSE))
00768         GWEN_Socket_Close(xio->socket);
00769       GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
00770       GWEN_Io_LayerSocket_AbortRequests(io, GWEN_ERROR_ABORTED);
00771     }
00772     else {
00773       /* not my request */
00774       DBG_INFO(GWEN_LOGDOMAIN, "Read request not registered with this io layer");
00775       return GWEN_ERROR_INVALID;
00776     }
00777     break;
00778 
00779   default:
00780     break;
00781   }
00782 
00783   return 0;
00784 }
00785 
00786 
00787 
00788 int GWEN_Io_LayerSocket_HasWaitingRequests(GWEN_IO_LAYER *io) {
00789   GWEN_IO_LAYER_SOCKET *xio;
00790 
00791   assert(io);
00792   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
00793   assert(xio);
00794 
00795   if (xio->readRequest || xio->writeRequest || xio->connectRequest)
00796     return 1;
00797   else
00798     return 0;
00799 }
00800 
00801 
00802 
00803 int GWEN_Io_LayerSocket_AddWaitingSockets(GWEN_IO_LAYER *io,
00804                                           GWEN_SOCKET_LIST2 *readSockets,
00805                                           GWEN_SOCKET_LIST2 *writeSockets) {
00806   GWEN_IO_LAYER_SOCKET *xio;
00807 
00808   assert(io);
00809   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
00810   assert(xio);
00811 
00812   if (xio->readRequest || GWEN_Io_Layer_GetStatus(io)==GWEN_Io_Layer_StatusListening)
00813     GWEN_Socket_List2_PushBack(readSockets, xio->socket);
00814   if (xio->writeRequest || xio->connectRequest)
00815     GWEN_Socket_List2_PushBack(writeSockets, xio->socket);
00816 
00817   return 0;
00818 }
00819 
00820 
00821 
00822 int GWEN_Io_LayerSocket_Listen(GWEN_IO_LAYER *io) {
00823   GWEN_IO_LAYER_SOCKET *xio;
00824   char addrBuffer[128];
00825   int port;
00826   int rv;
00827 
00828   assert(io);
00829   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
00830   assert(xio);
00831 
00832   /* get address for logging */
00833   GWEN_InetAddr_GetAddress(xio->localAddr, addrBuffer, sizeof(addrBuffer));
00834   port=GWEN_InetAddr_GetPort(xio->localAddr);
00835 
00836   /* open socket */
00837   rv=GWEN_Socket_Open(xio->socket);
00838   if (rv) {
00839     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00840     return rv;
00841   }
00842   
00843   /* set nonblocking */
00844   rv=GWEN_Socket_SetBlocking(xio->socket, 0);
00845   if (rv) {
00846     GWEN_Socket_Close(xio->socket);
00847     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00848     return rv;
00849   }
00850 
00851   /* allow reuse of addresses */
00852   rv=GWEN_Socket_SetReuseAddress(xio->socket, 1);
00853   if (rv) {
00854     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00855   }
00856 
00857   /* bind socket to local address */
00858   rv=GWEN_Socket_Bind(xio->socket, xio->localAddr);
00859   if (rv) {
00860     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00861     return rv;
00862   }
00863 
00864   /* start listening */
00865   DBG_NOTICE(GWEN_LOGDOMAIN, "Starting to listen on %s (port %d)", addrBuffer, port);
00866   rv=GWEN_Socket_Listen(xio->socket, 10);
00867   if (rv) {
00868     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00869     return rv;
00870   }
00871 
00872   GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusListening);
00873 
00874   return 0;
00875 }
00876 
00877 
00878 
00879 
00880 
00881 
00882 
00883 
00884 
00885 
00886 
00887 
00888 

Generated on Thu Aug 20 13:54:38 2009 for gwenhywfar by  doxygen 1.5.9