src/Network/TCP.cc
author terom
Thu, 04 Dec 2008 21:59:23 +0000
changeset 200 2dbf40661580
parent 186 0738f2949a2b
child 203 3ec7ab40755f
permissions -rw-r--r--
better NetworkBuffer/Packet stuff + some additional Physics+Network stuff + random fixes

#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_triggered(), this, &NetworkTCPTransport::on_read);
    slots.connect(socket.sig_write_triggered(), this, &NetworkTCPTransport::on_write);
    slots.connect(socket.sig_disconnected(), this, &NetworkTCPTransport::on_disconnected);
}


void NetworkTCPTransport::on_read (void) {
    uint16_t length;
    char *buf_ptr;
    
    // let the in stream read length-prefixed packets and pass them on to handle_packet
    while (in.peek_data<uint16_t>(length, buf_ptr)) {
        // 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<uint16_t>();
    }
}

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

void NetworkTCPTransport::on_disconnected (void) {
    // pass right through
    _sig_disconnect();
}
        
void NetworkTCPTransport::write_packet (const NetworkPacketBuffer &packet) {
    uint16_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 (Error &e) {
        const char *err = e.what();

        Engine::log(ERROR, "tcp.write_packet") << err;
        
        throw;    
    }
}

NetworkTCPServer::NetworkTCPServer (const NetworkAddress &listen_addr) :
    socket(CL_Socket::tcp, CL_Socket::ipv4) {
    
    // bind
    socket.bind(listen_addr);

    // assign slots
    slots.connect(socket.sig_read_triggered(), 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();

    // create a new NetworkTCPTransport
    NetworkTCPTransport *client = buildTransport(client_sock);
        
    // let our user handle it
    _sig_client(client);
}
        
NetworkTCPTransport* NetworkTCPServer::buildTransport (CL_Socket &socket) {
    return new NetworkTCPTransport(socket);
}
        
NetworkTCPClient::NetworkTCPClient (const NetworkAddress &connect_addr) :
    NetworkTCPTransport(NetworkSocket(CL_Socket::tcp, CL_Socket::ipv4)) {

    // connect
    socket.connect(connect_addr);
    
    // use nonblocking sockets
    socket.set_nonblocking(true);
}