summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2023-09-10 13:40:05 -0400
committerpommicket <pommicket@gmail.com>2023-09-10 13:40:05 -0400
commit6586f9e66d87017984f57b3b4579c78897ba66f2 (patch)
treef84ab9a9b4a6449e123cfed0a3e9245750a19fd6
parent5e22cc67e92a87a0448dea70c89a4472b961fa14 (diff)
LSP over TCP on windows
-rw-r--r--base.h3
-rw-r--r--build.c2
-rw-r--r--lsp-write.c6
-rw-r--r--lsp.c10
-rw-r--r--main.c5
-rw-r--r--os-posix.c3
-rw-r--r--os-win.c104
-rw-r--r--tags.c2
8 files changed, 126 insertions, 9 deletions
diff --git a/base.h b/base.h
index dfc9f2f..b438b19 100644
--- a/base.h
+++ b/base.h
@@ -22,6 +22,9 @@
#endif
#if _WIN32
+// windows is stupid — we have to include winsock2.h first
+#include <winsock2.h>
+#include <ws2tcpip.h>
#include <windows.h>
#include <shlobj.h>
#include <dbghelp.h>
diff --git a/build.c b/build.c
index 59bf72c..f45b025 100644
--- a/build.c
+++ b/build.c
@@ -121,7 +121,7 @@ void build_start(Ted *ted) {
Assoc associations[] = {
#if _WIN32
- {"make.bat", "make.bat"},
+ {"make.bat", "cmd /c make.bat"},
#endif
{"Cargo.toml", "cargo build"},
{"Makefile", "make -j16"},
diff --git a/lsp-write.c b/lsp-write.c
index 0eed987..974a845 100644
--- a/lsp-write.c
+++ b/lsp-write.c
@@ -332,8 +332,12 @@ static void message_writer_write_and_free(LSP *lsp, JSONWriter *o) {
memcpy(content, header_str, header_size);
#if LSP_SHOW_C2S
- printf("%s%s%s\n",term_bold(stdout),content,term_clear(stdout));
+ const int limit = 1000;
+ debug_println("%s%.*s%s%s",term_italics(stdout),limit,content,
+ strlen(content) > (size_t)limit ? "..." : "",
+ term_clear(stdout));
#endif
+
if (lsp->log) {
fprintf(lsp->log, "LSP MESSAGE FROM CLIENT TO SERVER\n%s\n\n", content + header_size);
}
diff --git a/lsp.c b/lsp.c
index 54a28d6..b4b65bb 100644
--- a/lsp.c
+++ b/lsp.c
@@ -395,7 +395,7 @@ static bool lsp_receive(LSP *lsp, size_t max_size) {
if (status != 0) {
bool not_found =
#if _WIN32
- false // @TODO
+ false
#else
info.exit_code == 127
#endif
@@ -444,7 +444,7 @@ static bool lsp_receive(LSP *lsp, size_t max_size) {
lsp->received_data[received_so_far] = '\0';// null terminate
#if LSP_SHOW_S2C
const int limit = 1000;
- printf("%s%.*s%s%s\n",term_italics(stdout),limit,lsp->received_data,
+ debug_println("%s%.*s%s%s",term_italics(stdout),limit,lsp->received_data,
strlen(lsp->received_data) > (size_t)limit ? "..." : "",
term_clear(stdout));
#endif
@@ -594,7 +594,6 @@ static int lsp_communication_thread(void *data) {
}
lsp->exited = true;
-
if (!lsp->process) {
// process already exited
return 0;
@@ -681,10 +680,8 @@ LSP *lsp_create(const LSPSetup *setup) {
lsp->port = port;
lsp->send_delay = setup->send_delay;
- #if DEBUG
- printf("Starting up LSP %p (ID %u) `%s` (port %u) in %s\n",
+ debug_println("Starting up LSP %p (ID %u) `%s` (port %u) in %s",
(void *)lsp, (unsigned)lsp->id, command ? command : "(no command)", port, root_dir);
- #endif
str_hash_table_create(&lsp->document_ids, sizeof(u32));
lsp->command = str_dup(command);
@@ -714,6 +711,7 @@ LSP *lsp_create(const LSPSetup *setup) {
#if _WIN32
if (strstr(error, " 2)")) {
if (lsp->log) fprintf(lsp->log, "Couldn't start LSP server %s: file not found.", command);
+ debug_println("error: %s", error);
} else
#endif
lsp_set_error(lsp, "Couldn't start LSP server: %s", error);
diff --git a/main.c b/main.c
index 5a252a9..930d6da 100644
--- a/main.c
+++ b/main.c
@@ -31,6 +31,7 @@ FUTURE FEATURES:
#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "shell32.lib")
+#pragma comment(lib, "ws2_32.lib")
#endif
@@ -262,6 +263,10 @@ INT WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
WideCharToMultiByte(CP_UTF8, 0, wide_arg, len, argv[i], bufsz - 1, NULL, NULL);
}
LocalFree(wide_argv);
+ {
+ WSADATA wsaData = {0};
+ WSAStartup(MAKEWORD(2, 2), &wsaData);
+ }
SetProcessDPIAware();
#else
diff --git a/os-posix.c b/os-posix.c
index 34a7f7b..32c1853 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -458,6 +458,8 @@ Socket *socket_connect_tcp(const char *address, u16 port) {
if (connect(fd, &addr, sizeof addr) < 0) {
strbuf_printf(s->error, "couldn't connect to %s:%u (%s)",
address, port, strerror(errno));
+ close(fd);
+ return s;
}
set_nonblocking(fd);
@@ -492,5 +494,6 @@ void socket_close(Socket **psocket) {
if (!s) return;
if (s->fd > 0)
close(s->fd);
+ free(s);
*psocket = NULL;
}
diff --git a/os-win.c b/os-win.c
index 3f93c53..fe08be3 100644
--- a/os-win.c
+++ b/os-win.c
@@ -431,3 +431,107 @@ bool open_with_default_application(const char *path) {
bool change_directory(const char *path) {
return _chdir(path) == 0;
}
+
+struct Socket {
+ SOCKET sock;
+ char error[256];
+};
+
+Socket *socket_connect_tcp(const char *address, u16 port) {
+ Socket *s = calloc(1, sizeof *s);
+ if (!s) return NULL;
+ s->sock = INVALID_SOCKET;
+ if (!address) address = "127.0.0.1";
+
+
+ struct sockaddr_in addr = {
+ .sin_family = AF_INET,
+ .sin_port = htons(port),
+ };
+ if (inet_pton(AF_INET, address, &addr.sin_addr) != 1) {
+ strbuf_printf(s->error, "Invalid address");
+ return s;
+ }
+
+ SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock == INVALID_SOCKET) {
+ strbuf_printf(s->error, "Couldn't create socket (error code %d)",
+ WSAGetLastError());
+ return s;
+ }
+ if (connect(sock, (SOCKADDR *)&addr, sizeof addr) != 0) {
+ strbuf_printf(s->error, "Couldn't connect to %s:%u (error code %d)",
+ address, port, WSAGetLastError());
+ closesocket(sock);
+ return s;
+ }
+
+ u_long mode = 1; // non-blocking
+ ioctlsocket(sock, FIONBIO, &mode);
+ s->sock = sock;
+ return s;
+}
+const char *socket_get_error(Socket *s) {
+ return s->error;
+}
+
+long long socket_read(Socket *s, char *data, size_t size) {
+ if (size > INT_MAX) {
+ strbuf_printf(s->error, "Too much data to read.");
+ return -2;
+ }
+ size_t so_far = 0;
+ while (so_far < size) {
+ int bytes_read = recv(s->sock, data + so_far, (int)(size - so_far), 0);
+ if (bytes_read > 0) {
+ so_far += (size_t)bytes_read;
+ } else if (bytes_read == 0) {
+ return (long long)so_far;
+ } else {
+ int err = WSAGetLastError();
+ if (err == WSAEWOULDBLOCK) {
+ return so_far == 0 ? -1 : (long long)so_far;
+ } else if (err == WSAECONNRESET) {
+ return 0;
+ } else {
+ strbuf_printf(s->error, "recv failed (error code %d)", err);
+ return -2;
+ }
+ }
+ }
+ return (long long)size;
+}
+
+long long socket_write(Socket *s, const char *data, size_t size) {
+ if (size > INT_MAX) {
+ strbuf_printf(s->error, "too much data to write");
+ return -2;
+ }
+ size_t so_far = 0;
+ while (so_far < size) {
+ int bytes_written = send(s->sock, data + so_far, (int)(size - so_far), 0);
+ if (bytes_written > 0) {
+ so_far += (size_t)bytes_written;
+ } else {
+ int err = WSAGetLastError();
+ if (err == WSAEWOULDBLOCK) {
+ return (long long)so_far;
+ } else if (err == WSAEHOSTUNREACH || err == WSAECONNRESET) {
+ return -1;
+ } else {
+ strbuf_printf(s->error, "write failed (error code %d)", err);
+ return -2;
+ }
+ }
+ }
+ return (long long)size;
+}
+
+void socket_close(Socket **psocket) {
+ Socket *s = *psocket;
+ if (!s) return;
+ if (s->sock != INVALID_SOCKET)
+ closesocket(s->sock);
+ free(s);
+ *psocket = NULL;
+}
diff --git a/tags.c b/tags.c
index 436a615..7d8086b 100644
--- a/tags.c
+++ b/tags.c
@@ -18,7 +18,7 @@ static bool get_tags_dir(Ted *ted, bool error_if_does_not_exist) {
strbuf_cpy(ted->tags_dir, path);
}
if (error_if_does_not_exist)
- ted_error(ted, "No tags file. Try running ctags.");
+ ted_flash_error_cursor(ted);
return false;
}