#include "networking.h"
+#include <msp/core/raii.h>
#include <msp/net/inet6.h>
#include <msp/net/resolve.h>
#include "director.h"
return next_id++;
}
-void Networking::set_protocol(unsigned id, unique_ptr<Net::Protocol> net_proto)
+void Networking::set_receiver(unsigned id, Net::DynamicReceiver *recv)
{
- if(protocols.size()<=id)
- protocols.resize(id+1);
-
- Protocol &proto = protocols[id];
- proto.protocol = move(net_proto);
+ protocols[id].receiver = recv;
if(state==SERVER)
{
for(const auto &c: clients)
- c->get_communicator().add_protocol(*proto.protocol, proto.receiver);
+ c->update_receiver(id);
}
else if(state==CONNECTING || state==CONNECTED)
- connection->get_communicator().add_protocol(*proto.protocol, proto.receiver);
+ connection->update_receiver(id);
}
uint16_t Networking::intern_string(const string &value)
}
+void Networking::ProxyReceiver::receive(unsigned i, const Variant &p)
+{
+ if(receiver)
+ {
+ SetForScope set_sender(networking.current_sender, &connection);
+ receiver->receive(i, p);
+ }
+}
+
+
Networking::Connection::Connection(Networking &n, unique_ptr<Net::StreamSocket> s):
networking(n),
socket(move(s)),
stale = true;
}
+void Networking::Connection::update_receiver(unsigned id)
+{
+ if(id>=receivers.size())
+ receivers.resize(id+1);
+
+ unique_ptr<ProxyReceiver> &proxy_ptr = receivers[id];
+ if(!proxy_ptr)
+ {
+ proxy_ptr = make_unique<ProxyReceiver>(networking, *this);
+ communicator.add_protocol(*networking.protocols[id].protocol, *proxy_ptr);
+ }
+ proxy_ptr->set_receiver(networking.protocols[id].receiver);
+}
+
Networking::ServerConnection::ServerConnection(Networking &n, const Net::SockAddr &addr):
Connection(n, make_unique<Net::StreamSocket>(addr.get_family()))
{
communicator.signal_protocol_ready.connect(sigc::mem_fun(this, &ClientConnection::protocol_ready));
communicator.add_protocol(networking.core_protocol, *this);
- for(Protocol &p: networking.protocols)
- communicator.add_protocol(*p.protocol, p.receiver);
+ receivers.resize(networking.protocols.size());
+ for(size_t i=0; i<networking.protocols.size(); ++i)
+ if(Net::Protocol *proto = networking.protocols[i].protocol.get())
+ {
+ ProxyReceiver *recv_ptr = (receivers[i] = make_unique<ProxyReceiver>(networking, *this)).get();
+ recv_ptr->set_receiver(networking.protocols[i].receiver);
+ communicator.add_protocol(*proto, *recv_ptr);
+ }
}
void Networking::ClientConnection::protocol_ready(const Net::Protocol &p)
Events::NetworkPlayerDeparted, Events::ServerStageActivated>;
private:
- class SwitchableReceiver: public Net::DynamicReceiver
+ class Connection;
+
+ class ProxyReceiver: public Net::DynamicReceiver
{
private:
+ Networking &networking;
+ Connection &connection;
Net::DynamicReceiver *receiver = nullptr;
public:
+ ProxyReceiver(Networking &n, Connection &c): networking(n), connection(c) { }
+
void set_receiver(Net::DynamicReceiver *r) { receiver = r; }
- void receive(unsigned i, const Variant &p) override { if(receiver) receiver->receive(i, p); }
+ void receive(unsigned, const Variant &) override;
};
struct Protocol
{
std::unique_ptr<Net::Protocol> protocol;
- SwitchableReceiver receiver;
+ Net::DynamicReceiver *receiver = nullptr;
};
class Connection
Networking &networking;
std::unique_ptr<Net::StreamSocket> socket;
Net::Communicator communicator;
+ std::vector<std::unique_ptr<ProxyReceiver>> receivers;
bool stale = false;
Connection(Networking &, std::unique_ptr<Net::StreamSocket>);
public:
Net::Communicator &get_communicator() { return communicator; }
+ void update_receiver(unsigned);
bool is_stale() const { return stale; }
};
std::vector<Player> players;
unsigned next_player_id = 1;
std::vector<std::string> strings;
+ Connection *current_sender = nullptr;
public:
Networking(Director &);
private:
static unsigned get_next_protocol_id();
- void set_protocol(unsigned, std::unique_ptr<Net::Protocol>);
+ void set_receiver(unsigned, Net::DynamicReceiver *);
public:
std::uint16_t intern_string(const std::string &);
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();
+ if(id>=protocols.size())
+ protocols.resize(id+1);
+ Protocol &proto = protocols[id];
+ if(!proto.protocol)
+ proto.protocol = std::make_unique<P>();
+
+ set_receiver(id, r);
+ return *proto.protocol.get();
}
template<typename P>