/* * PVVMUD a 3D MUD * Copyright (C) 1998-1999 Programvareverkstedet (pvv@pvv.org) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "pvvmud.H" #include #include #include #include #include #include "stream.H" #define INC_START if (++start >= STREAMSIZE) start = 0; size-- #define INC_STOP if (++stop >= STREAMSIZE) stop = 0; size++ ///////////////////////////////////////////////////////////////////////////// // Stream exceptions CEmptyStreamException::CEmptyStreamException() :CException("Empty stream exception"){ } CEOFException::CEOFException():CException("EOF exception"){ } CIOException::CIOException():CException("IO exception"){ } ///////////////////////////////////////////////////////////////////////////// // Constructor and destructor CStream::CStream(int fd){ start = stop = size = 0; this->fd = fd; } CStream::~CStream(){ close(fd); } ///////////////////////////////////////////////////////////////////////////// // Private functions ///////////////////////////////////////////////////////////////////////////// int CStream::writeInBuf(char * msg, int length){ int nn = 0; if ((STREAMSIZE - size) < length) return FALSE; while (nn < length){ buf[stop] = msg[nn++]; INC_STOP; } return TRUE; } unsigned long totalread = 0; unsigned long totalwrite = 0; int CStream::fillBuf(){ long length,max; char rbuf[STREAMSIZE]; max = MIN(STREAMSIZE-size,READBUFSIZE); #ifndef CRYPTO length=::read(fd,&rbuf,max); if (length > 0) { totalread+=length; writeInBuf(rbuf,length); }; #else length=CCrypto::read(fd,&m_rbuf,(STREAMSIZE-size)); if (length > 0) { totalread+=length; writeInBuf(m_rbuf,length); }; #endif // Check for errors if ((max != 0) && (length == 0)){ throw new CEOFException(); } else if (length == -1){ switch(errno){ case EAGAIN: // Non-blocking I/O break; default: cdebug << "Error reading socket: " << strerror(errno) << "\n"; throw new CIOException(); break; } } return size; } ///////////////////////////////////////////////////////////////////////////// // Public functions ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // peepByte // // Description: Returning first byte in input stream without removing it from // input buf. // // Return : First byte in input stream // // Exceptions : CEmptyStreamException, CEOFException, CIOException // BYTE CStream::peepByte(){ fillBuf(); if (size < 1) throw new CEmptyStreamException(); return buf[start]; } ///////////////////////////////////////////////////////////////////////////// // readBuf // // Description: Read length bytes from stream // // Return : Number of bytes read or -1 if read would have blocked // // Exceptions : CEOFException , CIOException // int CStream::readBuf(BYTE * msg, int length){ if (fillBuf() == 0) return -1; int nn = 0; while ((size >= 1) && (nn < length)){ msg[nn++] = buf[start]; INC_START; if (size == 0) fillBuf(); } return nn; } ///////////////////////////////////////////////////////////////////////////// // writeBuf // // Description: Write length bytes to stream // // Return : Number of bytes writen or -1 if write would have blocked // // Exceptions : CEOFException , CIOException // int CStream::writeBuf(BYTE * buf,int length){ #ifdef CRYPTO int num = CCrypto::write(fd,buf,length); #else int num = ::write(fd,buf,length); #endif if (num >= 0){ totalwrite += num; } else { if (num == -2) return -1; // Error handling in crypto-routines switch (errno){ case EPIPE: throw new CEOFException(); break; case EAGAIN: // Non-Blocking I/O return -1; break; default: throw new CIOException(); break; } } return num; }