2020-12-28 16:22:12 +00:00
|
|
|
/**
|
|
|
|
** Supermodel
|
|
|
|
** A Sega Model 3 Arcade Emulator.
|
|
|
|
** Copyright 2011-2020 Bart Trzynadlowski, Nik Henson, Ian Curtis,
|
|
|
|
** Harry Tuttle, and Spindizzi
|
|
|
|
**
|
|
|
|
** This file is part of Supermodel.
|
|
|
|
**
|
|
|
|
** Supermodel is free software: you can redistribute it and/or modify it under
|
|
|
|
** the terms of the GNU General Public License as published by the Free
|
|
|
|
** Software Foundation, either version 3 of the License, or (at your option)
|
|
|
|
** any later version.
|
|
|
|
**
|
|
|
|
** Supermodel is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
|
** more details.
|
|
|
|
**
|
|
|
|
** You should have received a copy of the GNU General Public License along
|
|
|
|
** with Supermodel. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
**/
|
|
|
|
|
2020-06-13 19:46:12 +00:00
|
|
|
#include "TCPReceive.h"
|
2020-12-28 16:22:12 +00:00
|
|
|
#include "OSD/Logger.h"
|
|
|
|
#include <chrono>
|
2020-06-13 19:46:12 +00:00
|
|
|
|
|
|
|
using namespace std::chrono_literals;
|
|
|
|
|
2020-06-16 11:55:38 +00:00
|
|
|
#if defined(_DEBUG)
|
|
|
|
#include <stdio.h>
|
2020-12-28 16:22:12 +00:00
|
|
|
#define DPRINTF DebugLog
|
2020-06-16 11:55:38 +00:00
|
|
|
#else
|
|
|
|
#define DPRINTF(a, ...)
|
|
|
|
#endif
|
|
|
|
|
2020-06-13 19:46:12 +00:00
|
|
|
TCPReceive::TCPReceive(int port) :
|
|
|
|
m_listenSocket(nullptr),
|
2021-03-15 15:55:39 +00:00
|
|
|
m_receiveSocket(nullptr),
|
|
|
|
m_socketSet(nullptr)
|
2020-06-13 19:46:12 +00:00
|
|
|
{
|
|
|
|
SDLNet_Init();
|
|
|
|
|
2021-03-15 15:55:39 +00:00
|
|
|
m_socketSet = SDLNet_AllocSocketSet(1);
|
|
|
|
|
2020-06-13 19:46:12 +00:00
|
|
|
IPaddress ip;
|
|
|
|
int result = SDLNet_ResolveHost(&ip, nullptr, port);
|
|
|
|
|
|
|
|
if (result == 0) {
|
|
|
|
m_listenSocket = SDLNet_TCP_Open(&ip);
|
|
|
|
if (m_listenSocket) {
|
|
|
|
m_running = true;
|
|
|
|
m_listenThread = std::thread(&TCPReceive::ListenFunc, this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TCPReceive::~TCPReceive()
|
|
|
|
{
|
|
|
|
m_running = false;
|
|
|
|
|
|
|
|
if (m_listenThread.joinable()) {
|
|
|
|
m_listenThread.join();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_listenSocket) {
|
|
|
|
SDLNet_TCP_Close(m_listenSocket);
|
|
|
|
m_listenSocket = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_receiveSocket) {
|
|
|
|
SDLNet_TCP_Close(m_receiveSocket);
|
|
|
|
m_receiveSocket = nullptr;
|
|
|
|
}
|
|
|
|
|
2021-03-15 15:55:39 +00:00
|
|
|
if (m_socketSet) {
|
|
|
|
SDLNet_FreeSocketSet(m_socketSet);
|
|
|
|
m_socketSet = nullptr;
|
|
|
|
}
|
|
|
|
|
2020-06-13 19:46:12 +00:00
|
|
|
SDLNet_Quit();
|
|
|
|
}
|
|
|
|
|
2021-03-15 15:55:39 +00:00
|
|
|
bool TCPReceive::CheckDataAvailable(int timeoutMS)
|
|
|
|
{
|
|
|
|
if (!m_receiveSocket) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SDLNet_CheckSockets(m_socketSet, timeoutMS) > 0;
|
|
|
|
}
|
|
|
|
|
2020-06-13 19:46:12 +00:00
|
|
|
std::vector<char>& TCPReceive::Receive()
|
|
|
|
{
|
|
|
|
if (!m_receiveSocket) {
|
2020-06-16 11:55:38 +00:00
|
|
|
DPRINTF("Can't receive because no socket.\n");
|
2020-06-13 19:46:12 +00:00
|
|
|
m_recBuffer.clear();
|
|
|
|
return m_recBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
int size = 0;
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
result = SDLNet_TCP_Recv(m_receiveSocket, &size, sizeof(int));
|
2020-06-16 11:55:38 +00:00
|
|
|
DPRINTF("Received %i bytes\n", result);
|
2020-06-13 19:46:12 +00:00
|
|
|
if (result <= 0) {
|
|
|
|
SDLNet_TCP_Close(m_receiveSocket);
|
|
|
|
m_receiveSocket = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// reserve our space
|
|
|
|
m_recBuffer.resize(size);
|
|
|
|
|
|
|
|
while (size) {
|
|
|
|
|
|
|
|
result = SDLNet_TCP_Recv(m_receiveSocket, m_recBuffer.data() + (m_recBuffer.size() - size), size);
|
2020-06-16 11:55:38 +00:00
|
|
|
DPRINTF("Received %i bytes\n", result);
|
2020-06-13 19:46:12 +00:00
|
|
|
if (result <= 0) {
|
|
|
|
SDLNet_TCP_Close(m_receiveSocket);
|
|
|
|
m_receiveSocket = nullptr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
size -= result;
|
|
|
|
}
|
|
|
|
|
|
|
|
return m_recBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TCPReceive::ListenFunc()
|
|
|
|
{
|
|
|
|
while (m_running) {
|
|
|
|
|
|
|
|
std::this_thread::sleep_for(16ms);
|
|
|
|
if (m_receiveSocket) continue;
|
|
|
|
|
|
|
|
auto socket = SDLNet_TCP_Accept(m_listenSocket);
|
|
|
|
|
|
|
|
if (socket) {
|
2021-03-15 15:55:39 +00:00
|
|
|
|
|
|
|
// remove old socket if required from socket set
|
|
|
|
if (m_receiveSocket) {
|
|
|
|
SDLNet_DelSocket(m_socketSet, (SDLNet_GenericSocket)m_receiveSocket.load());
|
|
|
|
}
|
|
|
|
|
2020-06-13 19:46:12 +00:00
|
|
|
m_receiveSocket = socket;
|
2021-03-15 15:55:39 +00:00
|
|
|
|
|
|
|
SDLNet_AddSocket(m_socketSet, (SDLNet_GenericSocket)socket);
|
|
|
|
|
|
|
|
// add socket to socket set
|
2020-06-16 11:55:38 +00:00
|
|
|
DPRINTF("Accepted connection.\n");
|
2020-06-13 19:46:12 +00:00
|
|
|
}
|
2020-12-28 16:22:12 +00:00
|
|
|
|
2020-06-13 19:46:12 +00:00
|
|
|
}
|
|
|
|
}
|