src/Network/TCP.cc
author terom
Mon, 15 Dec 2008 23:56:42 +0000
changeset 378 5589abf5e61b
parent 263 8c999cf4c182
child 380 d193dd1d8a7e
permissions -rw-r--r--
break the network code. Too late to set up a branch for this now

#include "TCP.hh"
#include "../Engine.hh"

/*
 * NetworkTCPTransport
 */
NetworkTCPTransport::NetworkTCPTransport (NetworkSocket *socket) :
    socket(socket), in(socket, NETWORK_TCP_INITIAL_IN_BUF), out(socket, NETWORK_TCP_INITIAL_OUT_BUF) {
    
    // connect signals
    slots.connect(socket->sig_read(), this, &NetworkTCPTransport::on_read);
    slots.connect(socket->sig_write(), this, &NetworkTCPTransport::on_write);
}
        
NetworkTCPTransport::~NetworkTCPTransport (void) {
    // release socket
    delete socket;
}

void NetworkTCPTransport::on_read (void) {
    uint32_t length;
    char *buf_ptr;
    
    try { 
        // let the in stream read length-prefixed packets and pass them on to handle_packet
        do {
            // not enough data -> return and wait 
            if (in.peek_data<uint32_t>(length, buf_ptr) == false)
                break;

            // allocate the NetworkPacketBuffer with the given buf_ptr/length
            NetworkPacketBuffer packet(buf_ptr, length, length);
            
            // pass the packet on
            _sig_packet(packet);

            // flush it
            in.flush_data<uint32_t>();
        } while (true);

    } catch (NetworkSocketError &e) {
        // log and disconnect
        Engine::log(ERROR, "tcp.on_read") << "socket error: " << e.what();

        _sig_disconnect();
    }
}

void NetworkTCPTransport::on_write (void) {
    try {
        // just flush the output buffer
        out.flush_write();

    } catch (NetworkSocketError &e) {
        // log and disconnect
        Engine::log(ERROR, "tcp.on_write") << "socket error: " << e.what();

        _sig_disconnect();
    }
}
        
void NetworkTCPTransport::write_packet (const NetworkPacketBuffer &packet) {
    uint32_t prefix = packet.get_data_size();
    
    if (prefix != packet.get_data_size())
        throw CL_Error("send prefix overflow");
    
    try {
        // just write to the output buffer
        out.write_prefix((char *) packet.get_buf(), prefix);

    } catch (NetworkSocketError &e) {
        const char *err = e.what();

        Engine::log(ERROR, "tcp.write_packet") << err;
        
        // XXX: these are not handled anywhere :(
        throw;    
    }
}

/*
 * NetworkTCPServer
 */
NetworkTCPServer::NetworkTCPServer (const NetworkAddress &listen_addr) :
    socket(AF_UNSPEC, SOCK_STREAM) {
    
    // bind
    socket.bind(listen_addr);

    // assign slots
    slots.connect(socket.sig_read(), this, &NetworkTCPServer::on_accept);

    // listen
    socket.listen(NETWORK_LISTEN_BACKLOG);
    
    // use nonblocking sockets
    socket.set_nonblocking(true);
}


void NetworkTCPServer::on_accept (void) {
    // accept a new socket
    NetworkSocket *client_sock = socket.accept(NULL);

    // create a new NetworkTCPTransport
    NetworkTCPTransport *client = buildTransport(client_sock);
        
    // let our user handle it
    _sig_client(client);
}
        
NetworkTCPTransport* NetworkTCPServer::buildTransport (NetworkSocket *socket) {
    return new NetworkTCPTransport(socket);
}
        
/*
 * NetworkTCPClient
 */
NetworkTCPClient::NetworkTCPClient (const NetworkAddress &connect_addr) :
    NetworkTCPTransport(new NetworkSocket(AF_UNSPEC, SOCK_STREAM)) {
    
    // connect
    socket->connect(connect_addr);
    
    // use nonblocking sockets
    socket->set_nonblocking(true);
}