Projekt

Allgemein

Profil

Herunterladen (28,7 KB) Statistiken
| Zweig: | Markierung: | Revision:
/***************************************************************************
$RCSfile$
-------------------
cvs : $Id$
begin : Fri Feb 07 2003
copyright : (C) 2003 by Martin Preuss
email : martin@libchipcard.de

***************************************************************************
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
* MA 02111-1307 USA *
* *
***************************************************************************/


#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#define DISABLE_DEBUGLOG


#include "bufferedio_p.h"
#include <gwenhyfwar/misc.h>
#include <gwenhyfwar/text.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

#include "gwenhyfwar/debug.h"


const char *GWEN_BufferedIO_ErrorString(int c){
const char *s;

switch(c) {
case GWEN_BUFFEREDIO_ERROR_READ:
s="Error on read";
break;
case GWEN_BUFFEREDIO_ERROR_WRITE:
s="Error on write";
break;
case GWEN_BUFFEREDIO_ERROR_CLOSE:
s="Error on write";
break;
case GWEN_BUFFEREDIO_ERROR_TIMEOUT:
s="Transaction timout";
break;
default:
s=0;
} /* switch */

return s;
}



static int gwen_bufferedio_is_initialized=0;
static GWEN_ERRORTYPEREGISTRATIONFORM *gwen_bufferedio_errorform=0;



GWEN_ERRORCODE GWEN_BufferedIO_ModuleInit(){
if (!gwen_bufferedio_is_initialized) {
GWEN_ERRORCODE err;

gwen_bufferedio_errorform=GWEN_ErrorType_new();
GWEN_ErrorType_SetName(gwen_bufferedio_errorform,
GWEN_BUFFEREDIO_ERROR_TYPE);
GWEN_ErrorType_SetMsgPtr(gwen_bufferedio_errorform,
GWEN_BufferedIO_ErrorString);
err=GWEN_Error_RegisterType(gwen_bufferedio_errorform);
if (!GWEN_Error_IsOk(err))
return err;
gwen_bufferedio_is_initialized=1;
}
return 0;
}



GWEN_ERRORCODE GWEN_BufferedIO_ModuleFini(){
if (gwen_bufferedio_is_initialized) {
GWEN_ERRORCODE err;

err=GWEN_Error_UnregisterType(gwen_bufferedio_errorform);
GWEN_ErrorType_free(gwen_bufferedio_errorform);
if (!GWEN_Error_IsOk(err))
return err;
gwen_bufferedio_is_initialized=0;
}
return 0;
}



GWEN_BUFFEREDIO *GWEN_BufferedIO_new(){
GWEN_BUFFEREDIO *bt;

GWEN_NEW_OBJECT(GWEN_BUFFEREDIO, bt);
bt->lineMode=GWEN_LineModeUnix;
return bt;
}



void GWEN_BufferedIO_free(GWEN_BUFFEREDIO *bt){
if (bt) {
if (bt->freePtr) {
bt->freePtr(bt->privateData);
}
if (!(bt->readerBuffer)) {
DBG_WARN(0, "No readerbuffer");
}
free(bt->readerBuffer);
bt->readerBuffer=0;
if (!(bt->writerBuffer)) {
DBG_WARN(0, "No writerbuffer");
}
free(bt->writerBuffer);
bt->writerBuffer=0;
free(bt);
}
}



void GWEN_BufferedIO_SetReadBuffer(GWEN_BUFFEREDIO *bt,
char *buffer, int len){
assert(bt);
free(bt->readerBuffer);
bt->readerBuffer=0;
if (buffer==0) {
if (len>0) {
bt->readerBuffer=malloc(len);
assert(bt->readerBuffer);
}
}
else
bt->readerBuffer=buffer;

bt->readerBufferLength=len;
bt->readerBufferFilled=0;
bt->readerBufferPos=0;
}



void GWEN_BufferedIO_SetWriteBuffer(GWEN_BUFFEREDIO *bt, char *buffer, int len){
assert(bt);
free(bt->writerBuffer);
bt->writerBuffer=0;
if (buffer==0) {
if (len>0) {
bt->writerBuffer=malloc(len);
assert(bt->writerBuffer);
}
}
else
bt->writerBuffer=buffer;

bt->writerBufferLength=len;
bt->writerBufferFilled=0;
bt->writerBufferPos=0;
}



int GWEN_BufferedIO_CheckEOF(GWEN_BUFFEREDIO *bt){
return (GWEN_BufferedIO_PeekChar(bt)==-2);
}



int GWEN_BufferedIO_PeekChar(GWEN_BUFFEREDIO *bt){
assert(bt);
assert(bt->readerBuffer);

/* do some fast checks */
if (bt->readerError) {
DBG_DEBUG(0, "Error flagged");
return -1;
}
if (bt->readerEOF) {
DBG_DEBUG(0, "EOF flagged");
return -2;
}

if (bt->readerBufferPos>=bt->readerBufferFilled) {
/* buffer empty, no EOF met, so fill it */
GWEN_ERRORCODE err;
int i;

assert(bt->readPtr);
i=bt->readerBufferLength;
err=bt->readPtr(bt,
bt->readerBuffer,
&i,
bt->timeout);
if (!GWEN_Error_IsOk(err)) {
DBG_ERROR_ERR(0, err);
bt->readerError=1;
return -1;
}
bt->readerBufferFilled=i;
bt->readerBufferPos=0;
bt->readerEOF=(i==0);
}
if (bt->readerEOF) {
DBG_DEBUG(0, "EOF now met");
return -2;
}
return (unsigned char)(bt->readerBuffer[bt->readerBufferPos]);
}



int GWEN_BufferedIO_ReadChar(GWEN_BUFFEREDIO *bt){
int i;

i=GWEN_BufferedIO_PeekChar(bt);
if (i>=0)
bt->readerBufferPos++;
return i;
}



GWEN_ERRORCODE GWEN_BufferedIO_Flush(GWEN_BUFFEREDIO *bt){
GWEN_ERRORCODE err;
int i;
int written;

assert(bt);
if (bt->writerBufferFilled==0) {
DBG_DEBUG(0, "WriteBuffer empty, nothing to flush.");
return 0;
}
assert(bt->writerBuffer);
assert(bt->writePtr);
written=bt->writerBufferFlushPos;
DBG_DEBUG(0, "Flushing %d bytes", bt->writerBufferFilled);
while(written<bt->writerBufferFilled) {
i=bt->writerBufferFilled-written;
err=bt->writePtr(bt,
&(bt->writerBuffer[written]),
&i,
bt->timeout);
if (!GWEN_Error_IsOk(err)) {
DBG_ERROR_ERR(0, err);
return err;
}
written+=i;
} /* while */

bt->writerBufferPos=0;
bt->writerBufferFilled=0;
bt->writerBufferFlushPos=0;

return 0;
}



GWEN_ERRORCODE GWEN_BufferedIO_ShortFlush(GWEN_BUFFEREDIO *bt){
GWEN_ERRORCODE err;
int i;

assert(bt);
if (bt->writerBufferFilled==0) {
DBG_DEBUG(0, "WriteBuffer empty, nothing to flush.");
return 0;
}
assert(bt->writerBuffer);
assert(bt->writePtr);
i=bt->writerBufferFilled-bt->writerBufferFlushPos;
DBG_DEBUG(0, "Flushing %d bytes", i);
err=bt->writePtr(bt,
&(bt->writerBuffer[bt->writerBufferFlushPos]),
&i,
bt->timeout);
if (!GWEN_Error_IsOk(err)) {
DBG_ERROR_ERR(0, err);
return err;
}
if (i<bt->writerBufferFilled-bt->writerBufferFlushPos) {
/* partial flush */
bt->writerBufferFlushPos+=i;
return GWEN_Error_new(0,
GWEN_ERROR_SEVERITY_WARN,
GWEN_Error_FindType(GWEN_BUFFEREDIO_ERROR_TYPE),
GWEN_BUFFEREDIO_ERROR_PARTIAL);
}
else {
/* all bytes written, flush finished */
bt->writerBufferFlushPos=0;
bt->writerBufferPos=0;
bt->writerBufferFilled=0;
return 0;
}
}



int GWEN_BufferedIO_ReadBufferEmpty(GWEN_BUFFEREDIO *bt) {
assert(bt);
return ((bt->readerBuffer==0) ||
!bt->readerBufferFilled ||
bt->readerBufferPos>=bt->readerBufferFilled);
}



int GWEN_BufferedIO_WriteBufferEmpty(GWEN_BUFFEREDIO *bt) {
assert(bt);
return ((bt->writerBuffer==0) ||
!bt->writerBufferFilled ||
bt->writerBufferPos>=bt->writerBufferFilled);
}



GWEN_ERRORCODE GWEN_BufferedIO_WriteChar(GWEN_BUFFEREDIO *bt, char c){
assert(bt);
assert(bt->writerBuffer);

/* flush buffer if needed (only needed if last flush attempt failed) */
if (bt->writerBufferFilled>=bt->writerBufferLength) {
GWEN_ERRORCODE err;

err=GWEN_BufferedIO_Flush(bt);
if (!GWEN_Error_IsOk(err)) {
DBG_ERROR_ERR(0, err);
return err;
}
}

/* write char to buffer */
bt->writerBuffer[bt->writerBufferPos++]=c;
if (bt->writerBufferPos>bt->writerBufferFilled)
bt->writerBufferFilled=bt->writerBufferPos;

/* flush buffer if needed */
if (bt->writerBufferFilled>=bt->writerBufferLength) {
GWEN_ERRORCODE err;

err=GWEN_BufferedIO_Flush(bt);
if (!GWEN_Error_IsOk(err)) {
DBG_ERROR_ERR(0, err);
return err;
}
}
return 0;
}



GWEN_ERRORCODE GWEN_BufferedIO_Close(GWEN_BUFFEREDIO *bt){
GWEN_ERRORCODE err, err2;

assert(bt);
assert(bt->closePtr);
err=GWEN_BufferedIO_Flush(bt);
err2=bt->closePtr(bt);
if (!GWEN_Error_IsOk(err)) {
DBG_ERROR_ERR(0, err);
return err;
}
if (!GWEN_Error_IsOk(err2)) {
DBG_ERROR_ERR(0, err2);
return err2;
}
return 0;
}



GWEN_ERRORCODE GWEN_BufferedIO_Abandon(GWEN_BUFFEREDIO *bt){
GWEN_ERRORCODE err;

assert(bt);
assert(bt->closePtr);
err=bt->closePtr(bt);
if (!GWEN_Error_IsOk(err)) {
DBG_ERROR_ERR(0, err);
return err;
}
return 0;
}



GWEN_ERRORCODE GWEN_BufferedIO_ReadLine(GWEN_BUFFEREDIO *bt,
char *buffer,
unsigned int s){
int c;
int pos;

assert(s);
pos=0;
/* now read */
while(s>1) {
if (GWEN_BufferedIO_CheckEOF(bt)) {
buffer[pos]=0;
break;
}
c=GWEN_BufferedIO_ReadChar(bt);
if (c<0) {
DBG_ERROR(0, "Error while reading");
return GWEN_Error_new(0,
GWEN_ERROR_SEVERITY_ERR,
GWEN_Error_FindType(GWEN_BUFFEREDIO_ERROR_TYPE),
GWEN_BUFFEREDIO_ERROR_READ);
}

if (c==GWEN_BUFFEREDIO_LF) {
/* LF ends every line */
buffer[pos]=0;
break;
}

if (c!=GWEN_BUFFEREDIO_CR || bt->lineMode==GWEN_LineModeUnix) {
buffer[pos]=(unsigned char)c;
pos++;
s--;
}
} /* while */

/* add terminating null */
if (s)
buffer[pos]=0;

/* reading done */
return 0;
}



GWEN_ERRORCODE GWEN_BufferedIO_Write(GWEN_BUFFEREDIO *bt,
const char *buffer){
GWEN_ERRORCODE err;

assert(bt);
assert(buffer);
while(*buffer) {
err=GWEN_BufferedIO_WriteChar(bt, *buffer);
if (!GWEN_Error_IsOk(err)) {
DBG_ERROR_ERR(0, err);
return err;
}
buffer++;
} /* while */
return 0;
}



GWEN_ERRORCODE GWEN_BufferedIO_WriteLine(GWEN_BUFFEREDIO *bt,
const char *buffer){
GWEN_ERRORCODE err;

assert(bt);
assert(buffer);
err=GWEN_BufferedIO_Write(bt, buffer);
if (!GWEN_Error_IsOk(err)) {
DBG_ERROR_ERR(0, err);
return err;
}
if (bt->lineMode==GWEN_LineModeDOS) {
err=GWEN_BufferedIO_WriteChar(bt, GWEN_BUFFEREDIO_CR);
if (!GWEN_Error_IsOk(err)) {
DBG_ERROR_ERR(0, err);
return err;
}
}
err=GWEN_BufferedIO_WriteChar(bt, GWEN_BUFFEREDIO_LF);
if (!GWEN_Error_IsOk(err)) {
DBG_ERROR_ERR(0, err);
return err;
}

err=GWEN_BufferedIO_Flush(bt);
if (!GWEN_Error_IsOk(err)) {
DBG_ERROR_ERR(0, err);
return err;
}

return 0;
}



void GWEN_BufferedIO_SetLineMode(GWEN_BUFFEREDIO *dm,
GWEN_BUFFEREDIOLINEMODE lm){
assert(dm);
dm->lineMode=lm;
}



GWEN_BUFFEREDIOLINEMODE GWEN_BufferedIO_GetLineMode(GWEN_BUFFEREDIO *dm){
assert(dm);
return dm->lineMode;
}



void GWEN_BufferedIO_SetTimeout(GWEN_BUFFEREDIO *dm, int timeout){
assert(dm);
dm->timeout=timeout;
}



int GWEN_BufferedIO_GetTimeout(GWEN_BUFFEREDIO *dm){
assert(dm);
return dm->timeout;
}



GWEN_ERRORCODE GWEN_BufferedIO_WriteRaw(GWEN_BUFFEREDIO *bt,
const char *buffer,
unsigned int *bsize){

GWEN_ERRORCODE err;
int i;

assert(bt);
assert(bsize);
assert(*bsize);

if (bt->writerBufferFilled) {
/* some data in the buffer, this must be flushed first */
err=GWEN_BufferedIO_ShortFlush(bt);
if (!GWEN_Error_IsOk(err)) {
DBG_ERROR_ERR(0, err);
return err;
}
if (GWEN_Error_GetType(err)==
GWEN_Error_FindType(GWEN_BUFFEREDIO_ERROR_TYPE) &&
GWEN_Error_GetCode(err)==GWEN_BUFFEREDIO_ERROR_PARTIAL) {
/* still some bytes in the buffer, can not write right now */
*bsize=0;
return err;
}
}

/* try to write as many bytes as possible */
i=*bsize;
err=bt->writePtr(bt,
buffer,
&i,
bt->timeout);
if (!GWEN_Error_IsOk(err)) {
DBG_ERROR_ERR(0, err);
return err;
}
*bsize=i;
return err;
}



GWEN_ERRORCODE GWEN_BufferedIO_ReadRaw(GWEN_BUFFEREDIO *bt,
char *buffer,
unsigned int *bsize){
assert(bt);

/* do some fast checks */
if (bt->readerError) {
DBG_DEBUG(0, "Error flagged");
return -1;
}
if (bt->readerEOF) {
DBG_DEBUG(0, "EOF flagged");
return -2;
}

if (bt->readerBufferPos<bt->readerBufferFilled) {
/* buffer not empty, so read from the buffer first */
unsigned int i;

i=bt->readerBufferFilled-bt->readerBufferPos;
if (i>*bsize)
i=*bsize;
DBG_DEBUG(0, "Reading rest from buffer (%d at %d of %d)",
i,bt->readerBufferPos, bt->readerBufferFilled);

if (i) {
/* copy as much bytes as needed, advance pointer */
memmove(buffer, bt->readerBuffer+bt->readerBufferPos, i);
bt->readerBufferPos+=i;
}
*bsize=i;
DBG_DEBUG(0, "Read %d bytes from buffer", i);
return 0;
}
else {
/* buffer empty, so read directly from source */
GWEN_ERRORCODE err;
int i;

DBG_DEBUG(0, "Reading directly from source");
assert(bt->readPtr);
i=*bsize;
err=bt->readPtr(bt,
buffer,
&i,
bt->timeout);
if (!GWEN_Error_IsOk(err)) {
DBG_ERROR_ERR(0, err);
bt->readerError=1;
return -1;
}
bt->readerEOF=(i==0);
*bsize=i;
DBG_DEBUG(0, "Read %d bytes from source", i);
}
if (bt->readerEOF) {
DBG_DEBUG(0, "EOF now met");
return -2;
}
return 0;
}




/*_________________________________________________________________________
*AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
* File Module
*YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
*/




struct GWEN_BUFFEREDIO_FILE_STRUCT {
int fd;
};
typedef struct GWEN_BUFFEREDIO_FILE_STRUCT GWEN_BUFFEREDIO_FILE_TABLE;




GWEN_BUFFEREDIO_FILE_TABLE *GWEN_BufferedIO_File_Table__new() {
GWEN_BUFFEREDIO_FILE_TABLE *bft;

bft=(GWEN_BUFFEREDIO_FILE_TABLE *)malloc(sizeof(GWEN_BUFFEREDIO_FILE_TABLE));
assert(bft);
memset(bft,0,sizeof(GWEN_BUFFEREDIO_FILE_TABLE));
bft->fd=-1;
return bft;
}



void GWEN_BufferedIO_File_Table__free(GWEN_BUFFEREDIO_FILE_TABLE *bft) {
free(bft);
}



GWEN_ERRORCODE GWEN_BufferedIO_File__Read(GWEN_BUFFEREDIO *dm,
char *buffer,
int *size,
int timeout){
int rv;
GWEN_BUFFEREDIO_FILE_TABLE *bft;

assert(dm);
bft=(GWEN_BUFFEREDIO_FILE_TABLE *)(dm->privateData);
assert(bft);
if (*size<1) {
DBG_WARN(0, "Nothing to read");
*size=0;
return 0;
}
rv=read(bft->fd, buffer, *size);
if (rv==0) {
DBG_DEBUG(0, "EOF met");
*size=0;
return 0;
}
if (rv<0) {
DBG_ERROR(0, "Could not read (%s)",
strerror(errno));
return GWEN_Error_new(0,
GWEN_ERROR_SEVERITY_ERR,
GWEN_Error_FindType(GWEN_BUFFEREDIO_ERROR_TYPE),
GWEN_BUFFEREDIO_ERROR_READ);
}
*size=rv;
return 0;
}



GWEN_ERRORCODE GWEN_BufferedIO_File__Write(GWEN_BUFFEREDIO *dm,
const char *buffer,
int *size,
int timeout){
int rv;
GWEN_BUFFEREDIO_FILE_TABLE *bft;

assert(dm);
bft=(GWEN_BUFFEREDIO_FILE_TABLE *)(dm->privateData);
assert(bft);
if (*size<1) {
DBG_WARN(0, "Nothing to write");
*size=0;
return 0;
}
rv=write(bft->fd, buffer, *size);
if (rv<1) {
DBG_ERROR(0, "Could not write (%s)",
strerror(errno));
return GWEN_Error_new(0,
GWEN_ERROR_SEVERITY_ERR,
GWEN_Error_FindType(GWEN_BUFFEREDIO_ERROR_TYPE),
GWEN_BUFFEREDIO_ERROR_WRITE);
}
*size=rv;
return 0;
}



GWEN_ERRORCODE GWEN_BufferedIO_File__Close(GWEN_BUFFEREDIO *dm){
GWEN_BUFFEREDIO_FILE_TABLE *bft;

assert(dm);
bft=(GWEN_BUFFEREDIO_FILE_TABLE *)(dm->privateData);
assert(bft);
if (close(bft->fd)) {
DBG_ERROR(0, "Could not close (%s)",
strerror(errno));
return GWEN_Error_new(0,
GWEN_ERROR_SEVERITY_ERR,
GWEN_Error_FindType(GWEN_BUFFEREDIO_ERROR_TYPE),
GWEN_BUFFEREDIO_ERROR_CLOSE);
}
return 0;
}



void GWEN_BufferedIO_File__free(void *p){
if (p)
GWEN_BufferedIO_File_Table__free((GWEN_BUFFEREDIO_FILE_TABLE *)p);
}



GWEN_BUFFEREDIO *GWEN_BufferedIO_File_new(int fd){
GWEN_BUFFEREDIO *bt;
GWEN_BUFFEREDIO_FILE_TABLE *bft;

bt=GWEN_BufferedIO_new();
bft=GWEN_BufferedIO_File_Table__new();
bt->privateData=bft;
bft->fd=fd;
bt->readPtr=GWEN_BufferedIO_File__Read;
bt->writePtr=GWEN_BufferedIO_File__Write;
bt->closePtr=GWEN_BufferedIO_File__Close;
bt->freePtr=GWEN_BufferedIO_File__free;
bt->iotype=GWEN_BufferedIOTypeFile;
bt->timeout=GWEN_BUFFEREDIO_FILE_TIMEOUT;
return bt;
}




/*_________________________________________________________________________
*AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
* Socket Module
*YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
*/




struct GWEN_BUFFEREDIO_SOCKET_STRUCT {
GWEN_SOCKET *sock;
};
typedef struct GWEN_BUFFEREDIO_SOCKET_STRUCT GWEN_BUFFEREDIO_SOCKET;


GWEN_BUFFEREDIO_SOCKET *GWEN_BufferedIO_Socket_Table__new() {
GWEN_BUFFEREDIO_SOCKET *bft;

GWEN_NEW_OBJECT(GWEN_BUFFEREDIO_SOCKET, bft);

return bft;
}



void GWEN_BufferedIO_Socket_Table__free(GWEN_BUFFEREDIO_SOCKET *bft) {
if (bft) {
GWEN_Socket_free(bft->sock);
free(bft);
}
}



GWEN_ERRORCODE GWEN_BufferedIO_Socket__Read(GWEN_BUFFEREDIO *dm,
char *buffer,
int *size,
int timeout){
GWEN_ERRORCODE err;
GWEN_BUFFEREDIO_SOCKET *bft;
int retrycount;

assert(dm);
assert(buffer);
assert(size);
bft=(GWEN_BUFFEREDIO_SOCKET *)(dm->privateData);
assert(bft);
assert(bft->sock);
if (*size<1) {
DBG_WARN(0, "Nothing to read");
*size=0;
return 0;
}

if (timeout>=0) {
retrycount=GWEN_BUFFEREDIO_SOCKET_TRIES;
while(retrycount) {
err=GWEN_Socket_WaitForRead(bft->sock, timeout);
if (!GWEN_Error_IsOk(err)) {
if (GWEN_Error_GetType(err)==
GWEN_Error_FindType(GWEN_SOCKET_ERROR_TYPE)) {
if (GWEN_Error_GetCode(err)==GWEN_SOCKET_ERROR_TIMEOUT)
return
GWEN_Error_new(0,
GWEN_ERROR_SEVERITY_ERR,
GWEN_Error_FindType(GWEN_BUFFEREDIO_ERROR_TYPE),
GWEN_BUFFEREDIO_ERROR_TIMEOUT);
else if (GWEN_Error_GetCode(err)!=GWEN_SOCKET_ERROR_INTERRUPTED) {
DBG_ERROR_ERR(0, err);
return err;
}
} /* if socket error */
else {
DBG_ERROR_ERR(0, err);
return err;
}
}
else
break;
retrycount--;
} /* while */
if (retrycount<1) {
DBG_ERROR(0, "Interrupted too often, giving up");
return GWEN_Error_new(0,
GWEN_ERROR_SEVERITY_ERR,
GWEN_Error_FindType(GWEN_BUFFEREDIO_ERROR_TYPE),
GWEN_BUFFEREDIO_ERROR_READ);
}
} /* if timeout */

/* ok. socket seems to be ready now */
retrycount=GWEN_BUFFEREDIO_SOCKET_TRIES;
while(retrycount) {
err=GWEN_Socket_Read(bft->sock, buffer, size);
if (!GWEN_Error_IsOk(err)) {
if (GWEN_Error_GetType(err)==
GWEN_Error_FindType(GWEN_SOCKET_ERROR_TYPE)) {
if (GWEN_Error_GetCode(err)!=GWEN_SOCKET_ERROR_INTERRUPTED) {
DBG_ERROR_ERR(0, err);
return err;
}
} /* if socket error */
else {
DBG_ERROR_ERR(0, err);
return err;
}
}
else
break;
retrycount--;
} /* while */
if (retrycount<1) {
DBG_ERROR(0, "Interrupted too often, giving up");
return GWEN_Error_new(0,
GWEN_ERROR_SEVERITY_ERR,
GWEN_Error_FindType(GWEN_BUFFEREDIO_ERROR_TYPE),
GWEN_BUFFEREDIO_ERROR_READ);
}

DBG_VERBOUS(0, "Reading ok (%d bytes)", *size);
return 0;
}



GWEN_ERRORCODE GWEN_BufferedIO_Socket__Write(GWEN_BUFFEREDIO *dm,
const char *buffer,
int *size,
int timeout){
GWEN_ERRORCODE err;
GWEN_BUFFEREDIO_SOCKET *bft;
int retrycount;

assert(dm);
assert(buffer);
assert(size);
bft=(GWEN_BUFFEREDIO_SOCKET *)(dm->privateData);
assert(bft);
assert(bft->sock);
if (*size<1) {
DBG_WARN(0, "Nothing to write");
*size=0;
return 0;
}

if (timeout>=0) {
retrycount=GWEN_BUFFEREDIO_SOCKET_TRIES;
while(retrycount) {
err=GWEN_Socket_WaitForWrite(bft->sock, timeout);
if (!GWEN_Error_IsOk(err)) {
if (GWEN_Error_GetType(err)==
GWEN_Error_FindType(GWEN_SOCKET_ERROR_TYPE)) {
if (GWEN_Error_GetCode(err)==GWEN_SOCKET_ERROR_TIMEOUT)
return GWEN_Error_new(0,
GWEN_ERROR_SEVERITY_ERR,
GWEN_Error_FindType(GWEN_BUFFEREDIO_ERROR_TYPE),
GWEN_BUFFEREDIO_ERROR_TIMEOUT);
else if (GWEN_Error_GetCode(err)!=GWEN_SOCKET_ERROR_INTERRUPTED) {
DBG_ERROR_ERR(0, err);
return err;
}
} /* if socket error */
else {
DBG_ERROR_ERR(0, err);
return err;
}
}
else
break;
retrycount--;
} /* while */
if (retrycount<1) {
DBG_ERROR(0, "Interrupted too often, giving up");
return GWEN_Error_new(0,
GWEN_ERROR_SEVERITY_ERR,
GWEN_Error_FindType(GWEN_BUFFEREDIO_ERROR_TYPE),
GWEN_BUFFEREDIO_ERROR_WRITE);
}
} /* if timeout */

/* ok. socket seems to be ready now */
retrycount=GWEN_BUFFEREDIO_SOCKET_TRIES;
while(retrycount) {
err=GWEN_Socket_Write(bft->sock, buffer, size);
if (!GWEN_Error_IsOk(err)) {
if (GWEN_Error_GetType(err)==
GWEN_Error_FindType(GWEN_SOCKET_ERROR_TYPE)) {
if (GWEN_Error_GetCode(err)!=GWEN_SOCKET_ERROR_INTERRUPTED) {
DBG_ERROR_ERR(0, err);
return err;
}
} /* if socket error */
else {
DBG_ERROR_ERR(0, err);
return err;
}
}
else
break;

retrycount--;
} /* while */
if (retrycount<1) {
DBG_ERROR(0, "Interrupted too often, giving up");
return GWEN_Error_new(0,
GWEN_ERROR_SEVERITY_ERR,
GWEN_Error_FindType(GWEN_BUFFEREDIO_ERROR_TYPE),
GWEN_BUFFEREDIO_ERROR_WRITE);
}

DBG_VERBOUS(0, "Writing ok");
return 0;
}



GWEN_ERRORCODE GWEN_BufferedIO_Socket__Close(GWEN_BUFFEREDIO *dm){
GWEN_BUFFEREDIO_SOCKET *bft;

assert(dm);
bft=(GWEN_BUFFEREDIO_SOCKET *)(dm->privateData);
assert(bft);
assert(bft->sock);
DBG_DEBUG(0, "Closing socket");
if (GWEN_Socket_Close(bft->sock)) {
DBG_ERROR(0, "Could not close (%s)",
strerror(errno));
return GWEN_Error_new(0,
GWEN_ERROR_SEVERITY_ERR,
GWEN_Error_FindType(GWEN_BUFFEREDIO_ERROR_TYPE),
GWEN_BUFFEREDIO_ERROR_CLOSE);
}
return 0;
}



void GWEN_BufferedIO_Socket__free(void *p){
if (p)
GWEN_BufferedIO_Socket_Table__free((GWEN_BUFFEREDIO_SOCKET *)p);
}



GWEN_BUFFEREDIO *GWEN_BufferedIO_Socket_new(GWEN_SOCKET *sock){
GWEN_BUFFEREDIO *bt;
GWEN_BUFFEREDIO_SOCKET *bft;

bt=GWEN_BufferedIO_new();
bft=GWEN_BufferedIO_Socket_Table__new();
bt->privateData=bft;
bft->sock=sock;
bt->readPtr=GWEN_BufferedIO_Socket__Read;
bt->writePtr=GWEN_BufferedIO_Socket__Write;
bt->closePtr=GWEN_BufferedIO_Socket__Close;
bt->freePtr=GWEN_BufferedIO_Socket__free;
bt->iotype=GWEN_BufferedIOTypeSocket;
bt->timeout=GWEN_BUFFEREDIO_SOCKET_TIMEOUT;
return bt;
}







/*_________________________________________________________________________
*AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
* Buffer Module
*YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
*/




struct GWEN_BUFFEREDIO_BUFFER_STRUCT {
GWEN_BUFFER *buffer;
int closed;
};
typedef struct GWEN_BUFFEREDIO_BUFFER_STRUCT GWEN_BUFFEREDIO_BUFFER;


GWEN_BUFFEREDIO_BUFFER *GWEN_BufferedIO_Buffer_Table__new() {
GWEN_BUFFEREDIO_BUFFER *bft;

GWEN_NEW_OBJECT(GWEN_BUFFEREDIO_BUFFER, bft);
bft->closed=0;
return bft;
}



void GWEN_BufferedIO_Buffer_Table__free(GWEN_BUFFEREDIO_BUFFER *bft) {
if (bft) {
GWEN_Buffer_free(bft->buffer);
free(bft);
}
}



GWEN_ERRORCODE GWEN_BufferedIO_Buffer__Read(GWEN_BUFFEREDIO *dm,
char *buffer,
int *size,
int timeout){
GWEN_BUFFEREDIO_BUFFER *bft;
unsigned int readSize;

assert(dm);
assert(buffer);
assert(size);
bft=(GWEN_BUFFEREDIO_BUFFER *)(dm->privateData);
assert(bft);
assert(bft->buffer);

if (bft->closed) {
DBG_INFO(0, "Channel closed");
return GWEN_Error_new(0,
GWEN_ERROR_SEVERITY_ERR,
GWEN_Error_FindType(GWEN_BUFFEREDIO_ERROR_TYPE),
GWEN_BUFFEREDIO_ERROR_READ);
}

if (*size<1) {
DBG_WARN(0, "Nothing to read");
*size=0;
return 0;
}

readSize=*size;
if (GWEN_Buffer_ReadBytes(bft->buffer, buffer, &readSize)) {
DBG_ERROR(0, "Error reading from buffer");
return GWEN_Error_new(0,
GWEN_ERROR_SEVERITY_ERR,
GWEN_Error_FindType(GWEN_BUFFEREDIO_ERROR_TYPE),
GWEN_BUFFEREDIO_ERROR_READ);
}
*size=readSize;
DBG_VERBOUS(0, "Reading ok (%d bytes)", *size);
return 0;
}



GWEN_ERRORCODE GWEN_BufferedIO_Buffer__Write(GWEN_BUFFEREDIO *dm,
const char *buffer,
int *size,
int timeout){
GWEN_BUFFEREDIO_BUFFER *bft;

assert(dm);
assert(buffer);
assert(size);
bft=(GWEN_BUFFEREDIO_BUFFER *)(dm->privateData);
assert(bft);
assert(bft->buffer);

if (bft->closed) {
DBG_INFO(0, "Channel closed");
return GWEN_Error_new(0,
GWEN_ERROR_SEVERITY_ERR,
GWEN_Error_FindType(GWEN_BUFFEREDIO_ERROR_TYPE),
GWEN_BUFFEREDIO_ERROR_WRITE);
}

if (*size<1) {
DBG_WARN(0, "Nothing to write");
*size=0;
return 0;
}

if (GWEN_Buffer_AppendBytes(bft->buffer, buffer, *size)) {
DBG_INFO(0, "called from here");
return GWEN_Error_new(0,
GWEN_ERROR_SEVERITY_ERR,
GWEN_Error_FindType(GWEN_BUFFEREDIO_ERROR_TYPE),
GWEN_BUFFEREDIO_ERROR_WRITE);
}

DBG_VERBOUS(0, "Writing ok");
return 0;
}



GWEN_ERRORCODE GWEN_BufferedIO_Buffer__Close(GWEN_BUFFEREDIO *dm){
GWEN_BUFFEREDIO_BUFFER *bft;

assert(dm);
bft=(GWEN_BUFFEREDIO_BUFFER *)(dm->privateData);
assert(bft);
assert(bft->buffer);
DBG_DEBUG(0, "Closing socket");

if (bft->closed) {
DBG_DEBUG(0, "Channel already closed");
}
else
bft->closed=1;
return 0;
}



void GWEN_BufferedIO_Buffer__free(void *p){
if (p)
GWEN_BufferedIO_Buffer_Table__free((GWEN_BUFFEREDIO_BUFFER *)p);
}




GWEN_BUFFEREDIO *GWEN_BufferedIO_Buffer_new(GWEN_BUFFER *buffer){
GWEN_BUFFEREDIO *bt;
GWEN_BUFFEREDIO_BUFFER *bft;

assert(buffer);
bt=GWEN_BufferedIO_new();
bft=GWEN_BufferedIO_Buffer_Table__new();
bt->privateData=bft;
bft->buffer=buffer;
bt->readPtr=GWEN_BufferedIO_Buffer__Read;
bt->writePtr=GWEN_BufferedIO_Buffer__Write;
bt->closePtr=GWEN_BufferedIO_Buffer__Close;
bt->freePtr=GWEN_BufferedIO_Buffer__free;
bt->iotype=GWEN_BufferedIOTypeBuffer;
bt->timeout=0;
return bt;
}








(2-2/4)