From 21591b40816ebdba52701f17336ade7552804bd9 Mon Sep 17 00:00:00 2001 From: Hackerpilot Date: Mon, 25 Jan 2016 17:03:55 -0800 Subject: [PATCH] Fix #288 --- src/client/client.d | 54 +++++---------------------------- src/common/messages.d | 69 +++++++++++++++++++++++++++++++++++++++++++ src/server/server.d | 10 ++++++- 3 files changed, 85 insertions(+), 48 deletions(-) diff --git a/src/client/client.d b/src/client/client.d index 8d91137..7511d9f 100644 --- a/src/client/client.d +++ b/src/client/client.d @@ -30,13 +30,14 @@ import std.conv; import std.string; import std.experimental.logger; -import msgpack; import common.messages; import common.dcd_version; import common.socket; int main(string[] args) { + sharedLog.fatalHandler = () {}; + size_t cursorPos = size_t.max; string[] importPaths; ushort port = 9166; @@ -106,24 +107,12 @@ int main(string[] args) if (query) { - try + if (serverIsRunning(useTCP, socketFile, port)) { - Socket socket = createSocket(socketFile, port); - scope (exit) { socket.shutdown(SocketShutdown.BOTH); socket.close(); } - request.kind = RequestKind.query; - if (sendRequest(socket, request)) - { - const AutocompleteResponse response = getResponse(socket); - if (response.completionType == "ack") - { - writeln("Server is running"); - return 0; - } - else - throw new Exception(""); - } + writeln("Server is running"); + return 0; } - catch (Exception ex) + else { writeln("Server is not running"); return 1; @@ -328,39 +317,10 @@ Socket createSocket(string socketFile, ushort port) return socket; } -/** - * Returns: true on success - */ -bool sendRequest(Socket socket, AutocompleteRequest request) -{ - ubyte[] message = msgpack.pack(request); - ubyte[] messageBuffer = new ubyte[message.length + message.length.sizeof]; - auto messageLength = message.length; - messageBuffer[0 .. size_t.sizeof] = (cast(ubyte*) &messageLength)[0 .. size_t.sizeof]; - messageBuffer[size_t.sizeof .. $] = message[]; - return socket.send(messageBuffer) == messageBuffer.length; -} - -/** - * Gets the response from the server - */ -AutocompleteResponse getResponse(Socket socket) -{ - ubyte[1024 * 16] buffer; - auto bytesReceived = socket.receive(buffer); - if (bytesReceived == Socket.ERROR) - throw new Exception("Incorrect number of bytes received"); - if (bytesReceived == 0) - throw new Exception("Server closed the connection, 0 bytes received"); - AutocompleteResponse response; - msgpack.unpack(buffer[0..bytesReceived], response); - return response; -} - void printDocResponse(AutocompleteResponse response) { import std.array: join; - response.docComments.join(r"\n\n").writeln; + response.docComments.join(r"\n\n").writeln; } void printLocationResponse(AutocompleteResponse response) diff --git a/src/common/messages.d b/src/common/messages.d index f1b0d95..a3d07de 100644 --- a/src/common/messages.d +++ b/src/common/messages.d @@ -18,6 +18,9 @@ module common.messages; +import std.socket; +import msgpack; + /** * The type of completion list being returned */ @@ -157,3 +160,69 @@ struct AutocompleteResponse */ string[] importPaths; } + +/** + * Returns: true on success + */ +bool sendRequest(Socket socket, AutocompleteRequest request) +{ + ubyte[] message = msgpack.pack(request); + ubyte[] messageBuffer = new ubyte[message.length + message.length.sizeof]; + auto messageLength = message.length; + messageBuffer[0 .. size_t.sizeof] = (cast(ubyte*) &messageLength)[0 .. size_t.sizeof]; + messageBuffer[size_t.sizeof .. $] = message[]; + return socket.send(messageBuffer) == messageBuffer.length; +} + +/** + * Gets the response from the server + */ +AutocompleteResponse getResponse(Socket socket) +{ + ubyte[1024 * 16] buffer; + auto bytesReceived = socket.receive(buffer); + if (bytesReceived == Socket.ERROR) + throw new Exception("Incorrect number of bytes received"); + if (bytesReceived == 0) + throw new Exception("Server closed the connection, 0 bytes received"); + AutocompleteResponse response; + msgpack.unpack(buffer[0..bytesReceived], response); + return response; +} + +/** + * Returns: true if a server instance is running + * Params: + * useTCP = `true` to check a TCP port, `false` for UNIX domain socket + * socketFile = the file name for the UNIX domain socket + * port = the TCP port + */ +bool serverIsRunning(bool useTCP, string socketFile, ushort port) +{ + scope (failure) + return false; + AutocompleteRequest request; + request.kind = RequestKind.query; + Socket socket; + scope (exit) + { + socket.shutdown(SocketShutdown.BOTH); + socket.close(); + } + if (useTCP) + { + socket = new TcpSocket(AddressFamily.INET); + socket.connect(new InternetAddress("localhost", port)); + } + else + { + socket = new Socket(AddressFamily.UNIX, SocketType.STREAM); + socket.connect(new UnixAddress(socketFile)); + } + socket.setOption(SocketOptionLevel.SOCKET, SocketOption.RCVTIMEO, dur!"seconds"(5)); + socket.blocking = true; + if (sendRequest(socket, request)) + return getResponse(socket).completionType == "ack"; + else + return false; +} diff --git a/src/server/server.d b/src/server/server.d index a77ef42..fa7a32f 100644 --- a/src/server/server.d +++ b/src/server/server.d @@ -73,6 +73,8 @@ int main(string[] args) string socketFile = generateSocketName(); } + sharedLog.fatalHandler = () {}; + try { getopt(args, "port|p", &port, "I", &importPaths, "help|h", &help, @@ -86,6 +88,8 @@ int main(string[] args) return 1; } + globalLogLevel = level; + if (printVersion) { version (Windows) @@ -109,7 +113,11 @@ int main(string[] args) return 1; } - globalLogLevel = level; + if (serverIsRunning(useTCP, socketFile, port)) + { + fatal("Another instance of DCD-server is already running"); + return 1; + } info("Starting up..."); StopWatch sw = StopWatch(AutoStart.yes);