1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #include <cmajor/build/SocketServer.hpp>
  7 #include <cmajor/build/ServerConfig.hpp>
  8 #include <cmajor/symbols/GlobalFlags.hpp>
  9 #include <soulng/util/Log.hpp>
 10 
 11 namespace cmajor { namespace build {
 12 
 13 using namespace cmajor::symbols;
 14 using namespace soulng::util;
 15 
 16 SocketServer::SocketServer(Log* log_const std::string& serverName_bool continuous_) :
 17     log(log_)serverName(serverName_)name("socket server: '" + serverName + "'")socket()running()isRunning(false)exiting(false)continuous(continuous_)
 18 {
 19     ServerInfo* serverInfo = ServerConfig::Instance().GetServerInfo(serverNametruetrue);
 20     if (serverInfo)
 21     {
 22         if (GetGlobalFlag(GlobalFlags::verbose))
 23         {
 24             LogMessage(-1"socket server: binding server '" + serverName + "' to port " + std::to_string(serverInfo->Port()) + "...");
 25         }
 26         socket.Bind(serverInfo->Port());
 27         if (GetGlobalFlag(GlobalFlags::verbose))
 28         {
 29             LogMessage(-1"socket server: server '" + serverName + "' listening...");
 30         }
 31         socket.Listen(10);
 32     }
 33     else
 34     {
 35         throw std::runtime_error("socket server: server name '" + serverName + "' not found");
 36     }
 37 }
 38 
 39 const std::string& SocketServer::Name() const
 40 {
 41     return name;
 42 }
 43 
 44 void SocketServer::WaitForRunning()
 45 {
 46     if (GetGlobalFlag(GlobalFlags::verbose))
 47     {
 48         LogMessage(-1"socket server: '" + serverName + "' wait for running...");
 49     }
 50     {
 51         std::unique_lock<std::mutex> lock(mtx);
 52         running.wait(lock[this]{ return isRunning; });
 53     }
 54     if (GetGlobalFlag(GlobalFlags::verbose))
 55     {
 56         LogMessage(-1"socket server: '" + serverName + "' running");
 57     }
 58 }
 59 
 60 void SocketServer::Run(const std::string& prompt)
 61 {
 62     while (!exiting)
 63     {
 64         if (!prompt.empty())
 65         {
 66             LogMessage(-1"socket server: " + prompt);
 67         }
 68         isRunning = true;
 69         running.notify_all();
 70         if (GetGlobalFlag(GlobalFlags::verbose))
 71         {
 72             LogMessage(-1"socket server: '" + serverName + "' waiting for client connection...");
 73         }
 74         TcpSocket connectedSocket = socket.Accept();
 75         if (GetGlobalFlag(GlobalFlags::verbose))
 76         {
 77             LogMessage(-1"socket server: '" + serverName + "' accepted a client connection...");
 78         }
 79         connection.reset(new SocketConnection(logthisstd::move(connectedSocket)));
 80         buildServer.reset(new BuildServer(connection.get()));
 81         if (GetGlobalFlag(GlobalFlags::verbose))
 82         {
 83             LogMessage(-1"socket server: '" + serverName + "' running build server...");
 84         }
 85         buildServer->Run();
 86     }
 87 }
 88 
 89 void SocketServer::Exit()
 90 {
 91     if (continuous)
 92     {
 93         buildServer->Exit();
 94         buildServer->SetConnection(nullptr);
 95         connection->SetServer(nullptr);
 96         return;
 97     }
 98     exiting = true;
 99     if (GetGlobalFlag(GlobalFlags::verbose))
100     {
101         LogMessage(-1"socket server: '" + serverName + "' exiting...");
102     }
103     try
104     {
105         socket.Close();
106     }
107     catch (const std::exception&;)
108     {
109     }
110     if (GetGlobalFlag(GlobalFlags::verbose))
111     {
112         LogMessage(-1"socket server: '" + serverName + "' exited");
113     }
114 }
115 
116 void SocketServer::ExitContinuous()
117 {
118     continuous = false;
119     Exit();
120 }
121 
122 } } // namespace cmajor::build