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

5 years ago
  1. #include <MWSessionI.h>
  2. #include <MWUtils.h>
  3. using namespace std;
  4. class SessionCallbackAdapter : public MWMapCallbackAdapter,
  5. public enable_shared_from_this<SessionCallbackAdapter>
  6. {
  7. public:
  8. SessionCallbackAdapter(const shared_ptr<MW::MWRoomCallbackPrx>& callback,
  9. const shared_ptr<MW::MWSessionPrx>& session,
  10. bool trace, const shared_ptr<Ice::Logger>& logger, const std::string& name) :
  11. _callback(callback),
  12. _session(session),
  13. _trace(trace),
  14. _logger(logger),
  15. _name(name)
  16. {
  17. }
  18. void init(Ice::StringSeq users) override
  19. {
  20. auto self = shared_from_this();
  21. try
  22. {
  23. _callback->initAsync(users, nullptr, [self](std::exception_ptr eptr) { self->failed(eptr); });
  24. }
  25. catch(const Ice::CommunicatorDestroyedException&)
  26. {
  27. // Ignored server is being shutdown
  28. }
  29. }
  30. void join(const shared_ptr<MW::UserJoinedEvent>& e) override
  31. {
  32. auto self = shared_from_this();
  33. try
  34. {
  35. _callback->joinAsync(e->timestamp, e->name, nullptr, [self](exception_ptr eptr) { self->failed(eptr); });
  36. }
  37. catch(const Ice::CommunicatorDestroyedException&)
  38. {
  39. // Ignored server is being shutdown
  40. }
  41. }
  42. void leave(const shared_ptr<MW::UserLeftEvent>& e) override
  43. {
  44. auto self = shared_from_this();
  45. try
  46. {
  47. _callback->leaveAsync(e->timestamp, e->name, nullptr, [self](exception_ptr eptr) { self->failed(eptr); });
  48. }
  49. catch(const Ice::CommunicatorDestroyedException&)
  50. {
  51. // Ignored server is being shutdown
  52. }
  53. }
  54. void send(const shared_ptr<MW::MessageEvent>& e) override
  55. {
  56. auto self = shared_from_this();
  57. try
  58. {
  59. _callback->sendAsync(e->timestamp, e->name, e->message, nullptr, [self](exception_ptr eptr) { self->failed(eptr); });
  60. }
  61. catch(const Ice::CommunicatorDestroyedException&)
  62. {
  63. // Ignored server is being shutdown
  64. }
  65. }
  66. void failed(exception_ptr)
  67. {
  68. if(_trace)
  69. {
  70. Ice::Trace out(_logger, "info");
  71. out << "Error sending request to user '" << _name << "'. The user's session will be destroyed.";
  72. }
  73. try
  74. {
  75. _session->ice_endpoints(Ice::EndpointSeq())->destroy(); // Collocated call.
  76. }
  77. catch(const Ice::LocalException&)
  78. {
  79. }
  80. }
  81. private:
  82. const shared_ptr<MW::MWMapCallbackPrx> _callback;
  83. const shared_ptr<MW::MWSessionPrx> _session;
  84. const bool _trace;
  85. const shared_ptr<Ice::Logger> _logger;
  86. const string _name;
  87. };
  88. MWSessionI::MWSessionI(const shared_ptr<MWMap>& MWMap, const string& name, bool trace, const shared_ptr<Ice::Logger>& logger) :
  89. _MWMap(MWMap),
  90. _name(name),
  91. _trace(trace),
  92. _logger(logger)
  93. {
  94. }
  95. void
  96. MWSessionI::setCallback(shared_ptr<MW::MWMapCallbackPrx> callback, const Ice::Current& current)
  97. {
  98. lock_guard<mutex> sync(_mutex);
  99. if(_destroy)
  100. {
  101. if(_trace)
  102. {
  103. Ice::Trace out(_logger, "info");
  104. out << "User '" << _name << "' tried to set the session callback but the session is already destroyed.";
  105. }
  106. throw Ice::ObjectNotExistException(__FILE__, __LINE__);
  107. }
  108. if(_callback || !callback)
  109. {
  110. return;
  111. }
  112. Ice::Context ctx;
  113. ctx["_fwd"] = "o";
  114. _callback = make_shared<SessionCallbackAdapter>(
  115. callback->ice_context(ctx),
  116. Ice::uncheckedCast<MW::MWSessionPrx>(current.adapter->createProxy(current.id)),
  117. _trace, _logger, _name);
  118. _MWRoom->join(_name, _callback);
  119. }
  120. long long
  121. MWSessionI::send(string message, const Ice::Current&)
  122. {
  123. lock_guard<mutex> sync(_mutex);
  124. if(_destroy)
  125. {
  126. if(_trace)
  127. {
  128. Ice::Trace out(_logger, "info");
  129. out << "User '" << _name << "' tried to send a message but the session is already destroyed.";
  130. }
  131. throw Ice::ObjectNotExistException(__FILE__, __LINE__);
  132. }
  133. if(!_callback)
  134. {
  135. if(_trace)
  136. {
  137. Ice::Trace out(_logger, "info");
  138. out << "User '" << _name << "' tried to send a message without setting the callback.";
  139. }
  140. throw MW::InvalidMessageException("You cannot send messages until you join the MW Map.");
  141. }
  142. string msg;
  143. try
  144. {
  145. msg = validateMessage(message);
  146. }
  147. catch(const exception& ex)
  148. {
  149. if(_trace)
  150. {
  151. Ice::Trace out(_logger, "info");
  152. out << "User '" << _name << "' sent an invalid message:\n" << ex;
  153. }
  154. throw MW::InvalidMessageException(ex.what());
  155. }
  156. return _MWMap->send(_name, move(msg));
  157. }
  158. void
  159. MWSessionI::destroy(const Ice::Current& current)
  160. {
  161. lock_guard<mutex> sync(_mutex);
  162. if(_destroy)
  163. {
  164. if(_trace)
  165. {
  166. Ice::Trace out(_logger, "info");
  167. out << "Trying to destroy the session for user '" << _name << "' but the session is already destroyed.";
  168. }
  169. throw Ice::ObjectNotExistException(__FILE__, __LINE__);
  170. }
  171. try
  172. {
  173. current.adapter->remove(current.id);
  174. if(_callback)
  175. {
  176. _MWMap->leave(_name);
  177. }
  178. else
  179. {
  180. _MWMap->unreserve(_name);
  181. }
  182. }
  183. catch(const Ice::ObjectAdapterDeactivatedException&)
  184. {
  185. // No need to clean up, the server is shutting down.
  186. }
  187. if(_trace)
  188. {
  189. Ice::Trace out(_logger, "info");
  190. out << "Push session for user '" << _name << "' destroyed.";
  191. }
  192. _destroy = true;
  193. }