X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fnet%2Fnet.cpp;h=314410ebbdb66fee6bb053f43a7dac6d02762dd6;hb=09b734344f31e18d0fa31c39acba6d012aa2cc56;hp=73ed73c2d006b06480bdef3c53310dd8501d4698;hpb=9ebe2c320fd9f94266ab93fa2f9d9908a0a284d3;p=blank.git diff --git a/src/net/net.cpp b/src/net/net.cpp index 73ed73c..314410e 100644 --- a/src/net/net.cpp +++ b/src/net/net.cpp @@ -5,6 +5,7 @@ #include "Server.hpp" #include "../app/init.hpp" +#include "../world/World.hpp" #include #include @@ -42,7 +43,7 @@ Client::Client(const Config &conf, World &world) client_pack.data = new Uint8[sizeof(Packet)]; client_pack.maxlen = sizeof(Packet); // establish connection - conn.SendPing(client_pack, client_sock); + SendPing(); } Client::~Client() { @@ -74,7 +75,7 @@ void Client::HandlePacket(const UDPpacket &udp_pack) { return; } - conn.FlagRecv(); + conn.Received(udp_pack); cout << "I got something!" << endl; } @@ -83,15 +84,26 @@ void Client::Update(int dt) { if (conn.TimedOut()) { cout << "connection timed out :(" << endl; } else if (conn.ShouldPing()) { - conn.SendPing(client_pack, client_sock); + SendPing(); } } +void Client::SendPing() { + conn.SendPing(client_pack, client_sock); +} + +void Client::SendLogin(const string &name) { + Packet &pack = *reinterpret_cast(client_pack.data); + client_pack.len = pack.Login(name); + conn.Send(client_pack, client_sock); +} + Connection::Connection(const IPaddress &addr) : addr(addr) , send_timer(5000) -, recv_timer(10000) { +, recv_timer(10000) +, ctrl{ 0, 0xFFFF, 0xFFFF } { send_timer.Start(); recv_timer.Start(); } @@ -122,14 +134,53 @@ void Connection::Update(int dt) { } -void Connection::Send(UDPpacket &pack, UDPsocket sock) { - pack.address = addr; - if (SDLNet_UDP_Send(sock, -1, &pack) == 0) { +void Connection::Send(UDPpacket &udp_pack, UDPsocket sock) { + Packet &pack = *reinterpret_cast(udp_pack.data); + pack.header.ctrl = ctrl; + + udp_pack.address = addr; + if (SDLNet_UDP_Send(sock, -1, &udp_pack) == 0) { throw NetError("SDLNet_UDP_Send"); } + FlagSend(); } +void Connection::Received(const UDPpacket &udp_pack) { + Packet &pack = *reinterpret_cast(udp_pack.data); + + int diff = std::int16_t(pack.header.ctrl.seq) - std::int16_t(ctrl.ack); + + if (diff > 0) { + // incoming more recent than last acked + + // TODO: packets considered lost are detected here + // this should have ones for all of them: + // ~hist & ((1 << dist) - 1) if dist is < 32 + + if (diff >= 32) { + // missed more than the last 32 oO + ctrl.hist = 0; + } else { + ctrl.hist >>= diff; + ctrl.hist |= 1 << (32 - diff); + } + } else if (diff < 0) { + // incoming older than acked + if (diff > -32) { + // too late :/ + } else { + ctrl.hist |= 1 << (32 + diff); + } + } else { + // incoming the same as last acked oO + } + + ctrl.ack = pack.header.ctrl.seq; + + FlagRecv(); +} + void Connection::SendPing(UDPpacket &udp_pack, UDPsocket sock) { Packet &pack = *reinterpret_cast(udp_pack.data); udp_pack.len = pack.Ping(); @@ -160,6 +211,20 @@ size_t Packet::Ping() noexcept { return sizeof(Header); } +size_t Packet::Login(const string &name) noexcept { + constexpr size_t maxname = 32; + + Tag(); + header.type = LOGIN; + if (name.size() < maxname) { + memset(payload, '\0', maxname); + memcpy(payload, name.c_str(), name.size()); + } else { + memcpy(payload, name.c_str(), maxname); + } + return sizeof(Header) + maxname; +} + Server::Server(const Config &conf, World &world) : serv_sock(nullptr) @@ -205,7 +270,19 @@ void Server::HandlePacket(const UDPpacket &udp_pack) { } Connection &client = GetClient(udp_pack.address); - client.FlagRecv(); + client.Received(udp_pack); + + switch (pack.header.type) { + case Packet::PING: + // already done all that's supposed to do + break; + case Packet::LOGIN: + HandleLogin(client, udp_pack); + break; + default: + // just drop packets of unknown type + break; + } } Connection &Server::GetClient(const IPaddress &addr) { @@ -244,4 +321,25 @@ void Server::OnDisconnect(Connection &client) { cout << "connection timeout from " << client.Address() << endl; } + +void Server::HandleLogin(Connection &client, const UDPpacket &udp_pack) { + const Packet &pack = *reinterpret_cast(udp_pack.data); + size_t maxlen = min(udp_pack.len - int(sizeof(Packet::Header)), 32); + string name; + name.reserve(maxlen); + for (size_t i = 0; i < maxlen && pack.payload[i] != '\0'; ++i) { + name.push_back(pack.payload[i]); + } + cout << "got login request from player \"" << name << '"' << endl; + + Entity *player = world.AddPlayer(name); + if (player) { + // success! + cout << "\taccepted" << endl; + } else { + // aw no :( + cout << "\trejected" << endl; + } +} + }