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 #include <gwenhywfar/url.h>
00027 
00028 #include <gwenhywfar/text.h>
00029 #include <gwenhywfar/base64.h>
00030 
00031 #include <assert.h>
00032 #include <errno.h>
00033 #include <string.h>
00034 #include <unistd.h>
00035 #include <fcntl.h>
00036 
00037 
00038 #define GWEN_PROXY_ENVVAR "GWEN_PROXY"
00039 
00040 
00041 
00042 GWEN_INHERIT(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET)
00043 
00044 
00045 
00046 int GWEN_Proxy_Connect(GWEN_SOCKET *sp,
00047                        const GWEN_INETADDRESS *addr,
00048                        uint32_t guiid) {
00049   const char *s;
00050 
00051   /* do nothing for protocols other than TCP */
00052   if (GWEN_Socket_GetSocketType(sp)!=GWEN_SocketTypeTCP)
00053     return GWEN_Socket_Connect(sp, addr);
00054 
00055   s=getenv(GWEN_PROXY_ENVVAR);
00056   if (s && *s) {
00057     GWEN_URL *url;
00058     GWEN_BUFFER *sendBuf;
00059     int tport;
00060     char taddr[64];
00061     char numbuf[16];
00062     const char *t;
00063     int rv;
00064     GWEN_INETADDRESS *in;
00065     int ok=0;
00066     int first=1;
00067     int len;
00068     int idx=0;
00069     char wrk[1024];
00070 
00071     url=GWEN_Url_fromString(s);
00072     if (url==NULL) {
00073       DBG_ERROR(GWEN_LOGDOMAIN, "Bad string for proxy [%s]", s);
00074       return GWEN_ERROR_IO;
00075     }
00076 
00077     sendBuf=GWEN_Buffer_new(0, 256, 0, 1);
00078 
00079     /* build command line */
00080     GWEN_Buffer_AppendString(sendBuf, "CONNECT ");
00081 
00082     tport=GWEN_InetAddr_GetPort(addr);
00083     GWEN_InetAddr_GetAddress(addr, taddr, sizeof(taddr));
00084 
00085     GWEN_Buffer_AppendString(sendBuf, taddr);
00086     GWEN_Buffer_AppendString(sendBuf, ":");
00087     snprintf(numbuf, sizeof(numbuf)-1, "%d", tport);
00088     numbuf[sizeof(numbuf)-1]=0;
00089     GWEN_Buffer_AppendString(sendBuf, numbuf);
00090 
00091     GWEN_Buffer_AppendString(sendBuf, " HTTP/1.1\r\n");
00092 
00093     /* build host line required for HTTP/1.1 */
00094     GWEN_Buffer_AppendString(sendBuf, "Host: ");
00095     GWEN_Buffer_AppendString(sendBuf, taddr);
00096     GWEN_Buffer_AppendString(sendBuf, ":");
00097     GWEN_Buffer_AppendString(sendBuf, numbuf);
00098     GWEN_Buffer_AppendString(sendBuf, "\r\n");
00099 
00100     /* possibly add auth info */
00101     t=GWEN_Url_GetUserName(url);
00102     if (t && *t) {
00103       GWEN_BUFFER *abuf;
00104 
00105       /* we have auth info */
00106       abuf=GWEN_Buffer_new(0, 64, 0, 1);
00107       GWEN_Buffer_AppendString(sendBuf, "Proxy-Authorization: Basic ");
00108 
00109       GWEN_Buffer_AppendString(abuf, t);
00110       t=GWEN_Url_GetPassword(url);
00111       if (t && *t) {
00112         GWEN_Buffer_AppendString(abuf, ":");
00113         GWEN_Buffer_AppendString(abuf, t);
00114       }
00115       /* base64 encode */
00116       rv=GWEN_Base64_Encode((const unsigned char*) GWEN_Buffer_GetStart(abuf),
00117                             GWEN_Buffer_GetUsedBytes(abuf),
00118                             sendBuf, 0);
00119       if (rv<0) {
00120         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00121         GWEN_Buffer_free(abuf);
00122         GWEN_Buffer_free(sendBuf);
00123         GWEN_Url_free(url);
00124         return rv;
00125       }
00126       GWEN_Buffer_free(abuf);
00127       GWEN_Buffer_AppendString(sendBuf, "\r\n");
00128     }
00129 
00130     /* end header */
00131     GWEN_Buffer_AppendString(sendBuf, "\r\n");
00132     /* now sendBuf contains all necessary data */
00133 
00134     DBG_ERROR(0, "Would send this:");
00135     GWEN_Buffer_Dump(sendBuf, stderr, 2);
00136 
00137     /* prepare connect to proxy */
00138     in=GWEN_InetAddr_new(GWEN_AddressFamilyIP);
00139     assert(in);
00140 
00141     rv=GWEN_InetAddr_SetPort(in, GWEN_Url_GetPort(url));
00142     if (rv<0) {
00143       GWEN_InetAddr_free(in);
00144       GWEN_Buffer_free(sendBuf);
00145       GWEN_Url_free(url);
00146       return rv;
00147     }
00148 
00149     rv=GWEN_InetAddr_SetAddress(in, GWEN_Url_GetServer(url));
00150     if (rv) {
00151       if (rv==GWEN_ERROR_BAD_ADDRESS) {
00152         rv=GWEN_InetAddr_SetName(in, GWEN_Url_GetServer(url));
00153         if (rv) {
00154           GWEN_InetAddr_free(in);
00155           GWEN_Buffer_free(sendBuf);
00156           GWEN_Url_free(url);
00157           return rv;
00158         }
00159       }
00160       else {
00161         GWEN_InetAddr_free(in);
00162         GWEN_Buffer_free(sendBuf);
00163         GWEN_Url_free(url);
00164         return rv;
00165       }
00166     }
00167     GWEN_Url_free(url);
00168 
00169     /* this is the part I don't like very much but for now it is
00170      * necessary. Later this should be implemented non-blocking because the
00171      * code leading to the calling of this function expects the whole call
00172      * to be non-blocking... */
00173     rv=GWEN_Socket_SetBlocking(sp, 1);
00174     if (rv) {
00175       GWEN_InetAddr_free(in);
00176       GWEN_Buffer_free(sendBuf);
00177       return rv;
00178     }
00179   
00180     tport=GWEN_InetAddr_GetPort(in);
00181     GWEN_InetAddr_GetAddress(in, taddr, sizeof(taddr));
00182     DBG_INFO(GWEN_LOGDOMAIN, "Connecting to proxy %s (port %d)", taddr, tport);
00183     if (1) {
00184       char dbuf[256];
00185 
00186       snprintf(dbuf, sizeof(dbuf)-1, I18N("Connecting to proxy %s (port %d)"), taddr, tport);
00187       dbuf[sizeof(dbuf)-1]=0;
00188       GWEN_Gui_ProgressLog(guiid, GWEN_LoggerLevel_Info, dbuf);
00189     }
00190   
00191     /* connect to proxy */
00192     rv=GWEN_Socket_Connect(sp, in);
00193     GWEN_InetAddr_free(in);
00194     if (rv) {
00195       if (rv==GWEN_ERROR_IN_PROGRESS) {
00196         rv=GWEN_Socket_WaitForWrite(sp, 10000);
00197         if (rv) {
00198           DBG_INFO(GWEN_LOGDOMAIN, "Error connecting to proxy (%d)", rv);
00199           GWEN_Buffer_free(sendBuf);
00200           return rv;
00201         }
00202       }
00203       else {
00204         DBG_INFO(GWEN_LOGDOMAIN, "Error connecting to proxy (%d)", rv);
00205         GWEN_Buffer_free(sendBuf);
00206         return rv;
00207       }
00208     }
00209   
00210     /* write connect command */
00211     first=1;
00212     if (1) {
00213       const char *p;
00214 
00215       len=GWEN_Buffer_GetUsedBytes(sendBuf);
00216       p=GWEN_Buffer_GetStart(sendBuf);
00217       while(len) {
00218         int rl;
00219 
00220         rv=GWEN_Socket_WaitForWrite(sp, first?40000:1000);
00221         if (rv) {
00222           DBG_INFO(GWEN_LOGDOMAIN, "Error writing to proxy (%d)", rv);
00223           GWEN_Buffer_free(sendBuf);
00224           return rv;
00225         }
00226     
00227         first=0;
00228 
00229         rl=len;
00230         rv=GWEN_Socket_Write(sp, p, &rl);
00231         if (rv<0) {
00232           DBG_INFO(GWEN_LOGDOMAIN, "Error writing to proxy (%d)", rv);
00233           GWEN_Buffer_free(sendBuf);
00234           return rv;
00235         }
00236         if (rl<1) {
00237           DBG_INFO(GWEN_LOGDOMAIN, "Zero bytes written to proxy, aborting");
00238           GWEN_Buffer_free(sendBuf);
00239           return GWEN_ERROR_IO;
00240         }
00241         p+=rl;
00242         len-=rl;
00243       }
00244     }
00245     GWEN_Buffer_free(sendBuf);
00246 
00247     /* read response */
00248     first=1;
00249     while (1) {
00250       rv=GWEN_Socket_WaitForRead(sp, first?40000:1000);
00251       if (rv) {
00252         DBG_INFO(GWEN_LOGDOMAIN, "Error reading from proxy (%d)", rv);
00253         return rv;
00254       }
00255   
00256       first=0;
00257       len=1;
00258       rv=GWEN_Socket_Read(sp, wrk+idx, &len);
00259       if (rv) {
00260         DBG_INFO(GWEN_LOGDOMAIN, "Error reading from proxy (%d)", rv);
00261         return rv;
00262       }
00263   
00264       if(wrk[idx]=='\r')
00265         continue;
00266   
00267       if (wrk[idx]=='\n') {
00268         if (!idx) {
00269           /* empty line: header end, return result of previous status check */
00270           if (ok) {
00271             DBG_INFO(GWEN_LOGDOMAIN, "Proxy accepted CONNECT request, EOLN met");
00272             GWEN_Gui_ProgressLog(guiid, GWEN_LoggerLevel_Info, I18N("Proxy accepted CONNECT request."));
00273             return 0;
00274           }
00275           else {
00276             DBG_INFO(GWEN_LOGDOMAIN, "Emtpy line end, unknown proxy status");
00277             return GWEN_ERROR_IO;
00278           }
00279         }
00280 
00281         if (!ok) {
00282           wrk[idx]=0;
00283           if (strncmp(wrk, "HTTP/1.0 200", 12)==0 ||
00284               strncmp(wrk, "HTTP/1.1 200", 12)==0)
00285             ok=1;
00286           else {
00287             DBG_ERROR(GWEN_LOGDOMAIN, "Proxy rejected CONNECT request: %s", wrk);
00288             if (1) {
00289               GWEN_BUFFER *dbuf;
00290 
00291               dbuf=GWEN_Buffer_new(0, 256, 0, 1);
00292               GWEN_Buffer_AppendString(dbuf, I18N("Proxy rejected CONNECT request: "));
00293               GWEN_Buffer_AppendString(dbuf, wrk);
00294               GWEN_Gui_ProgressLog(guiid, GWEN_LoggerLevel_Info, GWEN_Buffer_GetStart(dbuf));
00295               GWEN_Buffer_free(dbuf);
00296             }
00297             return GWEN_ERROR_IO;
00298           }
00299         }
00300         idx=0;
00301       }
00302       else if (++idx==sizeof(wrk))
00303         return GWEN_ERROR_IO;
00304     }
00305   }
00306   else
00307     return GWEN_Socket_Connect(sp, addr);
00308 }
00309 
00310 
00311 
00312 #if 0
00313 int GWEN_Proxy_Connect(GWEN_SOCKET *sp, const GWEN_INETADDRESS *addr) {
00314   int err;
00315   int tport;
00316   int len;
00317   int idx=0;
00318   int ok=0;
00319   int first=1;
00320   char *proxy;
00321   char *port;
00322   GWEN_INETADDRESS *in;
00323   char taddr[64];
00324   char wrk[1024];
00325 
00326   if (GWEN_Socket_GetSocketType(sp)!=GWEN_SocketTypeTCP)
00327     return GWEN_Socket_Connect(sp, addr);
00328 
00329   tport=GWEN_InetAddr_GetPort(addr);
00330   GWEN_InetAddr_GetAddress(addr, taddr, sizeof(taddr));
00331   snprintf(wrk, sizeof(wrk)-1, "CONNECT %s:%d\n", taddr, tport);
00332   wrk[sizeof(wrk)-1]=0;
00333   len=strlen(wrk);
00334 
00335   port=proxy=strdup(getenv("GWEN_PROXY"));
00336   assert(port);
00337 
00338   while (*port) {
00339     if (*port==':') {
00340       *port++=0;
00341       break;
00342     }
00343     else
00344       port++;
00345   }
00346 
00347   if (!*port) {
00348     free(proxy);
00349     return GWEN_ERROR_BAD_ADDRESS;
00350   }
00351 
00352   in=GWEN_InetAddr_new(GWEN_AddressFamilyIP);
00353   assert(in);
00354 
00355   err=GWEN_InetAddr_SetPort(in, atoi(port));
00356   if (err) {
00357     free(proxy);
00358     GWEN_InetAddr_free(in);
00359     return err;
00360   }
00361 
00362   err=GWEN_InetAddr_SetAddress(in, proxy);
00363   if (err) {
00364     if (err==GWEN_ERROR_BAD_ADDRESS) {
00365       err=GWEN_InetAddr_SetName(in, proxy);
00366       if (err) {
00367         free(proxy);
00368         GWEN_InetAddr_free(in);
00369         return err;
00370       }
00371     }
00372     else {
00373       free(proxy);
00374       GWEN_InetAddr_free(in);
00375       return err;
00376     }
00377   }
00378 
00379   free(proxy);
00380 
00381   /* this is the part I don't like very much but for now it is
00382    * necessary. Later this should be implemented non-blocking because the
00383    * code leading to the calling of this function expects the whole call
00384    * to be non-blocking... */
00385   err=GWEN_Socket_SetBlocking(sp, 1);
00386   if (err) {
00387     GWEN_InetAddr_free(in);
00388     return err;
00389   }
00390 
00391   tport=GWEN_InetAddr_GetPort(in);
00392   GWEN_InetAddr_GetAddress(in, taddr, sizeof(taddr));
00393   DBG_INFO(GWEN_LOGDOMAIN, "Connecting to proxy %s (port %d)", taddr, tport);
00394 
00395   /* connect to proxy */
00396   err=GWEN_Socket_Connect(sp, in);
00397   GWEN_InetAddr_free(in);
00398   if (err) {
00399     if (err==GWEN_ERROR_IN_PROGRESS) {
00400       err=GWEN_Socket_WaitForWrite(sp, 10000);
00401       if (err)
00402         return err;
00403     }
00404     else
00405       return err;
00406   }
00407 
00408   /* write connect command */
00409   err=GWEN_Socket_Write(sp, wrk, &len);
00410   if (err)
00411     return err;
00412 
00413   while (1) {
00414     err=GWEN_Socket_WaitForRead(sp, first?40000:1000);
00415     if (err)
00416       return err;
00417 
00418     first=0;
00419     len=1;
00420     err=GWEN_Socket_Read(sp, wrk+idx, &len);
00421     if (err)
00422       return err;
00423 
00424     if(wrk[idx]=='\r')
00425       continue;
00426 
00427     if(wrk[idx]=='\n') {
00428       if (!idx) {
00429         if (ok)
00430           return 0;
00431         else
00432           return GWEN_ERROR_IO;
00433       }
00434 
00435       if(!ok) {
00436         wrk[idx]=0;
00437         if (strncmp(wrk, "HTTP/1.0 200", 12)==0 ||
00438             strncmp(wrk, "HTTP/1.1 200", 12)==0)
00439           ok=1;
00440         else
00441           return GWEN_ERROR_IO;
00442       }
00443 
00444       idx=0;
00445     }
00446     else if (++idx==sizeof(wrk))
00447       return GWEN_ERROR_IO;
00448   }
00449 }
00450 #endif
00451 
00452 
00453 
00454 GWEN_IO_LAYER *GWEN_Io_LayerSocket_new(GWEN_SOCKET *sk) {
00455   GWEN_IO_LAYER *io;
00456   GWEN_IO_LAYER_SOCKET *xio;
00457 
00458   io=GWEN_Io_Layer_new(GWEN_IO_LAYER_SOCKET_TYPE, NULL);
00459   assert(io);
00460   GWEN_NEW_OBJECT(GWEN_IO_LAYER_SOCKET, xio);
00461   assert(xio);
00462   GWEN_INHERIT_SETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io, xio, GWEN_Io_LayerSocket_freeData);
00463 
00464   GWEN_Io_Layer_SetWorkOnRequestsFn(io, GWEN_Io_LayerSocket_WorkOnRequests);
00465   GWEN_Io_Layer_SetAddRequestFn(io, GWEN_Io_LayerSocket_AddRequest);
00466   GWEN_Io_Layer_SetDelRequestFn(io, GWEN_Io_LayerSocket_DelRequest);
00467   GWEN_Io_Layer_SetHasWaitingRequestsFn(io, GWEN_Io_LayerSocket_HasWaitingRequests);
00468   GWEN_Io_Layer_SetAddWaitingSocketsFn(io, GWEN_Io_LayerSocket_AddWaitingSockets);
00469   GWEN_Io_Layer_SetListenFn(io, GWEN_Io_LayerSocket_Listen);
00470 
00471   xio->socket=sk;
00472 
00473   GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusUnconnected);
00474 
00475 
00476   return io;
00477 }
00478 
00479 
00480 
00481 GWENHYWFAR_CB
00482 void GWEN_Io_LayerSocket_freeData(void *bp, void *p) {
00483   GWEN_IO_LAYER *io;
00484   GWEN_IO_LAYER_SOCKET *xio;
00485   uint32_t lflags;
00486 
00487   io=(GWEN_IO_LAYER*) bp;
00488   assert(io);
00489   xio=(GWEN_IO_LAYER_SOCKET*) p;
00490   assert(xio);
00491 
00492   GWEN_Io_LayerSocket_AbortRequests(io, GWEN_ERROR_ABORTED);
00493   lflags=GWEN_Io_Layer_GetFlags(io);
00494 
00495   /* close socket (if it not already is) */
00496   if (!(lflags & GWEN_IO_LAYER_FLAGS_DONTCLOSE))
00497     GWEN_Socket_Close(xio->socket);
00498 
00499   /* free ressource (if requested) */
00500   if (lflags & GWEN_IO_LAYER_FLAGS_TAKEOVER) {
00501     GWEN_Socket_free(xio->socket);
00502     xio->socket=(GWEN_SOCKET*) -1;
00503   }
00504 
00505   /* done */
00506   GWEN_FREE_OBJECT(xio);
00507 }
00508 
00509 
00510 
00511 GWEN_INETADDRESS *GWEN_Io_LayerSocket_GetLocalAddr(const GWEN_IO_LAYER *io) {
00512   GWEN_IO_LAYER_SOCKET *xio;
00513 
00514   assert(io);
00515   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
00516   assert(xio);
00517 
00518   return xio->localAddr;
00519 }
00520 
00521 
00522 
00523 void GWEN_Io_LayerSocket_SetLocalAddr(GWEN_IO_LAYER *io, const GWEN_INETADDRESS *addr) {
00524   GWEN_IO_LAYER_SOCKET *xio;
00525 
00526   assert(io);
00527   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
00528   assert(xio);
00529 
00530   GWEN_InetAddr_free(xio->localAddr);
00531   if (addr) xio->localAddr=GWEN_InetAddr_dup(addr);
00532   else xio->localAddr=NULL;
00533 }
00534 
00535 
00536 
00537 GWEN_INETADDRESS *GWEN_Io_LayerSocket_GetPeerAddr(const GWEN_IO_LAYER *io) {
00538   GWEN_IO_LAYER_SOCKET *xio;
00539 
00540   assert(io);
00541   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
00542   assert(xio);
00543 
00544   return xio->peerAddr;
00545 }
00546 
00547 
00548 
00549 void GWEN_Io_LayerSocket_SetPeerAddr(GWEN_IO_LAYER *io, const GWEN_INETADDRESS *addr) {
00550   GWEN_IO_LAYER_SOCKET *xio;
00551 
00552   assert(io);
00553   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
00554   assert(xio);
00555 
00556   GWEN_InetAddr_free(xio->peerAddr);
00557   if (addr) xio->peerAddr=GWEN_InetAddr_dup(addr);
00558   else xio->peerAddr=NULL;
00559 }
00560 
00561 
00562 
00563 GWEN_SOCKET *GWEN_Io_LayerSocket_GetSocket(const GWEN_IO_LAYER *io) {
00564   GWEN_IO_LAYER_SOCKET *xio;
00565 
00566   assert(io);
00567   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
00568   assert(xio);
00569 
00570   return xio->socket;
00571 }
00572 
00573 
00574 
00575 void GWEN_Io_LayerSocket_AbortRequests(GWEN_IO_LAYER *io, int errorCode) {
00576   GWEN_IO_LAYER_SOCKET *xio;
00577 
00578   assert(io);
00579   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
00580   assert(xio);
00581 
00582   if (xio->connectRequest) {
00583     GWEN_IO_REQUEST *r;
00584 
00585     r=xio->connectRequest;
00586     xio->connectRequest=NULL;
00587     GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, errorCode);
00588     GWEN_Io_Request_free(r);
00589   }
00590   if (xio->readRequest) {
00591     GWEN_IO_REQUEST *r;
00592 
00593     r=xio->readRequest;
00594     xio->readRequest=NULL;
00595     GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, errorCode);
00596     GWEN_Io_Request_free(r);
00597   }
00598   if (xio->writeRequest) {
00599     GWEN_IO_REQUEST *r;
00600 
00601    r=xio->writeRequest;
00602    xio->writeRequest=NULL;
00603    GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, errorCode);
00604    GWEN_Io_Request_free(r);
00605   }
00606 }
00607 
00608 
00609 
00610 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerSocket_CheckForIncoming(GWEN_IO_LAYER *io) {
00611   GWEN_IO_LAYER_SOCKET *xio;
00612   int doneSomething=0;
00613 
00614   assert(io);
00615   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
00616   assert(xio);
00617 
00618   if (GWEN_Io_Layer_GetStatus(io)==GWEN_Io_Layer_StatusListening) {
00619     int rv;
00620     GWEN_SOCKET *newS=NULL;
00621     GWEN_INETADDRESS *iaddr=NULL;
00622 
00623     /* accept new connection (if there is any) */
00624     rv=GWEN_Socket_Accept(xio->socket, &iaddr, &newS);
00625     if (rv<0) {
00626       if (rv!=GWEN_ERROR_TIMEOUT && rv!=GWEN_ERROR_INTERRUPTED) {
00627         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00628         GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
00629         doneSomething=1;
00630       }
00631       /* still no incoming connection */
00632     }
00633     else {
00634       char addrBuffer[128];
00635       int port;
00636       GWEN_IO_LAYER *newIo;
00637 
00638       /* get peer address for logging */
00639       GWEN_InetAddr_GetAddress(iaddr, addrBuffer, sizeof(addrBuffer));
00640       port=GWEN_InetAddr_GetPort(iaddr);
00641       DBG_INFO(GWEN_LOGDOMAIN, "Incoming connection from %s (port %d)", addrBuffer, port);
00642 
00643       rv=GWEN_Socket_SetBlocking(newS, 0);
00644       if (rv) {
00645         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00646         GWEN_Socket_Close(newS);
00647         GWEN_Socket_free(newS);
00648         GWEN_InetAddr_free(iaddr);
00649       }
00650       else {
00651         /* got a connection, set it up */
00652         newIo=GWEN_Io_LayerSocket_new(newS);
00653         GWEN_Io_LayerSocket_SetLocalAddr(newIo, xio->localAddr);
00654         GWEN_Io_LayerSocket_SetPeerAddr(newIo, iaddr);
00655         GWEN_InetAddr_free(iaddr);
00656         GWEN_Io_Layer_AddFlags(newIo,
00657                                GWEN_IO_LAYER_FLAGS_PASSIVE |
00658                                GWEN_IO_LAYER_FLAGS_TAKEOVER); /* take over new socket */
00659         GWEN_Io_Layer_SetStatus(newIo, GWEN_Io_Layer_StatusConnected);
00660 
00661         GWEN_Io_Layer_AddIncomingLayer(io, newIo);
00662       }
00663       doneSomething=1;
00664     }
00665   }
00666 
00667   return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
00668 }
00669 
00670 
00671 
00672 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerSocket_WorkOnRequests(GWEN_IO_LAYER *io) {
00673   GWEN_IO_LAYER_SOCKET *xio;
00674   int doneSomething=0;
00675 
00676   assert(io);
00677   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
00678   assert(xio);
00679 
00680   DBG_VERBOUS(GWEN_LOGDOMAIN, "LayerSocket: Working");
00681 
00682   /* work on connect request */
00683   if (xio->connectRequest) {
00684     int rv;
00685     GWEN_IO_REQUEST *r;
00686 
00687     r=xio->connectRequest;
00688     rv=GWEN_Socket_GetSocketError(xio->socket);
00689     if (rv<0) {
00690       if (rv!=GWEN_ERROR_TIMEOUT && rv!=GWEN_ERROR_INTERRUPTED) {
00691         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00692         GWEN_Io_LayerSocket_AbortRequests(io, GWEN_ERROR_ABORTED);
00693         GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
00694         doneSomething=1;
00695       }
00696       /* still not connected */
00697     }
00698     else {
00699       char addrBuffer[128];
00700       int port;
00701 
00702       /* get address for logging */
00703       GWEN_InetAddr_GetAddress(xio->peerAddr, addrBuffer, sizeof(addrBuffer));
00704       port=GWEN_InetAddr_GetPort(xio->peerAddr);
00705       /* connected */
00706       xio->connectRequest=NULL;
00707       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00708       GWEN_Io_Request_free(r);
00709       GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusConnected);
00710       DBG_INFO(GWEN_LOGDOMAIN, "Now connected to %s (port %d)", addrBuffer, port);
00711       doneSomething=1;
00712     }
00713   }
00714 
00715   /* work on read request */
00716   if (xio->readRequest) {
00717     ssize_t rv;
00718     int bytesRead;
00719     GWEN_IO_REQUEST *r;
00720 
00721     r=xio->readRequest;
00722     bytesRead=GWEN_Io_Request_GetBufferSize(r)-GWEN_Io_Request_GetBufferPos(r);
00723     rv=GWEN_Socket_Read(xio->socket,
00724                         (char*) GWEN_Io_Request_GetBufferPtr(r)+
00725                         GWEN_Io_Request_GetBufferPos(r),
00726                         &bytesRead);
00727     if (rv<0) {
00728       if (rv!=GWEN_ERROR_TIMEOUT && rv!=GWEN_ERROR_INTERRUPTED) {
00729         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int)rv);
00730         xio->readRequest=NULL;
00731         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_IO);
00732         GWEN_Io_Request_free(r);
00733         doneSomething=1;
00734       }
00735       /* nothing to read, nothing done, so we don't set doneSomething=1 here ! */
00736     }
00737     else {
00738       if (bytesRead==0) {
00739         /* end of stream reached */
00740         DBG_INFO(GWEN_LOGDOMAIN, "End of stream reached");
00741         xio->readRequest=NULL;
00742         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_EOF);
00743         GWEN_Io_Request_free(r);
00744         doneSomething=1;
00745       }
00746       else {
00747         uint32_t newPos;
00748 
00749         /* some data returned */
00750         newPos=GWEN_Io_Request_GetBufferPos(r)+bytesRead;
00751         GWEN_Io_Request_SetBufferPos(r, newPos);
00752 
00753         if (newPos>=GWEN_Io_Request_GetBufferSize(r) ||
00754             !(GWEN_Io_Request_GetFlags(r) & GWEN_IO_REQUEST_FLAGS_READALL)) {
00755           xio->readRequest=NULL;
00756           GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00757           GWEN_Io_Request_free(r);
00758           DBG_VERBOUS(GWEN_LOGDOMAIN, "Read request finished (read %d bytes)", newPos);
00759         }
00760         else {
00761           DBG_VERBOUS(GWEN_LOGDOMAIN, "Read request waiting (got %d bytes)", newPos);
00762         }
00763         doneSomething=1;
00764       }
00765     }
00766   }
00767 
00768   /* work on write request */
00769   if (xio->writeRequest) {
00770     int bytesWritten;
00771     GWEN_IO_REQUEST *r;
00772     int rv;
00773 
00774     r=xio->writeRequest;
00775     bytesWritten=GWEN_Io_Request_GetBufferSize(r)-GWEN_Io_Request_GetBufferPos(r);
00776     rv=GWEN_Socket_Write(xio->socket,
00777                          (const char*)GWEN_Io_Request_GetBufferPtr(r)+
00778                          GWEN_Io_Request_GetBufferPos(r),
00779                          &bytesWritten);
00780     if (rv<0) {
00781       if (rv!=GWEN_ERROR_TIMEOUT && rv!=GWEN_ERROR_INTERRUPTED) {
00782         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00783         xio->writeRequest=NULL;
00784         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_IO);
00785         GWEN_Io_Request_free(r);
00786         doneSomething=1;
00787       }
00788       /* nothing to read, nothing done, so we don't set doneSomething=1 here ! */
00789     }
00790     else {
00791       uint32_t newPos;
00792 
00793       /* some data returned */
00794       newPos=GWEN_Io_Request_GetBufferPos(r)+bytesWritten;
00795       GWEN_Io_Request_SetBufferPos(r, newPos);
00796 
00797       if (newPos>=GWEN_Io_Request_GetBufferSize(r) ||
00798           !(GWEN_Io_Request_GetFlags(r) & GWEN_IO_REQUEST_FLAGS_WRITEALL)) {
00799         /* request complete */
00800         xio->writeRequest=NULL;
00801         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00802         GWEN_Io_Request_free(r);
00803         DBG_INFO(GWEN_LOGDOMAIN, "Write request finished (%d bytes written)", newPos);
00804       }
00805       doneSomething=1;
00806     }
00807   }
00808 
00809   /* possibly check for incoming layers */
00810   if (GWEN_Io_LayerSocket_CheckForIncoming(io)!=GWEN_Io_Layer_WorkResultBlocking)
00811     doneSomething=1;
00812 
00813 
00814   return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
00815 }
00816 
00817 
00818 
00819 int GWEN_Io_LayerSocket_AddRequest(GWEN_IO_LAYER *io, GWEN_IO_REQUEST *r) {
00820   GWEN_IO_LAYER_SOCKET *xio;
00821   GWEN_IO_LAYER_STATUS st;
00822   uint32_t lflags;
00823 
00824   assert(io);
00825   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
00826   assert(xio);
00827 
00828   st=GWEN_Io_Layer_GetStatus(io);
00829   lflags=GWEN_Io_Layer_GetFlags(io);
00830 
00831   switch(GWEN_Io_Request_GetType(r)) {
00832   case GWEN_Io_Request_TypeConnect:
00833     /* check status */
00834     if (st==GWEN_Io_Layer_StatusConnected &&
00835         (lflags & GWEN_IO_LAYER_FLAGS_PASSIVE)) {
00836       DBG_INFO(GWEN_LOGDOMAIN, "Socket already connected");
00837       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00838       return 0;
00839     }
00840     if (st!=GWEN_Io_Layer_StatusUnconnected &&
00841         st!=GWEN_Io_Layer_StatusDisconnected) {
00842       DBG_INFO(GWEN_LOGDOMAIN, "Socket is open");
00843       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_INVALID);
00844       return GWEN_ERROR_NOT_OPEN;
00845     }
00846 
00847     /* check whether we already have a read request */
00848     if (xio->connectRequest) {
00849       DBG_INFO(GWEN_LOGDOMAIN, "There already is a connect request");
00850       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_IN_PROGRESS);
00851       return GWEN_ERROR_IN_PROGRESS;
00852     }
00853     else {
00854       char addrBuffer[128];
00855       int port;
00856       int rv;
00857 
00858       /* get address for logging */
00859       GWEN_InetAddr_GetAddress(xio->peerAddr, addrBuffer, sizeof(addrBuffer));
00860       port=GWEN_InetAddr_GetPort(xio->peerAddr);
00861       DBG_INFO(GWEN_LOGDOMAIN, "Starting to connect to %s (port %d)", addrBuffer, port);
00862 
00863       /* not a passive io layer */
00864       GWEN_Io_Layer_SubFlags(io, GWEN_IO_LAYER_FLAGS_PASSIVE);
00865 
00866       /* open socket */
00867       rv=GWEN_Socket_Open(xio->socket);
00868       if (rv) {
00869         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00870         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, rv);
00871         return rv;
00872       }
00873 
00874       /* set nonblocking */
00875       rv=GWEN_Socket_SetBlocking(xio->socket, 0);
00876       if (rv) {
00877         GWEN_Socket_Close(xio->socket);
00878         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00879         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, rv);
00880         return rv;
00881       }
00882 
00883       /* actually start to connect */
00884       rv=GWEN_Proxy_Connect(xio->socket, xio->peerAddr, GWEN_Io_Request_GetGuiId(r));
00885       /* not yet finished or real error ? */
00886       if (rv) {
00887         if (rv!=GWEN_ERROR_IN_PROGRESS) {
00888           /* real error, so return that error */
00889           DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00890           GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, rv);
00891         }
00892         else {
00893           /* enqueue request */
00894           xio->connectRequest=r;
00895           GWEN_Io_Request_Attach(xio->connectRequest);
00896           GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusConnecting);
00897         }
00898       }
00899       else {
00900         /* connected */
00901         DBG_INFO(GWEN_LOGDOMAIN, "Immediately connected to %s (port %d)", addrBuffer, port);
00902         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00903         GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusConnected);
00904       }
00905     }
00906     break;
00907 
00908   case GWEN_Io_Request_TypeDisconnect:
00909     /* check status */
00910     if (st!=GWEN_Io_Layer_StatusConnected) {
00911       DBG_INFO(GWEN_LOGDOMAIN, "Io layer not connected");
00912       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
00913       return GWEN_ERROR_NOT_OPEN;
00914     }
00915     else {
00916       if ((xio->readRequest==NULL && xio->writeRequest==NULL) ||
00917           (GWEN_Io_Request_GetFlags(r) & GWEN_IO_REQUEST_FLAGS_FORCE)) {
00918         /* close files if not forbidden */
00919         if (!(lflags & GWEN_IO_LAYER_FLAGS_DONTCLOSE))
00920           GWEN_Socket_Close(xio->socket);
00921         GWEN_Io_LayerSocket_AbortRequests(io, GWEN_ERROR_ABORTED);
00922 
00923         /* closed */
00924         GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
00925         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00926       }
00927       else {
00928         /* still some pending operations, try again */
00929         return GWEN_ERROR_TRY_AGAIN;
00930       }
00931     }
00932     break;
00933 
00934   case GWEN_Io_Request_TypeRead:
00935     /* check status */
00936     if (st!=GWEN_Io_Layer_StatusConnected) {
00937       DBG_INFO(GWEN_LOGDOMAIN, "Socket is not open");
00938       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
00939       return GWEN_ERROR_NOT_OPEN;
00940     }
00941 
00942     /* check whether we already have a read request */
00943     if (xio->readRequest) {
00944       DBG_INFO(GWEN_LOGDOMAIN, "There already is a read request");
00945       return GWEN_ERROR_TRY_AGAIN;
00946     }
00947 
00948     /* enqueue request */
00949     xio->readRequest=r;
00950     GWEN_Io_Request_Attach(xio->readRequest);
00951     break;
00952 
00953   case GWEN_Io_Request_TypeWrite:
00954     /* check status */
00955     if (st!=GWEN_Io_Layer_StatusConnected) {
00956       DBG_INFO(GWEN_LOGDOMAIN, "File is not open");
00957       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
00958       return GWEN_ERROR_NOT_OPEN;
00959     }
00960 
00961     /* check whether we already have a write request */
00962     if (xio->writeRequest) {
00963       DBG_INFO(GWEN_LOGDOMAIN, "There already is a write request");
00964       return GWEN_ERROR_TRY_AGAIN;
00965     }
00966 
00967     /* enqueue request */
00968     xio->writeRequest=r;
00969     GWEN_Io_Request_Attach(xio->writeRequest);
00970     break;
00971 
00972   default:
00973     DBG_INFO(GWEN_LOGDOMAIN, "This request type is not supported (%d)", GWEN_Io_Request_GetType(r));
00974     GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_SUPPORTED);
00975     return GWEN_ERROR_NOT_SUPPORTED;
00976   }
00977 
00978   return 0;
00979 }
00980 
00981 
00982 
00983 int GWEN_Io_LayerSocket_DelRequest(GWEN_IO_LAYER *io, GWEN_IO_REQUEST *r) {
00984   GWEN_IO_LAYER_SOCKET *xio;
00985 
00986   assert(io);
00987   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
00988   assert(xio);
00989 
00990   switch(GWEN_Io_Request_GetType(r)) {
00991   case GWEN_Io_Request_TypeRead:
00992     if (xio->readRequest==r) {
00993       DBG_DEBUG(GWEN_LOGDOMAIN, "Aborted read request");
00994       xio->readRequest=NULL;
00995       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_ABORTED);
00996       GWEN_Io_Request_free(r);
00997     }
00998     else {
00999       /* not my request */
01000       DBG_INFO(GWEN_LOGDOMAIN, "Read request not registered with this io layer");
01001       return GWEN_ERROR_INVALID;
01002     }
01003     break;
01004 
01005   case GWEN_Io_Request_TypeWrite:
01006     if (xio->writeRequest==r) {
01007       DBG_DEBUG(GWEN_LOGDOMAIN, "Aborted write request");
01008       xio->writeRequest=NULL;
01009       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_ABORTED);
01010       GWEN_Io_Request_free(r);
01011     }
01012     else {
01013       /* not my request */
01014       DBG_INFO(GWEN_LOGDOMAIN, "Write request not registered with this io layer");
01015       return GWEN_ERROR_INVALID;
01016     }
01017     break;
01018 
01019   case GWEN_Io_Request_TypeConnect:
01020     if (xio->connectRequest==r) {
01021       DBG_DEBUG(GWEN_LOGDOMAIN, "Aborted connect request");
01022       if (!(GWEN_Io_Layer_GetFlags(io) & GWEN_IO_LAYER_FLAGS_DONTCLOSE))
01023         GWEN_Socket_Close(xio->socket);
01024       GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
01025       GWEN_Io_LayerSocket_AbortRequests(io, GWEN_ERROR_ABORTED);
01026     }
01027     else {
01028       /* not my request */
01029       DBG_INFO(GWEN_LOGDOMAIN, "Read request not registered with this io layer");
01030       return GWEN_ERROR_INVALID;
01031     }
01032     break;
01033 
01034   default:
01035     break;
01036   }
01037 
01038   return 0;
01039 }
01040 
01041 
01042 
01043 int GWEN_Io_LayerSocket_HasWaitingRequests(GWEN_IO_LAYER *io) {
01044   GWEN_IO_LAYER_SOCKET *xio;
01045 
01046   assert(io);
01047   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
01048   assert(xio);
01049 
01050   if (xio->readRequest || xio->writeRequest || xio->connectRequest)
01051     return 1;
01052   else
01053     return 0;
01054 }
01055 
01056 
01057 
01058 int GWEN_Io_LayerSocket_AddWaitingSockets(GWEN_IO_LAYER *io,
01059                                           GWEN_SOCKET_LIST2 *readSockets,
01060                                           GWEN_SOCKET_LIST2 *writeSockets) {
01061   GWEN_IO_LAYER_SOCKET *xio;
01062 
01063   assert(io);
01064   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
01065   assert(xio);
01066 
01067   if (xio->readRequest || GWEN_Io_Layer_GetStatus(io)==GWEN_Io_Layer_StatusListening)
01068     GWEN_Socket_List2_PushBack(readSockets, xio->socket);
01069   if (xio->writeRequest || xio->connectRequest)
01070     GWEN_Socket_List2_PushBack(writeSockets, xio->socket);
01071 
01072   return 0;
01073 }
01074 
01075 
01076 
01077 int GWEN_Io_LayerSocket_Listen(GWEN_IO_LAYER *io) {
01078   GWEN_IO_LAYER_SOCKET *xio;
01079   char addrBuffer[128];
01080   int port;
01081   int rv;
01082 
01083   assert(io);
01084   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_SOCKET, io);
01085   assert(xio);
01086 
01087   /* get address for logging */
01088   GWEN_InetAddr_GetAddress(xio->localAddr, addrBuffer, sizeof(addrBuffer));
01089   port=GWEN_InetAddr_GetPort(xio->localAddr);
01090 
01091   /* open socket */
01092   rv=GWEN_Socket_Open(xio->socket);
01093   if (rv) {
01094     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01095     return rv;
01096   }
01097   
01098   /* set nonblocking */
01099   rv=GWEN_Socket_SetBlocking(xio->socket, 0);
01100   if (rv) {
01101     GWEN_Socket_Close(xio->socket);
01102     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01103     return rv;
01104   }
01105 
01106   /* allow reuse of addresses */
01107   rv=GWEN_Socket_SetReuseAddress(xio->socket, 1);
01108   if (rv) {
01109     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01110   }
01111 
01112   /* bind socket to local address */
01113   rv=GWEN_Socket_Bind(xio->socket, xio->localAddr);
01114   if (rv) {
01115     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01116     return rv;
01117   }
01118 
01119   /* start listening */
01120   DBG_NOTICE(GWEN_LOGDOMAIN, "Starting to listen on %s (port %d)", addrBuffer, port);
01121   rv=GWEN_Socket_Listen(xio->socket, 10);
01122   if (rv) {
01123     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01124     return rv;
01125   }
01126 
01127   GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusListening);
01128 
01129   return 0;
01130 }
01131 
01132 
01133 
01134 
01135 
01136 
01137 
01138 
01139 
01140 
01141 
01142 
01143 
Generated on Mon Jul 5 22:51:13 2010 for gwenhywfar by  doxygen 1.6.3