}
}
+unsigned Networking::get_next_protocol_id()
+{
+ static unsigned next_id = 0;
+ return next_id++;
+}
+
+void Networking::set_protocol(unsigned id, unique_ptr<Net::Protocol> net_proto)
+{
+ if(protocols.size()<=id)
+ protocols.resize(id+1);
+
+ Protocol &proto = protocols[id];
+ proto.protocol = move(net_proto);
+ if(state==SERVER)
+ {
+ for(const auto &c: clients)
+ c->get_communicator().add_protocol(*proto.protocol, proto.receiver);
+ }
+ else if(state==CONNECTING || state==CONNECTED)
+ connection->get_communicator().add_protocol(*proto.protocol, proto.receiver);
+}
+
uint16_t Networking::intern_string(const string &value)
{
auto i = find(strings, value);
void Networking::protocol_ready(const Net::Protocol &p)
{
- if(state==CONNECTING && &p==&protocol)
+ if(state==CONNECTING && &p==&core_protocol)
set_state(CONNECTED);
}
Networking::ServerConnection::ServerConnection(Networking &n, const Net::SockAddr &addr):
Connection(n, make_unique<Net::StreamSocket>(addr.get_family()))
{
- communicator.add_protocol(networking.protocol, *this);
+ communicator.add_protocol(networking.core_protocol, *this);
socket->set_block(false);
socket->signal_connect_finished.connect(sigc::mem_fun(this, &ServerConnection::connect_finished));
socket->connect(addr);
Connection(n, move(s))
{
communicator.signal_protocol_ready.connect(sigc::mem_fun(this, &ClientConnection::protocol_ready));
- communicator.add_protocol(networking.protocol, *this);
+ communicator.add_protocol(networking.core_protocol, *this);
+ for(Protocol &p: networking.protocols)
+ communicator.add_protocol(*p.protocol, p.receiver);
}
void Networking::ClientConnection::protocol_ready(const Net::Protocol &p)
{
- if(&p==&networking.protocol)
+ if(&p==&networking.core_protocol)
{
size_t n_strings = networking.strings.size();
for(size_t i=1; i<n_strings; ++i)
Events::NetworkPlayerDeparted, Events::ServerStageActivated>;
private:
+ class SwitchableReceiver: public Net::DynamicReceiver
+ {
+ private:
+ Net::DynamicReceiver *receiver = nullptr;
+
+ public:
+ void set_receiver(Net::DynamicReceiver *r) { receiver = r; }
+ void receive(unsigned i, const Variant &p) override { if(receiver) receiver->receive(i, p); }
+ };
+
+ struct Protocol
+ {
+ std::unique_ptr<Net::Protocol> protocol;
+ SwitchableReceiver receiver;
+ };
+
class Connection
{
protected:
EventSource event_source;
EventObserver observer;
IO::EventDispatcher &io_disp;
- Protocol protocol;
State state = DISABLED;
+ CoreProtocol core_protocol;
+ std::vector<Protocol> protocols;
std::unique_ptr<Net::StreamServerSocket> server_socket;
std::unique_ptr<ServerConnection> connection;
std::vector<std::unique_ptr<ClientConnection>> clients;
void disable();
void reap_connections();
+ template<typename P>
+ const Net::Protocol &set_receiver(Net::DynamicReceiver *);
+
+private:
+ static unsigned get_next_protocol_id();
+
+ void set_protocol(unsigned, std::unique_ptr<Net::Protocol>);
+
+public:
std::uint16_t intern_string(const std::string &);
const std::string &get_string(std::uint16_t) const;
private:
Player &create_player(const std::string &, unsigned = 0);
+public:
+ template<typename P>
+ void send(const P &);
+
+ template<typename P>
+ void send(unsigned, const P &);
+
+private:
void set_state(State);
void protocol_ready(const Net::Protocol &);
void incoming_connection();
};
+template<typename P>
+const Net::Protocol &Networking::set_receiver(Net::DynamicReceiver *r)
+{
+ static unsigned id = get_next_protocol_id();
+ if(id>=protocols.size() || !protocols[id].protocol)
+ set_protocol(id, std::make_unique<P>());
+
+ protocols[id].receiver.set_receiver(r);
+ return *protocols[id].protocol.get();
+}
+
+template<typename P>
+void Networking::send(const P &packet)
+{
+ if(state==SERVER)
+ {
+ for(const auto &c: clients)
+ c->get_communicator().send(packet);
+ }
+ else if(state==CONNECTED)
+ connection->get_communicator().send(packet);
+ else
+ throw invalid_state("Networking::send");
+}
+
+template<typename P>
+void Networking::send(unsigned target, const P &packet)
+{
+ if(state!=SERVER)
+ throw invalid_state("Networking::send");
+
+ auto i = lower_bound_member(players, target, &Player::id);
+ if(i==players.end() || i->id!=target)
+ throw key_error(i);
+
+ i->owner->get_communicator().send(packet);
+}
+
+
namespace Events {
struct NetworkStateChanged