Files
pvvmud/common/lib/srvcli/stream.C
2025-03-05 08:37:43 +01:00

190 lines
4.5 KiB
C

/*
* 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 <unistd.h>
#include <iostream.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#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;
}