//*****************************************************************************
// RCF - Remote Call Framework
// Copyright (c) 2005. All rights reserved.
// Developed by Jarl Lindrud.
// Contact: jlindrud@hotmail.com .
//*****************************************************************************
#ifndef INCLUDE_RCF_TCPASIOCLIENT_TRANSPORT_HPP
#define INCLUDE_RCF_TCPASIOCLIENT_TRANSPORT_HPP
#include <boost/shared_ptr.hpp>
#include <boost/asio.hpp>
#include <RCF/ClientTransport.hpp>
#include <RCF/ThreadLibrary.hpp>
namespace RCF {
namespace asio = boost::asio;
class TcpAsioSynchronizedSocket;
class TcpAsioServerTransport;
typedef asio::io_service Demuxer;
typedef boost::shared_ptr<Demuxer> DemuxerPtr;
class TcpAsioClientTransport : public I_ClientTransport
{
public:
TcpAsioClientTransport(const std::string &ip, int port, DemuxerPtr demuxerPtr = getSharedDemuxerPtr()/* DemuxerPtr()*/);
TcpAsioClientTransport(const TcpAsioClientTransport &rhs);
~TcpAsioClientTransport();
// I_ClientTransport implementation
ClientTransportAutoPtr clone() const;
EndpointPtr getEndpointPtr() const;
int send(const std::string &data, unsigned int timeoutMs);
int receive(std::string &data, unsigned int timeoutMs);
bool isConnected();
void close();
void setTransportFilters(const std::vector<FilterPtr> &filters);
private:
friend class TcpAsioServerTransport;
typedef TcpAsioSynchronizedSocket SynchronizedSocket;
typedef boost::shared_ptr<SynchronizedSocket> SynchronizedSocketPtr;
TcpAsioClientTransport(SynchronizedSocketPtr synchronizedSocketPtr, DemuxerPtr demuxerPtr = getSharedDemuxerPtr()/* DemuxerPtr()*/);
SynchronizedSocketPtr releaseSynchronizedSocketPtr();
SynchronizedSocketPtr getSynchronizedSocketPtr();
private:
int connect();
void readSingle(char *buffer, std::size_t bufferLen);
void writeSingle(const char *buffer, std::size_t bufferLen);
std::size_t read(char *buffer, std::size_t bufferLen);
std::size_t write(const char *buffer, std::size_t bufferLen);
int errFromAsioErr();
void onFilteredReadWriteCompletion(std::size_t bytesTransferred, int error);
// shared instance functions
private:
class State;
typedef boost::shared_ptr<State> StatePtr;
static ReadWriteMutexPtr * spReadWriteMutexPtr;
static DemuxerPtr * spDemuxerPtr;
public:
static void init();
static void deinit();
static ReadWriteMutexPtr getSharedReadWriteMutexPtr();
static DemuxerPtr getSharedDemuxerPtr();
// data
private:
class State
{
public:
State(Demuxer &demuxer) : mTimer(demuxer), mBytesTransferred(), mTimeoutFlag() {}
asio::deadline_timer mTimer;
std::size_t mBytesTransferred;
volatile bool mTimeoutFlag;
asio::error mError;
Mutex mEventMutex;
Condition mEvent;
};
DemuxerPtr mDemuxerPtr;
SynchronizedSocketPtr mSynchronizedSocketPtr;
// following are at times generated lazily, hence the mutable
mutable std::string mIp;
mutable int mPort;
mutable asio::ip::tcp::endpoint mEndpoint;
std::vector<FilterPtr> mTransportFilters;
std::vector<char> mReadBuffer;
std::vector<char> mWriteBuffer;
unsigned int mEndTimeMs;
StatePtr mStatePtr;
asio::deadline_timer & mTimer;
std::size_t & mBytesTransferred;
volatile bool & mTimeoutFlag;
asio::error & mError;
Mutex & mEventMutex;
Condition & mEvent;
};
} // namespace RCF
#endif // ! INCLUDE_RCF_TCPASIOCLIENT_TRANSPORT_HPP