Initial Comit

This commit is contained in:
2025-08-10 11:35:20 -04:00
commit e2b653e51f
34 changed files with 3741 additions and 0 deletions

33
listener/.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,33 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/listener",
"args": ["SERVERMODE","55000"],
"stopAtEntry": true,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
}
]
}

57
listener/.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,57 @@
{
"files.associations": {
"array": "cpp",
"atomic": "cpp",
"bit": "cpp",
"cctype": "cpp",
"chrono": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"compare": "cpp",
"complex": "cpp",
"concepts": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"string": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"random": "cpp",
"ratio": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"initializer_list": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"new": "cpp",
"numbers": "cpp",
"ostream": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"typeinfo": "cpp",
"semaphore": "cpp",
"stop_token": "cpp",
"thread": "cpp",
"*.tpp": "cpp"
}
}

28
listener/.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,28 @@
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++ build active file",
"command": "/usr/bin/g++",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-o",
"${fileDirname}/${fileBasenameNoExtension}"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "Task generated by Debugger."
}
],
"version": "2.0.0"
}

11
listener/CMakeLists.txt Normal file
View File

@@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 3.10.0)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I/home/pi/Boneyard")
project(listener VERSION 0.1.0 LANGUAGES C CXX)
add_executable(listener main.cpp ClientSocketSender.cpp SocketConnectionReceiver.cpp SocketServer.cpp)
add_subdirectory(/home/pi/Boneyard/common /home/pi/Boneyard/common/build)
target_link_libraries(listener PRIVATE common)

View File

@@ -0,0 +1,118 @@
#include <listener/ClientSocketSender.hpp>
ClientSocketSender::ClientSocketSender(String ipAddress, int port)
: mIPAddress(ipAddress), mPort(port)
{
mSocket = ::socket(AF_INET,SOCK_STREAM,0);
if(!isOkay())
{
std::cout << "Unable to initialize socket " << std::endl;
return;
}
mInternalSocketAddress.sin_family = AF_INET;
mInternalSocketAddress.sin_port= ::htons(mPort);
int result = ::inet_pton(AF_INET, ipAddress.str(), &mInternalSocketAddress.sin_addr);
if(result<0)
{
std::cout << "Unable to convert ipaddress to network address" << std::endl;
close();
return;
}
result = ::connect(mSocket, (struct sockaddr*)&mInternalSocketAddress, sizeof(mInternalSocketAddress));
if(result<0)
{
close();
std::cout << "Unable to connect to host " << mIPAddress << ":" << mPort << std::endl;
}
}
ClientSocketSender::~ClientSocketSender()
{
close();
}
void ClientSocketSender::close(void)
{
if(-1!=mSocket)
{
::close(mSocket);
mSocket=-1;
}
}
bool ClientSocketSender::sendFile(String &pathFileName)
{
Profiler profiler;
FileIO readFile(pathFileName, FileIO::ByteOrder::LittleEndian, FileIO::Mode::ReadOnly, FileIO::CreationFlags::None);
if(!readFile.isOkay())
{
std::cout << "File open failed " << pathFileName << std::endl;
return false;
}
readFile.setBufferLength(BUFFER_LENGTH);
DWORD fileLength = readFile.size();
sendPutIndicator(pathFileName, fileLength);
Array<char> readBuffer;
readBuffer.size(BUFFER_LENGTH);
while(true)
{
size_t bytesRead = readFile.read(&readBuffer[0], readBuffer.size());
if(0==bytesRead)
{
std::cout << "No data was read from the file" << std::endl;
break;
}
sendPacketIndicator(bytesRead);
sendPacket(readBuffer, bytesRead);
if(bytesRead<readBuffer.size())break;
}
sendPacketIndicator(0);
sendQuit();
readFile.close();
std::cout << "SendFile done, total took " << profiler.end() << "(ms)" << std::endl;
return true;
}
bool ClientSocketSender::sendPacketIndicator(DWORD bytesToSend)
{
if(!isOkay())return false;
String packetIndicator = "PCKT|";
packetIndicator+=String().fromULong(bytesToSend);
packetIndicator+="\r\n";
::send(mSocket, (char*)packetIndicator, packetIndicator.length(),0);
return true;
}
bool ClientSocketSender::sendPutIndicator(String fileName,DWORD fileLength)
{
if(!isOkay())return false;
Block<String> parts = fileName.split('/');
String pureFileName = parts[parts.size()-1];
String putIndicator = "PUT|";
putIndicator+=pureFileName;
putIndicator+="|";
putIndicator+=String().fromULong(fileLength);
putIndicator+="\r\n";
::send(mSocket, (char*)putIndicator, putIndicator.length(),0);
return true;
}
bool ClientSocketSender::sendQuit(void)
{
if(!isOkay())return false;
String quitIndicator = "QUIT\r\n";
::send(mSocket, (char*)quitIndicator, quitIndicator.length(),0);
return true;
}
bool ClientSocketSender::sendPacket(Array<char> &buffer,DWORD bytesToSend)
{
if(!isOkay())return false;
::send(mSocket, (char*)&buffer[0], bytesToSend,0);
return true;
}
bool ClientSocketSender::isOkay(void)
{
return -1==mSocket?false:true;
}

View File

@@ -0,0 +1,37 @@
#ifndef _LISTENER_CLIENTSOCKETSENDER_HPP_
#define _LISTENER_CLIENTSOCKETSENDER_HPP_
#include <stdio.h>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <thread>
#include <common/string.hpp>
#include <common/profiler.hpp>
#include <common/block.hpp>
#include <common/fileio.hpp>
class ClientSocketSender
{
public:
ClientSocketSender(String ipAddress,int port);
virtual ~ClientSocketSender();
bool sendFile(String &pathFileName);
bool isOkay(void);
private:
// static constexpr int BUFFER_LENGTH=65536;
static constexpr int BUFFER_LENGTH=1048576;
void close(void);
bool sendPacketIndicator(DWORD bytesToSend);
bool sendPacket(Array<char> &buffer,DWORD bytesToSend);
bool sendPutIndicator(String fileName,DWORD fileLength);
bool sendQuit(void);
struct sockaddr_in mInternalSocketAddress;
int mSocket;
String mIPAddress;
int mPort;
};
#endif

View File

@@ -0,0 +1,157 @@
#include <listener/SocketConnectionReceiver.hpp>
#include <common/utility.hpp>
SocketConnectionReceiver::SocketConnectionReceiver(int socket, sockaddr_in internalSocketAddress)
: mSocket(socket), mInternalSocketAddress(internalSocketAddress)
{
}
SocketConnectionReceiver::~SocketConnectionReceiver()
{
}
void SocketConnectionReceiver::close(void)
{
if(-1==mSocket)return;
std::cout << "Closing connection " << mSocket << std::endl;
::close(mSocket);
mSocket=-1;
}
void SocketConnectionReceiver::threadFunction(int data)
{
String line;
while(true)
{
readLine(line);
if(0==line.length())
{
std::cout << "Received an empty command" << std::endl;
break;
}
if(line=="QUIT" || line=="quit")break;
Block<String> commands = line.split('|');
if(0==commands.size())continue;
std::cout << commands[0] << std::endl;
commands[0].upper();
if(commands[0]=="PUT")
{
handlePut(commands);
}
else
{
std::cout << "Unrecognized command >" << line << "<" << std::endl;
}
}
close();
return;
}
/// @brief The client wants to put a file. put {filename} {lengthbytes}
/// @param commands [0]=PUT, [1]=filename, [2]=total length
/// This will read PCKT {length}.
/// The connection will continue reading and writing until it receives PCKT 0
/// @return
bool SocketConnectionReceiver::handlePut(Block<String> &commands)
{
Profiler profiler;
Array<char> receiveBuffer;
Block<String> subCommands;
String strLine;
String fileName;
size_t fileLength;
size_t totalBytesRead=0;
fileName = commands[1];
fileLength = commands[commands.size()-1].toLong();
std::cout << "PUT" << " " << fileName << " " << fileLength << std::endl;
FileIO writeFile(fileName, FileIO::ByteOrder::LittleEndian, FileIO::Mode::ReadWrite,FileIO::CreationFlags::CreateAlways);
if(!writeFile.isOkay())
{
std::cout << "Error creating " << fileName << std::endl;
return false;
}
while(true)
{
readLine(strLine);
strLine.makeBlock(subCommands, "|");
if(subCommands.size()!=2 || !(subCommands[0]=="PCKT"))
{
std::cout << "Unexpected command sequence" << std::endl;
break;
}
int bufferLength = subCommands[1].toLong();
if(0==bufferLength)
{
std::cout << "Client indicated end of data" << std::endl;
break;
}
receiveBuffer.size(bufferLength);
size_t bytes_read = read(receiveBuffer);
totalBytesRead+=bytes_read;
if(bufferLength!=bytes_read)
{
std::cout << "Send/Receive size mismatch. The client indicated a data length of " << bufferLength << " but a data length of " << bytes_read << " was received";
break;
}
writeFile.write(&receiveBuffer[0], receiveBuffer.size());
double percent = ((double)totalBytesRead / (double)fileLength)*100.00;
if(Utility::fmod(percent,10.00,0.0078125))
{
double elapsedTimeSeconds = profiler.elapsed()/1000.00;
double bytesPerSecond = totalBytesRead / elapsedTimeSeconds;
String strBytesPerSecond = Utility::bytesTransferredToString(bytesPerSecond);
std::cout << "Transferred " << totalBytesRead << " of " << fileLength << " " << percent << " percent " << strBytesPerSecond << std::endl;
}
}
std::cout << "Transfer complete" << std::endl;
std::cout << "Received " << totalBytesRead << std::endl;
writeFile.close();
return totalBytesRead==fileLength;
}
size_t SocketConnectionReceiver::readLine(String &line)
{
size_t bytes_read = 0;
size_t total_bytes = 0;
char ch;
char *lpLineBuffer = (char*)line;
while (total_bytes < line.lengthBytes() - 1)
{
bytes_read = ::recv(mSocket, &ch, 1, 0);
if (bytes_read <= 0)
{
return bytes_read;
}
if (ch=='\r') // Carriage return
{
recv(mSocket, &ch, 1, 0); // consume the line feed
break;
}
lpLineBuffer[total_bytes++] = ch;
}
lpLineBuffer[total_bytes] = '\0';
return total_bytes;
}
size_t SocketConnectionReceiver::read(Array<char> &buffer)
{
size_t bytes_read = 0;
size_t bytes_to_read = buffer.size();
size_t total_bytes_read =0;
char *lpLineBuffer = (char*)&buffer[0];
while(bytes_to_read>0)
{
bytes_read = ::recv(mSocket, lpLineBuffer, bytes_to_read, 0);
lpLineBuffer+=bytes_read;
bytes_to_read -= bytes_read;
total_bytes_read += bytes_read;
}
return total_bytes_read;
}

View File

@@ -0,0 +1,35 @@
#ifndef _LISTENER_SOCKETCONNECTIONRECEIVER_HPP_
#define _LISTENER_SOCKETCONNECTIONRECEIVER_HPP_
#include <stdio.h>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <thread>
#include <common/string.hpp>
#include <common/profiler.hpp>
#include <common/block.hpp>
#include <common/fileio.hpp>
class SocketConnectionReceiver
{
public:
SocketConnectionReceiver(int socket, sockaddr_in inernalSocketAddress);
virtual ~SocketConnectionReceiver();
void close(void);
private:
static constexpr size_t BUFFER_LENGTH=65536; // this is the buffer length for the socket
void threadFunction(int data);
bool handlePut(Block<String> &commands);
size_t readLine(String &line);
size_t read(Array<char> &buffer);
String restoreFileName(Block<String> block,DWORD startIndex,DWORD endIndex);
friend class SocketServer;
char mBuffer[BUFFER_LENGTH] = {0};
int mSocket;
sockaddr_in mInternalSocketAddress;
};
#endif

85
listener/SocketServer.cpp Normal file
View File

@@ -0,0 +1,85 @@
#include <listener/SocketServer.hpp>
#include <listener/SocketConnectionReceiver.hpp>
/// @brief This will construct the socket listener. You must then call listen() to listen for connections
/// @param port
SocketServer::SocketServer(int port)
: mListenPort(port), mIsOkay(false), mSocketFileDescriptor(-1)
{
std::cout << "SocketServer()" << std::endl;
int opt=-1;
int result;
// create socket file descriptor
mSocketFileDescriptor = ::socket(AF_INET,SOCK_STREAM,0);
if(0==mSocketFileDescriptor)return;
// attach socket to port
result = ::setsockopt(mSocketFileDescriptor, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));
if(result)
{
close();
return;
}
// bind socket to network address and port
mInternalSocketAddress.sin_family = AF_INET;
mInternalSocketAddress.sin_addr.s_addr=INADDR_ANY;
mInternalSocketAddress.sin_port = htons(mListenPort);
result = ::bind(mSocketFileDescriptor,(struct sockaddr*)&mInternalSocketAddress,sizeof(mInternalSocketAddress));
if(result)
{
close();
return;
}
mIsOkay=true;
}
SocketServer::~SocketServer()
{
std::cout << "~SocketServer()" << std::endl;
close();
}
bool SocketServer::isOkay(void)
{
return mIsOkay;
}
void SocketServer::listen(void)
{
while(isOkay())
{
std::cout << "Listening on port " << mListenPort << std::endl;
int result = ::listen(mSocketFileDescriptor, MAX_CONNECTIONS);
if(result)
{
std::cout << "Error listening on port " << mListenPort << std::endl;
close();
return;
}
struct sockaddr_in internalSocketAddress;
socklen_t addressLength = sizeof(internalSocketAddress);
int socket = ::accept(mSocketFileDescriptor, (struct sockaddr*)&internalSocketAddress, &addressLength);
if(result)
{
std::cout << "Error accepting connection " << mListenPort << std::endl;
close();
return;
}
SocketConnectionReceiver socketConnectionReceiver(socket, internalSocketAddress);
mExecutionThreads.push_back(std::thread(&SocketConnectionReceiver::threadFunction, &socketConnectionReceiver, 0));
}
}
void SocketServer::close(void)
{
if(-1!=mSocketFileDescriptor)
{
::close(mSocketFileDescriptor);
mSocketFileDescriptor=-1;
}
}

34
listener/SocketServer.hpp Normal file
View File

@@ -0,0 +1,34 @@
#ifndef _LISTENER_SOCKETSERVER_HPP_
#define _LISTENER_SOCKETSERVER_HPP_
#include <stdio.h>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <thread>
#include <vector>
#include <common/string.hpp>
#include <common/profiler.hpp>
#include <common/block.hpp>
#include <common/fileio.hpp>
class SocketServer
{
public:
SocketServer(int port);
virtual ~SocketServer();
void listen(void);
void close(void);
bool isOkay(void);
private:
static constexpr int MAX_CONNECTIONS=10; // The maximum connections to be queued at a time
bool mIsOkay;
int mListenPort;
int mSocketFileDescriptor;
struct sockaddr_in mInternalSocketAddress;
socklen_t mAddressLength = sizeof(mInternalSocketAddress);
std::vector<std::thread> mExecutionThreads;
};
#endif

101
listener/main.cpp Normal file
View File

@@ -0,0 +1,101 @@
#include <stdio.h>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <thread>
#include <vector>
#include <common/string.hpp>
#include <common/profiler.hpp>
#include <common/block.hpp>
#include <common/fileio.hpp>
#include <common/utility.hpp>
#include <listener/SocketServer.hpp>
#include <listener/ClientSocketSender.hpp>
// https://www.man7.org/linux/man-pages/man2/accept.2.html
void handleServer(Block<String> &commands);
void handleClient(Block<String> &commands);
/// @brief
/// @param argc
/// @param argv [0] program. [1] SERVERMODE {port} [2] CLIENTMODE {serveripaddress} {serverport} SEND {FileName}
/// @return
int main(int argc, char **argv)
{
Profiler profiler;
if(argc<2)
{
std::cout << "listener SERVERMODE {port} | CLIENTMODE {serveripaddress} {serverport} SEND {FileName}" << std::endl;
return 1;
}
Block<String> arguments;
for(int index=0;index<argc;index++)
{
String item(argv[index]);
arguments.insert(item);
}
std::cout << argv[1] << std::endl;
if(arguments[1]=="SERVERMODE")
{
handleServer(arguments);
}
else if(arguments[1]=="CLIENTMODE")
{
handleClient(arguments);
}
else
{
std::cout << "Unknown command " << arguments[1] << std::endl;
}
return 0;
std::cout << "Done, total took " << profiler.end() << "(ms)" << std::endl;
}
/// @brief [0]=program [1]=SERVERMODE [2]={port}
/// @param commands
void handleServer(Block<String> &commands)
{
Profiler profiler;
if(commands.size()!=3)
{
std::cout << "Missing required parameters" << std::endl;
return;
}
int port = commands[2].toInt();
std::cout << commands[1] << ":" << commands[2] << std::endl;
SocketServer socketServer(commands[2].toInt());
socketServer.listen();
std::cout << "Done, total took " << profiler.end() << "(ms)" << std::endl;
}
/// @brief [0]=program, [1]=CLIENTMODE, [2]=serveripaddress, [3]=serverport, [4]=pathfilename
/// @param commands
void handleClient(Block<String> &commands)
{
Profiler profiler;
if(commands.size()!=5)
{
std::cout << "Missing required parameters" << std::endl;
return;
}
ClientSocketSender clientSocketSender(commands[2],commands[3].toInt());
bool returnCode = clientSocketSender.sendFile(commands[4]);
if(!returnCode)
{
std::cout << "The transfer failed." << std::endl;
}
else
{
std::cout << "Transfer complete" << std::endl;
}
std::cout << "Done, total took " << profiler.end() << "(ms)" << std::endl;
}

435
listener/scraps.txt Normal file
View File

@@ -0,0 +1,435 @@
// class ClientSocketSender
// {
// public:
// ClientSocketSender(String ipAddress,int port);
// virtual ~ClientSocketSender();
// bool sendFile(String &pathFileName);
// bool isOkay(void);
// private:
// static constexpr int BUFFER_LENGTH=65536;
// void close(void);
// bool sendPacketIndicator(long bytesToSend);
// bool sendPacket(Array<char> &buffer,long bytesToSend);
// bool sendPutIndicator(String fileName,long fileLength);
// bool sendQuit(void);
// struct sockaddr_in mInternalSocketAddress;
// int mSocket;
// String mIPAddress;
// int mPort;
// };
// inline
// ClientSocketSender::ClientSocketSender(String ipAddress, int port)
// : mIPAddress(ipAddress), mPort(port)
// {
// mSocket = ::socket(AF_INET,SOCK_STREAM,0);
// if(!isOkay())
// {
// std::cout << "Unable to initialize socket " << std::endl;
// return;
// }
// mInternalSocketAddress.sin_family = AF_INET;
// mInternalSocketAddress.sin_port= ::htons(mPort);
// int result = ::inet_pton(AF_INET, ipAddress.str(), &mInternalSocketAddress.sin_addr);
// if(result<0)
// {
// std::cout << "Unable to convert ipaddress to network address" << std::endl;
// close();
// return;
// }
// result = ::connect(mSocket, (struct sockaddr*)&mInternalSocketAddress, sizeof(mInternalSocketAddress));
// if(result<0)
// {
// close();
// std::cout << "Unable to connect to host " << mIPAddress << ":" << mPort << std::endl;
// }
// }
// inline
// ClientSocketSender::~ClientSocketSender()
// {
// close();
// }
// inline
// void ClientSocketSender::close(void)
// {
// if(-1!=mSocket)
// {
// ::close(mSocket);
// mSocket=-1;
// }
// }
// inline
// bool ClientSocketSender::sendFile(String &pathFileName)
// {
// FileIO readFile(pathFileName, FileIO::ByteOrder::LittleEndian, FileIO::Mode::ReadOnly, FileIO::CreationFlags::None);
// if(!readFile.isOkay())
// {
// std::cout << "File open failed " << pathFileName << std::endl;
// return false;
// }
// readFile.setBufferLength(BUFFER_LENGTH);
// DWORD fileLength = readFile.size();
// sendPutIndicator(pathFileName, fileLength);
// Array<char> readBuffer;
// readBuffer.size(BUFFER_LENGTH);
// while(true)
// {
// size_t bytesRead = readFile.read(&readBuffer[0], readBuffer.size());
// if(0==bytesRead)
// {
// std::cout << "No data was read from the file" << std::endl;
// break;
// }
// sendPacketIndicator(bytesRead);
// sendPacket(readBuffer, bytesRead);
// if(bytesRead<readBuffer.size())break;
// }
// sendPacketIndicator(0);
// sendQuit();
// readFile.close();
// std::cout << "SendFile complete" << std::endl;
// return true;
// }
// bool ClientSocketSender::sendPacketIndicator(long bytesToSend)
// {
// if(!isOkay())return false;
// String packetIndicator = "PCKT|";
// packetIndicator+=String().fromInt(bytesToSend);
// packetIndicator+="\r\n";
// ::send(mSocket, (char*)packetIndicator, packetIndicator.length(),0);
// return true;
// }
// bool ClientSocketSender::sendPutIndicator(String fileName,long fileLength)
// {
// if(!isOkay())return false;
// Block<String> parts = fileName.split('/');
// String pureFileName = parts[parts.size()-1];
// String putIndicator = "PUT|";
// putIndicator+=pureFileName;
// putIndicator+="|";
// putIndicator+=String().fromInt(fileLength);
// putIndicator+="\r\n";
// ::send(mSocket, (char*)putIndicator, putIndicator.length(),0);
// return true;
// }
// inline
// bool ClientSocketSender::sendQuit(void)
// {
// if(!isOkay())return false;
// String quitIndicator = "QUIT\r\n";
// ::send(mSocket, (char*)quitIndicator, quitIndicator.length(),0);
// return true;
// }
// inline
// bool ClientSocketSender::sendPacket(Array<char> &buffer,long bytesToSend)
// {
// if(!isOkay())return false;
// ::send(mSocket, (char*)&buffer[0], bytesToSend,0);
// return true;
// }
// inline
// bool ClientSocketSender::isOkay(void)
// {
// return -1==mSocket?false:true;
// }
// ***********************************************************************************************************************************************************
// ***********************************************************************************************************************************************************
// ***********************************************************************************************************************************************************
// class SocketConnectionReceiver
// {
// public:
// SocketConnectionReceiver(int socket, sockaddr_in inernalSocketAddress);
// virtual ~SocketConnectionReceiver();
// void close(void);
// private:
// static constexpr int BUFFER_LENGTH=65536; // this is the buffer length for the socket
// void threadFunction(int data);
// bool handlePut(Block<String> &commands);
// int readLine(String &line);
// long read(Array<char> &buffer);
// String restoreFileName(Block<String> block,DWORD startIndex,DWORD endIndex);
// friend class SocketServer;
// char mBuffer[BUFFER_LENGTH] = {0};
// int mSocket;
// sockaddr_in mInternalSocketAddress;
// };
// inline
// SocketConnectionReceiver::SocketConnectionReceiver(int socket, sockaddr_in internalSocketAddress)
// : mSocket(socket), mInternalSocketAddress(internalSocketAddress)
// {
// }
// inline
// SocketConnectionReceiver::~SocketConnectionReceiver()
// {
// }
// inline
// void SocketConnectionReceiver::close(void)
// {
// if(-1==mSocket)return;
// std::cout << "Closing connection " << mSocket << std::endl;
// ::close(mSocket);
// mSocket=-1;
// }
// inline
// void SocketConnectionReceiver::threadFunction(int data)
// {
// String line;
// while(true)
// {
// readLine(line);
// if(0==line.length())
// {
// std::cout << "Received an empty command" << std::endl;
// break;
// }
// // std::cout << "'" << (char*)line << "'" << std::endl;
// if(line=="QUIT" || line=="quit")break;
// Block<String> commands = line.split('|');
// if(0==commands.size())continue;
// std::cout << commands[0] << std::endl;
// commands[0].upper();
// if(commands[0]=="PUT")
// {
// handlePut(commands);
// }
// else
// {
// std::cout << "Unrecognized command >" << line << "<" << std::endl;
// }
// }
// close();
// return;
// }
// /// @brief The client wants to put a file. put {filename} {lengthbytes}
// /// @param commands [0]=PUT, [1]=filename, [2]=total length
// /// This will read PCKT {length}.
// /// The connection will continue reading and writing until it receives PCKT 0
// /// @return
// inline
// bool SocketConnectionReceiver::handlePut(Block<String> &commands)
// {
// Array<char> receiveBuffer;
// Block<String> subCommands;
// String strLine;
// String fileName;
// long fileLength;
// long totalBytesRead=0;
// fileName = commands[1];
// fileLength = commands[commands.size()-1].toLong();
// std::cout << "PUT" << " " << fileName << " " << fileLength << std::endl;
// FileIO writeFile(fileName, FileIO::ByteOrder::LittleEndian, FileIO::Mode::ReadWrite,FileIO::CreationFlags::CreateAlways);
// if(!writeFile.isOkay())
// {
// std::cout << "Error creating " << fileName << std::endl;
// return false;
// }
// while(true)
// {
// readLine(strLine);
// strLine.makeBlock(subCommands, "|");
// if(subCommands.size()!=2 || !(subCommands[0]=="PCKT"))
// {
// std::cout << "Unexpected command sequence" << std::endl;
// break;
// }
// int bufferLength = subCommands[1].toLong();
// if(0==bufferLength)
// {
// std::cout << "Client indicated end of data" << std::endl;
// break;
// }
// receiveBuffer.size(bufferLength);
// long bytes_read = read(receiveBuffer);
// totalBytesRead+=bytes_read;
// if(bufferLength!=bytes_read)
// {
// std::cout << "Send/Receive size mismatch. The client indicated a data length of " << bufferLength << " but a data length of " << bytes_read << " was received";
// break;
// }
// writeFile.write(&receiveBuffer[0], receiveBuffer.size());
// int percent = ((double)totalBytesRead / (double)fileLength)*100.00;
// if(0==(percent%10))
// {
// std::cout << "Transferred " << totalBytesRead << " of " << fileLength << " " << percent << " percent" << std::endl;
// }
// }
// std::cout << "Transfer complete" << std::endl;
// std::cout << "Received " << totalBytesRead << std::endl;
// writeFile.close();
// return totalBytesRead==fileLength;
// }
// inline
// int SocketConnectionReceiver::readLine(String &line)
// {
// int bytes_read = 0;
// int total_bytes = 0;
// char ch;
// char *lpLineBuffer = (char*)line;
// while (total_bytes < line.lengthBytes() - 1)
// {
// bytes_read = ::recv(mSocket, &ch, 1, 0);
// if (bytes_read <= 0)
// {
// return bytes_read;
// }
// if (ch=='\r') // Carriage return
// {
// recv(mSocket, &ch, 1, 0); // consume the line feed
// break;
// }
// lpLineBuffer[total_bytes++] = ch;
// }
// lpLineBuffer[total_bytes] = '\0';
// return total_bytes;
// }
// inline
// long SocketConnectionReceiver::read(Array<char> &buffer)
// {
// long bytes_read = 0;
// long bytes_to_read = buffer.size();
// long total_bytes_read =0;
// char *lpLineBuffer = (char*)&buffer[0];
// while(bytes_to_read>0)
// {
// bytes_read = ::recv(mSocket, lpLineBuffer, bytes_to_read, 0);
// lpLineBuffer+=bytes_read;
// bytes_to_read -= bytes_read;
// total_bytes_read += bytes_read;
// }
// return total_bytes_read;
// }
// ***********************************************************************************************************************************************************
// ***********************************************************************************************************************************************************
// ***********************************************************************************************************************************************************
// class SocketServer
// {
// public:
// SocketServer(int port);
// virtual ~SocketServer();
// void listen(void);
// void close(void);
// bool isOkay(void);
// private:
// static constexpr int MAX_CONNECTIONS=10; // The maximum connections to be queued at a time
// bool mIsOkay;
// int mListenPort;
// int mSocketFileDescriptor;
// struct sockaddr_in mInternalSocketAddress;
// socklen_t mAddressLength = sizeof(mInternalSocketAddress);
// std::vector<std::thread> mExecutionThreads;
// };
// /// @brief This will construct the socket listener. You must then call listen() to listen for connections
// /// @param port
// inline
// SocketServer::SocketServer(int port)
// : mListenPort(port), mIsOkay(false), mSocketFileDescriptor(-1)
// {
// std::cout << "SocketServer()" << std::endl;
// int opt=-1;
// int result;
// // create socket file descriptor
// mSocketFileDescriptor = ::socket(AF_INET,SOCK_STREAM,0);
// if(0==mSocketFileDescriptor)return;
// // attach socket to port
// result = ::setsockopt(mSocketFileDescriptor, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));
// if(result)
// {
// close();
// return;
// }
// // bind socket to network address and port
// mInternalSocketAddress.sin_family = AF_INET;
// mInternalSocketAddress.sin_addr.s_addr=INADDR_ANY;
// mInternalSocketAddress.sin_port = htons(mListenPort);
// result = ::bind(mSocketFileDescriptor,(struct sockaddr*)&mInternalSocketAddress,sizeof(mInternalSocketAddress));
// if(result)
// {
// close();
// return;
// }
// mIsOkay=true;
// }
// inline
// SocketServer::~SocketServer()
// {
// std::cout << "~SocketServer()" << std::endl;
// close();
// }
// inline
// bool SocketServer::isOkay(void)
// {
// return mIsOkay;
// }
// inline
// void SocketServer::listen(void)
// {
// while(isOkay())
// {
// std::cout << "Listening on port " << mListenPort << std::endl;
// int result = ::listen(mSocketFileDescriptor, MAX_CONNECTIONS);
// if(result)
// {
// std::cout << "Error listening on port " << mListenPort << std::endl;
// close();
// return;
// }
// struct sockaddr_in internalSocketAddress;
// socklen_t addressLength = sizeof(internalSocketAddress);
// int socket = ::accept(mSocketFileDescriptor, (struct sockaddr*)&internalSocketAddress, &addressLength);
// if(result)
// {
// std::cout << "Error accepting connection " << mListenPort << std::endl;
// close();
// return;
// }
// SocketConnectionReceiver socketConnectionReceiver(socket, internalSocketAddress);
// mExecutionThreads.push_back(std::thread(&SocketConnectionReceiver::threadFunction, &socketConnectionReceiver, 0));
// }
// }
// inline
// void SocketServer::close(void)
// {
// if(-1!=mSocketFileDescriptor)
// {
// mSocketFileDescriptor=-1;
// }
// }