2021-09-13 15:53:43 +03:00
|
|
|
//
|
|
|
|
// Created by Neirokan on 30.04.2020
|
|
|
|
//
|
|
|
|
|
2021-10-31 11:39:08 +03:00
|
|
|
#include <algorithm>
|
|
|
|
|
2021-09-13 15:53:43 +03:00
|
|
|
#include "UDPSocket.h"
|
2021-10-09 13:41:12 +03:00
|
|
|
#include "../utils/Time.h"
|
2021-10-16 20:22:55 +03:00
|
|
|
#include "../Consts.h"
|
2021-09-13 15:53:43 +03:00
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
UDPSocket::UDPSocket() : _ownId(0), _nextRelyMsgId(0) {
|
2021-09-13 15:53:43 +03:00
|
|
|
_socket.setBlocking(false);
|
|
|
|
}
|
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
void UDPSocket::addConnection(sf::Uint16 id, sf::IpAddress ip, sf::Uint16 port) {
|
2021-10-31 11:39:08 +03:00
|
|
|
_connections.insert({id, UDPConnection(id, ip, port)});
|
2021-09-13 15:53:43 +03:00
|
|
|
}
|
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
void UDPSocket::removeConnection(sf::Uint16 id) {
|
2021-09-13 15:53:43 +03:00
|
|
|
_connections.erase(id);
|
|
|
|
}
|
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
bool UDPSocket::bind(sf::Uint16 port) {
|
2021-09-13 15:53:43 +03:00
|
|
|
return _socket.bind(port) == sf::Socket::Status::Done;
|
|
|
|
}
|
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
void UDPSocket::unbind() {
|
2021-09-13 15:53:43 +03:00
|
|
|
sf::Packet packet;
|
|
|
|
packet << MsgType::Disconnect << _ownId;
|
|
|
|
|
2021-10-29 18:19:30 +03:00
|
|
|
for (auto it = _connections.begin(); it != _connections.end();) {
|
2021-09-13 15:53:43 +03:00
|
|
|
send(packet, it->first);
|
|
|
|
_connections.erase(it++);
|
|
|
|
}
|
|
|
|
|
|
|
|
_relyPackets.clear();
|
|
|
|
_confirmTimes.clear();
|
|
|
|
_socket.unbind();
|
|
|
|
setId(0);
|
|
|
|
}
|
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
void UDPSocket::setTimeoutCallback(std::function<bool(sf::Uint16)> callback) {
|
2021-09-13 15:53:43 +03:00
|
|
|
_timeoutCallback = std::move(callback);
|
|
|
|
}
|
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
void UDPSocket::setId(sf::Uint16 id) {
|
2021-09-13 15:53:43 +03:00
|
|
|
_ownId = id;
|
|
|
|
}
|
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
sf::Uint16 UDPSocket::ownId() const {
|
2021-09-13 15:53:43 +03:00
|
|
|
return _ownId;
|
|
|
|
}
|
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
sf::Uint16 UDPSocket::serverId() const {
|
2021-09-13 15:53:43 +03:00
|
|
|
return _serverId;
|
|
|
|
}
|
|
|
|
|
2021-10-31 11:39:08 +03:00
|
|
|
void UDPSocket::sendRely(const sf::Packet &packet, const sf::IpAddress &ip, sf::Uint16 port) {
|
2021-09-13 15:53:43 +03:00
|
|
|
sf::Packet finalPacket;
|
|
|
|
finalPacket << _ownId << true << _nextRelyMsgId;
|
|
|
|
finalPacket.append(packet.getData(), packet.getDataSize());
|
2021-10-31 11:39:08 +03:00
|
|
|
_relyPackets.insert({_nextRelyMsgId++, ReliableMsg(finalPacket, ip, port)});
|
2021-09-13 15:53:43 +03:00
|
|
|
}
|
|
|
|
|
2021-10-31 11:39:08 +03:00
|
|
|
void UDPSocket::sendRely(const sf::Packet &packet, sf::Uint16 id) {
|
2021-10-28 16:58:02 +03:00
|
|
|
if (!_connections.count(id)) {
|
2021-09-13 15:53:43 +03:00
|
|
|
return;
|
2021-10-28 16:58:02 +03:00
|
|
|
}
|
2021-09-13 15:53:43 +03:00
|
|
|
this->sendRely(packet, _connections.at(id).ip(), _connections.at(id).port());
|
|
|
|
}
|
|
|
|
|
2021-10-31 11:39:08 +03:00
|
|
|
void UDPSocket::send(const sf::Packet &packet, const sf::IpAddress &ip, sf::Uint16 port) {
|
2021-09-13 15:53:43 +03:00
|
|
|
sf::Packet finalPacket;
|
|
|
|
finalPacket << _ownId << false << _serverId;
|
|
|
|
finalPacket.append(packet.getData(), packet.getDataSize());
|
|
|
|
_socket.send(finalPacket, ip, port);
|
|
|
|
}
|
|
|
|
|
2021-10-31 11:39:08 +03:00
|
|
|
void UDPSocket::send(const sf::Packet &packet, sf::Uint16 id) {
|
2021-10-28 16:58:02 +03:00
|
|
|
if (!_connections.count(id)) {
|
2021-09-13 15:53:43 +03:00
|
|
|
return;
|
2021-10-28 16:58:02 +03:00
|
|
|
}
|
2021-09-13 15:53:43 +03:00
|
|
|
this->send(packet, _connections.at(id).ip(), _connections.at(id).port());
|
|
|
|
}
|
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
void UDPSocket::update() {
|
|
|
|
for (auto it = _connections.begin(); it != _connections.end();) {
|
|
|
|
if (!it->second.timeout()) {
|
2021-09-13 15:53:43 +03:00
|
|
|
++it;
|
2021-10-28 16:58:02 +03:00
|
|
|
} else {
|
|
|
|
if (_timeoutCallback && !_timeoutCallback(it->first)) {
|
2021-09-13 15:53:43 +03:00
|
|
|
return;
|
2021-10-28 16:58:02 +03:00
|
|
|
}
|
2021-09-13 15:53:43 +03:00
|
|
|
_connections.erase(it++);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
for (auto it = _relyPackets.begin(); it != _relyPackets.end();) {
|
|
|
|
if (!it->second.trySend(_socket)) {
|
2021-09-13 15:53:43 +03:00
|
|
|
_relyPackets.erase(it++);
|
2021-10-28 16:58:02 +03:00
|
|
|
} else {
|
2021-09-13 15:53:43 +03:00
|
|
|
++it;
|
2021-10-28 16:58:02 +03:00
|
|
|
}
|
2021-09-13 15:53:43 +03:00
|
|
|
}
|
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
for (auto it = _confirmTimes.begin(); it != _confirmTimes.end();) {
|
|
|
|
if (Time::time() - it->second > Consts::NETWORK_TIMEOUT) {
|
2021-09-13 15:53:43 +03:00
|
|
|
_confirmTimes.erase(it++);
|
2021-10-28 16:58:02 +03:00
|
|
|
} else {
|
2021-09-13 15:53:43 +03:00
|
|
|
++it;
|
2021-10-28 16:58:02 +03:00
|
|
|
}
|
2021-09-13 15:53:43 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-31 11:39:08 +03:00
|
|
|
MsgType UDPSocket::receive(sf::Packet &packet, sf::Uint16 &senderId) {
|
2021-09-13 15:53:43 +03:00
|
|
|
// Receive message
|
|
|
|
sf::IpAddress ip;
|
|
|
|
sf::Uint16 port;
|
|
|
|
|
|
|
|
packet.clear();
|
2021-10-28 16:58:02 +03:00
|
|
|
if (_socket.receive(packet, ip, port) != sf::Socket::Status::Done) {
|
2021-09-13 15:53:43 +03:00
|
|
|
return MsgType::Empty;
|
2021-10-28 16:58:02 +03:00
|
|
|
}
|
2021-09-13 15:53:43 +03:00
|
|
|
|
|
|
|
// Read header
|
|
|
|
bool reply = false;
|
|
|
|
sf::Uint16 msgId = 0;
|
|
|
|
MsgType type;
|
|
|
|
senderId = 0;
|
2021-10-28 16:58:02 +03:00
|
|
|
if (!(packet >> senderId >> reply >> msgId >> type)) {
|
2021-09-13 15:53:43 +03:00
|
|
|
return MsgType::Error;
|
2021-10-28 16:58:02 +03:00
|
|
|
}
|
2021-09-13 15:53:43 +03:00
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
if (_connections.count(senderId)) {
|
2021-09-13 15:53:43 +03:00
|
|
|
_connections.at(senderId).update();
|
2021-10-28 16:58:02 +03:00
|
|
|
}
|
2021-09-13 15:53:43 +03:00
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
if (type == MsgType::Confirm) {
|
2021-09-13 15:53:43 +03:00
|
|
|
_relyPackets.erase(msgId);
|
2021-10-28 16:58:02 +03:00
|
|
|
// you don't need this information on the highest levels
|
|
|
|
return MsgType::Empty;
|
2021-09-13 15:53:43 +03:00
|
|
|
}
|
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
if (type == MsgType::Connect) {
|
2021-09-13 15:53:43 +03:00
|
|
|
sf::Uint32 version = 0;
|
2021-10-28 16:58:02 +03:00
|
|
|
if (!(packet >> version) || version != Consts::NETWORK_VERSION) {
|
2021-09-13 15:53:43 +03:00
|
|
|
return MsgType::Error;
|
2021-10-28 16:58:02 +03:00
|
|
|
}
|
2021-09-13 15:53:43 +03:00
|
|
|
sf::Uint16 tmp;
|
2021-10-28 16:58:02 +03:00
|
|
|
for (tmp = Consts::NETWORK_MAX_CLIENTS; tmp >= 1; tmp--) {
|
|
|
|
if (!_connections.count(tmp)) {
|
2021-09-13 15:53:43 +03:00
|
|
|
senderId = tmp;
|
2021-10-28 16:58:02 +03:00
|
|
|
} else {
|
|
|
|
if (_connections.at(tmp).same(ip, port)) {
|
2021-09-13 15:53:43 +03:00
|
|
|
return MsgType::Error;
|
2021-10-28 16:58:02 +03:00
|
|
|
}
|
|
|
|
}
|
2021-09-13 15:53:43 +03:00
|
|
|
}
|
2021-10-31 11:39:08 +03:00
|
|
|
_connections.insert({senderId, UDPConnection(senderId, ip, port)});
|
2021-09-13 15:53:43 +03:00
|
|
|
}
|
|
|
|
|
2021-10-31 11:39:08 +03:00
|
|
|
if (!_connections.count(senderId) || !_connections.at(senderId).same(ip, port) ||
|
|
|
|
reply && confirmed(msgId, senderId)) {
|
2021-09-13 15:53:43 +03:00
|
|
|
return MsgType::Error;
|
2021-10-28 16:58:02 +03:00
|
|
|
}
|
2021-09-13 15:53:43 +03:00
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
bool UDPSocket::confirmed(sf::Uint16 msgId, sf::Uint16 senderId) {
|
2021-09-13 15:53:43 +03:00
|
|
|
sf::Packet confirmPacket;
|
|
|
|
confirmPacket << _ownId << false << msgId << MsgType::Confirm;
|
|
|
|
_connections.at(senderId).send(_socket, confirmPacket);
|
|
|
|
|
|
|
|
sf::Uint32 confirmId;
|
|
|
|
confirmId = (senderId << 16) | msgId;
|
|
|
|
|
|
|
|
bool repeat = _confirmTimes.count(confirmId);
|
|
|
|
_confirmTimes[confirmId] = Time::time();
|
|
|
|
|
|
|
|
return repeat;
|
|
|
|
}
|
2021-10-16 20:22:55 +03:00
|
|
|
|
|
|
|
UDPSocket::~UDPSocket() {
|
|
|
|
unbind();
|
|
|
|
}
|