Last active
May 22, 2022 15:04
-
-
Save chebert/92f748f86cbbbead0afd40e6e821ec36 to your computer and use it in GitHub Desktop.
Full RunPipeServer.c implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "run_pipe_server.h" | |
#include <windows.h> | |
#include <stdio.h> | |
// Create a named pipe with the given pipe_filename. | |
static Pipe CreateServerPipe(String pipe_filename); | |
// Wait for a client connection to pipe. | |
static b4 ConnectPipe(Pipe); | |
// Loop that processes and responds to client requests from Pipe, until the client disconnects. | |
static void ProccessPipeRequests(Pipe, ClientRequestProcessor); | |
b4 RunPipeServer(String pipe_filename, ClientRequestProcessor process_request) { | |
while (1) { | |
printf("\nPipe Server: awaiting client connection on %s\n", pipe_filename); | |
fflush(stdout); | |
Pipe pipe = CreateServerPipe(pipe_filename); | |
if (pipe == INVALID_HANDLE_VALUE) { | |
printf("CreateNamedPipe failed, GLE=%d.\n", GetLastError()); | |
return FALSE; | |
} | |
if (ConnectPipe(pipe)) { | |
printf("Client connected: processing pipe requests.\n"); | |
fflush(stdout); | |
// Process pipe requests until the client disconnects | |
ProccessPipeRequests(pipe, process_request); | |
} else { | |
CloseHandle(pipe); | |
} | |
} | |
return TRUE; | |
} | |
Pipe CreateServerPipe(String pipe_filename) { | |
// Create a bi-directional pipe that allows for exactly one client, | |
// that blocks while waiting for messages. | |
const DWORD max_num_instances = 1; // allow for one client | |
const DWORD pipe_message_type = | |
// Treat pipe stream as stream of messages | |
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | | |
// Blocking mode | |
PIPE_WAIT; | |
return CreateNamedPipe( | |
pipe_filename, | |
PIPE_ACCESS_DUPLEX, // bi-directional read/write | |
pipe_message_type, | |
max_num_instances, | |
RESPONSE_BUFFER_SIZE, | |
REQUEST_BUFFER_SIZE, | |
0, // default timeout | |
NULL); // default security attribute | |
} | |
b4 ConnectPipe(Pipe pipe) { | |
// Connect to pipe (non-overlapped mode), or return true if already connected. | |
return ConnectNamedPipe(pipe, NULL) || (GetLastError() == ERROR_PIPE_CONNECTED); | |
} | |
// Wait for and read the next client request from pipe. Read into request_buffer, | |
// and set the num_bytes_read. | |
static b4 ReadClientRequest(Pipe pipe, u1 *request_buffer, u4 *num_bytes_read); | |
// Send a response to the client message in the pipe. | |
static b4 RespondToClientRequest(Pipe pipe, u1 *response_buffer, u4 num_bytes_to_write); | |
void ProccessPipeRequests(Pipe pipe, ClientRequestProcessor process_request) { | |
static u1 request_buffer[REQUEST_BUFFER_SIZE]; | |
static u1 response_buffer[RESPONSE_BUFFER_SIZE]; | |
// Loop until the client disconnects | |
while (1) { | |
// Read the next client request | |
u4 num_request_bytes = 0; | |
if (!ReadClientRequest(pipe, request_buffer, &num_request_bytes)) | |
break; | |
// Process the client request and write the response in the response buffer. | |
u4 num_response_bytes = 0; | |
process_request(request_buffer, num_request_bytes, response_buffer, &num_response_bytes); | |
// Send the response to the client | |
if (!RespondToClientRequest(pipe, response_buffer, num_response_bytes)) | |
break; | |
} | |
// Client disconnected or error occurred: | |
// Flush, disconnect, and close the pipe | |
FlushFileBuffers(pipe); | |
DisconnectNamedPipe(pipe); | |
CloseHandle(pipe); | |
} | |
b4 ReadClientRequest(Pipe pipe, u1 *request_buffer, u4 *num_request_bytes) { | |
DWORD num_bytes_read = 0; | |
b4 success = ReadFile( | |
pipe, request_buffer, REQUEST_BUFFER_SIZE, &num_bytes_read, | |
// not overlapped I/O | |
NULL); | |
*num_request_bytes = num_bytes_read; | |
if (!success || num_bytes_read == 0) { | |
if (GetLastError() == ERROR_BROKEN_PIPE) { | |
printf("ProccessPipeRequests: client disconnected.\n"); | |
} else { | |
printf("ProccessPipeRequests ReadFile failed, GLE=%d.\n", GetLastError()); | |
} | |
return FALSE; | |
} | |
return TRUE; | |
} | |
b4 RespondToClientRequest(Pipe pipe, u1 *response_buffer, u4 num_bytes_to_write) { | |
DWORD num_bytes_written = 0; | |
// Write the reply to the pipe. | |
b4 success = WriteFile( | |
pipe, response_buffer, num_bytes_to_write, &num_bytes_written, | |
// not overlapped I/O | |
NULL); | |
if (!success || num_bytes_to_write != num_bytes_written) { | |
printf("ProccessPipeRequests WriteFile failed, GLE=%d.\n", GetLastError()); | |
return FALSE; | |
} | |
return TRUE; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment