Skip to content

Instantly share code, notes, and snippets.

@chebert
Last active May 22, 2022 15:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chebert/92f748f86cbbbead0afd40e6e821ec36 to your computer and use it in GitHub Desktop.
Save chebert/92f748f86cbbbead0afd40e6e821ec36 to your computer and use it in GitHub Desktop.
Full RunPipeServer.c implementation
#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