Added subclass of broadcast - UDPClient

parent 0fcc8a8b
......@@ -12,130 +12,28 @@ using namespace std;
std::shared_ptr<BroadcastClient> BroadcastClient::self;
BroadcastClient::~BroadcastClient()
{
if (enet_socket_shutdown(discoverSocket, ENET_SOCKET_SHUTDOWN_READ_WRITE) != 0)
{
cerr << "eNet: Failed to shutdown discover socket" << endl;
}
enet_socket_destroy(discoverSocket);
if (enet_socket_shutdown(dataSocket, ENET_SOCKET_SHUTDOWN_READ_WRITE) != 0)
{
cerr << "eNet: Failed to shutdown data socket" << endl;
}
enet_socket_destroy(dataSocket);
discoverSocket = ENET_SOCKET_NULL;
dataSocket = ENET_SOCKET_NULL;
networkThread.join();
}
ENetSocket BroadcastClient::initSocket(enet_uint16 port)
{
ENetSocket socket = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM);
if (socket == ENET_SOCKET_NULL)
{
cerr << "eNet: Failed to create discover UDP socket." << endl;
return socket;
}
if (enet_socket_set_option(socket, ENET_SOCKOPT_BROADCAST, 1) != 0)
{
cerr << "eNet: Failed to enable broadcast socket." << endl;
return ENET_SOCKET_NULL;
}
ENetAddress address;
address.host = ENET_HOST_ANY;
address.port = port;
if (enet_socket_bind(socket, &address) != 0)
{
cerr << "eNet: Failed to bind listen socket" << endl;
return ENET_SOCKET_NULL;
}
if (enet_socket_get_address(socket, &address) != 0)
{
cerr << "eNet: Cannot get listen socket address" << endl;
return ENET_SOCKET_NULL;
}
return socket;
}
bool BroadcastClient::start()
{
if(started)
{
cerr << "BroadcastClient: a client was already started" << endl;
return false;
}
if (enet_initialize() != 0)
{
cerr << "eNet: An error occurred while initializing eNet." << endl;
return false;
}
discoverSocket = initSocket(DISCOVER_PORT);
if(discoverSocket == ENET_SOCKET_NULL)
{
cerr << "BroadcastClient: An error occurred while initializing discover socket" << endl;
return false;
}
dataSocket = initSocket(BROADCAST_DATA_PORT);
if(dataSocket == ENET_SOCKET_NULL)
{
cerr << "BroadcastClient: An error occurred while initializing data socket" << endl;
return false;
}
networkThread = thread(&BroadcastClient::networkLoop, this);
started = true;
return true;
return UDPClient::start(DISCOVER_PORT, ENET_PORT_ANY);
}
void BroadcastClient::sendPacket(enet_uint32 host, enet_uint16 port, PacketType type, const std::string &data)
{
ENetAddress address;
address.host = host;
address.port = port;
broadcast_packet packet(LOW_PRIORITY, type, data);
ENetBuffer buffer;
buffer.data = &packet;
buffer.dataLength = sizeof(broadcast_packet);
ENetSocket socket = type == DISCOVER_INFO ? discoverSocket : dataSocket;
if (enet_socket_send(socket, &address, &buffer, 1) != (int)buffer.dataLength)
{
cerr << "eNet: Failed to reply to discover server" <<endl;
}
UDPClient::sendPacket(host, port, type, &packet, sizeof(broadcast_packet));
}
broadcast_packet *BroadcastClient::recieveData(ENetSocket socket, ENetAddress *address)
void BroadcastClient::recieveData(ENetSocket socket, ENetAddress *address)
{
if(socket == ENET_SOCKET_NULL)
return nullptr;
return;
ENetSocketSet set;
ENET_SOCKETSET_EMPTY(set);
ENET_SOCKETSET_ADD(set, socket);
if (enet_socketset_select(socket, &set, NULL, 0) <= 0)
return nullptr;
return;
ENetBuffer buffer;
......@@ -147,7 +45,7 @@ broadcast_packet *BroadcastClient::recieveData(ENetSocket socket, ENetAddress *a
if (recvlen <= 0)
{
delete[] buffer.data;
return nullptr;
return;
}
char addrbuf[256];
......@@ -158,45 +56,20 @@ broadcast_packet *BroadcastClient::recieveData(ENetSocket socket, ENetAddress *a
if(packet->priority == LOW_PRIORITY && hidden)
{
delete[] buffer.data;
return nullptr;
return;
}
printf("BroadcastClient: received broadcast packet(priority: %d, type: %d, size: %d) from %s:%d\n", packet->priority, packet->type, packet->size, addrbuf, address->port);
switch (packet->type) {
case DISCOVER_REQUEST:
discoverCallback(address->host, address->port);
break;
case DATA_REQUEST:
dataCallback(address->host, address->port, packet->buffer);
break;
default:
break;
}
return packet;
printf("BroadcastClient: received broadcast packet(priority: %d, type: %d, size: %d) from %s:%d\n", packet->priority, packet->type, packet->size, addrbuf, address->port);
}
void BroadcastClient::networkLoop()
{
while(true)
{
if(discoverSocket == ENET_SOCKET_NULL || dataSocket == ENET_SOCKET_NULL)
return;
std::this_thread::sleep_for(std::chrono::milliseconds(BROADCAST_CLIENT_THREAD_SLEEP));
if(paused)
continue;
ENetAddress address;
broadcast_packet * packet = recieveData(discoverSocket, &address);
if(packet != nullptr && packet->type == DISCOVER_REQUEST)
{
if(discoverCallback)
discoverCallback(address.host, address.port);
delete[] packet;
}
packet = recieveData(dataSocket, &address);
if(packet != nullptr && packet->type == DATA_REQUEST)
{
if(dataCallback)
dataCallback(address.host, address.port, packet->buffer);
delete[] packet;
}
}
}
......@@ -11,15 +11,9 @@
#include <stdio.h>
#include <stdio.h>
#include <memory>
#include <thread>
#include <iostream>
#include <functional>
#include "common.h"
#include "UDPClient.h"
class BroadcastClient
class BroadcastClient : public UDPClient
{
static std::shared_ptr<BroadcastClient> self;
public:
......@@ -33,10 +27,9 @@ public:
typedef std::function<void (enet_uint32 senderHost, enet_uint16 senderPort,const std::string &data)> DataCallback;
typedef std::function<void (enet_uint32 senderHost, enet_uint16 senderPort)> DiscoverCallback;
BroadcastClient()
BroadcastClient():
UDPClient()
{}
~BroadcastClient();
bool start();
......@@ -49,6 +42,12 @@ public:
}
void sendPacket(enet_uint32 host, enet_uint16 port, PacketType type, const std::string &data);
void clearCallbacks()
{
dataCallback = nullptr;
discoverCallback = nullptr;
}
void setHidden(bool flag) {
hidden = flag;
......@@ -58,36 +57,14 @@ public:
return hidden;
}
void setPaused(bool flag) {
paused = flag;
}
bool isPaused() {
return paused;
}
void clearCallbacks()
{
dataCallback = nullptr;
discoverCallback = nullptr;
}
private:
bool started = false;
std::thread networkThread;
ENetSocket discoverSocket = ENET_SOCKET_NULL;
ENetSocket dataSocket = ENET_SOCKET_NULL;
void networkLoop();
bool hidden = false;
bool paused = false;
DataCallback dataCallback;
DiscoverCallback discoverCallback;
ENetSocket initSocket(enet_uint16 port);
broadcast_packet *recieveData(ENetSocket socket, ENetAddress *address);
bool hidden = false;
virtual void recieveData(ENetSocket socket, ENetAddress *address);
};
......
//
// UDPClient.cpp
// pm-network
//
// Created by Никита Бесшапошников on 15.07.2019.
//
#include "UDPClient.h"
using namespace std;
UDPClient::~UDPClient()
{
if (enet_socket_shutdown(discoverSocket, ENET_SOCKET_SHUTDOWN_READ_WRITE) != 0)
{
cerr << "eNet: Failed to shutdown discover socket" << endl;
}
enet_socket_destroy(discoverSocket);
if (enet_socket_shutdown(dataSocket, ENET_SOCKET_SHUTDOWN_READ_WRITE) != 0)
{
cerr << "eNet: Failed to shutdown data socket" << endl;
}
enet_socket_destroy(dataSocket);
discoverSocket = ENET_SOCKET_NULL;
dataSocket = ENET_SOCKET_NULL;
networkThread.join();
}
ENetSocket UDPClient::initSocket(enet_uint16 port, bool bindSocket)
{
ENetSocket socket = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM);
if (socket == ENET_SOCKET_NULL)
{
cerr << "eNet: Failed to create discover UDP socket." << endl;
return socket;
}
if (enet_socket_set_option(socket, ENET_SOCKOPT_BROADCAST, 1) != 0)
{
cerr << "eNet: Failed to enable broadcast socket." << endl;
return ENET_SOCKET_NULL;
}
ENetAddress address;
address.host = ENET_HOST_ANY;
address.port = port;
if (bindSocket && enet_socket_bind(socket, &address) != 0)
{
cerr << "eNet: Failed to bind listen socket" << endl;
return ENET_SOCKET_NULL;
}
if (enet_socket_get_address(socket, &address) != 0)
{
cerr << "eNet: Cannot get listen socket address" << endl;
return ENET_SOCKET_NULL;
}
return socket;
}
bool UDPClient::start(enet_uint16 discoverPort, enet_uint16 dataPort, bool bindDataSocket)
{
if(started)
{
cerr << "UDPClient: a client was already started" << endl;
return false;
}
if (enet_initialize() != 0)
{
cerr << "eNet: An error occurred while initializing eNet." << endl;
return false;
}
discoverSocket = initSocket(discoverPort, bindDataSocket);
if(discoverSocket == ENET_SOCKET_NULL)
{
cerr << "UDPClient: An error occurred while initializing discover socket" << endl;
return false;
}
dataSocket = initSocket(dataPort, true);
if(dataSocket == ENET_SOCKET_NULL)
{
cerr << "UDPClient: An error occurred while initializing data socket" << endl;
return false;
}
networkThread = thread(&UDPClient::networkLoop, this);
started = true;
return true;
}
void UDPClient::sendPacket(enet_uint32 host, enet_uint16 port, PacketType type, void *data, size_t dataLength)
{
ENetAddress address;
address.host = host;
address.port = port;
ENetBuffer buffer;
buffer.data = (void *)data;
buffer.dataLength = dataLength;
ENetSocket socket = type == DISCOVER_INFO ? discoverSocket : dataSocket;
if (enet_socket_send(socket, &address, &buffer, 1) != (int)buffer.dataLength)
{
cerr << "eNet: Failed to send upda packet " << endl;
}
}
void UDPClient::networkLoop()
{
while(true)
{
if(discoverSocket == ENET_SOCKET_NULL && dataSocket == ENET_SOCKET_NULL)
return;
std::this_thread::sleep_for(std::chrono::milliseconds(UDP_CLIENT_THREAD_SLEEP));
if(paused)
continue;
ENetAddress address;
if(discoverSocket != ENET_SOCKET_NULL)
{
recieveData(discoverSocket, &address);
}
if(discoverSocket != ENET_SOCKET_NULL)
{
recieveData(dataSocket, &address);
}
}
}
//
// UDPClient.hpp
// pm-network
//
// Created by Никита Бесшапошников on 15.07.2019.
//
#ifndef UDPClient_hpp
#define UDPClient_hpp
#include <stdio.h>
#include <memory>
#include <thread>
#include <iostream>
#include <functional>
#include "common.h"
class UDPClient
{
public:
UDPClient()
{}
~UDPClient();
bool start(enet_uint16 discoverPort, enet_uint16 dataPort, bool bindDataSocket = true);
void sendPacket(enet_uint32 host, enet_uint16 port, PacketType type, void *data, size_t dataLength);
void setPaused(bool flag) {
paused = flag;
}
bool isPaused() {
return paused;
}
protected:
bool started = false;
std::thread networkThread;
ENetSocket discoverSocket = ENET_SOCKET_NULL;
ENetSocket dataSocket = ENET_SOCKET_NULL;
void networkLoop();
bool paused = false;
ENetSocket initSocket(enet_uint16 port, bool bindSocket);
virtual void recieveData(ENetSocket socket, ENetAddress *address) = 0;
};
#endif /* UDPClient_hpp */
......@@ -21,7 +21,7 @@ const long long MESSAGE_THREAD_SLEEP = 50;
const long long DISCOVER_DEFAULT_TIMEOUT = 5000;
const long long DISCOVER_SELECT_TIMEOUT = 1000;
const long long BROADCAST_SERVER_THREAD_SLEEP = 50;
const long long BROADCAST_CLIENT_THREAD_SLEEP = 50;
const long long UDP_CLIENT_THREAD_SLEEP = 50;
const size_t MAXIMUM_CLIENTS_COUNT = 64;
......
......@@ -7,6 +7,10 @@
objects = {
/* Begin PBXBuildFile section */
0A0E4FCE22DC60F300964744 /* UDPClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A0E4FCC22DC60F300964744 /* UDPClient.cpp */; };
0A0E4FCF22DC60F300964744 /* UDPClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A0E4FCC22DC60F300964744 /* UDPClient.cpp */; };
0A0E4FD022DC60F300964744 /* UDPClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A0E4FCC22DC60F300964744 /* UDPClient.cpp */; };
0A0E4FD122DC60F300964744 /* UDPClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 0A0E4FCD22DC60F300964744 /* UDPClient.h */; };
0AB59B381F46D83900D950D0 /* BroadcastClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0AB59B341F46D83900D950D0 /* BroadcastClient.cpp */; };
0AB59B391F46D83900D950D0 /* BroadcastClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0AB59B341F46D83900D950D0 /* BroadcastClient.cpp */; };
0AB59B3A1F46D83900D950D0 /* BroadcastClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 0AB59B351F46D83900D950D0 /* BroadcastClient.h */; };
......@@ -116,6 +120,8 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0A0E4FCC22DC60F300964744 /* UDPClient.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = UDPClient.cpp; sourceTree = "<group>"; };
0A0E4FCD22DC60F300964744 /* UDPClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UDPClient.h; sourceTree = "<group>"; };
0AB59B341F46D83900D950D0 /* BroadcastClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BroadcastClient.cpp; sourceTree = "<group>"; };
0AB59B351F46D83900D950D0 /* BroadcastClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BroadcastClient.h; sourceTree = "<group>"; };
0AB59B361F46D83900D950D0 /* BroadcastServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BroadcastServer.cpp; sourceTree = "<group>"; };
......@@ -201,6 +207,8 @@
0AB59B351F46D83900D950D0 /* BroadcastClient.h */,
0AB59B361F46D83900D950D0 /* BroadcastServer.cpp */,
0AB59B371F46D83900D950D0 /* BroadcastServer.h */,
0A0E4FCC22DC60F300964744 /* UDPClient.cpp */,
0A0E4FCD22DC60F300964744 /* UDPClient.h */,
);
name = Broadcast;
sourceTree = "<group>";
......@@ -297,6 +305,7 @@
buildActionMask = 2147483647;
files = (
DA72F7CB1E7149F800D97DF2 /* GameClient.h in Headers */,
0A0E4FD122DC60F300964744 /* UDPClient.h in Headers */,
0AB59B3A1F46D83900D950D0 /* BroadcastClient.h in Headers */,
DA1749371E6EA64B00AEA0C2 /* GameServerClient.h in Headers */,
DA06372B1D50AC5600ACA75C /* common.h in Headers */,
......@@ -450,6 +459,7 @@
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
);
mainGroup = DA0636D91D50A52800ACA75C;
......@@ -507,6 +517,7 @@
DA72F7C91E7149F800D97DF2 /* GameClient.cpp in Sources */,
0AB59B3B1F46D83900D950D0 /* BroadcastServer.cpp in Sources */,
0AB59B381F46D83900D950D0 /* BroadcastClient.cpp in Sources */,
0A0E4FCE22DC60F300964744 /* UDPClient.cpp in Sources */,
DA17492D1E6D8F0B00AEA0C2 /* GameServer.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
......@@ -519,6 +530,7 @@
DA72F7CA1E7149F800D97DF2 /* GameClient.cpp in Sources */,
0AB59B3C1F46D83900D950D0 /* BroadcastServer.cpp in Sources */,
0AB59B391F46D83900D950D0 /* BroadcastClient.cpp in Sources */,
0A0E4FCF22DC60F300964744 /* UDPClient.cpp in Sources */,
DA17492E1E6D8F0B00AEA0C2 /* GameServer.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
......@@ -528,6 +540,7 @@
buildActionMask = 2147483647;
files = (
0AB59B4D1F46D89200D950D0 /* BroadcastClient.cpp in Sources */,
0A0E4FD022DC60F300964744 /* UDPClient.cpp in Sources */,
0AB59B481F46D88100D950D0 /* main.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment