2014-09-17 04:04:50 +03:00
|
|
|
#include "interface/module.h"
|
|
|
|
#include "interface/server.h"
|
|
|
|
#include "interface/event.h"
|
|
|
|
#include "interface/tcpsocket.h"
|
2014-09-17 23:00:31 +03:00
|
|
|
#include "interface/mutex.h"
|
2014-09-17 16:43:05 +03:00
|
|
|
#include "network/include/api.h"
|
2014-09-17 23:44:42 +03:00
|
|
|
#include "core/log.h"
|
2014-09-17 04:04:50 +03:00
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
using interface::Event;
|
|
|
|
|
|
|
|
namespace network {
|
|
|
|
|
2014-09-17 16:43:05 +03:00
|
|
|
struct Peer
|
|
|
|
{
|
|
|
|
typedef size_t Id;
|
|
|
|
|
|
|
|
Id id = 0;
|
|
|
|
sp_<interface::TCPSocket> socket;
|
|
|
|
|
|
|
|
Peer(){}
|
|
|
|
Peer(Id id, sp_<interface::TCPSocket> socket):
|
|
|
|
id(id), socket(socket){}
|
|
|
|
};
|
|
|
|
|
2014-09-17 23:22:00 +03:00
|
|
|
struct PacketTypeRegistry
|
|
|
|
{
|
|
|
|
sm_<ss_, Packet::Type> m_types;
|
|
|
|
Packet::Type m_next_type = 100;
|
|
|
|
|
|
|
|
Packet::Type get(const ss_ &name){
|
|
|
|
auto it = m_types.find(name);
|
|
|
|
if(it != m_types.end())
|
|
|
|
return it->second;
|
|
|
|
Packet::Type type = m_next_type++;
|
|
|
|
m_types[name] = type;
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Module: public interface::Module, public network::Interface
|
2014-09-17 04:04:50 +03:00
|
|
|
{
|
2014-09-17 23:00:31 +03:00
|
|
|
interface::Mutex m_interface_mutex;
|
2014-09-17 04:04:50 +03:00
|
|
|
interface::Server *m_server;
|
2014-09-17 16:43:05 +03:00
|
|
|
sp_<interface::TCPSocket> m_listening_socket;
|
|
|
|
sm_<Peer::Id, Peer> m_peers;
|
|
|
|
size_t m_next_peer_id = 1;
|
2014-09-17 23:22:00 +03:00
|
|
|
PacketTypeRegistry m_packet_types;
|
2014-09-17 04:04:50 +03:00
|
|
|
|
|
|
|
Module(interface::Server *server):
|
2014-09-17 23:00:31 +03:00
|
|
|
interface::Module("network"),
|
2014-09-17 04:04:50 +03:00
|
|
|
m_server(server),
|
2014-09-17 16:43:05 +03:00
|
|
|
m_listening_socket(interface::createTCPSocket())
|
2014-09-17 04:04:50 +03:00
|
|
|
{
|
2014-09-17 23:44:42 +03:00
|
|
|
log_v(MODULE, "network construct");
|
2014-09-17 14:58:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void init()
|
|
|
|
{
|
2014-09-17 23:00:31 +03:00
|
|
|
interface::MutexScope ms(m_interface_mutex);
|
|
|
|
|
2014-09-17 23:44:42 +03:00
|
|
|
log_v(MODULE, "network init");
|
2014-09-17 16:43:05 +03:00
|
|
|
m_server->sub_event(this, Event::t("core:start"));
|
2014-09-17 18:26:58 +03:00
|
|
|
m_server->sub_event(this, Event::t("network:listen_event"));
|
2014-09-17 15:52:15 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
~Module()
|
|
|
|
{
|
2014-09-17 23:44:42 +03:00
|
|
|
log_v(MODULE, "network destruct");
|
2014-09-17 15:52:15 +03:00
|
|
|
}
|
|
|
|
|
2014-09-17 18:52:59 +03:00
|
|
|
void event(const Event::Type &type, const Event::Private *p)
|
2014-09-17 15:52:15 +03:00
|
|
|
{
|
2014-09-17 23:00:31 +03:00
|
|
|
interface::MutexScope ms(m_interface_mutex);
|
|
|
|
|
2014-09-17 20:15:46 +03:00
|
|
|
EVENT_VOIDN("core:start", on_start)
|
|
|
|
EVENT_TYPEN("network:listen_event", on_listen_event, interface::SocketEvent)
|
2014-09-17 15:52:15 +03:00
|
|
|
}
|
2014-09-17 04:04:50 +03:00
|
|
|
|
2014-09-17 23:00:31 +03:00
|
|
|
void* get_interface()
|
|
|
|
{
|
2014-09-17 23:22:00 +03:00
|
|
|
return dynamic_cast<Interface*>(this);
|
2014-09-17 23:00:31 +03:00
|
|
|
}
|
|
|
|
|
2014-09-17 16:43:05 +03:00
|
|
|
void on_start()
|
2014-09-17 15:52:15 +03:00
|
|
|
{
|
2014-09-17 13:37:34 +03:00
|
|
|
ss_ address = "any4";
|
2014-09-17 04:04:50 +03:00
|
|
|
ss_ port = "20000";
|
|
|
|
|
2014-09-17 16:43:05 +03:00
|
|
|
if(!m_listening_socket->bind_fd(address, port) ||
|
2014-09-17 23:05:05 +03:00
|
|
|
!m_listening_socket->listen_fd()){
|
2014-09-17 23:44:42 +03:00
|
|
|
log_i(MODULE, "Failed to bind to %s:%s", cs(address), cs(port));
|
2014-09-17 04:04:50 +03:00
|
|
|
} else {
|
2014-09-17 23:44:42 +03:00
|
|
|
log_i(MODULE, "Listening at %s:%s", cs(address), cs(port));
|
2014-09-17 04:04:50 +03:00
|
|
|
}
|
2014-09-17 16:43:05 +03:00
|
|
|
|
|
|
|
m_server->add_socket_event(m_listening_socket->fd(),
|
2014-09-17 23:05:05 +03:00
|
|
|
Event::t("network:listen_event"));
|
2014-09-17 16:43:05 +03:00
|
|
|
}
|
|
|
|
|
2014-09-17 18:26:58 +03:00
|
|
|
void on_listen_event(const interface::SocketEvent &event)
|
2014-09-17 16:43:05 +03:00
|
|
|
{
|
2014-09-17 23:44:42 +03:00
|
|
|
log_i(MODULE, "network: on_listen_event(): fd=%i", event.fd);
|
2014-09-17 20:15:46 +03:00
|
|
|
// Create socket
|
2014-09-17 18:26:58 +03:00
|
|
|
sp_<interface::TCPSocket> socket(interface::createTCPSocket());
|
2014-09-17 20:15:46 +03:00
|
|
|
// Accept connection
|
2014-09-17 18:26:58 +03:00
|
|
|
socket->accept_fd(*m_listening_socket.get());
|
2014-09-17 20:15:46 +03:00
|
|
|
// Store socket
|
2014-09-17 18:26:58 +03:00
|
|
|
Peer::Id peer_id = m_next_peer_id++;
|
|
|
|
m_peers[peer_id] = Peer(peer_id, socket);
|
2014-09-17 20:15:46 +03:00
|
|
|
// Emit event
|
|
|
|
PeerInfo pinfo;
|
|
|
|
pinfo.id = peer_id;
|
|
|
|
pinfo.address = socket->get_remote_address();
|
2014-09-17 20:24:06 +03:00
|
|
|
m_server->emit_event("network:new_client", new NewClient(pinfo));
|
2014-09-17 04:04:50 +03:00
|
|
|
}
|
2014-09-17 20:49:30 +03:00
|
|
|
|
2014-09-17 23:22:00 +03:00
|
|
|
// Interface
|
2014-09-17 23:00:31 +03:00
|
|
|
|
|
|
|
Packet::Type packet_type(const ss_ &name)
|
|
|
|
{
|
|
|
|
interface::MutexScope ms(m_interface_mutex);
|
2014-09-17 23:22:00 +03:00
|
|
|
|
|
|
|
return m_packet_types.get(name);
|
2014-09-17 23:00:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void send(PeerInfo::Id recipient, const Packet::Type &type, const ss_ &data)
|
|
|
|
{
|
2014-09-17 23:44:42 +03:00
|
|
|
log_i(MODULE, "network::send()");
|
2014-09-17 23:00:31 +03:00
|
|
|
interface::MutexScope ms(m_interface_mutex);
|
|
|
|
|
2014-09-17 23:22:00 +03:00
|
|
|
auto it = m_peers.find(recipient);
|
|
|
|
if(it == m_peers.end()){
|
|
|
|
throw Exception(ss_()+"network::send(): Peer "+itos(recipient) +
|
|
|
|
" doesn't exist");
|
|
|
|
}
|
|
|
|
Peer &peer = it->second;
|
|
|
|
// TODO: Create actual packet including type and length
|
|
|
|
peer.socket->send_fd(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
void send(PeerInfo::Id recipient, const ss_ &name, const ss_ &data)
|
|
|
|
{
|
|
|
|
send(recipient, m_packet_types.get(name), data);
|
2014-09-17 23:00:31 +03:00
|
|
|
}
|
2014-09-17 04:04:50 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
EXPORT void* createModule_network(interface::Server *server){
|
|
|
|
return (void*)(new Module(server));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|