Migrate relevant PLIB netXXX classes into SimGear.
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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
156
simgear/io/sg_netBuffer.cxx
Normal 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
155
simgear/io/sg_netBuffer.hxx
Normal 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
|
||||
305
simgear/io/sg_netChannel.cxx
Normal file
305
simgear/io/sg_netChannel.cxx
Normal 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
|
||||
115
simgear/io/sg_netChannel.hxx
Normal file
115
simgear/io/sg_netChannel.hxx
Normal 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
138
simgear/io/sg_netChat.cxx
Normal 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
90
simgear/io/sg_netChat.hxx
Normal 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
|
||||
Reference in New Issue
Block a user