io_buffered.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_buffered_p.h"
00019 #include <gwenhywfar/iolayer_be.h>
00020 #include <gwenhywfar/iorequest_be.h>
00021 #include <gwenhywfar/iomanager.h>
00022 
00023 #include "i18n_l.h"
00024 #include <gwenhywfar/misc.h>
00025 #include <gwenhywfar/debug.h>
00026 #include <gwenhywfar/gui.h>
00027 
00028 #include <assert.h>
00029 
00030 
00031 
00032 GWEN_INHERIT(GWEN_IO_LAYER, GWEN_IO_LAYER_BUFFERED)
00033 
00034 
00035 
00036 GWEN_IO_LAYER *GWEN_Io_LayerBuffered_new(GWEN_IO_LAYER *baseLayer) {
00037   GWEN_IO_LAYER *io;
00038   GWEN_IO_LAYER_BUFFERED *xio;
00039 
00040   io=GWEN_Io_Layer_new(GWEN_IO_LAYER_BUFFERED_TYPE, baseLayer);
00041   assert(io);
00042   GWEN_NEW_OBJECT(GWEN_IO_LAYER_BUFFERED, xio);
00043   assert(xio);
00044   GWEN_INHERIT_SETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_BUFFERED, io, xio, GWEN_Io_LayerBuffered_freeData);
00045 
00046   GWEN_Io_Layer_SetWorkOnRequestsFn(io, GWEN_Io_LayerBuffered_WorkOnRequests);
00047   GWEN_Io_Layer_SetAddRequestFn(io, GWEN_Io_LayerBuffered_AddRequest);
00048   GWEN_Io_Layer_SetDelRequestFn(io, GWEN_Io_LayerBuffered_DelRequest);
00049   GWEN_Io_Layer_SetHasWaitingRequestsFn(io, GWEN_Io_LayerBuffered_HasWaitingRequests);
00050 
00051   /* this io layer is always initially connected */
00052   GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusConnected);
00053 
00054   return io;
00055 }
00056 
00057 
00058 
00059 GWENHYWFAR_CB
00060 void GWEN_Io_LayerBuffered_freeData(void *bp, void *p) {
00061   GWEN_IO_LAYER *io;
00062   GWEN_IO_LAYER_BUFFERED *xio;
00063 
00064   io=(GWEN_IO_LAYER*) bp;
00065   assert(io);
00066   xio=(GWEN_IO_LAYER_BUFFERED*) p;
00067   assert(xio);
00068 
00069   GWEN_Io_LayerBuffered_AbortInRequests(io, GWEN_ERROR_ABORTED);
00070   GWEN_Io_LayerBuffered_AbortOutRequests(io);
00071 
00072   GWEN_RingBuffer_free(xio->readBuffer);
00073   GWEN_RingBuffer_free(xio->writeBuffer);
00074 
00075   GWEN_FREE_OBJECT(xio);
00076 }
00077 
00078 
00079 
00080 void GWEN_Io_LayerBuffered_AbortInRequests(GWEN_IO_LAYER *io, int errorCode) {
00081   GWEN_IO_LAYER_BUFFERED *xio;
00082 
00083   assert(io);
00084   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_BUFFERED, io);
00085   assert(xio);
00086 
00087   if (xio->readRequestIn) {
00088     GWEN_IO_REQUEST *r;
00089 
00090     r=xio->readRequestIn;
00091     xio->readRequestIn=NULL;
00092     DBG_INFO(GWEN_LOGDOMAIN, "Aborting in read request");
00093     GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, errorCode);
00094     GWEN_Io_Request_free(r);
00095   }
00096   if (xio->writeRequestIn) {
00097     GWEN_IO_REQUEST *r;
00098 
00099     r=xio->writeRequestIn;
00100     xio->writeRequestIn=NULL;
00101     DBG_INFO(GWEN_LOGDOMAIN, "Aborting in write request");
00102     GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, errorCode);
00103     GWEN_Io_Request_free(r);
00104   }
00105 }
00106 
00107 
00108 
00109 void GWEN_Io_LayerBuffered_AbortOutRequests(GWEN_IO_LAYER *io) {
00110   GWEN_IO_LAYER_BUFFERED *xio;
00111 
00112   assert(io);
00113   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_BUFFERED, io);
00114   assert(xio);
00115 
00116   if (xio->readRequestOut) {
00117     GWEN_IO_REQUEST *r;
00118 
00119     r=xio->readRequestOut;
00120     GWEN_Io_Layer_DelRequest(GWEN_Io_Layer_GetBaseLayer(io), r);
00121     xio->readRequestOut=NULL;
00122     GWEN_Io_Request_free(r);
00123   }
00124   if (xio->writeRequestIn) {
00125     GWEN_IO_REQUEST *r;
00126 
00127     r=xio->writeRequestIn;
00128     GWEN_Io_Layer_DelRequest(GWEN_Io_Layer_GetBaseLayer(io), r);
00129     xio->writeRequestIn=NULL;
00130     GWEN_Io_Request_free(r);
00131   }
00132 }
00133 
00134 
00135 
00136 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerBuffered_WorkOnReadRequest(GWEN_IO_LAYER *io) {
00137   GWEN_IO_LAYER_BUFFERED *xio;
00138   int doneSomething=0;
00139 
00140   assert(io);
00141   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_BUFFERED, io);
00142   assert(xio);
00143 
00144   if (xio->readRequestOut) {
00145     /* check for finished outbound read request */
00146     if (GWEN_Io_Request_GetStatus(xio->readRequestOut)==GWEN_Io_Request_StatusFinished) {
00147       uint32_t bpos;
00148 
00149       doneSomething=1;
00150 
00151       /* get all available data */
00152       bpos=GWEN_Io_Request_GetBufferPos(xio->readRequestOut);
00153       if (bpos==0) {
00154         DBG_INFO(GWEN_LOGDOMAIN, "No bytes read");
00155       }
00156       DBG_VERBOUS(GWEN_LOGDOMAIN, "Read %d bytes into ringbuffer", bpos);
00157       GWEN_RingBuffer_SkipBytesWrite(xio->readBuffer, bpos);
00158 
00159       /* save result code */
00160       xio->lastReadOutResult=GWEN_Io_Request_GetResultCode(xio->readRequestOut);
00161 
00162       GWEN_Io_Request_free(xio->readRequestOut);
00163       xio->readRequestOut=NULL;
00164     }
00165   }
00166 
00167   if (xio->readRequestIn) {
00168     uint32_t len;
00169     GWEN_IO_REQUEST *r;
00170     uint32_t rflags;
00171 
00172     r=xio->readRequestIn;
00173     if (xio->readBuffer==NULL)
00174       xio->readBuffer=GWEN_RingBuffer_new(GWEN_IO_LAYER_BUFFERED_BUFSIZE);
00175 
00176     rflags=GWEN_Io_Request_GetFlags(r);
00177 
00178     /* now check whether we have some data */
00179     len=GWEN_RingBuffer_GetMaxUnsegmentedRead(xio->readBuffer);
00180     if (len==0) {
00181       /* empty read buffer, fill it if possible */
00182       if (xio->lastReadOutResult) {
00183         xio->readRequestIn=NULL;
00184         DBG_INFO(GWEN_LOGDOMAIN, "Aborting in read request (reason: %d)",
00185                  xio->lastReadOutResult);
00186         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, xio->lastReadOutResult);
00187         GWEN_Io_Request_free(r);
00188         doneSomething=1;
00189       }
00190       else {
00191         if (xio->readRequestOut==NULL) {
00192           GWEN_IO_REQUEST *br;
00193           int rv;
00194 
00195           /* there is no outbound read request, create one */
00196           len=GWEN_RingBuffer_GetMaxUnsegmentedWrite(xio->readBuffer);
00197           assert(len);
00198 
00199           br=GWEN_Io_Request_new(GWEN_Io_Request_TypeRead,
00200                                  (uint8_t*)GWEN_RingBuffer_GetWritePointer(xio->readBuffer), len,
00201                                  NULL, NULL,
00202                                  GWEN_Io_Request_GetGuiId(xio->readRequestIn));
00203           rv=GWEN_Io_Layer_AddRequest(GWEN_Io_Layer_GetBaseLayer(io), br);
00204           if (rv) {
00205             GWEN_Io_Request_free(br);
00206             if (rv!=GWEN_ERROR_TRY_AGAIN) {
00207               xio->lastReadOutResult=rv;
00208               DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00209               xio->readRequestIn=NULL;
00210               DBG_INFO(GWEN_LOGDOMAIN, "Aborting in read request (reason: %d)",
00211                        xio->lastReadOutResult);
00212               GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, rv);
00213               GWEN_Io_Request_free(r);
00214             }
00215           }
00216           else {
00217             xio->readRequestOut=br;
00218           }
00219           doneSomething=1;
00220         }
00221       }
00222     } /* if read buffer empty */
00223     else {
00224       const uint8_t *src;
00225 
00226       /* read buffer is not empty, so we *will* do something */
00227       doneSomething=1;
00228 
00229       src=(const uint8_t*)GWEN_RingBuffer_GetReadPointer(xio->readBuffer);
00230       if (rflags & GWEN_IO_REQUEST_BUFFERED_FLAGS_RAW) {
00231         uint32_t maxBytes;
00232         uint32_t bpos;
00233         uint8_t *dst;
00234 
00235         /* read raw data */
00236         bpos=GWEN_Io_Request_GetBufferPos(r);
00237         dst=GWEN_Io_Request_GetBufferPtr(r)+bpos;
00238         maxBytes=GWEN_Io_Request_GetBufferSize(r)-bpos;
00239         if (maxBytes>len)
00240           maxBytes=len;
00241         if (maxBytes) {
00242           memmove(dst, src, maxBytes);
00243           if (!(rflags & GWEN_IO_REQUEST_BUFFERED_FLAGS_PEEK)) {
00244             /* just peek, don't update */
00245             GWEN_RingBuffer_SkipBytesRead(xio->readBuffer, maxBytes);
00246           }
00247           bpos+=maxBytes;
00248           GWEN_Io_Request_SetBufferPos(r, bpos);
00249         }
00250 
00251         /* check whether request has been fullfilled, ignore possible flag GWEN_IO_REQUEST_FLAGS_READALL
00252          * when peeking */
00253         if (!(rflags & GWEN_IO_REQUEST_FLAGS_READALL) ||
00254             (rflags & GWEN_IO_REQUEST_BUFFERED_FLAGS_PEEK) ||
00255             bpos>=GWEN_Io_Request_GetBufferSize(r)) {
00256           /* request completed */
00257           xio->readRequestIn=NULL;
00258           GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00259           GWEN_Io_Request_free(r);
00260         }
00261       }
00262       else {
00263         uint32_t maxBytes;
00264         uint32_t bpos;
00265         uint32_t i;
00266         uint8_t *dst;
00267 
00268         /* read line */
00269         bpos=GWEN_Io_Request_GetBufferPos(r);
00270         dst=GWEN_Io_Request_GetBufferPtr(r)+bpos;
00271         maxBytes=GWEN_Io_Request_GetBufferSize(r)-bpos;
00272         i=0;
00273 
00274         if (rflags & GWEN_IO_REQUEST_BUFFERED_FLAGS_PEEK) {
00275           /* just peek, don't update counters etc */
00276           while(i<len && bpos<maxBytes) {
00277             if (*src==10) {
00278               GWEN_Io_Request_AddFlags(r, GWEN_IO_REQUEST_FLAGS_PACKETEND);
00279               GWEN_Io_Request_SetBufferPos(r, bpos);
00280               xio->readRequestIn=NULL;
00281               GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00282               GWEN_Io_Request_free(r);
00283               break;
00284             }
00285             else if (*src!=13) {
00286               *(dst++)=*src;
00287               bpos++;
00288             }
00289             i++;
00290             src++;
00291           }
00292           if (xio->readRequestIn && bpos>=GWEN_Io_Request_GetBufferSize(xio->readRequestIn)) {
00293             GWEN_Io_Request_SetBufferPos(r, bpos);
00294             xio->readRequestIn=NULL;
00295             GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00296             GWEN_Io_Request_free(r);
00297           }
00298         }
00299         else {
00300           while(i<len && bpos<maxBytes) {
00301             if (*src==10) {
00302               xio->lastReadWasPacketEnd=1;
00303               xio->readLineCount++;
00304               GWEN_Io_Request_AddFlags(r, GWEN_IO_REQUEST_FLAGS_PACKETEND);
00305               GWEN_Io_Request_SetBufferPos(r, bpos);
00306               if (xio->readLinePos==0 &&
00307                   (GWEN_Io_Layer_GetFlags(io) & GWEN_IO_REQUEST_BUFFERED_FLAGS_UNTILEMPTYLINE)) {
00308                 xio->lastReadOutResult=GWEN_ERROR_EOF;
00309                 xio->readLinePos=0;
00310                 xio->readRequestIn=NULL;
00311                 GWEN_Io_Request_SetBufferPos(r, bpos);
00312                 DBG_INFO(GWEN_LOGDOMAIN,
00313                          "Aborting in read request (reason: %d)",
00314                          xio->lastReadOutResult);
00315                 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_EOF);
00316                 GWEN_Io_Request_free(r);
00317               }
00318               else {
00319                 xio->readLinePos=0;
00320                 xio->readRequestIn=NULL;
00321                 GWEN_Io_Request_SetBufferPos(r, bpos);
00322                 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00323                 GWEN_Io_Request_free(r);
00324               }
00325               i++;
00326               break;
00327             }
00328             else if (*src!=13) {
00329               *(dst++)=*src;
00330               bpos++;
00331             }
00332             xio->readLinePos++;
00333             i++;
00334             src++;
00335           }
00336           GWEN_RingBuffer_SkipBytesRead(xio->readBuffer, i);
00337 
00338           if (xio->readRequestIn) {
00339             GWEN_Io_Request_SetBufferPos(r, bpos);
00340 
00341             if (bpos>=GWEN_Io_Request_GetBufferSize(xio->readRequestIn)) {
00342               /* there still is a read request and its buffer is filled completely without reaching EOLN */
00343               xio->lastReadWasPacketEnd=0;
00344               xio->readRequestIn=NULL;
00345               GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00346               GWEN_Io_Request_free(r);
00347             }
00348           }
00349         }
00350       }
00351     }
00352   }
00353 
00354   if (GWEN_Io_Layer_GetStatus(io)==GWEN_Io_Layer_StatusListening) {
00355     GWEN_IO_LAYER *newIo;
00356 
00357     newIo=GWEN_Io_Layer_GetNextIncomingLayer(GWEN_Io_Layer_GetBaseLayer(io));
00358     if (newIo) {
00359       GWEN_IO_LAYER *newNewIo;
00360       uint32_t fl;
00361 
00362       fl=GWEN_Io_Layer_GetFlags(io);
00363       newNewIo=GWEN_Io_LayerBuffered_new(newIo);
00364       GWEN_Io_Layer_AddFlags(newNewIo, GWEN_IO_LAYER_FLAGS_PASSIVE);
00365       GWEN_Io_Layer_AddFlags(newNewIo, fl & 0xffff);
00366       GWEN_Io_Layer_AddIncomingLayer(io, newNewIo);
00367       doneSomething=1;
00368     }
00369   }
00370 
00371   return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
00372 }
00373 
00374 
00375 
00376 int GWEN_Io_LayerBuffered_TryFlush(GWEN_IO_LAYER *io) {
00377   GWEN_IO_LAYER_BUFFERED *xio;
00378 
00379   assert(io);
00380   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_BUFFERED, io);
00381   assert(xio);
00382 
00383   if (xio->writeBuffer!=NULL) {
00384     uint32_t len;
00385 
00386     len=GWEN_RingBuffer_GetMaxUnsegmentedRead(xio->writeBuffer);
00387     if (len!=0) {
00388       /* write buffer not empty, flush it if possible */
00389       if (xio->writeRequestOut==NULL) {
00390         if (xio->lastWriteOutResult)
00391           return xio->lastWriteOutResult;
00392         else {
00393           GWEN_IO_REQUEST *br;
00394           int rv;
00395 
00396           /* there is no outbound write request, create one */
00397           len=GWEN_RingBuffer_GetMaxUnsegmentedRead(xio->writeBuffer);
00398           assert(len);
00399 
00400           br=GWEN_Io_Request_new(GWEN_Io_Request_TypeWrite,
00401                                  (uint8_t*)GWEN_RingBuffer_GetReadPointer(xio->writeBuffer), len,
00402                                  NULL, NULL,
00403                                  GWEN_Io_Request_GetGuiId(xio->writeRequestIn));
00404           DBG_DEBUG(GWEN_LOGDOMAIN, "Adding write request (%d bytes)", len);
00405           rv=GWEN_Io_Layer_AddRequest(GWEN_Io_Layer_GetBaseLayer(io), br);
00406           if (rv) {
00407             if (rv!=GWEN_ERROR_TRY_AGAIN)
00408               xio->lastWriteOutResult=rv;
00409             DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00410             GWEN_Io_Request_free(br);
00411             return rv;
00412           }
00413           else {
00414             xio->writeRequestOut=br;
00415             return 0;
00416           }
00417         }
00418       }
00419       else
00420         /* there already is a write request */
00421         return GWEN_ERROR_IN_PROGRESS;
00422     }
00423   }
00424   return GWEN_ERROR_NO_DATA;
00425 }
00426 
00427 
00428 
00429 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerBuffered_WorkOnWriteRequest(GWEN_IO_LAYER *io) {
00430   GWEN_IO_LAYER_BUFFERED *xio;
00431   int doneSomething=0;
00432 
00433   assert(io);
00434   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_BUFFERED, io);
00435   assert(xio);
00436 
00437   if (xio->writeRequestOut) {
00438     /* check for finished outbound write request */
00439     if (GWEN_Io_Request_GetStatus(xio->writeRequestOut)==GWEN_Io_Request_StatusFinished) {
00440       uint32_t bpos;
00441 
00442       doneSomething=1;
00443 
00444       /* handle all available data */
00445       bpos=GWEN_Io_Request_GetBufferPos(xio->writeRequestOut);
00446       DBG_VERBOUS(GWEN_LOGDOMAIN, "Written %d bytes into ringbuffer", bpos);
00447       GWEN_RingBuffer_SkipBytesRead(xio->writeBuffer, bpos);
00448 
00449       /* save result code */
00450       xio->lastWriteOutResult=GWEN_Io_Request_GetResultCode(xio->writeRequestOut);
00451       GWEN_Io_Request_free(xio->writeRequestOut);
00452       xio->writeRequestOut=NULL;
00453     }
00454   }
00455 
00456   if (xio->writeRequestIn) {
00457     uint32_t len;
00458     GWEN_IO_REQUEST *r;
00459     uint32_t rflags;
00460 
00461     r=xio->writeRequestIn;
00462     if (xio->writeBuffer==NULL)
00463       xio->writeBuffer=GWEN_RingBuffer_new(GWEN_IO_LAYER_BUFFERED_BUFSIZE);
00464 
00465     rflags=GWEN_Io_Request_GetFlags(r);
00466 
00467     len=GWEN_RingBuffer_GetMaxUnsegmentedWrite(xio->writeBuffer);
00468     if (len==0) {
00469       int rv;
00470 
00471       /* buffer full, try to flush */
00472       rv=GWEN_Io_LayerBuffered_TryFlush(io);
00473       if (rv==0) {
00474         doneSomething=1;
00475       }
00476       else {
00477         assert(rv!=GWEN_ERROR_NO_DATA);
00478         if (rv!=GWEN_ERROR_TRY_AGAIN &&
00479             rv!=GWEN_ERROR_IN_PROGRESS) {
00480           xio->writeRequestIn=NULL;
00481           DBG_INFO(GWEN_LOGDOMAIN,
00482                    "Aborting in write request (reason: %d)",
00483                    rv);
00484           GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, rv);
00485           GWEN_Io_Request_free(r);
00486           doneSomething=1;
00487         }
00488       }
00489     }
00490     else {
00491       uint8_t *dst;
00492       uint32_t maxBytes;
00493       uint32_t bpos;
00494       const uint8_t *src;
00495 
00496       /* write buffer is not full */
00497       dst=(uint8_t*)GWEN_RingBuffer_GetWritePointer(xio->writeBuffer);
00498 
00499       /* write all data (if any) */
00500       bpos=GWEN_Io_Request_GetBufferPos(r);
00501       src=GWEN_Io_Request_GetBufferPtr(r)+bpos;
00502       maxBytes=GWEN_Io_Request_GetBufferSize(r)-bpos;
00503       if (maxBytes>len)
00504         maxBytes=len;
00505       if (maxBytes) {
00506         memmove(dst, src, maxBytes);
00507         GWEN_RingBuffer_SkipBytesWrite(xio->writeBuffer, maxBytes);
00508         bpos+=maxBytes;
00509         GWEN_Io_Request_SetBufferPos(r, bpos);
00510         doneSomething=1;
00511       }
00512 
00513       if (bpos>=GWEN_Io_Request_GetBufferSize(r)) {
00514         int rv;
00515 
00516         /* request data written completely, now check whether we have to add CR/LF */
00517         if (rflags & GWEN_IO_REQUEST_FLAGS_PACKETEND) {
00518           if (GWEN_Io_Layer_GetFlags(io) & GWEN_IO_LAYER_BUFFERED_FLAGS_DOSMODE)
00519             rflags|=GWEN_IO_REQUEST_BUFFERED_FLAGS_WRITE13 | GWEN_IO_REQUEST_BUFFERED_FLAGS_WRITE10;
00520           else
00521             rflags|=GWEN_IO_REQUEST_BUFFERED_FLAGS_WRITE10;
00522           rflags&=~GWEN_IO_REQUEST_FLAGS_PACKETEND;
00523           GWEN_Io_Request_SetFlags(r, rflags);
00524           doneSomething=1;
00525         }
00526 
00527         if (rflags & GWEN_IO_REQUEST_BUFFERED_FLAGS_WRITE13) {
00528           rv=GWEN_RingBuffer_WriteByte(xio->writeBuffer, 13);
00529           if (rv==0) {
00530             rflags&=~GWEN_IO_REQUEST_BUFFERED_FLAGS_WRITE13;
00531             GWEN_Io_Request_SubFlags(r, GWEN_IO_REQUEST_BUFFERED_FLAGS_WRITE13);
00532             doneSomething=1;
00533           }
00534         }
00535 
00536         if (rflags & GWEN_IO_REQUEST_BUFFERED_FLAGS_WRITE10) {
00537           rv=GWEN_RingBuffer_WriteByte(xio->writeBuffer, 10);
00538           if (rv==0) {
00539             rflags&=~GWEN_IO_REQUEST_BUFFERED_FLAGS_WRITE10;
00540             GWEN_Io_Request_SubFlags(r, GWEN_IO_REQUEST_BUFFERED_FLAGS_WRITE10);
00541             doneSomething=1;
00542           }
00543         }
00544       }
00545 
00546       if (bpos>=GWEN_Io_Request_GetBufferSize(r) &&
00547           !(rflags & GWEN_IO_REQUEST_BUFFERED_FLAGS_WRITE13) &&
00548           !(rflags & GWEN_IO_REQUEST_BUFFERED_FLAGS_WRITE10)) {
00549         if (rflags & GWEN_IO_REQUEST_FLAGS_FLUSH) {
00550           int rv;
00551 
00552           /* flush requested, so do it */
00553           rv=GWEN_Io_LayerBuffered_TryFlush(io);
00554           if (rv==GWEN_ERROR_NO_DATA) {
00555             /* flushed, request finished */
00556             xio->writeRequestIn=NULL;
00557             GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00558             GWEN_Io_Request_free(r);
00559             doneSomething=1;
00560           }
00561           else if (rv==0) {
00562             /* flush started */
00563             doneSomething=1;
00564           }
00565           else if (rv!=GWEN_ERROR_TRY_AGAIN && rv!=GWEN_ERROR_IN_PROGRESS) {
00566             xio->writeRequestIn=NULL;
00567             DBG_INFO(GWEN_LOGDOMAIN,
00568                      "Aborting in write request (reason: %d)",
00569                      rv);
00570             GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, rv);
00571             GWEN_Io_Request_free(r);
00572             doneSomething=1;
00573           }
00574         }
00575         else {
00576           xio->writeRequestIn=NULL;
00577           GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00578           GWEN_Io_Request_free(r);
00579           doneSomething=1;
00580         }
00581       }
00582     }
00583   }
00584 
00585   return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
00586 }
00587 
00588 
00589 
00590 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerBuffered_WorkOnRequests(GWEN_IO_LAYER *io) {
00591   GWEN_IO_LAYER_BUFFERED *xio;
00592   int doneSomething=0;
00593 
00594   assert(io);
00595   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_BUFFERED, io);
00596   assert(xio);
00597 
00598   DBG_VERBOUS(GWEN_LOGDOMAIN, "LayerBuffered: Working");
00599 
00600   /* work on read request */
00601   if (GWEN_Io_LayerBuffered_WorkOnReadRequest(io)!=GWEN_Io_Layer_WorkResultBlocking)
00602     doneSomething=1;
00603 
00604   /* work on write request */
00605   if (GWEN_Io_LayerBuffered_WorkOnWriteRequest(io)!=GWEN_Io_Layer_WorkResultBlocking)
00606     doneSomething=1;
00607 
00608   /* let base layer work */
00609   if (GWEN_Io_Layer_WorkOnRequests(GWEN_Io_Layer_GetBaseLayer(io))!=GWEN_Io_Layer_WorkResultBlocking)
00610     doneSomething=1;
00611 
00612   if (GWEN_Io_Layer_GetStatus(io)==GWEN_Io_Layer_StatusListening) {
00613     GWEN_IO_LAYER *newIo;
00614 
00615     newIo=GWEN_Io_Layer_GetNextIncomingLayer(GWEN_Io_Layer_GetBaseLayer(io));
00616     if (newIo) {
00617       GWEN_IO_LAYER *newNewIo;
00618 
00619       newNewIo=GWEN_Io_LayerBuffered_new(newIo);
00620       GWEN_Io_Layer_AddIncomingLayer(io, newNewIo);
00621       doneSomething=1;
00622     }
00623   }
00624 
00625   return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
00626 }
00627 
00628 
00629 
00630 int GWEN_Io_LayerBuffered_AddRequest(GWEN_IO_LAYER *io, GWEN_IO_REQUEST *r) {
00631   GWEN_IO_LAYER_BUFFERED *xio;
00632   GWEN_IO_LAYER_STATUS st;
00633 
00634   assert(io);
00635   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_BUFFERED, io);
00636   assert(xio);
00637 
00638   st=GWEN_Io_Layer_GetStatus(io);
00639 
00640   switch(GWEN_Io_Request_GetType(r)) {
00641   case GWEN_Io_Request_TypeRead:
00642     /* check status */
00643     if (st!=GWEN_Io_Layer_StatusConnected) {
00644       DBG_INFO(GWEN_LOGDOMAIN, "File is not open");
00645       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
00646       return GWEN_ERROR_NOT_OPEN;
00647     }
00648 
00649     /* return data from buffer if there is any */
00650     if (xio->lastReadOutResult &&
00651         (xio->readBuffer &&
00652          GWEN_RingBuffer_GetMaxUnsegmentedRead(xio->readBuffer)==0)) {
00653       DBG_INFO(GWEN_LOGDOMAIN, "Unable to read (%d)", xio->lastReadOutResult);
00654       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, xio->lastReadOutResult);
00655       return xio->lastReadOutResult;
00656     }
00657 
00658     /* check whether we already have a read request */
00659     if (xio->readRequestIn) {
00660       DBG_INFO(GWEN_LOGDOMAIN, "There already is a read request");
00661       return GWEN_ERROR_TRY_AGAIN;
00662     }
00663 
00664     /* check for begin of line */
00665     if (!(GWEN_Io_Request_GetFlags(r) && GWEN_IO_REQUEST_BUFFERED_FLAGS_RAW)) {
00666       if (xio->lastReadWasPacketEnd) {
00667         /* if the previous line read request ended at the end of a line then this line read request
00668          * starts at the beginning of a new line. Therefore we set the PACKETBEGIN flag and clear
00669          * the lastReadWasPacketEnd flag (since the line didn't end just yet). */
00670         GWEN_Io_Request_AddFlags(r, GWEN_IO_REQUEST_FLAGS_PACKETBEGIN);
00671         xio->lastReadWasPacketEnd=0;
00672       }
00673     }
00674     else
00675       /* when reading raw data the last line has definately ended, so the next line read will start
00676        * with a new line */
00677       xio->lastReadWasPacketEnd=0;
00678 
00679     /* enqueue request */
00680     xio->readRequestIn=r;
00681     GWEN_Io_Request_Attach(xio->readRequestIn);
00682     break;
00683 
00684   case GWEN_Io_Request_TypeWrite:
00685     /* check status */
00686     if (st!=GWEN_Io_Layer_StatusConnected) {
00687       DBG_INFO(GWEN_LOGDOMAIN, "File is not open");
00688       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
00689       return GWEN_ERROR_NOT_OPEN;
00690     }
00691 
00692     /* check whether we already have a read request */
00693     if (xio->writeRequestIn) {
00694       DBG_INFO(GWEN_LOGDOMAIN, "There already is a write request");
00695       return GWEN_ERROR_TRY_AGAIN;
00696     }
00697 
00698     /* enqueue request */
00699     xio->writeRequestIn=r;
00700     GWEN_Io_Request_Attach(xio->writeRequestIn);
00701     break;
00702 
00703   case GWEN_Io_Request_TypeConnect:
00704     /* check status */
00705     if (st!=GWEN_Io_Layer_StatusUnconnected &&
00706         st!=GWEN_Io_Layer_StatusDisconnected) {
00707       DBG_INFO(GWEN_LOGDOMAIN, "IO layer is not open");
00708       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
00709       return GWEN_ERROR_NOT_OPEN;
00710     }
00711     else {
00712       xio->lastReadOutResult=0;
00713       GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusConnected);
00714       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00715       DBG_INFO(GWEN_LOGDOMAIN, "Layer now connected");
00716     }
00717     break;
00718 
00719   case GWEN_Io_Request_TypeDisconnect:
00720     /* check status */
00721     if (st!=GWEN_Io_Layer_StatusConnected) {
00722       DBG_INFO(GWEN_LOGDOMAIN, "IO layer is not open");
00723       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
00724       return GWEN_ERROR_NOT_OPEN;
00725     }
00726     else {
00727       /* abort incoming requests, if any */
00728       GWEN_Io_LayerBuffered_AbortInRequests(io, GWEN_ERROR_ABORTED);
00729       GWEN_Io_LayerBuffered_AbortOutRequests(io);
00730 
00731       /* free ring buffers */
00732       GWEN_RingBuffer_free(xio->readBuffer);
00733       xio->readBuffer=NULL;
00734       GWEN_RingBuffer_free(xio->writeBuffer);
00735       xio->writeBuffer=NULL;
00736 
00737       xio->lastReadOutResult=0;
00738 
00739       /* closed */
00740       GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
00741       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
00742     }
00743     break;
00744 
00745   default:
00746     DBG_INFO(GWEN_LOGDOMAIN, "This request type is not supported (%d)", GWEN_Io_Request_GetType(r));
00747     GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_SUPPORTED);
00748     return GWEN_ERROR_NOT_SUPPORTED;
00749   }
00750 
00751   return 0;
00752 }
00753 
00754 
00755 
00756 int GWEN_Io_LayerBuffered_DelRequest(GWEN_IO_LAYER *io, GWEN_IO_REQUEST *r) {
00757   GWEN_IO_LAYER_BUFFERED *xio;
00758 
00759   assert(io);
00760   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_BUFFERED, io);
00761   assert(xio);
00762 
00763   switch(GWEN_Io_Request_GetType(r)) {
00764   case GWEN_Io_Request_TypeRead:
00765     if (xio->readRequestIn==r) {
00766       DBG_DEBUG(GWEN_LOGDOMAIN, "Aborted read request");
00767       xio->readRequestIn=NULL;
00768       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_ABORTED);
00769       GWEN_Io_Request_free(r);
00770     }
00771     else {
00772       /* not my request */
00773       DBG_INFO(GWEN_LOGDOMAIN, "Read request not registered with this io layer");
00774       return GWEN_ERROR_INVALID;
00775     }
00776     break;
00777 
00778   case GWEN_Io_Request_TypeWrite:
00779     if (xio->writeRequestIn==r) {
00780       DBG_DEBUG(GWEN_LOGDOMAIN, "Aborted write request");
00781       xio->writeRequestIn=NULL;
00782       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_ABORTED);
00783       GWEN_Io_Request_free(r);
00784     }
00785     else {
00786       /* not my request */
00787       DBG_INFO(GWEN_LOGDOMAIN, "Write request not registered with this io layer");
00788       return GWEN_ERROR_INVALID;
00789     }
00790     break;
00791 
00792   default:
00793     break;
00794   }
00795 
00796   return 0;
00797 }
00798 
00799 
00800 
00801 int GWEN_Io_LayerBuffered_HasWaitingRequests(GWEN_IO_LAYER *io) {
00802   GWEN_IO_LAYER_BUFFERED *xio;
00803 
00804   assert(io);
00805   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_BUFFERED, io);
00806   assert(xio);
00807 
00808   if (xio->readRequestIn || xio->writeRequestIn)
00809     return 1;
00810   else
00811     return 0;
00812 }
00813 
00814 
00815 
00816 int GWEN_Io_LayerBuffered_ReadLineToBuffer(GWEN_IO_LAYER *io, GWEN_BUFFER *fbuf, uint32_t guiid, int msecs) {
00817   for (;;) {
00818     GWEN_IO_REQUEST *r;
00819     GWEN_IO_REQUEST_STATUS st;
00820     uint8_t buffer[257];
00821     int rv;
00822 
00823     r=GWEN_Io_Request_new(GWEN_Io_Request_TypeRead,
00824                           buffer, sizeof(buffer)-1, NULL, NULL, guiid);
00825     rv=GWEN_Io_Layer_AddRequest(io, r);
00826     if (rv<0) {
00827       GWEN_Io_Request_free(r);
00828       if (rv==GWEN_ERROR_EOF) {
00829         return rv;
00830       }
00831       else {
00832         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00833         return rv;
00834       }
00835     }
00836 
00837     /* wait for request to finish */
00838     rv=GWEN_Io_Manager_WaitForRequest(r, msecs);
00839     if (rv<0) {
00840       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00841       GWEN_Io_Request_free(r);
00842       return rv;
00843     }
00844 
00845     /* if not finished, report an error */
00846     st=GWEN_Io_Request_GetStatus(r);
00847     if (st!=GWEN_Io_Request_StatusFinished) {
00848       DBG_INFO(GWEN_LOGDOMAIN, "Bad request status (%d)", st);
00849       GWEN_Io_Request_free(r);
00850       return GWEN_ERROR_INTERNAL;
00851     }
00852   
00853     /* check result code */
00854     rv=GWEN_Io_Request_GetResultCode(r);
00855     if (rv && rv!=GWEN_ERROR_EOF) {
00856       DBG_INFO(GWEN_LOGDOMAIN, "Result of request is an error (%d)", rv);
00857       GWEN_Io_Request_free(r);
00858       return rv;
00859     }
00860 
00861     if (GWEN_Io_Request_GetBufferPos(r))
00862       GWEN_Buffer_AppendBytes(fbuf, (const char*)buffer, GWEN_Io_Request_GetBufferPos(r));
00863 
00864     if (GWEN_Io_Request_GetFlags(r) & GWEN_IO_REQUEST_FLAGS_PACKETEND) {
00865       GWEN_Io_Request_free(r);
00866       break;
00867     }
00868 
00869     GWEN_Io_Request_free(r);
00870   }
00871 
00872   return 0;
00873 }
00874 
00875 
00876 
00877 int GWEN_Io_LayerBuffered_WriteLine(GWEN_IO_LAYER *io, const char *buffer, int len, int flush,
00878                                     uint32_t guiid, int msecs) {
00879   int rv;
00880   uint32_t rflags;
00881 
00882   if (len==-1)
00883     len=strlen(buffer);
00884 
00885   rflags=GWEN_IO_REQUEST_FLAGS_PACKETEND|GWEN_IO_REQUEST_FLAGS_WRITEALL;
00886   if (flush)
00887     rflags|=GWEN_IO_REQUEST_FLAGS_FLUSH;
00888   rv=GWEN_Io_Layer_WriteBytes(io, (const uint8_t*)buffer, len, rflags, guiid, msecs);
00889   if (rv<0) {
00890     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00891   }
00892 
00893   return rv;
00894 }
00895 
00896 
00897 
00898 uint32_t GWEN_Io_LayerBuffered_GetReadLineCount(const GWEN_IO_LAYER *io) {
00899   GWEN_IO_LAYER_BUFFERED *xio;
00900 
00901   assert(io);
00902   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_BUFFERED, io);
00903   assert(xio);
00904 
00905   return xio->readLineCount;
00906 }
00907 
00908 
00909 
00910 uint32_t GWEN_Io_LayerBuffered_GetReadLinePos(const GWEN_IO_LAYER *io) {
00911   GWEN_IO_LAYER_BUFFERED *xio;
00912 
00913   assert(io);
00914   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_BUFFERED, io);
00915   assert(xio);
00916 
00917   return xio->readLinePos;
00918 }
00919 
00920 
00921 
00922 void GWEN_Io_LayerBuffered_ResetLinePosAndCounter(GWEN_IO_LAYER *io) {
00923   GWEN_IO_LAYER_BUFFERED *xio;
00924 
00925   assert(io);
00926   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_BUFFERED, io);
00927   assert(xio);
00928 
00929   xio->readLineCount=0;
00930   xio->readLinePos=0;
00931 }
00932 
00933 
00934 
00935 
00936 
00937 
00938 
00939 
00940 
00941 
00942 
00943 
00944 

Generated on Sat Jan 2 09:32:35 2010 for gwenhywfar by  doxygen 1.6.1