mirror of
https://github.com/reactos/reactos.git
synced 2024-08-20 10:23:22 +00:00
318 lines
6.5 KiB
C++
318 lines
6.5 KiB
C++
//
|
|
// 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 <windows.h>
|
|
|
|
#include <winsock.h>
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma comment(lib, "wsock32")
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
|
|
|
|
// This definition currently missing in MinGW.
|
|
#ifndef FILE_FLAG_FIRST_PIPE_INSTANCE
|
|
#define FILE_FLAG_FIRST_PIPE_INSTANCE 0x00080000
|
|
#endif
|
|
|
|
|
|
static void print_error(DWORD win32_error)
|
|
{
|
|
fprintf(stderr, "WIN32 error %lu\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;
|
|
}
|