src/proto2/NetworkSession.cc
author terom
Thu, 20 Nov 2008 22:55:28 +0000
branchno-netsession
changeset 39 cfb8b6e2a35f
parent 37 ed2957490bbf
permissions -rw-r--r--
almost playable

#include "NetworkSession.hh"
#include "Engine.hh"

#include <cassert>

NetworkSession::NetworkSession (uint64_t magic) :
    magic(magic), tcp_srv(NULL), udp_srv(NULL), udp_client(NULL) {
   
    // nothing
}
        
void NetworkSession::listen (const NetworkAddress &addr) {
    assert(tcp_srv == NULL && udp_srv == NULL);
    
    // create TCP/UDP servers
    tcp_srv = new NetworkTCPServer(addr);
    udp_srv = new NetworkUDP(addr);
    
    // connect signals
    slots.connect(tcp_srv->sig_client(), this, &NetworkSession::on_tcp_client);
    slots.connect(udp_srv->sig_packet(), this, &NetworkSession::on_udp_packet);
}
        
NetworkNode *NetworkSession::build_node (NetworkTCPTransport *tcp, NetworkUDP *udp, const NetworkAddress &addr, enum NetworkNodeType type) {
    // XXX: unused
    (void) type;

    // create node
    return new NetworkNode(*this, tcp, udp, addr);
}

NetworkNode* NetworkSession::connect (const NetworkAddress &addr) {
    // XXX: only one connect
    assert(!udp_client);

    // connect TCP
    NetworkTCPClient *tcp_client = new NetworkTCPClient(addr);
        
    // create UDP socket on same address
    udp_client = new NetworkUDP(tcp_client->getLocalAddress());
    
    // build client
    NetworkNode *client_node = build_node(tcp_client, udp_client, addr, NETWORK_NODE_CLIENT_SERVER);

    // add to nodes
    nodes[addr] = client_node;

    // connect signals
    slots.connect(udp_client->sig_packet(), this, &NetworkSession::on_udp_packet);
        
    // return the "server" node
    return client_node;
}
                
void NetworkSession::handle_disconnect (NetworkNode *node) {
    // remove from nodes
    nodes.erase(node->getRemoteAddress());
}
        
void NetworkSession::handle_message (NetworkPacket &pkt, NetworkNode *node) {
    // read the channel id
    NetworkChannelID channel_id = pkt.read_uint16();

    // fire signal
    _map_sig_chan_message[channel_id](pkt, node);
}
 
void NetworkSession::on_tcp_client (NetworkTCPTransport *tcp_client) {
    // get remote address manually, because NetworkTCPServer doesn't pass it in to us
    NetworkAddress addr = tcp_client->getRemoteAddress();

    // build client
    NetworkNode *client_node = build_node(tcp_client, udp_srv, addr, NETWORK_NODE_SERVER_CLIENT);

    // add to nodes
    nodes[addr] = client_node;
    
    // fire signals
    _sig_node_connected(client_node);
}
        
void NetworkSession::on_udp_packet (NetworkPacket &pkt, const NetworkAddress &addr) {
    NetworkNode *node = nodes[addr];
    
    // drop from unknown sources
    if (!node) {
        Engine::log(WARN, "net_session.on_udp_packet") << "dropping unsolicted UDP packet from " << addr;
        return;
    }

    // handle
    handle_message(pkt, node);
}
       
void NetworkSession::send_all (NetworkChannelID channel_id, const NetworkPacket &pkt, bool reliable) {
    send_all_except(channel_id, pkt, NULL, reliable);
}
        
void NetworkSession::send_all_except (NetworkChannelID channel_id, const NetworkPacket &pkt, const NetworkNode *node, bool reliable) {
    for (std::map<NetworkAddress, NetworkNode*>::iterator it = nodes.begin(); it != nodes.end(); it++) {
        if (it->second == node)
            continue;

        it->second->send(channel_id, pkt, reliable);
    }
}