From 85ba55d94e40874ec48aede368e5d12582749743 Mon Sep 17 00:00:00 2001 From: Martin Fuchs Date: Sun, 30 Nov 2003 22:48:19 +0000 Subject: [PATCH] added first version of pipetools svn path=/trunk/; revision=6838 --- reactos/tools/pipetools/.cvsignore | 2 + reactos/tools/pipetools/Makefile | 44 ++++ reactos/tools/pipetools/piperead.cpp | 81 +++++++ reactos/tools/pipetools/pipetunnel.cpp | 317 +++++++++++++++++++++++++ 4 files changed, 444 insertions(+) create mode 100644 reactos/tools/pipetools/.cvsignore create mode 100644 reactos/tools/pipetools/Makefile create mode 100644 reactos/tools/pipetools/piperead.cpp create mode 100644 reactos/tools/pipetools/pipetunnel.cpp diff --git a/reactos/tools/pipetools/.cvsignore b/reactos/tools/pipetools/.cvsignore new file mode 100644 index 00000000000..774f00871dc --- /dev/null +++ b/reactos/tools/pipetools/.cvsignore @@ -0,0 +1,2 @@ +*.exe +*.o diff --git a/reactos/tools/pipetools/Makefile b/reactos/tools/pipetools/Makefile new file mode 100644 index 00000000000..b26df5467cb --- /dev/null +++ b/reactos/tools/pipetools/Makefile @@ -0,0 +1,44 @@ +# +# pipetools Makefile +# + +CC = gcc +CXX = g++ +LINK = g++ + +TOOLS_PATH = .. + +CFLAGS = -DWIN32 -Wall +RCFLAGS = -DWIN32 +LFLAGS = + +ifdef DEBUG +CFLAGS += -D_DEBUG -g +RCFLAGS += -D_DEBUG +LFLAGS += -g +else +CFLAGS += -DNDEBUG -Os +RCFLAGS += -DNDEBUG +LFLAGS += -s +endif + +CXXFLAGS = $(CFLAGS) + +LIBS = wsock32 + + +%.exe: %.c + $(CC) -o$@ $(CFLAGS) $^ + +%.exe: %.cpp + $(CXX) -o$@ $(CXXFLAGS) $^ $(addprefix -l,$(LIBS)) + + +TARGETS = piperead.exe pipetunnel.exe + +all: $(TARGETS) + + +clean: + $(TOOLS_PATH)/rdel $(TARGETS) *.o + diff --git a/reactos/tools/pipetools/piperead.cpp b/reactos/tools/pipetools/piperead.cpp new file mode 100644 index 00000000000..17b4c294985 --- /dev/null +++ b/reactos/tools/pipetools/piperead.cpp @@ -0,0 +1,81 @@ +// +// piperead.cpp +// +// Martin Fuchs, 30.11.2003 +// + +// +// Invoke as: "piperead [pipe_name]", +// for example: "piperead com_1" +// + + +#define WIN32_LEAN_AND_MEAN +#include +#include + + + // This definition currently missing in MinGW. +#ifndef FILE_FLAG_FIRST_PIPE_INSTANCE +#define FILE_FLAG_FIRST_PIPE_INSTANCE 0x00080000 +#endif + + +static void print_error(LONG win32_error) +{ + fprintf(stderr, "WIN32 error %d\n", win32_error); +} + + +int main(int argc, char** argv) +{ + char path[MAX_PATH]; + const char* pipe_name; + + if (argc > 1) + pipe_name = *++argv; + else + pipe_name = "com_1"; + + sprintf(path, "\\\\.\\pipe\\%s", pipe_name); + + HANDLE hPipe = CreateNamedPipe(path, PIPE_ACCESS_DUPLEX|FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_WAIT|PIPE_TYPE_BYTE, 1, 4096, 4096, 30000, NULL); + + if (hPipe == INVALID_HANDLE_VALUE) { + print_error(GetLastError()); + return 1; + } + + for(;;) { + DWORD read; + BYTE buffer[1024]; + + if (!ReadFile(hPipe, buffer, sizeof(buffer), &read, NULL)) { + DWORD error = GetLastError(); + + if (error == ERROR_PIPE_LISTENING) + Sleep(1000); + else if (error == ERROR_BROKEN_PIPE) { + CloseHandle(hPipe); + + hPipe = CreateNamedPipe(path, PIPE_ACCESS_DUPLEX|FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_WAIT|PIPE_TYPE_BYTE, 1, 4096, 4096, 30000, NULL); + + if (hPipe == INVALID_HANDLE_VALUE) { + print_error(GetLastError()); + return 1; + } + } else { + print_error(error); + break; + } + } + + if (read) + fwrite(buffer, read, 1, stdout); + } + + if (!CloseHandle(hPipe)) + print_error(GetLastError()); + + return 0; +} diff --git a/reactos/tools/pipetools/pipetunnel.cpp b/reactos/tools/pipetools/pipetunnel.cpp new file mode 100644 index 00000000000..dc714316f47 --- /dev/null +++ b/reactos/tools/pipetools/pipetunnel.cpp @@ -0,0 +1,317 @@ +// +// pipetunnel.cpp +// +// Martin Fuchs, 30.11.2003 +// + +// +// Invoke as: "pipetunnel [pipe_name]", +// for example: "pipetunnel com_2" +// +// Then start up RectOS in VMWare, wait for the serial connect. +// After that you can connect GDB using the command "target remote :9999". +// + + +#define WIN32_LEAN_AND_MEAN +#include + +#include + +#ifdef _MSC_VER +#pragma comment(lib, "wsock32") +#endif + +#include +#include + + + // This definition currently missing in MinGW. +#ifndef FILE_FLAG_FIRST_PIPE_INSTANCE +#define FILE_FLAG_FIRST_PIPE_INSTANCE 0x00080000 +#endif + + +static void print_error(LONG win32_error) +{ + fprintf(stderr, "WIN32 error %d\n", win32_error); +} + + +#ifdef _DEBUG + + // critical section wrapper +struct CritSect : public CRITICAL_SECTION +{ + CritSect() + { + InitializeCriticalSection(this); + } + + ~CritSect() + { + DeleteCriticalSection(this); + } +}; + +static void dbg_trace(char mode, const char* buffer, int l) +{ + static char s_mode = '\0'; + static CritSect crit_sect; + + EnterCriticalSection(&crit_sect); + + if (l) { + for(const char*p=buffer; l--; ++p) { + if (mode != s_mode) { + putchar('\n'); + putchar(mode); + putchar(' '); + + s_mode = mode; + } + + if (*p=='\n' || !*p /*|| *p=='#'*/) { + /*if (*p == '#') + putchar(*p);*/ + + s_mode = '\0'; + } else + putchar(*p); + } + } + + LeaveCriticalSection(&crit_sect); +} + +#endif + + +static SOCKET s_srv_socket = (SOCKET)-1; + +SOCKET open_tcp_connect() +{ + if (s_srv_socket == (SOCKET)-1) { + SOCKADDR_IN srv_addr = {0}; + + srv_addr.sin_family = AF_INET; + srv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + srv_addr.sin_port = htons(9999); + + s_srv_socket = socket(PF_INET, SOCK_STREAM, 0); + if (s_srv_socket == (SOCKET)-1) { + perror("socket()"); + return 0; + } + + if (bind(s_srv_socket, (struct sockaddr*) &srv_addr, sizeof(srv_addr)) == -1) { + perror("bind()"); + return 0; + } + + if (listen(s_srv_socket, 4) == -1) { + perror("listen()"); + return 0; + } + } + + SOCKADDR_IN rem_addr; + int rem_len = sizeof(rem_addr); + + for(;;) { + SOCKET sock = accept(s_srv_socket, (struct sockaddr*)&rem_addr, &rem_len); + + if (sock < 0) { + if (errno == EINTR) + continue; + + perror("accept()"); + return 0; + } + + return sock; + } +} + + + +struct WriterThread +{ + WriterThread(SOCKET sock, HANDLE hPipe) + : _sock(sock), + _hPipe(hPipe) + { + DWORD tid; + + HANDLE hThread = CreateThread(NULL, 0, WriterThreadRoutine, this, 0, &tid); + + if (hThread) { + SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST); + + CloseHandle(hThread); + } else + delete this; + } + +protected: + SOCKET _sock; + HANDLE _hPipe; + + static DWORD WINAPI WriterThreadRoutine(LPVOID param) + { + WriterThread* pThis = (WriterThread*) param; + + DWORD ret = pThis->Run(); + + delete pThis; + + return ret; + } + + DWORD Run() + { + char buffer[1024]; + + for(;;) { + int r = recv(_sock, buffer, sizeof(buffer), 0); + + if (r == -1) { + perror("recv()"); + fprintf(stderr, "debugger connection broken\n"); + _sock = (SOCKET)-1; + return 1; + } + + if (r) { + DWORD wrote; + + if (!WriteFile(_hPipe, buffer, r, &wrote, NULL)) + break; + +#ifdef _DEBUG + dbg_trace('<', buffer, r); +#endif + } + } + + return 0; + } +}; + + +LONG read_pipe(HANDLE hPipe, SOCKET sock) +{ + for(;;) { + DWORD read; + char buffer[1024]; + + // wait for input data + WaitForSingleObject(hPipe, INFINITE); + + if (!ReadFile(hPipe, buffer, sizeof(buffer), &read, NULL)) { + DWORD error = GetLastError(); + + if (error == ERROR_PIPE_LISTENING) + Sleep(1000); + else + return error; + } + + if (read) { +#ifdef _DEBUG + dbg_trace('>', buffer, read); +#endif + + if (!send(sock, buffer, read, 0)) { + perror("send()"); + return GetLastError(); + } + } + } +} + + +int main(int argc, char** argv) +{ + char path[MAX_PATH]; + const char* pipe_name; + + if (argc > 1) + pipe_name = *++argv; + else + pipe_name = "com_2"; + + sprintf(path, "\\\\.\\pipe\\%s", pipe_name); + + + // initialize winsock + WSADATA wsa_data; + + if (WSAStartup(MAKEWORD(2,2), &wsa_data)) { + fprintf(stderr, "WSAStartup() failed\n"); + return 0; + } + + + // increment priority to be faster than the cpu eating VMWare process + SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); + + + HANDLE hPipe = INVALID_HANDLE_VALUE; + + for(;;) { + DWORD read; + + if (hPipe == INVALID_HANDLE_VALUE) { + hPipe = CreateNamedPipe(path, PIPE_ACCESS_DUPLEX|FILE_FLAG_FIRST_PIPE_INSTANCE|FILE_FLAG_OVERLAPPED, PIPE_WAIT|PIPE_TYPE_BYTE, 1, 4096, 4096, 30000, NULL); + + if (hPipe == INVALID_HANDLE_VALUE) { + print_error(GetLastError()); + return 1; + } + } + + // wait for the client side of the pipe + while(!ReadFile(hPipe, NULL, 0, &read, NULL) && + GetLastError()==ERROR_PIPE_LISTENING) + Sleep(1000); + + puts("\nnamed pipe connected, now waiting for TCP connection..."); + + SOCKET sock = open_tcp_connect(); + if (sock == (SOCKET)-1) + break; + + puts("TCP connection established."); + + // launch writer thread + new WriterThread(sock, hPipe); + + // launch reader loop + LONG error = read_pipe(hPipe, sock); + + + // close TCP connectiom + closesocket(sock); + sock = (SOCKET)-1; + + // close named pipe + CloseHandle(hPipe); + hPipe = INVALID_HANDLE_VALUE; + + + if (error == ERROR_BROKEN_PIPE) + puts("\nconnection closed."); // normal connection termination + else { + print_error(GetLastError()); + break; + } + } + + if (hPipe != INVALID_HANDLE_VALUE) + if (!CloseHandle(hPipe)) + print_error(GetLastError()); + + return 0; +}