diff options
Diffstat (limited to 'xmake/modules/private/service/distributed_build/client.lua')
| -rw-r--r-- | xmake/modules/private/service/distributed_build/client.lua | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/xmake/modules/private/service/distributed_build/client.lua b/xmake/modules/private/service/distributed_build/client.lua new file mode 100644 index 000000000..da263c796 --- /dev/null +++ b/xmake/modules/private/service/distributed_build/client.lua @@ -0,0 +1,198 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file client.lua +-- + +-- imports +import("core.base.bytes") +import("core.base.base64") +import("core.base.socket") +import("core.base.option") +import("core.base.scheduler") +import("core.project.config", {alias = "project_config"}) +import("lib.detect.find_tool") +import("private.service.config") +import("private.service.message") +import("private.service.client") +import("private.service.stream", {alias = "socket_stream"}) + +-- define module +local distributed_build_client = distributed_build_client or client() +local super = distributed_build_client:class() + +-- init client +function distributed_build_client:init() + super.init(self) + + -- init address + local address = assert(config.get("distributed_build.client.connect"), "config(distributed_build.client.connect): not found!") + super.address_set(self, address) + + -- get project directory + local projectdir = os.projectdir() + local projectfile = os.projectfile() + if projectfile and os.isfile(projectfile) and projectdir then + self._PROJECTDIR = projectdir + self._WORKDIR = path.join(project_config.directory(), "distributed_build") + else + raise("we need enter a project directory with xmake.lua first!") + end + + -- check environment + environment.check(false) +end + +-- connect to the remote server +function distributed_build_client:connect() + if self:is_connected() then + print("%s: has been connected!", self) + return + end + + -- we need user authorization? + local token = config.get("distributed_build.client.token") + if not token and self:user() then + + -- get user password + cprint("Please input user ${bright}%s${clear} password:", self:user()) + io.flush() + local pass = (io.read() or ""):trim() + assert(pass ~= "", "password is empty!") + + -- compute user authorization + token = base64.encode(self:user() .. ":" .. pass) + token = hash.md5(bytes(token)) + end + + -- do connect + local addr = self:addr() + local port = self:port() + local sock = assert(socket.connect(addr, port), "%s: server unreachable!", self) + local session_id = self:session_id() + local ok = false + local errors + print("%s: connect %s:%d ..", self, addr, port) + if sock then + local stream = socket_stream(sock) + if stream:send_msg(message.new_connect(session_id, {token = token})) and stream:flush() then + local msg = stream:recv_msg() + if msg then + vprint(msg:body()) + if msg:success() then + ok = true + else + errors = msg:errors() + end + end + end + end + if ok then + print("%s: connected!", self) + else + print("%s: connect %s:%d failed, %s", self, addr, port, errors or "unknown") + end + + -- update status + local status = self:status() + status.addr = addr + status.port = port + status.token = token + status.connected = ok + status.session_id = session_id + self:status_save() + + -- sync files + if ok then + self:sync() + end +end + +-- disconnect server +function distributed_build_client:disconnect() + if not self:is_connected() then + print("%s: has been disconnected!", self) + return + end + local addr = self:addr() + local port = self:port() + local sock = socket.connect(addr, port) + local session_id = self:session_id() + local errors + local ok = false + print("%s: disconnect %s:%d ..", self, addr, port) + if sock then + local stream = socket_stream(sock) + if stream:send_msg(message.new_disconnect(session_id, {token = self:token()})) and stream:flush() then + local msg = stream:recv_msg() + if msg then + vprint(msg:body()) + if msg:success() then + ok = true + else + errors = msg:errors() + end + end + end + else + -- server unreachable, but we still disconnect it. + wprint("%s: server unreachable!", self) + ok = true + end + if ok then + print("%s: disconnected!", self) + else + print("%s: disconnect %s:%d failed, %s", self, addr, port, errors or "unknown") + end + + -- update status + local status = self:status() + status.token = nil + status.connected = not ok + self:status_save() +end + +-- get class +function distributed_build_client:class() + return distributed_build_client +end + +-- is connected? we cannot depend on client:init when run action +function is_connected() + -- the current process is in service? we cannot enable it + if os.getenv("XMAKE_IN_SERVICE") then + return false + end + local projectdir = os.projectdir() + local projectfile = os.projectfile() + if projectfile and os.isfile(projectfile) and projectdir then + local workdir = path.join(project_config.directory(), "distributed_build") + local statusfile = path.join(workdir, "status.txt") + if os.isfile(statusfile) then + local status = io.load(statusfile) + if status and status.connected then + return true + end + end + end +end + +function main() + local instance = distributed_build_client() + instance:init() + return instance +end |
