127 lines
3.9 KiB
C++
127 lines
3.9 KiB
C++
#include <sstp/socketserver.hpp>
|
|
#include <sstp/socketconnectionreceiver.hpp>
|
|
|
|
/// @brief Defauly constructor. This is to provide a definition for SmartPointer
|
|
/// @param port
|
|
SocketServer::SocketServer()
|
|
: mListenPort(-1), mIsOkay(false), mSocketFileDescriptor(-1)
|
|
{
|
|
}
|
|
|
|
/// @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;
|
|
}
|
|
|
|
/// @brief Close down the listener
|
|
SocketServer::~SocketServer()
|
|
{
|
|
std::cout << "~SocketServer" << std::endl;
|
|
std::cout << "shutdownConnectionReceivers" << std::endl;
|
|
shutdownConnectionReceivers();
|
|
std::cout << "join" << std::endl;
|
|
join(); // Then join all socket threads
|
|
std::cout << "close" << std::endl;
|
|
close(); // close the listener socket
|
|
std::cout << "~SocketServer, done" << std::endl;
|
|
}
|
|
|
|
/// @brief Join all threads
|
|
/// @param
|
|
void SocketServer::join(void)
|
|
{
|
|
for (std::thread& executionThread : mExecutionThreads)
|
|
{
|
|
if (executionThread.joinable())
|
|
{
|
|
executionThread.join();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// @brief Remove object references to the connection receivers. This will force socket threads to exit and close connections
|
|
void SocketServer::shutdownConnectionReceivers()
|
|
{
|
|
mSocketConnectionReceivers.remove();
|
|
}
|
|
|
|
|
|
/// @brief returns true if we have a valid socket connection otherwise false
|
|
/// @return
|
|
bool SocketServer::isOkay(void)
|
|
{
|
|
return mIsOkay;
|
|
}
|
|
|
|
/// @brief This is the listener. It will wait for incoming connections.
|
|
/// When an incoming connection is received it will create a SocketConnectionReceiver object and call it's threadFunction
|
|
/// to handle further interactions such as transmitting a file.
|
|
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;
|
|
}
|
|
mSocketConnectionReceivers.insert(SmartPointer<SocketConnectionReceiver>());
|
|
SmartPointer<SocketConnectionReceiver> &pSocketConnectionReceiver = mSocketConnectionReceivers[mSocketConnectionReceivers.size()-1];
|
|
pSocketConnectionReceiver = ::new SocketConnectionReceiver(socket, internalSocketAddress);
|
|
pSocketConnectionReceiver.disposition(PointerDisposition::Delete);
|
|
mExecutionThreads.push_back(std::thread(&SocketConnectionReceiver::threadFunction, *pSocketConnectionReceiver, 0));
|
|
}
|
|
}
|
|
|
|
/// @brief Shut down the listener socket
|
|
/// @param
|
|
void SocketServer::close(void)
|
|
{
|
|
if(-1==mSocketFileDescriptor)return;
|
|
std::cout << "SocketServer::close, closing socket" << std::endl;
|
|
::close(mSocketFileDescriptor);
|
|
mSocketFileDescriptor=-1;
|
|
}
|