//******************************************************************************
// RCF - Remote Call Framework
// Copyright (c) 2005 - 2007. All rights reserved.
// Consult your license for conditions of use.
// Developed by Jarl Lindrud.
// Contact: jlindrud@hotmail.com .
//******************************************************************************
#include <RCF/Marshal.hpp>
#include <algorithm>
#include <boost/function.hpp>
#include <boost/serialization/split_free.hpp>
#include <RCF/ClientProgress.hpp>
#include <RCF/SerializationProtocol.hpp>
#ifdef RCF_USE_SF_SERIALIZATION
#include <SF/memory.hpp>
#endif
namespace boost {
namespace serialization {
template<typename Archive, typename T>
void serialize(Archive &ar, std::auto_ptr<T> &apt, const unsigned int version)
{
split_free(ar, apt, version);
}
template<typename Archive, typename T>
void save(Archive &ar, const std::auto_ptr<T> &apt, const unsigned int)
{
ar & apt.get();
}
template<typename Archive, typename T>
void load(Archive &ar, std::auto_ptr<T> &apt, const unsigned int)
{
T *pt = NULL;
ar & pt;
apt.reset(pt);
}
}
}
namespace RCF {
namespace IDL {
void doInReturnValue(
ClientStub &clientStub,
SerializationProtocolIn &in,
SerializationProtocolOut &out,
bool oneway,
bool &retry)
{
RCF_ASSERT(!retry);
unsigned int totalTimeoutMs = clientStub.getRemoteCallTimeoutMs();
unsigned int startTimeMs = getCurrentTimeMs();
unsigned int endTimeMs = startTimeMs + totalTimeoutMs;
unsigned int timeoutMs = 0;
clientStub.verifyTransport();
I_ClientTransport &connection = clientStub.getTransport();
const std::vector<FilterPtr> &filters = clientStub.getMessageFilters();
WithProgressCallback *pWithCallbackProgress =
dynamic_cast<WithProgressCallback *>(&connection);
if (pWithCallbackProgress)
{
pWithCallbackProgress->setClientProgressPtr(
clientStub.getClientProgressPtr());
}
// TODO: make sure timeouts behave as expected, esp. when connect() is doing round trip filter setup calls
clientStub.connect();
ThreadLocalCached< std::vector<ByteBuffer> > tlcByteBuffers;
std::vector<ByteBuffer> &byteBuffers = tlcByteBuffers.get();
out.extractByteBuffers(byteBuffers);
int protocol = out.getSerializationProtocol();
ThreadLocalCached< std::vector<ByteBuffer> > tlcEncodedByteBuffers;
std::vector<ByteBuffer> &encodedByteBuffers = tlcEncodedByteBuffers.get();
RCF::MethodInvocationRequest &request = clientStub.mRequest;
request.encodeRequest(
byteBuffers,
encodedByteBuffers,
filters);
timeoutMs = generateTimeoutMs(endTimeMs);
int err = connection.send(encodedByteBuffers, timeoutMs);
RCF_ASSERT(err == 1)(err);
if (!oneway)
{
timeoutMs = generateTimeoutMs(endTimeMs);
ByteBuffer encodedByteBuffer;
int err = connection.receive(encodedByteBuffer, timeoutMs);
RCF_ASSERT(err == 1)(err);
ByteBuffer unfilteredByteBuffer;
MethodInvocationResponse response;
request.decodeResponse(
encodedByteBuffer,
unfilteredByteBuffer,
response,
filters);
in.reset(
unfilteredByteBuffer,
protocol);
if (response.isException())
{
std::auto_ptr<RemoteException> remoteExceptionAutoPtr;
deserialize(in, remoteExceptionAutoPtr);
remoteExceptionAutoPtr->throwCopy();
}
else if (response.isError())
{
int err = response.getError();
if (err == RcfError_VersionMismatch)
{
int version = response.getArg0();
RCF_VERIFY(
version < clientStub.getRcfRuntimeVersion(),
Exception(RcfError_Encoding));
if (clientStub.getAutoVersioning() && clientStub.getTries() == 0)
{
clientStub.setRcfRuntimeVersion(version);
clientStub.setTries(1);
retry = true;
}
else
{
RCF_THROW(VersioningException(version));
}
}
else
{
RCF_THROW(RemoteException(response.getError()))
(response.getError());
}
}
}
}
}
} // namespace RCF