190 lines
4.5 KiB
C
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;
|
|
}
|
|
|