diff --git a/program/Build/RaspberryCloud.sdf b/program/Build/RaspberryCloud.sdf index 955739a198c833a77c7cebaa928dcbf56e7c235a..ae172f687a6ba1eeb16ae5ce9a64c5a413b51407 100644 Binary files a/program/Build/RaspberryCloud.sdf and b/program/Build/RaspberryCloud.sdf differ diff --git a/program/Build/RaspberryCloud.v12.suo b/program/Build/RaspberryCloud.v12.suo index d016c74cd39840bae5bc413c3ee67a2e37a4220f..c2be689bb2e0fc064d45f6722d5bbba67c3fae0e 100644 Binary files a/program/Build/RaspberryCloud.v12.suo and b/program/Build/RaspberryCloud.v12.suo differ diff --git a/program/Build/RaspberryCloud/RaspberryCloud.vcxproj b/program/Build/RaspberryCloud/RaspberryCloud.vcxproj index aca42221e628ce5508623c6789ff9017585b0c9d..87605e933ce98884180b9d5f497622c0d2617ffb 100644 --- a/program/Build/RaspberryCloud/RaspberryCloud.vcxproj +++ b/program/Build/RaspberryCloud/RaspberryCloud.vcxproj @@ -109,7 +109,9 @@ <ClCompile Include="..\..\Source\fileModel\LockFile.cpp" /> <ClCompile Include="..\..\Source\logger\Logger.cpp" /> <ClCompile Include="..\..\Source\networking\ConcreteEncryption.cpp" /> + <ClCompile Include="..\..\Source\networking\FileServerConnection.cpp" /> <ClCompile Include="..\..\Source\networking\HomeNetworkCommunications.cpp" /> + <ClCompile Include="..\..\Source\networking\IPServer.cpp" /> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\Source\app\Application.h" /> @@ -138,8 +140,11 @@ <ClInclude Include="..\..\Source\fileModel\LockFile.h" /> <ClInclude Include="..\..\Source\logger\Logger.h" /> <ClInclude Include="..\..\Source\networking\ConcreteEncryption.h" /> + <ClInclude Include="..\..\Source\networking\FileServerConnection.h" /> <ClInclude Include="..\..\Source\networking\HomeNetworkCommunications.h" /> <ClInclude Include="..\..\Source\networking\HomeNetworkEncryption.h" /> + <ClInclude Include="..\..\Source\networking\IPServer.h" /> + <ClInclude Include="..\..\Source\networking\NetworkHelperMethods.h" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> diff --git a/program/Build/RaspberryCloud/RaspberryCloud.vcxproj.filters b/program/Build/RaspberryCloud/RaspberryCloud.vcxproj.filters index a0b9d38c5259d509a6dcc64e4d3a84ba21edac6d..d447ccf9cc8d692ca5dd302fbd70d779ebb8ffed 100644 --- a/program/Build/RaspberryCloud/RaspberryCloud.vcxproj.filters +++ b/program/Build/RaspberryCloud/RaspberryCloud.vcxproj.filters @@ -120,6 +120,12 @@ <ClCompile Include="..\..\Source\cloud\FTPAdapter.cpp"> <Filter>Source Files\cloud</Filter> </ClCompile> + <ClCompile Include="..\..\Source\networking\FileServerConnection.cpp"> + <Filter>Source Files\networking</Filter> + </ClCompile> + <ClCompile Include="..\..\Source\networking\IPServer.cpp"> + <Filter>Source Files\networking</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\Source\app\UI.h"> @@ -206,5 +212,14 @@ <ClInclude Include="..\..\Source\cloud\FTPAdapter.h"> <Filter>Header Files\cloud</Filter> </ClInclude> + <ClInclude Include="..\..\Source\networking\FileServerConnection.h"> + <Filter>Header Files\networking</Filter> + </ClInclude> + <ClInclude Include="..\..\Source\networking\NetworkHelperMethods.h"> + <Filter>Header Files\networking</Filter> + </ClInclude> + <ClInclude Include="..\..\Source\networking\IPServer.h"> + <Filter>Header Files\networking</Filter> + </ClInclude> </ItemGroup> </Project> \ No newline at end of file diff --git a/program/Build/RaspberryCloud/RaspberryCloud.vcxproj.user b/program/Build/RaspberryCloud/RaspberryCloud.vcxproj.user index ef5ff2a1fae669e995b58fb11281de92ca5fab27..ff5921cf0d2fd9ab81317dc308955058e0042125 100644 --- a/program/Build/RaspberryCloud/RaspberryCloud.vcxproj.user +++ b/program/Build/RaspberryCloud/RaspberryCloud.vcxproj.user @@ -1,4 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <PropertyGroup /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <LocalDebuggerCommandArguments> + </LocalDebuggerCommandArguments> + <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> + </PropertyGroup> </Project> \ No newline at end of file diff --git a/program/Source/app/Application.cpp b/program/Source/app/Application.cpp index 0e6216a08ec18d086b1bfa9d69cee7ef1ed6a5aa..0bcd8f93cecfee788a9543b73c402d2fc701d226 100644 --- a/program/Source/app/Application.cpp +++ b/program/Source/app/Application.cpp @@ -7,6 +7,8 @@ using namespace std; +Application* Application::DeleteThisUglyWorkaround_App_Instance = nullptr; + /** * Application implementation */ @@ -15,6 +17,8 @@ Application::Application(CloudManager cloudMan) : cm(cloudMan), cfs(*this){ LOG_ENTER_EXIT; } +const string Application::SERVER = "server"; + /** * Entry method of the software * Initiates application @@ -31,16 +35,39 @@ int main(int argc, char **argv) { cloudMan.addCloud(make_shared<FTPAdapter>()); Application application(cloudMan); - application.cal = CloudAccessLayer(); + //application.cal = CloudAccessLayer(); application.cal.app = &application; - application.ui = app::UI(); + //application.ui = app::UI(); application.ui.app = &application; + Application::DeleteThisUglyWorkaround_App_Instance = &application; + + if (argc > 1 && (Application::SERVER.compare(argv[1]) == 0)) + { + cout << "Starting in server mode!" << endl; + application.ui.setComputeOnPi(false); + + application.ui.startServer(); + + cout << "To exit enter \"exit\"." << endl; + string command; + while (true) + { + cin >> command; + + if (command == "exit") + { + return 0; + } + } + } + string command = ""; cout << "=================================================" << endl; cout << "Welcome to the amazing RaspberryCloud application" << endl; cout << "=================================================" << endl << endl; cout << "Setting up system" << endl; + while (true){ cout << "Please set home network behaviour (pi/client)" << endl; string answer = ""; @@ -54,6 +81,7 @@ int main(int argc, char **argv) { break; } } + cout << "To list avaliable orders enter \"help\"." << endl; @@ -69,6 +97,7 @@ int main(int argc, char **argv) { cout << "To get the avaliable files enter \"getFileList\"." << endl; cout << "To delete a file enter \"deleteFile\"." << endl; cout << "To authorize a cloud adapter enter \"authCA\"." << endl; + cout << "To start or stop the server enter \"serverCfg\"." << endl; } else if (command == "addFile"){ cout << "Adding file. Please enter local file id" << endl; @@ -120,6 +149,17 @@ int main(int argc, char **argv) { cin >> cloudAdapterId; application.ui.authCloudAdapter(cloudAdapterId); } + else if (command == "serverCfg") + { + string startOrStop; + cout << "Start or stop server?" << endl; + cin >> startOrStop; + + if (startOrStop == "start") + application.ui.startServer(true); + else + application.ui.startServer(false); + } else if (command == "exit"){ cout << "Bye! Thanks for choosing us." << endl; return 0; diff --git a/program/Source/app/Application.h b/program/Source/app/Application.h index 77ce9f30aa4b221678039663481a84926101c451..890cdc142882a91d8018e4adee83e7db06f07fc2 100644 --- a/program/Source/app/Application.h +++ b/program/Source/app/Application.h @@ -14,6 +14,8 @@ */ class Application { public: + static const std::string SERVER; + CloudManager cm; CloudAccessLayer cal; CloudFileSystem cfs; @@ -24,6 +26,9 @@ public: * Default Application constructor */ Application(CloudManager cm); + + + static Application* DeleteThisUglyWorkaround_App_Instance; }; #endif //_APPLICATION_H \ No newline at end of file diff --git a/program/Source/app/UI.cpp b/program/Source/app/UI.cpp index 524d6769dfd70e2fbd349a30c6e18b2f1dfe163b..f3535bd4a21049289df210c95a5407ce3604f242 100644 --- a/program/Source/app/UI.cpp +++ b/program/Source/app/UI.cpp @@ -66,4 +66,9 @@ list<FileDescriptor*>* UI::getFileTree() { LOG_ENTER_EXIT; return app->cfs.getFileTree(); +} + +void UI::startServer(bool start) +{ + app->hnc.startServer(start); } \ No newline at end of file diff --git a/program/Source/app/UI.h b/program/Source/app/UI.h index 92bfa8af85d4e3e2f6c90e53778a2c7047213648..3ff5edf39b4be62b06c5e987561d7301fd378ecc 100644 --- a/program/Source/app/UI.h +++ b/program/Source/app/UI.h @@ -74,7 +74,17 @@ public: */ list<FileDescriptor*>* getFileTree(); + /** + * Call auth function of a cloud adapter. + * Used for example to aquire OAuth token. + */ void authCloudAdapter(string cloudAdapterId); + + /** + * Starts or stops the server functionality. + * @param start Start server if true, else stop. + */ + void startServer(bool start = true); }; } #endif //_UI_H \ No newline at end of file diff --git a/program/Source/cloud/CloudAccessLayer.cpp b/program/Source/cloud/CloudAccessLayer.cpp index 3ce456a73eeaa1a5a0d3bbdf1547ebf094c6c719..96a55f9863349bc5049884154a745fbbd3b472d3 100644 --- a/program/Source/cloud/CloudAccessLayer.cpp +++ b/program/Source/cloud/CloudAccessLayer.cpp @@ -3,8 +3,6 @@ #include "app\Application.h" #include "CloudException.h" -using namespace fileModel; - /** * CloudAccessLayer implementation */ @@ -40,7 +38,7 @@ bool CloudAccessLayer::upload(const FileDescriptor& fileDescriptor) const return succesful; } -bool CloudAccessLayer::upload(LockFile lockFile) { +bool CloudAccessLayer::upload(fileModel::LockFile lockFile) { LOG_ENTER_EXIT; bool success = true; if (!(app->cm.getCloudAdapter(lockFile.getCloudId())->upload(lockFile))){ @@ -74,7 +72,7 @@ FileDescriptor* CloudAccessLayer::download(FileDescriptor fileDescriptor) { return fd; } -bool CloudAccessLayer::download(LockFile lockFile) { +bool CloudAccessLayer::download(fileModel::LockFile lockFile) { LOG_ENTER_EXIT; if ((app->cm.getCloudAdapter(lockFile.getCloudId())->download(lockFile)) != NULL) return true; @@ -105,7 +103,7 @@ bool CloudAccessLayer::deleteFile(FileDescriptor fileDescriptor) { return succesful; } -bool CloudAccessLayer::deleteFile(LockFile lockFile) { +bool CloudAccessLayer::deleteFile(fileModel::LockFile lockFile) { LOG_ENTER_EXIT; bool succesful = true; if (!(app->cm.getCloudAdapter(lockFile.getCloudId())->deleteFile(lockFile))){ @@ -140,7 +138,7 @@ bool CloudAccessLayer::checkExists(FileDescriptor fileDescriptor) { return exists; } -bool CloudAccessLayer::checkExists(LockFile lockFile) { +bool CloudAccessLayer::checkExists(fileModel::LockFile lockFile) { LOG_ENTER_EXIT; return (app->cm.getCloudAdapter(lockFile.getCloudId())->checkExists(lockFile)); diff --git a/program/Source/dataAccess/CloudFileSystem.cpp b/program/Source/dataAccess/CloudFileSystem.cpp index 78474f37ac10861d6be2d576885bc4c88f5f17c2..ff700e2b48f6e5f5c584a427114fce2107af14ee 100644 --- a/program/Source/dataAccess/CloudFileSystem.cpp +++ b/program/Source/dataAccess/CloudFileSystem.cpp @@ -2,7 +2,11 @@ #include "ComputeOnPi.h" #include "ComputeOnClient.h" -using namespace fileModel; +CloudFileSystem& CloudFileSystem::getInstance() +{ + return Application::DeleteThisUglyWorkaround_App_Instance->cfs; +} + /** * @file CloudFileSystem.cpp @@ -10,14 +14,12 @@ using namespace fileModel; */ CloudFileSystem::CloudFileSystem(Application &application) : + computeOnPi(false), + homeNetworkBehaviour(new ComputeOnClient(*this)), application(application), distributor(application.cm), - homeNetworkBehaviour(new ComputeOnClient(*this)), - cache(new ConcreteCache()), - computeOnPi(false) + cache(new ConcreteCache()) { - //cfl = *(new CloudFileList()); - cfl.setPersPath("store.dat"); cfl.load(); @@ -122,7 +124,7 @@ void CloudFileSystem::lock(FileDescriptor fileDescriptor) { lockFileTmp << "Client ID comes here"; lockFileTmp.close(); - LockFile lockFile(cloudId, lockFileName); + fileModel::LockFile lockFile(cloudId, lockFileName); application.cal.upload(lockFile); } } @@ -132,7 +134,7 @@ void CloudFileSystem::unlock(FileDescriptor fileDescriptor) { for each (string cloudId in fileDescriptor.getUniqueClouds()) { - LockFile lockFile(cloudId, fileDescriptor); + fileModel::LockFile lockFile(cloudId, fileDescriptor); application.cal.deleteFile(lockFile); } } @@ -144,7 +146,7 @@ bool CloudFileSystem::isLocked(FileDescriptor fileDescriptor) { for each (string cloudId in fileDescriptor.getUniqueClouds()) { - LockFile lockFile(cloudId, fileDescriptor); + fileModel::LockFile lockFile(cloudId, fileDescriptor); if (application.cal.checkExists(lockFile)) { diff --git a/program/Source/dataAccess/CloudFileSystem.h b/program/Source/dataAccess/CloudFileSystem.h index 6c5530743e4ed83af026f9e9dd7f34e3f493ac41..d8b567c71a1550687da1a75926cd1787955a4872 100644 --- a/program/Source/dataAccess/CloudFileSystem.h +++ b/program/Source/dataAccess/CloudFileSystem.h @@ -59,6 +59,12 @@ private: CloudFileList cfl; public: + static CloudFileSystem& getInstance(); + /*{ + static CloudFileSystem instance; + return instance; + }*/ + /** * Setter to the setComputePi variable * Sets the right HomeNetworkBehaviour diff --git a/program/Source/dataAccess/ComputeOnClient.cpp b/program/Source/dataAccess/ComputeOnClient.cpp index 3ad024d12c8e8cc989cbdd4fa88d2f231764e7de..48af852906ea0d83bfa52b41787c29cff532aeee 100644 --- a/program/Source/dataAccess/ComputeOnClient.cpp +++ b/program/Source/dataAccess/ComputeOnClient.cpp @@ -40,7 +40,7 @@ bool ComputeOnClient::addFile(string localFileID, string destinationFileID) { string ComputeOnClient::getFile(FileDescriptor fileDescriptor) { LOG_ENTER_EXIT; - //TODO: check is anything is returned... where does it even return anything? + //TODO: check if anything is returned... where does it even return anything? cloudFileSystem.getCache()->getFile(); if (cloudFileSystem.findByID(&fileDescriptor) == nullptr){ diff --git a/program/Source/dataAccess/ComputeOnPi.cpp b/program/Source/dataAccess/ComputeOnPi.cpp index 654d9d5178473cbbe21d761dfa3e8aa25831dc1f..46124e508d3652191949c7db58341d7455e3f0c0 100644 --- a/program/Source/dataAccess/ComputeOnPi.cpp +++ b/program/Source/dataAccess/ComputeOnPi.cpp @@ -10,5 +10,5 @@ bool ComputeOnPi::addFile(string localFileID, string destinationFileID) { string ComputeOnPi::getFile(FileDescriptor fileDescriptor) { //TODO: change HomeNetworkCommunications' getFileRemote's attribute's type to fileDescriptor - return cloudFileSystem.getHomeNetworkCommunications()->getFileRemote(fileDescriptor.getFileID()); + return cloudFileSystem.getHomeNetworkCommunications()->getFileRemote(fileDescriptor.getFileID()) ? "File downloaded successfully" : "Could't download file"; } \ No newline at end of file diff --git a/program/Source/networking/FileServerConnection.cpp b/program/Source/networking/FileServerConnection.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0296b141babec840886f4ab3d2d8c8d060ad61d3 --- /dev/null +++ b/program/Source/networking/FileServerConnection.cpp @@ -0,0 +1,97 @@ +#include "FileServerConnection.h" +#include <fstream> +#include "NetworkHelperMethods.h" +#include <dataAccess/CloudFileSystem.h> + +using namespace std; + +const std::string FileServerConnection::dataFolder = "C:\\Users\\krisz\\raspberrycloud\\skeleton\\Program\\data\\"; + +void FileServerConnection::run() +{ + char buffer[1024]; + + socket().receiveBytes(buffer, sizeof(buffer)); + + if (GET_CMD.compare(buffer) == 0) + { + // GET command received, send OK + sendString(socket(), OK_ANS); + + // Get file name + socket().receiveBytes(buffer, sizeof(buffer)); + ifstream file(dataFolder + buffer, ios::in | ios::binary); + + // If file doesn't exist try to get it + if (!file) + { + file.close(); + CloudFileSystem::getInstance().getFile(FileDescriptor(buffer)); + file.open(dataFolder + buffer, ios::in | ios::binary); + + if (!file) + { + sendString(socket(), ERR_ANS); + return; + } + } + + // Get file size and send it + long size = getFileSize(file); + socket().sendBytes(&size, sizeof(long)); + + socket().receiveBytes(buffer, sizeof(buffer)); + if (OK_ANS.compare(buffer) != 0) + return; + + // Send file + while (file) + { + file.read(buffer, sizeof(buffer)); + socket().sendBytes(buffer, file.gcount()); + } + + } + else if (PUT_CMD.compare(buffer) == 0) + { + // PUT command received, send OK + sendString(socket(), OK_ANS); + + // Get file size + long size; + socket().receiveBytes(&size, sizeof(long)); + + // File size received, send OK + sendString(socket(), OK_ANS); + + // Get file name, create file + socket().receiveBytes(buffer, sizeof(buffer)); + ofstream file(dataFolder + buffer, ios::out | ios::binary); + string fileName(buffer); + + // If file is created send OK, else send ERR + if (file) + { + sendString(socket(), OK_ANS); + } + else + { + sendString(socket(), ERR_ANS); + return; + } + + // Start receiving file + while (size != 0) + { + auto receivedBytes = socket().receiveBytes(buffer, sizeof(buffer)); + file.write(buffer, receivedBytes); + size -= receivedBytes; + } + + CloudFileSystem::getInstance().addFile(fileName, fileName); + } + else + { + sendString(socket(), ERR_ANS); + } +} diff --git a/program/Source/networking/FileServerConnection.h b/program/Source/networking/FileServerConnection.h new file mode 100644 index 0000000000000000000000000000000000000000..02d015a516e39352298114dde93a1e721d6eafe0 --- /dev/null +++ b/program/Source/networking/FileServerConnection.h @@ -0,0 +1,16 @@ +#ifndef _FILESERVERCONNECTION_H +#define _FILESERVERCONNECTION_H + +#include <Poco/Net/TCPServerConnection.h> + +class FileServerConnection : public Poco::Net::TCPServerConnection +{ + static const std::string dataFolder; + +public: + explicit FileServerConnection(const Poco::Net::StreamSocket& socket) : TCPServerConnection(socket) {} + + virtual void run(); +}; + +#endif //_FILESERVERCONNECTION_H diff --git a/program/Source/networking/HomeNetworkCommunications.cpp b/program/Source/networking/HomeNetworkCommunications.cpp index 28698cf08b962242879359f8e1a9323bb787f52e..fda709258cb3bd1c464f55c12781a275656b0c1c 100644 --- a/program/Source/networking/HomeNetworkCommunications.cpp +++ b/program/Source/networking/HomeNetworkCommunications.cpp @@ -1,34 +1,195 @@ #include "logger\Logger.h" #include "HomeNetworkCommunications.h" +#include "FileServerConnection.h" +#include "NetworkHelperMethods.h" +#include "IPServer.h" +#include "Poco/Thread.h" +#include "Poco/Net/TCPServerConnectionFactory.h" +#include "Poco/Net/TCPServer.h" +#include <Poco/Net/DatagramSocket.h> + using namespace std; +using namespace Poco; +using namespace Poco::Net; + /** * HomeNetworkCommunications implementation */ -HomeNetworkCommunications::HomeNetworkCommunications(){ - encryption = ConcreteEncryption(); -} +const string HomeNetworkCommunications::dataFolder = "C:\\Users\\krisz\\raspberrycloud\\skeleton\\Program\\dataClient\\"; -bool HomeNetworkCommunications::addFileRemote(string fileID) { +HomeNetworkCommunications::HomeNetworkCommunications() : + tcpServer(nullptr), + udpServerThread(nullptr), + udpServer(nullptr) +{} + +bool HomeNetworkCommunications::addFileRemote(string fileID) +{ LOG_ENTER_EXIT; + refresh(); - if (!piAvaliable) return false; - string encrypted = encryption.encrypt(fileID); - cout << "REMOTE UPLOAD INITIATED." << endl; + if (!piAvaliable) + return false; + + char buffer[1024]; + + // Open file, check if exists + ifstream file(dataFolder + fileID, ios::in | ios::binary); + if (!file) + return false; + + // Create socket, connect to server + StreamSocket socket; + socket.connect(SocketAddress(piAddress, TCP_PORT)); + + // Send PUT command + sendString(socket, PUT_CMD); + + socket.receiveBytes(buffer, sizeof(buffer)); + if (OK_ANS.compare(buffer) != 0) + return false; + + // Get file size and send it + long size = getFileSize(file); + socket.sendBytes(&size, sizeof(long)); + + socket.receiveBytes(buffer, sizeof(buffer)); + if (OK_ANS.compare(buffer) != 0) + return false; + + // Send file name + sendString(socket, fileID); + + socket.receiveBytes(buffer, sizeof(buffer)); + if (OK_ANS.compare(buffer) != 0) + return false; + + // Send file + while (file) + { + file.read(buffer, sizeof(buffer)); + socket.sendBytes(buffer, file.gcount()); + } + return true; } -string HomeNetworkCommunications::getFileRemote(string fileID) { +bool HomeNetworkCommunications::getFileRemote(string fileID) +{ LOG_ENTER_EXIT; + refresh(); - if (!piAvaliable) return false; - string decrypted = encryption.decrypt(fileID); - cout << "REMOTE DOWNLOAD INITIATED." << endl; - return decrypted; + if (!piAvaliable) + return false; + + char buffer[1024]; + long size; + + // Create socket, connect to server + StreamSocket socket; + socket.connect(SocketAddress(piAddress, TCP_PORT)); + + // Send GET command + sendString(socket, GET_CMD); + + // Get server answer, exit if not OK + socket.receiveBytes(buffer, sizeof(buffer)); + if (OK_ANS.compare(buffer) != 0) + return false; + + // Send file name + sendString(socket, fileID); + + // Get server answer, if ERR then exit + socket.receiveBytes(buffer, sizeof(buffer)); + if (ERR_ANS.compare(buffer) == 0) + return false; + + // If server answer wasn't ERR, it's the file size + memcpy(&size, buffer, sizeof(long)); + + // Send OK to server, start receiving file + sendString(socket, OK_ANS); + + ofstream file(dataFolder + fileID, ios::out | ios::binary); + while (size != 0) + { + auto receivedBytes = socket.receiveBytes(buffer, sizeof(buffer)); + file.write(buffer, receivedBytes); + size -= receivedBytes; + } + + return true; } -void HomeNetworkCommunications::refresh() { +void HomeNetworkCommunications::refresh() +{ LOG_ENTER_EXIT; - cout << "THE PI IS READY." << endl; - piAvaliable = true; -} \ No newline at end of file + + try + { + piAddress = getServerIP(); + piAvaliable = true; + } + catch (TimeoutException& e) + { + piAddress = IPAddress(); + piAvaliable = false; + } +} + +void HomeNetworkCommunications::startServer(bool start) +{ + if (start) + { + // Start IP server + if (udpServer == nullptr && udpServerThread == nullptr) + { + udpServer = new IPServer(); + udpServerThread = new Thread(); + + udpServerThread->start(*udpServer); + } + + + // Start file server + if (tcpServer == nullptr) + { + tcpServer = new TCPServer(new TCPServerConnectionFactoryImpl<FileServerConnection>(), TCP_PORT); + tcpServer->start(); + } + } + else + { + // Stop file server + delete tcpServer; + tcpServer = nullptr; + + // Stop IP server + udpServer->stop(); + udpServerThread->join(); + delete udpServer; + delete udpServerThread; + udpServer = nullptr; + udpServerThread = nullptr; + } +} + +IPAddress HomeNetworkCommunications::getServerIP() +{ + SocketAddress bdcast(IPAddress::broadcast(), UDP_PORT); + DatagramSocket dgs; + + dgs.setBroadcast(true); + dgs.setReceiveTimeout(1000000); + + string msg = "Hello server!"; + dgs.sendTo(msg.c_str(), msg.size() + 1, bdcast); + + SocketAddress sender; + char buffer[1024]; + dgs.receiveFrom(buffer, sizeof(buffer), sender); + + return sender.host(); +} diff --git a/program/Source/networking/HomeNetworkCommunications.h b/program/Source/networking/HomeNetworkCommunications.h index fb9137f443824dca1f88150138b151cda67cbc5f..41fb94fd8241c8e3a1f24c247bd2c4c02443f52f 100644 --- a/program/Source/networking/HomeNetworkCommunications.h +++ b/program/Source/networking/HomeNetworkCommunications.h @@ -1,21 +1,37 @@ -/** - * Project Untitled - */ - - #ifndef _HOMENETWORKCOMMUNICATIONS_H #define _HOMENETWORKCOMMUNICATIONS_H #include <string> -#include "ConcreteEncryption.h" -using namespace std; +#include <Poco/Net/IPAddress.h> + +namespace Poco { + class Thread; + + namespace Net + { + class TCPServer; + } +} + +class IPServer; + /** * HomeNetworkCommunications class * */ class HomeNetworkCommunications { -private: - ConcreteEncryption encryption; + + static const std::string dataFolder; + + bool piAvaliable; + Poco::Net::IPAddress piAddress; + + Poco::Net::TCPServer* tcpServer; + Poco::Thread* udpServerThread; + IPServer* udpServer; + + Poco::Net::IPAddress getServerIP(); + public: /** * HomeNetworkCommunications constructor @@ -26,20 +42,24 @@ public: * Sends a file to the PI be added remotely * @param fileID ID of the file to be added */ - bool addFileRemote(string fileID); + bool addFileRemote(std::string fileID); /** * Sends a file to the PI be added remotely * @param fileID ID of the file to be added */ - string getFileRemote(string fileID); + bool getFileRemote(std::string fileID); /** * Checks if the pi is avaliable */ void refresh(); -private: - bool piAvaliable; + + /** + * Starts or stops the server functionality. + * @param start Start server if true, else stop. + */ + void startServer(bool start = true); }; #endif //_HOMENETWORKCOMMUNICATIONS_H \ No newline at end of file diff --git a/program/Source/networking/IPServer.cpp b/program/Source/networking/IPServer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ff2acb671f0e190b9940a71e8be475b84c20ad56 --- /dev/null +++ b/program/Source/networking/IPServer.cpp @@ -0,0 +1,33 @@ +#include "IPServer.h" +#include <Poco/Net/IPAddress.h> +#include <Poco/Net/DatagramSocket.h> +#include "NetworkHelperMethods.h" + +using namespace Poco; +using namespace Poco::Net; + +void IPServer::run() +{ + std::string welcomeMsg = "Hi!"; + + SocketAddress address(IPAddress(), UDP_PORT); + DatagramSocket socket(address); + + socket.setReceiveTimeout(1000000); + + char buffer[1024]; + while (!stopped) + { + SocketAddress sender; + + try + { + socket.receiveFrom(buffer, sizeof(buffer), sender); + socket.sendTo(welcomeMsg.c_str(), welcomeMsg.size() + 1, sender); + } + catch (TimeoutException& e) + { + // Timeout is used to let a thread check whether it should exit + } + } +} diff --git a/program/Source/networking/IPServer.h b/program/Source/networking/IPServer.h new file mode 100644 index 0000000000000000000000000000000000000000..f773f1677dcf933f3c4cec3ffd9dbf82163a7476 --- /dev/null +++ b/program/Source/networking/IPServer.h @@ -0,0 +1,18 @@ +#ifndef _IPSERVER_H +#define _IPSERVER_H +#include <Poco/Runnable.h> + +class IPServer : public Poco::Runnable +{ + volatile bool stopped = false; + +public: + virtual void run(); + + void stop() + { + stopped = true; + } +}; + +#endif diff --git a/program/Source/networking/NetworkHelperMethods.cpp b/program/Source/networking/NetworkHelperMethods.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/program/Source/networking/NetworkHelperMethods.h b/program/Source/networking/NetworkHelperMethods.h new file mode 100644 index 0000000000000000000000000000000000000000..73872a2098369ea4791c7316b15687009c7ad720 --- /dev/null +++ b/program/Source/networking/NetworkHelperMethods.h @@ -0,0 +1,33 @@ +#ifndef _NETWORKHELPERMETHODS_H +#define _NETWORKHELPERMETHODS_H + +#include <string> +#include <Poco/Net/StreamSocket.h> +#include <fstream> + +const int UDP_PORT = 42420; +const int TCP_PORT = 42421; +const std::string GET_CMD("GET"); +const std::string PUT_CMD("PUT"); +const std::string OK_ANS("OK"); +const std::string ERR_ANS("ERR"); + +inline long getFileSize(std::ifstream& file) +{ + auto currPos = file.tellg(); + + file.seekg(0, file.beg); + auto begin = file.tellg(); + file.seekg(0, file.end); + auto end = file.tellg(); + file.seekg(0, currPos); + + return end - begin; +} + +inline void sendString(Poco::Net::StreamSocket& socket, const std::string string) +{ + socket.sendBytes(string.c_str(), string.size() + 1); +} + +#endif //_NETWORKHELPERMETHODS_H