Migrate relevant PLIB netXXX classes into SimGear.

This commit is contained in:
James Turner
2010-10-23 20:07:35 +01:00
parent 48c6d3d89a
commit bfd76880a9
8 changed files with 973 additions and 2 deletions

View File

@@ -503,6 +503,12 @@
RelativePath="..\..\simgear\io\sg_socket_udp.hxx"
>
</File>
<File RelativePath="..\..\simgear\io\sg_netChannel.hxx"></File>
<File RelativePath="..\..\simgear\io\sg_netChannel.cxx"></File>
<File RelativePath="..\..\simgear\io\sg_netChat.hxx"></File>
<File RelativePath="..\..\simgear\io\sg_netChat.cxx"></File>
<File RelativePath="..\..\simgear\io\sg_netBuffer.cxx"></File>
<File RelativePath="..\..\simgear\io\sg_netBuffer.hxx"></File>
</Filter>
<Filter
Name="Lib_sgmagvar"

View File

@@ -10,7 +10,10 @@ include_HEADERS = \
sg_serial.hxx \
sg_socket.hxx \
sg_socket_udp.hxx \
raw_socket.hxx
raw_socket.hxx \
sg_netBuffer.hxx \
sg_netChannel.hxx \
sg_netChat.hxx
libsgio_a_SOURCES = \
iochannel.cxx \
@@ -20,7 +23,10 @@ libsgio_a_SOURCES = \
sg_serial.cxx \
sg_socket.cxx \
sg_socket_udp.cxx \
raw_socket.cxx
raw_socket.cxx \
sg_netBuffer.cxx \
sg_netChannel.cxx \
sg_netChat.cxx
INCLUDES = -I$(top_srcdir)

156
simgear/io/sg_netBuffer.cxx Normal file
View File

@@ -0,0 +1,156 @@
/*
Copied from PLIB into SimGear
PLIB - A Suite of Portable Game Libraries
Copyright (C) 1998,2002 Steve Baker
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library 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
For further information visit http://plib.sourceforge.net
$Id: netBuffer.cxx 1568 2002-09-02 06:05:49Z sjbaker $
*/
#include "sg_netBuffer.hxx"
#include <simgear/debug/logstream.hxx>
namespace simgear {
NetBuffer::NetBuffer( int _max_length )
{
length = 0 ;
max_length = _max_length ;
data = new char [ max_length+1 ] ; //for null terminator
}
NetBuffer::~NetBuffer ()
{
delete[] data ;
}
void NetBuffer::remove ()
{
length = 0 ;
}
void NetBuffer::remove (int pos, int n)
{
assert (pos>=0 && pos<length && (pos+n)<=length) ;
//if (pos>=0 && pos<length && (pos+n)<=length)
{
memmove(&data[pos],&data[pos+n],length-(pos+n)) ;
length -= n ;
}
}
bool NetBuffer::append (const char* s, int n)
{
if ((length+n)<=max_length)
{
memcpy(&data[length],s,n) ;
length += n ;
return true ;
}
return false ;
}
bool NetBuffer::append (int n)
{
if ((length+n)<=max_length)
{
length += n ;
return true ;
}
return false ;
}
NetBufferChannel::NetBufferChannel (int in_buffer_size, int out_buffer_size) :
in_buffer (in_buffer_size),
out_buffer (out_buffer_size),
should_close (0)
{ /* empty */
}
void NetBufferChannel::handleClose ( void )
{
in_buffer.remove () ;
out_buffer.remove () ;
should_close = 0 ;
NetChannel::handleClose () ;
}
bool NetBufferChannel::bufferSend (const char* msg, int msg_len)
{
if ( out_buffer.append(msg,msg_len) )
return true ;
SG_LOG(SG_IO, SG_WARN, "NetBufferChannel: output buffer overflow!" ) ;
return false ;
}
void NetBufferChannel::handleBufferRead (NetBuffer& buffer)
{
/* do something here */
buffer.remove();
}
void
NetBufferChannel::handleRead (void)
{
int max_read = in_buffer.getMaxLength() - in_buffer.getLength() ;
if (max_read)
{
char* data = in_buffer.getData() + in_buffer.getLength() ;
int num_read = recv (data, max_read) ;
if (num_read > 0)
{
in_buffer.append (num_read) ;
//ulSetError ( UL_DEBUG, "netBufferChannel: %d read", num_read ) ;
}
}
if (in_buffer.getLength())
{
handleBufferRead (in_buffer);
}
}
void
NetBufferChannel::handleWrite (void)
{
if (out_buffer.getLength())
{
if (isConnected())
{
int length = out_buffer.getLength() ;
if (length>512)
length=512;
int num_sent = NetChannel::send (
out_buffer.getData(), length);
if (num_sent > 0)
{
out_buffer.remove (0, num_sent);
//ulSetError ( UL_DEBUG, "netBufferChannel: %d sent", num_sent ) ;
}
}
}
else if (should_close)
{
close();
}
}
} // of namespace simgear

155
simgear/io/sg_netBuffer.hxx Normal file
View File

@@ -0,0 +1,155 @@
/*
Copied from PLIB into SimGear
PLIB - A Suite of Portable Game Libraries
Copyright (C) 1998,2002 Steve Baker
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library 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
For further information visit http://plib.sourceforge.net
$Id: netBuffer.h 1901 2004-03-21 18:19:11Z sjbaker $
*/
/****
* NAME
* netBuffer - network buffer class
*
* DESCRIPTION
* Clients and servers built on top of netBufferChannel
* automatically support pipelining.
*
* Pipelining refers to a protocol capability. Normally,
* a conversation with a server has a back-and-forth
* quality to it. The client sends a command, and
* waits for the response. If a client needs to send
* many commands over a high-latency connection,
* waiting for each response can take a long time.
*
* For example, when sending a mail message to many recipients
* with SMTP, the client will send a series of RCPT commands, one
* for each recipient. For each of these commands, the server will
* send back a reply indicating whether the mailbox specified is
* valid. If you want to send a message to several hundred recipients,
* this can be rather tedious if the round-trip time for each command
* is long. You'd like to be able to send a bunch of RCPT commands
* in one batch, and then count off the responses to them as they come.
*
* I have a favorite visual when explaining the advantages of
* pipelining. Imagine each request to the server is a boxcar on a train.
* The client is in Los Angeles, and the server is in New York.
* Pipelining lets you hook all your cars in one long chain; send
* them to New York, where they are filled and sent back to you.
* Without pipelining you have to send one car at a time.
*
* Not all protocols allow pipelining. Not all servers support it;
* Sendmail, for example, does not support pipelining because it tends
* to fork unpredictably, leaving buffered data in a questionable state.
* A recent extension to the SMTP protocol allows a server to specify
* whether it supports pipelining. HTTP/1.1 explicitly requires that
* a server support pipelining.
*
* NOTES
* When a user passes in a buffer object, it belongs to
* the user. When the library gives a buffer to the user,
* the user should copy it.
*
* AUTHORS
* Sam Rushing <rushing@nightmare.com> - original version for Medusa
* Dave McClurg <dpm@efn.org> - modified for use in PLIB
*
* CREATION DATE
* Dec-2000
*
****/
#ifndef SG_NET_BUFFER_H
#define SG_NET_BUFFER_H
#include <simgear/io/sg_netChannel.hxx>
namespace simgear
{
// ===========================================================================
// NetBuffer
// ===========================================================================
class NetBuffer
{
protected:
int length ;
int max_length ;
char* data ;
public:
NetBuffer( int _max_length );
~NetBuffer ();
int getLength() const { return length ; }
int getMaxLength() const { return max_length ; }
/*
** getData() returns a pointer to the data
** Note: a zero (0) byte is appended for convenience
** but the data may have internal zero (0) bytes already
*/
char* getData() { data [length] = 0 ; return data ; }
const char* getData() const { ((char*)data) [length] = 0 ; return data ; }
void remove ();
void remove (int pos, int n);
bool append (const char* s, int n);
bool append (int n);
};
// ===========================================================================
// NetBufferChannel
// ===========================================================================
class NetBufferChannel : public NetChannel
{
NetBuffer in_buffer;
NetBuffer out_buffer;
int should_close ;
virtual bool readable (void)
{
return (NetChannel::readable() &&
(in_buffer.getLength() < in_buffer.getMaxLength()));
}
virtual void handleRead (void) ;
virtual bool writable (void)
{
return (out_buffer.getLength() || should_close);
}
virtual void handleWrite (void) ;
public:
NetBufferChannel (int in_buffer_size = 4096, int out_buffer_size = 16384);
virtual void handleClose ( void );
void closeWhenDone (void) { should_close = 1 ; }
virtual bool bufferSend (const char* msg, int msg_len);
virtual void handleBufferRead (NetBuffer& buffer);
};
} // namespace simgear
#endif // SG_NET_BUFFER_H

View File

@@ -0,0 +1,305 @@
/*
Copied from PLIB into SimGear
PLIB - A Suite of Portable Game Libraries
Copyright (C) 1998,2002 Steve Baker
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library 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
For further information visit http://plib.sourceforge.net
$Id: netChannel.cxx 1906 2004-03-22 19:44:50Z sjbaker $
*/
// TODO:
// have all socket-related functions assert that the socket has not
// been closed. [a read event may close it, and a write event may try
// to write or something...]
// Maybe assert valid handle, too?
#include "sg_netChannel.hxx"
#include <memory>
#include <simgear/debug/logstream.hxx>
namespace simgear {
static NetChannel* channels = 0 ;
NetChannel::NetChannel ()
{
closed = true ;
connected = false ;
accepting = false ;
write_blocked = false ;
should_delete = false ;
next_channel = channels ;
channels = this ;
}
NetChannel::~NetChannel ()
{
close();
NetChannel* prev = NULL ;
for ( NetChannel* ch = channels; ch != NULL;
ch = ch -> next_channel )
{
if (ch == this)
{
ch = ch -> next_channel ;
if ( prev != NULL )
prev -> next_channel = ch ;
else
channels = ch ;
next_channel = 0 ;
break;
}
prev = ch ;
}
}
void
NetChannel::setHandle (int handle, bool is_connected)
{
close () ;
Socket::setHandle ( handle ) ;
connected = is_connected ;
//if ( connected ) this->handleConnect();
closed = false ;
}
bool
NetChannel::open (void)
{
close();
if (Socket::open(true)) {
closed = false ;
setBlocking ( false ) ;
return true ;
}
return false ;
}
int
NetChannel::listen ( int backlog )
{
accepting = true ;
return Socket::listen ( backlog ) ;
}
int
NetChannel::connect ( const char* host, int port )
{
int result = Socket::connect ( host, port ) ;
if (result == 0) {
connected = true ;
//this->handleConnect();
return 0;
} else if (isNonBlockingError ()) {
return 0;
} else {
// some other error condition
this->handleError (result);
close();
return -1;
}
}
int
NetChannel::send (const void * buffer, int size, int flags)
{
int result = Socket::send (buffer, size, flags);
if (result == (int)size) {
// everything was sent
write_blocked = false ;
return result;
} else if (result >= 0) {
// not all of it was sent, but no error
write_blocked = true ;
return result;
} else if (isNonBlockingError ()) {
write_blocked = true ;
return 0;
} else {
this->handleError (result);
close();
return -1;
}
}
int
NetChannel::recv (void * buffer, int size, int flags)
{
int result = Socket::recv (buffer, size, flags);
if (result > 0) {
return result;
} else if (result == 0) {
close();
return 0;
} else if (isNonBlockingError ()) {
return 0;
} else {
this->handleError (result);
close();
return -1;
}
}
void
NetChannel::close (void)
{
if ( !closed )
{
this->handleClose();
closed = true ;
connected = false ;
accepting = false ;
write_blocked = false ;
}
Socket::close () ;
}
void
NetChannel::handleReadEvent (void)
{
if (accepting) {
if (!connected) {
connected = true ;
//this->handleConnect();
}
this->handleAccept();
} else if (!connected) {
connected = true ;
//this->handleConnect();
this->handleRead();
} else {
this->handleRead();
}
}
void
NetChannel::handleWriteEvent (void)
{
if (!connected) {
connected = true ;
//this->handleConnect();
}
write_blocked = false ;
this->handleWrite();
}
bool
NetChannel::poll (unsigned int timeout)
{
if (!channels)
return false ;
enum { MAX_SOCKETS = 256 } ;
Socket* reads [ MAX_SOCKETS+1 ] ;
Socket* writes [ MAX_SOCKETS+1 ] ;
Socket* deletes [ MAX_SOCKETS+1 ] ;
int nreads = 0 ;
int nwrites = 0 ;
int ndeletes = 0 ;
int nopen = 0 ;
NetChannel* ch;
for ( ch = channels; ch != NULL; ch = ch -> next_channel )
{
if ( ch -> should_delete )
{
assert(ndeletes<MAX_SOCKETS);
deletes[ndeletes++] = ch ;
}
else if ( ! ch -> closed )
{
nopen++ ;
if (ch -> readable()) {
assert(nreads<MAX_SOCKETS);
reads[nreads++] = ch ;
}
if (ch -> writable()) {
assert(nwrites<MAX_SOCKETS);
writes[nwrites++] = ch ;
}
}
}
reads[nreads] = NULL ;
writes[nwrites] = NULL ;
deletes[ndeletes] = NULL ;
int i ;
for ( i=0; deletes[i]; i++ )
{
ch = (NetChannel*)deletes[i];
delete ch ;
}
if (!nopen)
return false ;
if (!nreads && !nwrites)
return true ; //hmmm- should we shutdown?
Socket::select (reads, writes, timeout) ;
for ( i=0; reads[i]; i++ )
{
ch = (NetChannel*)reads[i];
if ( ! ch -> closed )
ch -> handleReadEvent();
}
for ( i=0; writes[i]; i++ )
{
ch = (NetChannel*)writes[i];
if ( ! ch -> closed )
ch -> handleWriteEvent();
}
return true ;
}
void
NetChannel::loop (unsigned int timeout)
{
while ( poll (timeout) ) ;
}
void NetChannel::handleRead (void) {
SG_LOG(SG_IO, SG_WARN, "Network:" << getHandle() << ": unhandled read");
}
void NetChannel::handleWrite (void) {
SG_LOG(SG_IO, SG_WARN, "Network:" << getHandle() << ": unhandled write");
}
void NetChannel::handleAccept (void) {
SG_LOG(SG_IO, SG_WARN, "Network:" << getHandle() << ": unhandled accept");
}
void NetChannel::handleError (int error) {
SG_LOG(SG_IO, SG_WARN,"Network:" << getHandle() << ": errno: " << strerror(errno) <<"(" << errno << ")");
}
} // of namespace simgear

View File

@@ -0,0 +1,115 @@
/*
NetChannel - copied from PLIB
PLIB - A Suite of Portable Game Libraries
Copyright (C) 1998,2002 Steve Baker
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library 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
For further information visit http://plib.sourceforge.net
$Id: netChannel.h 1899 2004-03-21 17:41:07Z sjbaker $
*/
/****
* NAME
* netChannel - network channel class
*
* DESCRIPTION
* netChannel is adds event-handling to the low-level
* netSocket class. Otherwise, it can be treated as
* a normal non-blocking socket object.
*
* The direct interface between the netPoll() loop and
* the channel object are the handleReadEvent and
* handleWriteEvent methods. These are called
* whenever a channel object 'fires' that event.
*
* The firing of these low-level events can tell us whether
* certain higher-level events have taken place, depending on
* the timing and state of the connection.
*
* AUTHORS
* Sam Rushing <rushing@nightmare.com> - original version for Medusa
* Dave McClurg <dpm@efn.org> - modified for use in PLIB
*
* CREATION DATE
* Dec-2000
*
****/
#ifndef SG_NET_CHANNEL_H
#define SG_NET_CHANNEL_H
#include <simgear/io/raw_socket.hxx>
namespace simgear
{
class NetChannel : public Socket
{
bool closed, connected, accepting, write_blocked, should_delete ;
NetChannel* next_channel ;
friend bool netPoll (unsigned int timeout);
public:
NetChannel () ;
virtual ~NetChannel () ;
void setHandle (int s, bool is_connected = true);
bool isConnected () const { return connected; }
bool isClosed () const { return closed; }
void shouldDelete () { should_delete = true ; }
// --------------------------------------------------
// socket methods
// --------------------------------------------------
bool open ( void ) ;
void close ( void ) ;
int listen ( int backlog ) ;
int connect ( const char* host, int port ) ;
int send ( const void * buf, int size, int flags = 0 ) ;
int recv ( void * buf, int size, int flags = 0 ) ;
// poll() eligibility predicates
virtual bool readable (void) { return (connected || accepting); }
virtual bool writable (void) { return (!connected || write_blocked); }
// --------------------------------------------------
// event handlers
// --------------------------------------------------
void handleReadEvent (void);
void handleWriteEvent (void);
// These are meant to be overridden.
virtual void handleClose (void) {
}
virtual void handleRead (void);
virtual void handleWrite (void);
virtual void handleAccept (void);
virtual void handleError (int error);
static bool poll (unsigned int timeout = 0 ) ;
static void loop (unsigned int timeout = 0 ) ;
};
} // of namespace simgear
#endif // SG_NET_CHANNEL_H

138
simgear/io/sg_netChat.cxx Normal file
View File

@@ -0,0 +1,138 @@
/*
Copied from PLIB into SimGear
PLIB - A Suite of Portable Game Libraries
Copyright (C) 1998,2002 Steve Baker
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library 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
For further information visit http://plib.sourceforge.net
$Id: NetChat.cxx 2117 2007-09-13 23:21:09Z fayjf $
*/
#include <simgear/io/sg_netChat.hxx>
#include <cstring> // for strdup
namespace simgear {
void
NetChat::setTerminator (const char* t)
{
if (terminator) delete[] terminator;
terminator = strdup(t);
}
const char*
NetChat::getTerminator (void)
{
return terminator;
}
// return the size of the largest prefix of needle at the end
// of haystack
#define MAX(a,b) (((a)>(b))?(a):(b))
static int
find_prefix_at_end (const NetBuffer& haystack, const char* needle)
{
const char* hd = haystack.getData();
int hl = haystack.getLength();
int nl = strlen(needle);
for (int i = MAX (nl-hl, 0); i < nl; i++) {
//if (haystack.compare (needle, hl-(nl-i), nl-i) == 0) {
if (memcmp(needle, &hd[hl-(nl-i)], nl-i) == 0) {
return (nl-i);
}
}
return 0;
}
static int
find_terminator (const NetBuffer& haystack, const char* needle)
{
if (needle && *needle)
{
const char* data = haystack.getData();
const char* ptr = strstr(data,needle);
if (ptr != NULL)
return(ptr-data);
}
return -1;
}
bool NetChat::push (const char* s)
{
return bufferSend ( s, strlen(s) ) ;
}
void
NetChat::handleBufferRead (NetBuffer& in_buffer)
{
// Continue to search for terminator in in_buffer,
// while calling collect_incoming_data. The while loop is
// necessary because we might read several data+terminator combos
// with a single recv().
while (in_buffer.getLength()) {
// special case where we're not using a terminator
if (terminator == 0 || *terminator == 0) {
collectIncomingData (in_buffer.getData(),in_buffer.getLength());
in_buffer.remove ();
return;
}
int terminator_len = strlen(terminator);
int index = find_terminator ( in_buffer, terminator ) ;
// 3 cases:
// 1) end of buffer matches terminator exactly:
// collect data, transition
// 2) end of buffer matches some prefix:
// collect data to the prefix
// 3) end of buffer does not match any prefix:
// collect data
if (index != -1) {
// we found the terminator
collectIncomingData ( in_buffer.getData(), index ) ;
in_buffer.remove (0, index + terminator_len);
foundTerminator();
} else {
// check for a prefix of the terminator
int num = find_prefix_at_end (in_buffer, terminator);
if (num) {
int bl = in_buffer.getLength();
// we found a prefix, collect up to the prefix
collectIncomingData ( in_buffer.getData(), bl - num ) ;
in_buffer.remove (0, bl - num);
break;
} else {
// no prefix, collect it all
collectIncomingData (in_buffer.getData(), in_buffer.getLength());
in_buffer.remove();
}
}
}
}
} // of namespace simgear

90
simgear/io/sg_netChat.hxx Normal file
View File

@@ -0,0 +1,90 @@
/*
Copied from PLIB into SimGear
PLIB - A Suite of Portable Game Libraries
Copyright (C) 1998,2002 Steve Baker
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library 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
For further information visit http://plib.sourceforge.net
$Id: netChat.h 1568 2002-09-02 06:05:49Z sjbaker $
*/
/****
* NAME
* netChat - network chat class
*
* DESCRIPTION
* This class adds support for 'chat' style protocols -
* where one side sends a 'command', and the other sends
* a response (examples would be the common internet
* protocols - smtp, nntp, ftp, etc..).
*
* The handle_buffer_read() method looks at the input
* stream for the current 'terminator' (usually '\r\n'
* for single-line responses, '\r\n.\r\n' for multi-line
* output), calling found_terminator() on its receipt.
*
* EXAMPLE
* Say you build an nntp client using this class.
* At the start of the connection, you'll have
* terminator set to '\r\n', in order to process
* the single-line greeting. Just before issuing a
* 'LIST' command you'll set it to '\r\n.\r\n'.
* The output of the LIST command will be accumulated
* (using your own 'collect_incoming_data' method)
* up to the terminator, and then control will be
* returned to you - by calling your found_terminator()
*
* AUTHORS
* Sam Rushing <rushing@nightmare.com> - original version for Medusa
* Dave McClurg <dpm@efn.org> - modified for use in PLIB
*
* CREATION DATE
* Dec-2000
*
****/
#ifndef SG_NET_CHAT_H
#define SG_NET_CHAT_H
#include <simgear/io/sg_netBuffer.hxx>
namespace simgear
{
class NetChat : public NetBufferChannel
{
char* terminator;
virtual void handleBufferRead (NetBuffer& buffer) ;
public:
NetChat () : terminator (0) {}
void setTerminator (const char* t);
const char* getTerminator (void);
bool push (const char* s);
virtual void collectIncomingData (const char* s, int n) {}
virtual void foundTerminator (void) {}
};
} // of namespace simgear
#endif // SG_NET_CHAT_H