/*
- * Copyright (c) 1987-2017 by the citadel.org team
+ * Copyright (c) 1987-2018 by the citadel.org team
*
* This program is open source software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
return StrLength(FB->Buf) - (FB->ReadWritePointer - FB->Buf->buf);
}
-inline static void FDIOBufferFlush(FDIOBuffer *FDB)
-{
- memset(FDB, 0, sizeof(FDIOBuffer));
- FDB->OtherFD = -1;
- FDB->SplicePipe[0] = -1;
- FDB->SplicePipe[1] = -1;
-}
-
-void FDIOBufferInit(FDIOBuffer *FDB, IOBuffer *IO, int FD, long TotalSendSize)
-{
- FDIOBufferFlush(FDB);
-
- FDB->TotalSendSize = TotalSendSize;
- if (TotalSendSize > 0)
- FDB->ChunkSize = TotalSendSize;
- else
- {
- TotalSendSize = SIZ * 10;
- FDB->ChunkSize = TotalSendSize;
- }
- FDB->IOB = IO;
-
-#ifdef LINUX_SPLICE
- if (EnableSplice)
- pipe(FDB->SplicePipe);
- else
-#endif
- FDB->ChunkBuffer = NewStrBufPlain(NULL, TotalSendSize+ 1);
-
- FDB->OtherFD = FD;
-}
-
-void FDIOBufferDelete(FDIOBuffer *FDB)
-{
-#ifdef LINUX_SPLICE
- if (EnableSplice)
- {
- if (FDB->SplicePipe[0] > 0)
- close(FDB->SplicePipe[0]);
- if (FDB->SplicePipe[1] > 0)
- close(FDB->SplicePipe[1]);
- }
- else
-#endif
- FreeStrBuf(&FDB->ChunkBuffer);
-
- if (FDB->OtherFD > 0)
- close(FDB->OtherFD);
- FDIOBufferFlush(FDB);
-}
-
-int FileSendChunked(FDIOBuffer *FDB, const char **Err)
-{
- ssize_t sent, pipesize;
-
- if (FDB->TotalSendSize > 0)
- {
-#ifdef LINUX_SPLICE
- if (EnableSplice)
- {
- if (FDB->PipeSize == 0)
- {
- pipesize = splice(FDB->OtherFD,
- &FDB->TotalSentAlready,
- FDB->SplicePipe[1],
- NULL,
- FDB->ChunkSendRemain,
- SPLICE_F_MOVE);
-
- if (pipesize == -1)
- {
- *Err = strerror(errno);
- return pipesize;
- }
- FDB->PipeSize = pipesize;
- }
- sent = splice(FDB->SplicePipe[0],
- NULL,
- FDB->IOB->fd,
- NULL,
- FDB->PipeSize,
- SPLICE_F_MORE | SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
- if (sent == -1)
- {
- *Err = strerror(errno);
- return sent;
- }
- FDB->PipeSize -= sent;
- FDB->ChunkSendRemain -= sent;
- return sent;
- }
- else
-#endif
- {
- char *pRead;
- long nRead = 0;
-
- pRead = FDB->ChunkBuffer->buf;
- while ((FDB->ChunkBuffer->BufUsed < FDB->TotalSendSize) && (nRead >= 0))
- {
- nRead = read(FDB->OtherFD, pRead, FDB->TotalSendSize - FDB->ChunkBuffer->BufUsed);
- if (nRead > 0) {
- FDB->ChunkBuffer->BufUsed += nRead;
- FDB->ChunkBuffer->buf[FDB->ChunkBuffer->BufUsed] = '\0';
- }
- else if (nRead == 0) {}
- else return nRead;
- }
-
- nRead = write(FDB->IOB->fd,
- FDB->ChunkBuffer->buf + FDB->TotalSentAlready,
- FDB->ChunkBuffer->BufUsed - FDB->TotalSentAlready);
-
- if (nRead >= 0) {
- FDB->TotalSentAlready += nRead;
- FDB->ChunkSendRemain -= nRead;
- return FDB->ChunkSendRemain;
- }
- else {
- return nRead;
- }
- }
- }
- else
- {
-#ifdef LINUX_SPLICE
- if (EnableSplice)
- {
- if (FDB->PipeSize == 0)
- {
- pipesize = splice(FDB->OtherFD,
- &FDB->TotalSentAlready,
- FDB->SplicePipe[1],
- NULL,
- SIZ * 10,
- SPLICE_F_MOVE);
-
- if (pipesize == -1)
- {
- *Err = strerror(errno);
- return pipesize;
- }
- FDB->PipeSize = pipesize;
- if (pipesize == 0)
- return -1;
- }
- sent = splice(FDB->SplicePipe[0],
- NULL,
- FDB->IOB->fd,
- NULL,
- FDB->PipeSize,
- SPLICE_F_MORE | SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
- if (sent == -1)
- {
- *Err = strerror(errno);
- return sent;
- }
- FDB->PipeSize -= sent;
- FDB->ChunkSendRemain -= sent;
- return sent;
- }
- else
-#endif
- {
- char *pRead;
- long nRead = 0;
-
- pRead = FDB->ChunkBuffer->buf;
- while ((FDB->ChunkSendRemain == 0) &&
- (FDB->ChunkBuffer->BufUsed < FDB->ChunkBuffer->BufSize) &&
- (nRead >= 0))
- {
- FDB->TotalSentAlready = 0;
- nRead = read(FDB->OtherFD, pRead, FDB->ChunkBuffer->BufSize - FDB->ChunkBuffer->BufUsed);
- if (nRead > 0) {
- FDB->ChunkBuffer->BufUsed += nRead;
- FDB->ChunkBuffer->buf[FDB->ChunkBuffer->BufUsed] = '\0';
- FDB->ChunkSendRemain += nRead;
- }
- else if (nRead == 0)
- {
- return -1;
- }
- else
- {
- *Err = strerror(errno);
- return nRead;
- }
- }
-
- nRead = write(FDB->IOB->fd,
- FDB->ChunkBuffer->buf + FDB->TotalSentAlready,
- FDB->ChunkBuffer->BufUsed - FDB->TotalSentAlready);
-
- if (nRead >= 0) {
- FDB->TotalSentAlready += nRead;
- FDB->ChunkSendRemain -= nRead;
- if (FDB->ChunkSendRemain == 0)
- {
- FDB->ChunkBuffer->BufUsed = 0;
- FDB->TotalSentAlready = 0;
- }
- return FDB->ChunkSendRemain;
- }
- else {
- return nRead;
- }
- }
- }
-}
-
-int FileRecvChunked(FDIOBuffer *FDB, const char **Err)
-{
- ssize_t sent, pipesize;
-
-#ifdef LINUX_SPLICE
- if (EnableSplice)
- {
- if (FDB->PipeSize == 0)
- {
- pipesize = splice(FDB->IOB->fd,
- NULL,
- FDB->SplicePipe[1],
- NULL,
- FDB->ChunkSendRemain,
- SPLICE_F_MORE | SPLICE_F_MOVE|SPLICE_F_NONBLOCK);
-
- if (pipesize == -1)
- {
- *Err = strerror(errno);
- return pipesize;
- }
- FDB->PipeSize = pipesize;
- }
-
- sent = splice(FDB->SplicePipe[0],
- NULL,
- FDB->OtherFD,
- &FDB->TotalSentAlready,
- FDB->PipeSize,
- SPLICE_F_MORE | SPLICE_F_MOVE);
-
- if (sent == -1)
- {
- *Err = strerror(errno);
- return sent;
- }
- FDB->PipeSize -= sent;
- FDB->ChunkSendRemain -= sent;
- return sent;
- }
- else
-#endif
- {
- sent = read(FDB->IOB->fd, FDB->ChunkBuffer->buf, FDB->ChunkSendRemain);
- if (sent > 0) {
- int nWritten = 0;
- int rc;
-
- FDB->ChunkBuffer->BufUsed = sent;
-
- while (nWritten < FDB->ChunkBuffer->BufUsed) {
- rc = write(FDB->OtherFD, FDB->ChunkBuffer->buf + nWritten, FDB->ChunkBuffer->BufUsed - nWritten);
- if (rc < 0) {
- *Err = strerror(errno);
- return rc;
- }
- nWritten += rc;
-
- }
- FDB->ChunkBuffer->BufUsed = 0;
- FDB->TotalSentAlready += sent;
- FDB->ChunkSendRemain -= sent;
- return FDB->ChunkSendRemain;
- }
- else if (sent < 0) {
- *Err = strerror(errno);
- return sent;
- }
- return 0;
- }
-}
-
-int FileMoveChunked(FDIOBuffer *FDB, const char **Err)
-{
- ssize_t sent, pipesize;
-
-#ifdef LINUX_SPLICE
- if (EnableSplice)
- {
- if (FDB->PipeSize == 0)
- {
- pipesize = splice(FDB->IOB->fd,
- &FDB->TotalReadAlready,
- FDB->SplicePipe[1],
- NULL,
- FDB->ChunkSendRemain,
- SPLICE_F_MORE | SPLICE_F_MOVE|SPLICE_F_NONBLOCK);
-
- if (pipesize == -1)
- {
- *Err = strerror(errno);
- return pipesize;
- }
- FDB->PipeSize = pipesize;
- }
-
- sent = splice(FDB->SplicePipe[0],
- NULL,
- FDB->OtherFD,
- &FDB->TotalSentAlready,
- FDB->PipeSize,
- SPLICE_F_MORE | SPLICE_F_MOVE);
-
- if (sent == -1)
- {
- *Err = strerror(errno);
- return sent;
- }
- FDB->PipeSize -= sent;
- FDB->ChunkSendRemain -= sent;
- return sent;
- }
- else
-#endif
- {
- sent = read(FDB->IOB->fd, FDB->ChunkBuffer->buf, FDB->ChunkSendRemain);
- if (sent > 0) {
- int nWritten = 0;
- int rc;
-
- FDB->ChunkBuffer->BufUsed = sent;
-
- while (nWritten < FDB->ChunkBuffer->BufUsed) {
- rc = write(FDB->OtherFD, FDB->ChunkBuffer->buf + nWritten, FDB->ChunkBuffer->BufUsed - nWritten);
- if (rc < 0) {
- *Err = strerror(errno);
- return rc;
- }
- nWritten += rc;
-
- }
- FDB->ChunkBuffer->BufUsed = 0;
- FDB->TotalSentAlready += sent;
- FDB->ChunkSendRemain -= sent;
- return FDB->ChunkSendRemain;
- }
- else if (sent < 0) {
- *Err = strerror(errno);
- return sent;
- }
- return 0;
- }
-}
-
-eReadState WriteIOBAlreadyRead(FDIOBuffer *FDB, const char **Error)
-{
- int IsNonBlock;
- int fdflags;
- long rlen;
- long should_write;
- int nSuccessLess = 0;
- struct timeval tv;
- fd_set rfds;
-
- fdflags = fcntl(FDB->OtherFD, F_GETFL);
- IsNonBlock = (fdflags & O_NONBLOCK) == O_NONBLOCK;
-
- while ((FDB->IOB->ReadWritePointer - FDB->IOB->Buf->buf < FDB->IOB->Buf->BufUsed) &&
- (FDB->ChunkSendRemain > 0))
- {
- if (IsNonBlock){
- tv.tv_sec = 1; /* selectresolution; */
- tv.tv_usec = 0;
-
- FD_ZERO(&rfds);
- FD_SET(FDB->OtherFD, &rfds);
- if (select(FDB->OtherFD + 1, NULL, &rfds, NULL, &tv) == -1) {
- *Error = strerror(errno);
- return eReadFail;
- }
- }
- if (IsNonBlock && ! FD_ISSET(FDB->OtherFD, &rfds)) {
- nSuccessLess ++;
- continue;
- }
-
- should_write = FDB->IOB->Buf->BufUsed -
- (FDB->IOB->ReadWritePointer - FDB->IOB->Buf->buf);
- if (should_write > FDB->ChunkSendRemain)
- should_write = FDB->ChunkSendRemain;
-
- rlen = write(FDB->OtherFD,
- FDB->IOB->ReadWritePointer,
- should_write);
- if (rlen < 1) {
- *Error = strerror(errno);
-
- return eReadFail;
- }
- FDB->TotalSentAlready += rlen;
- FDB->IOB->ReadWritePointer += rlen;
- FDB->ChunkSendRemain -= rlen;
- }
- if (FDB->IOB->ReadWritePointer >= FDB->IOB->Buf->buf + FDB->IOB->Buf->BufUsed)
- {
- FlushStrBuf(FDB->IOB->Buf);
- FDB->IOB->ReadWritePointer = NULL;
- }
-
- if (FDB->ChunkSendRemain == 0)
- return eReadSuccess;
- else
- return eMustReadMore;
-}
/*******************************************************************************
* File I/O; Prefer buffered read since its faster! *
return len - slen;
}
+
/**
* @ingroup StrBuf_BufferedIO
* @brief Read a line from socket