4 // Martin Fuchs, 30.11.2003
8 // Invoke as: "pipetunnel [pipe_name]",
9 // for example: "pipetunnel com_2"
11 // Then start up RectOS in VMWare, wait for the serial connect.
12 // After that you can connect GDB using the command "target remote :9999".
16 #define WIN32_LEAN_AND_MEAN
22 #pragma comment(lib, "wsock32")
29 // This definition currently missing in MinGW.
30 #ifndef FILE_FLAG_FIRST_PIPE_INSTANCE
31 #define FILE_FLAG_FIRST_PIPE_INSTANCE 0x00080000
35 static void print_error(DWORD win32_error
)
37 fprintf(stderr
, "WIN32 error %lu\n", win32_error
);
43 // critical section wrapper
44 struct CritSect
: public CRITICAL_SECTION
48 InitializeCriticalSection(this);
53 DeleteCriticalSection(this);
57 static void dbg_trace(char mode
, const char* buffer
, int l
)
59 static char s_mode
= '\0';
60 static CritSect crit_sect
;
62 EnterCriticalSection(&crit_sect
);
65 for(const char*p
=buffer
; l
--; ++p
) {
74 if (*p
=='\n' || !*p
/*|| *p=='#'*/) {
84 LeaveCriticalSection(&crit_sect
);
90 static SOCKET s_srv_socket
= (SOCKET
)-1;
92 SOCKET
open_tcp_connect()
94 if (s_srv_socket
== (SOCKET
)-1) {
95 SOCKADDR_IN srv_addr
= {0};
97 srv_addr
.sin_family
= AF_INET
;
98 srv_addr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
99 srv_addr
.sin_port
= htons(9999);
101 s_srv_socket
= socket(PF_INET
, SOCK_STREAM
, 0);
102 if (s_srv_socket
== (SOCKET
)-1) {
107 if (bind(s_srv_socket
, (struct sockaddr
*) &srv_addr
, sizeof(srv_addr
)) == -1) {
112 if (listen(s_srv_socket
, 4) == -1) {
118 SOCKADDR_IN rem_addr
;
119 int rem_len
= sizeof(rem_addr
);
122 SOCKET sock
= accept(s_srv_socket
, (struct sockaddr
*)&rem_addr
, &rem_len
);
140 WriterThread(SOCKET sock
, HANDLE hPipe
)
146 HANDLE hThread
= CreateThread(NULL
, 0, WriterThreadRoutine
, this, 0, &tid
);
149 SetThreadPriority(hThread
, THREAD_PRIORITY_HIGHEST
);
151 CloseHandle(hThread
);
160 static DWORD WINAPI
WriterThreadRoutine(LPVOID param
)
162 WriterThread
* pThis
= (WriterThread
*) param
;
164 DWORD ret
= pThis
->Run();
176 int r
= recv(_sock
, buffer
, sizeof(buffer
), 0);
180 fprintf(stderr
, "debugger connection broken\n");
188 if (!WriteFile(_hPipe
, buffer
, r
, &wrote
, NULL
))
192 dbg_trace('<', buffer
, r
);
202 LONG
read_pipe(HANDLE hPipe
, SOCKET sock
)
208 // wait for input data
209 WaitForSingleObject(hPipe
, INFINITE
);
211 if (!ReadFile(hPipe
, buffer
, sizeof(buffer
), &read
, NULL
)) {
212 DWORD error
= GetLastError();
214 if (error
== ERROR_PIPE_LISTENING
)
222 dbg_trace('>', buffer
, read
);
225 if (!send(sock
, buffer
, read
, 0)) {
227 return GetLastError();
234 int main(int argc
, char** argv
)
237 const char* pipe_name
;
244 sprintf(path
, "\\\\.\\pipe\\%s", pipe_name
);
247 // initialize winsock
250 if (WSAStartup(MAKEWORD(2,2), &wsa_data
)) {
251 fprintf(stderr
, "WSAStartup() failed\n");
256 // increment priority to be faster than the cpu eating VMWare process
257 SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS
);
258 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST
);
261 HANDLE hPipe
= INVALID_HANDLE_VALUE
;
266 if (hPipe
== INVALID_HANDLE_VALUE
) {
267 hPipe
= CreateNamedPipe(path
, PIPE_ACCESS_DUPLEX
|FILE_FLAG_FIRST_PIPE_INSTANCE
|FILE_FLAG_OVERLAPPED
, PIPE_WAIT
|PIPE_TYPE_BYTE
, 1, 4096, 4096, 30000, NULL
);
269 if (hPipe
== INVALID_HANDLE_VALUE
) {
270 print_error(GetLastError());
275 // wait for the client side of the pipe
276 while(!ReadFile(hPipe
, NULL
, 0, &read
, NULL
) &&
277 GetLastError()==ERROR_PIPE_LISTENING
)
280 puts("\nnamed pipe connected, now waiting for TCP connection...");
282 SOCKET sock
= open_tcp_connect();
283 if (sock
== (SOCKET
)-1)
286 puts("TCP connection established.");
288 // launch writer thread
289 new WriterThread(sock
, hPipe
);
291 // launch reader loop
292 LONG error
= read_pipe(hPipe
, sock
);
295 // close TCP connectiom
301 hPipe
= INVALID_HANDLE_VALUE
;
304 if (error
== ERROR_BROKEN_PIPE
)
305 puts("\nconnection closed."); // normal connection termination
307 print_error(GetLastError());
312 if (hPipe
!= INVALID_HANDLE_VALUE
)
313 if (!CloseHandle(hPipe
))
314 print_error(GetLastError());