Magic World game server
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

210 lines
5.1 KiB

#include <MWSessionI.h>
#include <MWUtils.h>
using namespace std;
class SessionCallbackAdapter : public MWMapCallbackAdapter,
public enable_shared_from_this<SessionCallbackAdapter>
{
public:
SessionCallbackAdapter(const shared_ptr<MW::MWRoomCallbackPrx>& callback,
const shared_ptr<MW::MWSessionPrx>& session,
bool trace, const shared_ptr<Ice::Logger>& logger, const std::string& name) :
_callback(callback),
_session(session),
_trace(trace),
_logger(logger),
_name(name)
{
}
void init(Ice::StringSeq users) override
{
auto self = shared_from_this();
try
{
_callback->initAsync(users, nullptr, [self](std::exception_ptr eptr) { self->failed(eptr); });
}
catch(const Ice::CommunicatorDestroyedException&)
{
// Ignored server is being shutdown
}
}
void join(const shared_ptr<MW::UserJoinedEvent>& e) override
{
auto self = shared_from_this();
try
{
_callback->joinAsync(e->timestamp, e->name, nullptr, [self](exception_ptr eptr) { self->failed(eptr); });
}
catch(const Ice::CommunicatorDestroyedException&)
{
// Ignored server is being shutdown
}
}
void leave(const shared_ptr<MW::UserLeftEvent>& e) override
{
auto self = shared_from_this();
try
{
_callback->leaveAsync(e->timestamp, e->name, nullptr, [self](exception_ptr eptr) { self->failed(eptr); });
}
catch(const Ice::CommunicatorDestroyedException&)
{
// Ignored server is being shutdown
}
}
void send(const shared_ptr<MW::MessageEvent>& e) override
{
auto self = shared_from_this();
try
{
_callback->sendAsync(e->timestamp, e->name, e->message, nullptr, [self](exception_ptr eptr) { self->failed(eptr); });
}
catch(const Ice::CommunicatorDestroyedException&)
{
// Ignored server is being shutdown
}
}
void failed(exception_ptr)
{
if(_trace)
{
Ice::Trace out(_logger, "info");
out << "Error sending request to user '" << _name << "'. The user's session will be destroyed.";
}
try
{
_session->ice_endpoints(Ice::EndpointSeq())->destroy(); // Collocated call.
}
catch(const Ice::LocalException&)
{
}
}
private:
const shared_ptr<MW::MWMapCallbackPrx> _callback;
const shared_ptr<MW::MWSessionPrx> _session;
const bool _trace;
const shared_ptr<Ice::Logger> _logger;
const string _name;
};
MWSessionI::MWSessionI(const shared_ptr<MWMap>& MWMap, const string& name, bool trace, const shared_ptr<Ice::Logger>& logger) :
_MWMap(MWMap),
_name(name),
_trace(trace),
_logger(logger)
{
}
void
MWSessionI::setCallback(shared_ptr<MW::MWMapCallbackPrx> callback, const Ice::Current& current)
{
lock_guard<mutex> sync(_mutex);
if(_destroy)
{
if(_trace)
{
Ice::Trace out(_logger, "info");
out << "User '" << _name << "' tried to set the session callback but the session is already destroyed.";
}
throw Ice::ObjectNotExistException(__FILE__, __LINE__);
}
if(_callback || !callback)
{
return;
}
Ice::Context ctx;
ctx["_fwd"] = "o";
_callback = make_shared<SessionCallbackAdapter>(
callback->ice_context(ctx),
Ice::uncheckedCast<MW::MWSessionPrx>(current.adapter->createProxy(current.id)),
_trace, _logger, _name);
_MWRoom->join(_name, _callback);
}
long long
MWSessionI::send(string message, const Ice::Current&)
{
lock_guard<mutex> sync(_mutex);
if(_destroy)
{
if(_trace)
{
Ice::Trace out(_logger, "info");
out << "User '" << _name << "' tried to send a message but the session is already destroyed.";
}
throw Ice::ObjectNotExistException(__FILE__, __LINE__);
}
if(!_callback)
{
if(_trace)
{
Ice::Trace out(_logger, "info");
out << "User '" << _name << "' tried to send a message without setting the callback.";
}
throw MW::InvalidMessageException("You cannot send messages until you join the MW Map.");
}
string msg;
try
{
msg = validateMessage(message);
}
catch(const exception& ex)
{
if(_trace)
{
Ice::Trace out(_logger, "info");
out << "User '" << _name << "' sent an invalid message:\n" << ex;
}
throw MW::InvalidMessageException(ex.what());
}
return _MWMap->send(_name, move(msg));
}
void
MWSessionI::destroy(const Ice::Current& current)
{
lock_guard<mutex> sync(_mutex);
if(_destroy)
{
if(_trace)
{
Ice::Trace out(_logger, "info");
out << "Trying to destroy the session for user '" << _name << "' but the session is already destroyed.";
}
throw Ice::ObjectNotExistException(__FILE__, __LINE__);
}
try
{
current.adapter->remove(current.id);
if(_callback)
{
_MWMap->leave(_name);
}
else
{
_MWMap->unreserve(_name);
}
}
catch(const Ice::ObjectAdapterDeactivatedException&)
{
// No need to clean up, the server is shutting down.
}
if(_trace)
{
Ice::Trace out(_logger, "info");
out << "Push session for user '" << _name << "' destroyed.";
}
_destroy = true;
}