Browse Source

MWMap class

master
Pedro Berrocal 5 years ago
parent
commit
8a0cd931ca
25 changed files with 1110 additions and 45 deletions
  1. +10
    -0
      .gitignore
  2. +5
    -0
      README.md
  3. +49
    -0
      certs/README.md
  4. BIN
      certs/cacert.der
  5. BIN
      certs/cacert.jks
  6. +23
    -0
      certs/cacert.pem
  7. BIN
      certs/client.jks
  8. BIN
      certs/client.p12
  9. +126
    -0
      certs/makedemocerts.py
  10. BIN
      certs/server.jks
  11. BIN
      certs/server.p12
  12. +38
    -0
      include/MWMap.h
  13. +28
    -0
      include/MWSessionI.h
  14. +25
    -0
      include/MWSessionManagerI.h
  15. +77
    -0
      src/MW.ice
  16. +99
    -0
      src/MWMap.cpp
  17. +84
    -0
      src/MWServer.cpp
  18. +113
    -0
      src/MWSession.ice
  19. +210
    -0
      src/MWSessionI.cpp
  20. +66
    -0
      src/MWSessionManagerI.cpp
  21. +29
    -0
      src/Makefile
  22. +0
    -7
      src/Printer.ice
  23. +0
    -38
      src/Server.cpp
  24. +84
    -0
      src/config.glacier2router
  25. +44
    -0
      src/config.mwserver

+ 10
- 0
.gitignore View File

@ -0,0 +1,10 @@
*~
#*
*#
/src/obj
/src/MW.cpp
/include/MW.h
/src/MWSession.cpp
/include/MWSession.h
/src/BuiltinSequences.cpp
/include/BuiltinSequences.h

+ 5
- 0
README.md View File

@ -31,3 +31,8 @@ c++ -std=c++11 -pthread -I. -DICE_CPP11_MAPPING -c Printer.cpp Server.cpp
```
c++ -pthread -o server Printer.o Server.o -lIce++11
```
# Develpment
## TODO
- User Object
- ...

+ 49
- 0
certs/README.md View File

@ -0,0 +1,49 @@
# Demo Certificates
This directory contains certificates used by the clients and servers in our
sample programs. These certificates are for testing purposes only and should
**never** be used in a production environment.
As provided, the server certificates use `127.0.0.1` for the Common Name, the
IP address and DNS name. This works fine when you run the client and server on
the same host. However, if you want to run them on separate hosts, you may need
to regenerate the certificates. (This is especially true for the JavaScript
examples.)
We've included the Python script `makedemocerts.py` to simplify this task.
## Prerequisites
You'll need Python to run the script. The script also depends on a utility
package from a separate [ZeroC repository][1]. You can install this package as
follows:
```
pip install zeroc-icecertutils
```
## Usage
Running the script with `-h` displays the following usage information:
```
Usage: certs/makedemocerts.py [options]
Options:
-h Show this message.
-d | --debug Debugging output.
--ip <ip> The IP address for the server certificate.
--dns <dns> The DNS name for the server certificate.
--use-dns Use the DNS name for the server certificate common
name (default is to use the IP address).
```
The `--ip`, `--dns`, and `--use-dns` options affect the generation of the server
certificate. Without any arguments, the script prompts for the value of the IP
address and DNS name.
You can specify an alternate IP address using `--ip` and an alternate DNS name
using `--dns`. The `--use-dns` flag forces the script to use the DNS name as
the server's Common Name instead of the IP address.
[1]: https://github.com/zeroc-ice/icecertutils

BIN
certs/cacert.der View File


BIN
certs/cacert.jks View File


+ 23
- 0
certs/cacert.pem View File

@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIIDyTCCArGgAwIBAgIIYY3YvoWm5Q0wDQYJKoZIhvcNAQELBQAwgYsxFTATBgNV
BAMMDEljZSBEZW1vcyBDQTEMMAoGA1UECwwDSWNlMRQwEgYDVQQKDAtaZXJvQywg
SW5jLjEQMA4GA1UEBwwHSnVwaXRlcjEQMA4GA1UECAwHRmxvcmlkYTELMAkGA1UE
BhMCVVMxHTAbBgkqhkiG9w0BCQEWDmluZm9AemVyb2MuY29tMB4XDTE4MDgwNzA2
MTk1MFoXDTIzMDgwNjA2MTk1MFowgYsxFTATBgNVBAMMDEljZSBEZW1vcyBDQTEM
MAoGA1UECwwDSWNlMRQwEgYDVQQKDAtaZXJvQywgSW5jLjEQMA4GA1UEBwwHSnVw
aXRlcjEQMA4GA1UECAwHRmxvcmlkYTELMAkGA1UEBhMCVVMxHTAbBgkqhkiG9w0B
CQEWDmluZm9AemVyb2MuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEApN5uTu4/GV2EeJqnh6VQPfJOVHZ8FBJ1GXGYtA6tA07EU7CCyDPZ3kS83J+h
n7cOit56f3exPbTK1zZiUYxjFt7ttkvHJau1z8o7eNm212kQ1jAa78bnSEWHK+3m
BVARsk0BOqG5xdTQleWKE0C4TcifceAIeoOaOY4gqHryFWmmfzQjiWmseN/LZG+z
EFjI65duSz51W/3ttb/Qs8iHomx88EyViatXAFVvVdC7t5wlat88sRpAL+zaNMhZ
fZQwmIzvCcZe7buWwEelUB7q5wFMoXhoIibZLDsOjY7nQ7lPCP3cv9V87v+r1ziM
AVX6F6+XuS8BZVFEE8BbvGx7XwIDAQABoy8wLTAMBgNVHRMEBTADAQH/MB0GA1Ud
DgQWBBQKSxy2SFmKdd72PjuZOqub4ZCFajANBgkqhkiG9w0BAQsFAAOCAQEAhGDc
qkGm7hhbXCBCK1eGLuh4t3Ktl5kRtDe/LReQu2f+HS9aGaKHOfJdaABOXaQUK8ip
jiCnqoWqton96lGZUN1AI4OrpPE9vMF/s6oJ84eEn+CyTjDFnnGX0yDuCQSRmSMs
zcwIynlnnyKls2WTJqzKG46QpdedHiMWYVNRNyQzQVgYjXEamMPXELkB6hseW34s
lnJnEE5xkxRyHhuunkWt76YyJcfUHNGzzIFgDbA/13tycGvqsPnOn27WJ654ergG
Ln7PPBm58AIb+7sDUgWL0quY/vUr7fd2gkXnrL4LOOL6DBFYH5NdHBg0MsdDB6bT
fBpVrDdZVkgcXPUWKQ==
-----END CERTIFICATE-----

BIN
certs/client.jks View File


BIN
certs/client.p12 View File


+ 126
- 0
certs/makedemocerts.py View File

@ -0,0 +1,126 @@
#!/usr/bin/env python
# **********************************************************************
#
# Copyright (c) 2003-2018 ZeroC, Inc. All rights reserved.
#
# **********************************************************************
import os, sys, socket, getopt
try:
import IceCertUtils
except Exception as ex:
print("couldn't load IceCertUtils, did you install the `zeroc-icecertutils'\n"
"package from the Python package repository?\nerror: " + str(ex))
sys.exit(1)
def usage():
print("Usage: " + sys.argv[0] + " [options]")
print("")
print("Options:")
print("-h Show this message.")
print("-d | --debug Debugging output.")
print("--ip <ip> The IP address for the server certificate.")
print("--dns <dns> The DNS name for the server certificate.")
print("--use-dns Use the DNS name for the server certificate common")
print(" name (default is to use the IP address)." )
sys.exit(1)
#
# Check arguments
#
debug = False
ip = None
dns = None
usedns = False
impl = ""
try:
opts, args = getopt.getopt(sys.argv[1:], "hd", ["help", "debug", "ip=", "dns=","use-dns","impl="])
except getopt.GetoptError as e:
print("Error %s " % e)
usage()
sys.exit(1)
for (o, a) in opts:
if o == "-h" or o == "--help":
usage()
sys.exit(0)
elif o == "-d" or o == "--debug":
debug = True
elif o == "--ip":
ip = a
elif o == "--dns":
dns = a
elif o == "--use-dns":
usedns = True
elif o == "--impl":
impl = a
def request(question, newvalue, value):
while True:
sys.stdout.write(question)
sys.stdout.flush()
input = sys.stdin.readline().strip()
if input == 'n':
sys.stdout.write(newvalue)
sys.stdout.flush()
return sys.stdin.readline().strip()
else:
return value
#
# Change to the directory where the certs files are stored
#
os.chdir(os.path.dirname(os.path.abspath(__file__)))
if not ip:
try:
ip = socket.gethostbyname(socket.gethostname())
except:
ip = "127.0.0.1"
ip = request("The IP address used for the server certificate will be: " + ip + "\n"
"Do you want to keep this IP address? (y/n) [y]", "IP : ", ip)
if not dns:
dns = "localhost"
dns = request("The DNS name used for the server certificate will be: " + dns + "\n"
"Do you want to keep this DNS name? (y/n) [y]", "DNS : ", dns)
CertificateFactory = vars(IceCertUtils)[impl + "CertificateFactory"]
factory = CertificateFactory(debug=debug, cn="Ice Demos CA")
#
# CA certificate
#
factory.getCA().save("cacert.pem").save("cacert.der")
# Client certificate
client = factory.create("client")
client.save("client.p12")
# Server certificate
server = factory.create("server", cn = (dns if usedns else ip), ip=ip, dns=dns)
server.save("server.p12")
try:
factory.getCA().save("cacert.pem").save("cacert.jks") # Used by the Database/library demo
server.save("server.jks", caalias="cacert")
client.save("client.jks", caalias="cacert")
# Don't try to generate the BKS if the JKS generation fails
try:
server.save("server.bks", caalias="cacert")
client.save("client.bks", caalias="cacert")
except Exception as ex:
for f in ["server.bks", "client.bks"]:
if os.path.exists(f): os.remove(f)
print("warning: couldn't generate BKS certificates for Android applications:\n" + str(ex))
print("Please fix this issue if you want to run the Android demos.")
except Exception as ex:
for f in ["server.jks", "client.jks"]:
if os.path.exists(f): os.remove(f)
print("warning: couldn't generate JKS certificates for Java applications:\n" + str(ex))
print("Please fix this issue if you want to run the Java demos.")
factory.destroy()

BIN
certs/server.jks View File


BIN
certs/server.p12 View File


+ 38
- 0
include/MWMap.h View File

@ -0,0 +1,38 @@
#ifndef MW_MAP_I_H
#define MW_MAP_I_H
#include <Ice/Ice.h>
#include <MW.h>
#include <set>
class MWMapCallbackAdapter
{
public:
virtual void init(Ice::StringSeq) = 0;
virtual void join(const std::shared_ptr<MW::UserJoinedEvent>&) = 0;
virtual void leave(const std::shared_ptr<MW::UserLeftEvent>&) = 0;
virtual void send(const std::shared_ptr<MW::PositionEvent>&) = 0;
};
class MWMap
{
public:
MWMap(bool trace, const std::shared_ptr<Ice::Logger>& logger);
void reserve(const std::string&);
void unreserve(const std::string&);
void join(const std::string&, const std::shared_ptr<MWMapCallbackAdapter>&);
void leave(const std::string&);
long long send(const std::string&, std::string);
private:
using MWMapCallbackMap = std::map<std::string, std::shared_ptr<MWMapCallbackAdapter>>;
MWMapCallbackMap _members;
std::set<std::string> _reserved;
std::mutex _mutex;
const bool _trace;
const std::shared_ptr<Ice::Logger> _logger;
};
#endif

+ 28
- 0
include/MWSessionI.h View File

@ -0,0 +1,28 @@
#ifndef MW_SESSION_I_H
#define MW_SESSION_I_H
#include <MWSession.h>
#include <MWMap.h>
class MWSessionI : public MW::MWSession
{
public:
MWSessionI(const std::shared_ptr<MWMap>&, const std::string&, bool trace, const std::shared_ptr<Ice::Logger>& logger);
virtual void setCallback(std::shared_ptr<MWMap::MWMapCallbackPrx>, const Ice::Current&) override;
virtual long long send(std::string, const Ice::Current&) override;
virtual void destroy(const Ice::Current&) override;
private:
const std::shared_ptr<MWMap> _MWMap;
const std::string _name;
std::shared_ptr<MWMapCallbackAdapter> _callback;
bool _destroy = false;
std::mutex _mutex;
const bool _trace;
const std::shared_ptr<Ice::Logger> _logger;
};
#endif

+ 25
- 0
include/MWSessionManagerI.h View File

@ -0,0 +1,25 @@
#ifndef MW_SESSION_MANAGER_I_H
#define MW_SESSION_MANAGER_I_H
#include <Glacier2/Glacier2.h>
#include <string>
#include <MWMap.h>
class MWSessionManagerI : public Glacier2::SessionManager
{
public:
MWSessionManagerI(const std::shared_ptr<MWMap>&, bool trace, const std::shared_ptr<Ice::Logger>& logger);
virtual std::shared_ptr<Glacier2::SessionPrx> create(std::string,
std::shared_ptr<Glacier2::SessionControlPrx>,
const Ice::Current&) override;
private:
const std::shared_ptr<MWMap> _MWMap;
const bool _trace;
const std::shared_ptr<Ice::Logger> _logger;
};
#endif

+ 77
- 0
src/MW.ice View File

@ -0,0 +1,77 @@
#pragma once
#include "Ice/BuiltinSequences.ice"
#include "Glacier2/Session.ice"
module MW
{
/**
*
* The InvalidMessageException is raised when a user sends an invalid
* message to the server. A message is considered invalid if the
* message size exceeds the maximum message size.
*
**/
exception InvalidMessageException
{
/**
*
* The reason why the message was rejected by the server.
*
**/
string reason;
}
class MWMapEvent
{
/** The timestamp. */
long timestamp;
/** The name of the user. */
string name;
}
/**
*
* A sequence of state changes in the MW map.
*
* @see MWMapEvent
*
**/
sequence<MWMapEvent> MWMapEventSeq;
/**
*
* This event is generated when a user joins the MW map.
*
* @see MWMapEvent
*
**/
class UserJoinedEvent extends MWMapEvent
{
}
/**
*
* This event is generated when a user leaves the MW map.
*
* @see MWMapEvent
*
**/
class UserLeftEvent extends MWMapEvent
{
}
/**
*
* This event is generated when a user sends a posotion in the
* map.
*
* @see MWMapEvent
*
**/
class PositionEvent extends MWMapEvent
{
/** The contents of the message. */
string message;
}
}

+ 99
- 0
src/MWMap.cpp View File

@ -0,0 +1,99 @@
#include <MWMap.h>
using namespace std;
MWMap::MWMap(bool trace, const shared_ptr<Ice::Logger>& logger) :
_trace(trace),
_logger(logger)
{
}
void
MWMap::reserve(const string& name)
{
lock_guard<mutex> sync(_mutex);
if(_reserved.find(name) != _reserved.end() || _members.find(name) != _members.end())
{
throw runtime_error("The name " + name + " is already in use.");
}
_reserved.insert(name);
}
void
MWMap::unreserve(const string& name)
{
lock_guard<mutex> sync(_mutex);
_reserved.erase(name);
}
void
MWMap::join(const string& name, const shared_ptr<MWMapCallbackAdapter>& callback)
{
lock_guard<mutex> sync(_mutex);
long long timestamp = chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now().time_since_epoch()).count();
_reserved.erase(name);
Ice::StringSeq names;
for(const auto& q : _members)
{
names.push_back(q.first);
}
callback->init(move(names));
_members[name] = callback;
auto e = make_shared<MW::UserJoinedEvent>(timestamp, name);
for(const auto& q: _members)
{
q.second->join(e);
}
if(_trace)
{
Ice::Trace out(_logger, "info");
out << "User '" << name << "' joined the MW Map.";
}
}
void
MWMap::leave(const string& name)
{
lock_guard<mutex> sync(_mutex);
long long timestamp = chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now().time_since_epoch()).count();
_members.erase(name);
auto e = make_shared<MW::UserLeftEvent>(timestamp, name);
for(const auto& q: _members)
{
q.second->leave(e);
}
if(_trace)
{
Ice::Trace out(_logger, "info");
out << "User '" << name << "' left the MWMap.";
}
}
Ice::Long
MWMap::send(const string& name, string message)
{
lock_guard<mutex> sync(_mutex);
long long timestamp = chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now().time_since_epoch()).count();
auto e = make_shared<MW::PositionEvent>(timestamp, name, message);
for(const auto& q: _members)
{
q.second->send(e);
}
if(_trace)
{
Ice::Trace out(_logger, "info");
out << name << ": " << message;
}
return timestamp;
}

+ 84
- 0
src/MWServer.cpp View File

@ -0,0 +1,84 @@
#include <Ice/Ice.h>
#include <MWSessionManagerI.h>
// #include <PollingChatSessionFactoryI.h>
using namespace std;
class MWServer : public Ice::Service
{
public:
virtual bool start(int argc, char* argv[], int&) override;
virtual bool stop() override;
private:
shared_ptr<Ice::ObjectAdapter> _adapter;
};
bool
MWServer::start(int, char*[], int& status)
{
// int timeout = communicator()->getProperties()->getPropertyAsIntWithDefault("PollingChatSessionTimeout", 10);
bool traceEnabled = communicator()->getProperties()->getPropertyAsIntWithDefault("Server.Trace", 0) != 0;
auto logger = communicator()->getLogger();
try
{
_adapter = communicator()->createObjectAdapter("MWServer");
auto mwmap = make_shared<MWMap>(traceEnabled, logger);
if(traceEnabled)
{
Ice::Trace out(logger, "info");
out << "MW room created ok.";
}
_adapter->add(make_shared<MWSessionManagerI>(mwmap, traceEnabled, logger),
Ice::stringToIdentity("MWSessionManager"));
if(traceEnabled)
{
Ice::Trace out(logger, "info");
out << "MW session manager created ok.";
}
// _adapter->add(make_shared<PollingChatSessionFactoryI>(chatRoom, timeout, traceEnabled, logger),
// Ice::stringToIdentity("PollingChatSessionFactory"));
// if(traceEnabled)
// {
// Ice::Trace out(logger, "info");
// out << "Polling chat session factory created ok.";
// }
_adapter->activate();
if(traceEnabled)
{
Ice::Trace out(logger, "info");
out << "MW server started ok.";
}
}
catch(const Ice::LocalException&)
{
status = 1;
throw;
}
status = 0;
return true;
}
bool
MWServer::stop()
{
return true;
}
int
main(int argc, char* argv[])
{
#ifdef ICE_STATIC_LIBS
Ice::registerIceSSL();
Ice::registerIceWS();
#endif
MWServer app;
return app.main(argc, argv);
}

+ 113
- 0
src/MWSession.ice View File

@ -0,0 +1,113 @@
#pragma once
#include <Ice/BuiltinSequences.ice>
#include <Glacier2/Session.ice>
#include <MW.ice>
module MW
{
/**
*
* The MWRoomCallback interface is the interface that clients implement
* as their callback object.
*
* The server calls operations of this interface to communicate
* with connected clients.
*
**/
interface MWMapCallback
{
/**
*
* The server invokes this operation when the client sets the callback
* for a session. This provides the client with the initial list of users
* currently in the MW room.
*
* @param users The names of users currently in the MW room.
*
**/
void init(Ice::StringSeq users);
/**
*
* The server invokes this operation to deliver a message
* that was sent to the MW room.
*
* @param name The name of the user that send the message.
*
* @param message The contents of the message.
*
* @param timestamp The time at which the message was sent.
*
**/
void send(long timestamp, string name, string message);
/**
*
* The server invokes this operation when a user joins
* the MW room.
*
* @param name The name of the user that joined the MW room.
*
* @param timestamp The time at which the user joined the MW room.
*
**/
void join(long timestamp, string name);
/**
*
* The servers invokes this operation when a user leaves
* the MW room.
*
* @param name The name of the user that left the MW room.
*
* @param timestamp The time at which the user left the MW room.
*
**/
void leave(long timestamp, string name);
}
/**
*
* A MWSession is a custom Glacier2::Session for clients that use
* Glacier2 and support callbacks (such as C++, C# and clients).
*
* @see Glacier2::Session
*
**/
interface MWSession extends Glacier2::Session
{
/**
*
* The setCallback operation is called by clients to set the
* callback used to receive notification of activity in the
* room. Clients receive notifications as soon as they call this
* operation (before setCallback returns).
*
* The first callback made by the server is a call to
* MWRoomCallback::init, which delivers the current list of
* users to the client.
*
* @param cb The callback the server uses to deliver notifications.
*
* @see MWRoomCallback
*
**/
void setCallback(MWMapCallback* cb);
/**
*
* Send a message to the MW room.
*
* @param message The message to be sent.
*
* @return The time at which the message is sent.
*
* @throws InvalidMessageException should the message be invalid.
*
**/
long send(string message) throws InvalidMessageException;
}
}

+ 210
- 0
src/MWSessionI.cpp View File

@ -0,0 +1,210 @@
#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;
}

+ 66
- 0
src/MWSessionManagerI.cpp View File

@ -0,0 +1,66 @@
#include <ChatSessionManagerI.h>
#include <ChatSessionI.h>
#include <ChatUtils.h>
using namespace std;
ChatSessionManagerI::ChatSessionManagerI(const shared_ptr<ChatRoom>& chatRoom, bool trace,
const shared_ptr<Ice::Logger>& logger) :
_chatRoom(chatRoom),
_trace(trace),
_logger(logger)
{
}
shared_ptr<Glacier2::SessionPrx>
ChatSessionManagerI::create(string name,
shared_ptr<Glacier2::SessionControlPrx> sessionControl,
const Ice::Current& current)
{
string vname;
try
{
vname = validateName(name);
_chatRoom->reserve(vname);
}
catch(const exception& ex)
{
if(_trace)
{
Ice::Trace out(_logger, "info");
out << "Cannot create push session:\n" << ex;
}
throw Glacier2::CannotCreateSessionException(ex.what());
}
shared_ptr<Glacier2::SessionPrx> proxy;
try
{
auto session = make_shared<ChatSessionI>(_chatRoom, vname, _trace, _logger);
proxy = Ice::uncheckedCast<Glacier2::SessionPrx>(current.adapter->addWithUUID(session));
Ice::IdentitySeq ids;
ids.push_back(proxy->ice_getIdentity());
sessionControl->identities()->add(ids);
}
catch(const Ice::LocalException& ex)
{
if(_trace)
{
Ice::Trace out(_logger, "info");
out << "Cannot create push session for user '" << vname << "':\n" << ex;
}
if(proxy)
{
proxy->destroy();
}
throw Glacier2::CannotCreateSessionException("internal server error");
}
if(_trace)
{
Ice::Trace out(_logger, "info");
out << "Push session created for user '" << vname << "'.";
}
return proxy;
}

+ 29
- 0
src/Makefile View File

@ -0,0 +1,29 @@
CC=c++
IDIR =../include
CFLAGS=-I. -DICE_CPP11_MAPPING -I $(IDIR) -std=c++11
ODIR=obj
LDIR =../lib
LIBS=-lm -lIce++11
_DEPS = MW.h MWMap.h MWSession.h MWSessionI.h MWSessionManagerI.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
_OBJ = MW.o MWServer.o MWMap.o MWSession.o MWSesionManagerI.o MWUtils.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
$(ODIR)/%.o: %.cpp $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
slice:
slice2cpp -I. -I../../ice/slice *.ice
mv *.h ../include
mwserver: $(OBJ)
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
.PHONY: clean
clean:
rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~

+ 0
- 7
src/Printer.ice View File

@ -1,7 +0,0 @@
module Demo
{
interface Printer
{
void printString(string s);
}
}

+ 0
- 38
src/Server.cpp View File

@ -1,38 +0,0 @@
#include <Ice/Ice.h>
#include <Printer.h>
using namespace std;
using namespace Demo;
class PrinterI : public Printer
{
public:
virtual void printString(string s, const Ice::Current&) override;
};
void
PrinterI::printString(string s, const Ice::Current&)
{
cout << s << endl;
}
int
main(int argc, char* argv[])
{
try
{
Ice::CommunicatorHolder ich(argc, argv);
// Server implementation here ...
auto adapter = ich->createObjectAdapterWithEndpoints("SimplePrinterAdapter", "default -p 10000");
auto servant = make_shared<PrinterI>();
adapter->add(servant, ich->stringToIdentity("SimplePrinter"));
adapter->activate();
ich->waitForShutdown();
}
catch(const std::exception& e)
{
cerr << e.what() << endl;
return 1;
}
return 0;
}

+ 84
- 0
src/config.glacier2router View File

@ -0,0 +1,84 @@
#
# Set the Glacier2 instance name.
#
Glacier2.InstanceName=MWServer
#
# The client-visible endpoint of Glacier2. This should be an endpoint
# visible from the public Internet.
#
Glacier2.Client.Endpoints=ssl -p 4064 -t 10000 -h 127.0.0.1:tcp -p 4502 -t 10000 -h 127.0.0.1
#
# The server-visible endpoint of Glacier2. This endpoint is only
# required if callbacks are needed (leave empty otherwise). This
# should be an endpoint on an internal network (like 192.168.x.x), or
# on the loopback, so that the server is not directly accessible from
# the Internet.
#
Glacier2.Server.Endpoints=tcp -h 127.0.0.1
#
# The proxy of the session manager.
#
Glacier2.SessionManager=ChatSessionManager:tcp -h 127.0.0.1 -p 10001
#
# Accept only requests to the machine where the session manager is
# running.
#
Glacier2.Filter.Address.Accept=127.0.0.1:10001
#
# For this demo, we use the null permissions verifier. This permissions
# verifier allows any user-id / password combination.
#
Glacier2.PermissionsVerifier=MWServer/NullPermissionsVerifier
#
# The timeout for inactive sessions. If any client session is inactive
# for longer than this value, the session expires and is removed. The
# unit is seconds.
#
Glacier2.SessionTimeout=30
#
# Turn off buffering, it's not useful for the chat demo.
#
Glacier2.Server.Buffered=0
Glacier2.Client.Buffered=0
#
# Security Tracing
#
# 0 = no security tracing
# 1 = trace messages
#
#IceSSL.Trace.Security=1
#
# SSL Configuration
#
Ice.Plugin.IceSSL=IceSSL:createIceSSL
IceSSL.DefaultDir=../certs
IceSSL.CAs=cacert.pem
IceSSL.CertFile=server.p12
IceSSL.Password=password
IceSSL.Keychain=../../../certs/glacier2.keychain
IceSSL.KeychainPassword=password
IceSSL.VerifyPeer=0
#
# Ice Tracing
#
#Ice.Trace.Network=1
#Ice.Warn.Connections=1
#Ice.Trace.Protocol=1
#
# We configure the server thread pool as we want the glacier2router
# to be multi threaded.
#
Ice.ThreadPool.Server.Size=4
Ice.ThreadPool.Server.SizeMax=10

+ 44
- 0
src/config.mwserver View File

@ -0,0 +1,44 @@
#
# The endpoint of the session server's object adapter. This should be
# an endpoint on an internal network (like 192.168.x.x), or on the
# loopback, so that the session server is not directly accessible from
# the Internet.
#
ChatServer.Endpoints=tcp -h 127.0.0.1 -p 10001
#
# Warn about connection exceptions
#
#Ice.Warn.Connections=1
#
# Network Tracing
#
# 0 = no network tracing
# 1 = trace connection establishment and closure
# 2 = like 1, but more detailed
# 3 = like 2, but also trace data transfer
#
#Ice.Trace.Network=3
#
# Protocol Tracing
#
# 0 = no protocol tracing
# 1 = trace protocol messages
#
#Ice.Trace.Protocol=1
#
# Chat Server Tracing
#
# 0 = disable chat server tracing
# 1 = enable chat server tracing
Server.Trace=1
#
# We configure the server thread pool as we want the chatserver
# to be multi threaded.
#
Ice.ThreadPool.Server.Size=4
Ice.ThreadPool.Server.SizeMax=10

Loading…
Cancel
Save