khanat-opennel-code/code/nel/include/nel/net/buf_client.h
2010-05-06 02:08:41 +02:00

249 lines
8.4 KiB
C++

// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_BUF_CLIENT_H
#define NL_BUF_CLIENT_H
#include "nel/misc/types_nl.h"
#include "buf_net_base.h"
#include "tcp_sock.h"
#include "buf_sock.h"
namespace NLNET {
class CInetAddress;
class CBufClient;
/**
* Code of receiving thread for clients
*/
class CClientReceiveTask : public NLMISC::IRunnable
{
public:
/// Constructor (increments the reference to the object pointed to by the smart pointer sockid)
CClientReceiveTask( CBufClient *client, CNonBlockingBufSock *bufsock ) : NbLoop(0), _Client(client), _NBBufSock(bufsock) {} // CHANGED: non-blocking client connection
/// Run
virtual void run();
/// Returns a pointer to the bufsock object
CNonBlockingBufSock *bufSock() { return _NBBufSock; } // CHANGED: non-blocking client connection (previously, returned _SockId->Sock)
/// Returns the socket identifier
TSockId sockId() { return (TSockId)_NBBufSock; }
uint32 NbLoop;
private:
CBufClient *_Client;
CNonBlockingBufSock *_NBBufSock; // CHANGED: non-blocking client connection
};
/**
* Client class for layer 1
*
* Active connection with packet scheme and buffering.
* The provided buffers are sent raw (no endianness conversion).
* By default, the size time trigger is disabled, the time trigger is set to 20 ms.
*
* Where do the methods take place:
* \code
* send() -> send buffer -> update(), flush(),
* bytesUploaded(), newBytesUploaded()
*
* receive(), <- receive buffer <- receive thread,
* dataAvailable(), bytesDownloaded(), newBytesDownloaded()
* disconnection callback
* \endcode
*
* \author Olivier Cado
* \author Nevrax France
* \date 2001
*/
class CBufClient : public CBufNetBase
{
public:
/** Constructor. Set nodelay to true to disable the Nagle buffering algorithm (see CTcpSock documentation)
* initPipeForDataAvailable is for Linux only. Set it to false if you provide an external pipe with
* setExternalPipeForDataAvailable().
*/
CBufClient( bool nodelay=true, bool replaymode=false, bool initPipeForDataAvailable=true );
/// Destructor
virtual ~CBufClient();
/// Connects to the specified host
void connect( const CInetAddress& addr );
/** Disconnects the remote host and empties the receive queue.
* Before that, tries to flush pending data to send unless quick is true.
* In case of network congestion, the entire pending data may not be flushed.
* If this is a problem, call flush() multiple times until it returns 0 before calling disconnect().
* The disconnection callback will *not* be called.
* Do not call if the socket is not connected.
*/
void disconnect( bool quick=false );
/** Sends a message to the remote host (in fact the message is buffered into the send queue)
*/
//void send( const std::vector<uint8>& buffer );
void send( const NLMISC::CMemStream& buffer );
/** Checks if there is some data to receive. Returns false if the receive queue is empty.
* This is where the connection/disconnection callbacks can be called
*/
bool dataAvailable();
#ifdef NL_OS_UNIX
/** Wait until the receive queue contains something to read (implemented with a select()).
* This is where the connection/disconnection callbacks can be called.
* If you use this method (blocking scheme), don't use dataAvailable() (non-blocking scheme).
* \param usecMax Max time to wait in microsecond (up to 1 sec)
*/
void sleepUntilDataAvailable( uint usecMax=100000 );
#endif
/** Receives next block of data in the specified buffer (resizes the vector)
* You must call dataAvailable() before every call to receive()
*/
//void receive( std::vector<uint8>& buffer );
void receive( NLMISC::CMemStream& buffer );
/// Update the network (call this method evenly)
void update();
// Returns the size in bytes of the data stored in the send queue.
uint32 getSendQueueSize() const { return _BufSock->SendFifo.size(); }
void displaySendQueueStat (NLMISC::CLog *log = NLMISC::InfoLog)
{
_BufSock->SendFifo.displayStats(log);
}
void displayThreadStat (NLMISC::CLog *log);
/** Sets the time flush trigger (in millisecond). When this time is elapsed,
* all data in the send queue is automatically sent (-1 to disable this trigger)
*/
void setTimeFlushTrigger( sint32 ms ) { _BufSock->setTimeFlushTrigger( ms ); }
/** Sets the size flush trigger. When the size of the send queue reaches or exceeds this
* calue, all data in the send queue is automatically sent (-1 to disable this trigger )
*/
void setSizeFlushTrigger( sint32 size ) { _BufSock->setSizeFlushTrigger( size ); }
/** Force to send data pending in the send queue now. If all the data could not be sent immediately,
* the returned nbBytesRemaining value is non-zero.
* \param nbBytesRemaining If the pointer is not NULL, the method sets the number of bytes still pending after the flush attempt.
* \returns False if an error has occured (e.g. the remote host is disconnected).
* To retrieve the reason of the error, call CSock::getLastError() and/or CSock::errorString()
*/
bool flush( uint *nbBytesRemaining=NULL ) { return _BufSock->flush( nbBytesRemaining ); }
/** Returns true if the connection is still connected (changed when a disconnection
* event has reached the front of the receive queue, just before calling the disconnection callback
* if there is one)
*/
bool connected() const { return _BufSock->connectedState(); }
/// Returns the address of the remote host
const CInetAddress& remoteAddress() const { return _BufSock->Sock->remoteAddr(); }
/// Returns the number of bytes downloaded (read or still in the receive buffer) since the latest connection
uint64 bytesDownloaded() const { return _BufSock->Sock->bytesReceived(); }
/// Returns the number of bytes uploaded (flushed) since the latest connection
uint64 bytesUploaded() const { return _BufSock->Sock->bytesSent(); }
/// Returns the number of bytes downloaded since the previous call to this method
uint64 newBytesDownloaded();
/// Returns the number of bytes uploaded since the previous call to this method
uint64 newBytesUploaded();
/*//Not right because we add callbacks in the receive queue
/// Returns the number of bytes popped by receive() since the beginning (mutexed on the receive queue)
uint64 bytesReceived() { }
/// Returns the number of bytes pushed by send() since the beginning
uint64 bytesSent() { return bytesUploaded() + getSendQueueSize(); }
/// Returns the number of bytes popped by receive() since the previous call to this method
uint64 newBytesReceived();
/// Returns the number of bytes pushed by send() since the previous call to this method
uint64 newBytesSent();
*/
/// Returns the id of the connection
TSockId id() const { return _BufSock; /*_RecvTask->sockId();*/ }
protected:
friend class CClientReceiveTask;
/// Send buffer and connection
CNonBlockingBufSock *_BufSock; // ADDED: non-blocking client connection
/// True when the Nagle algorithm must be disabled (TCP_NODELAY)
bool _NoDelay;
/// Previous number of bytes downloaded
uint64 _PrevBytesDownloaded;
/// Previous number of bytes uploaded
uint64 _PrevBytesUploaded;
/*
/// Previous number of bytes received
uint32 _PrevBytesReceived;
/// Previous number of bytes sent
uint32 _PrevBytesSent;
*/
private:
/// Receive task
CClientReceiveTask *_RecvTask;
/// Receive thread
NLMISC::IThread *_RecvThread;
};
} // NLNET
#endif // NL_BUF_CLIENT_H
/* End of buf_client.h */