/* gcc -g -Wall -o server.exe server4.c */ #include #include #include #define BUFSIZE 512 HANDLE objects[3]; typedef struct { HANDLE pipe; HANDLE event_exit; OVERLAPPED ol; OVERLAPPED ol_read; DWORD read_count; int exit_thread; /* in normal struct */ void *data; int size; } Server; void print_last_error(const char *fct); static __stdcall unsigned int _read_data_cb(void *data) { #define READ_BUFSIZE 5 char buf[READ_BUFSIZE]; Server *svr; DWORD ret; DWORD nbr_bytes; BOOL res; svr = (Server *)data; while (!svr->exit_thread) { ret = ReadFile(svr->pipe, buf, sizeof(buf), &nbr_bytes, &svr->ol_read); if (!ret) { DWORD err = GetLastError(); if (err == ERROR_IO_PENDING) { /* Let's wait for the event to be signaled ?? */ /* Call GetOverlappedResult ?? */ } else if (ret == ERROR_BROKEN_PIPE) { printf(" * broken pipe\n"); SetEvent(svr->event_exit); } else { printf(" * unexpected error %ld\n", ret); SetEvent(svr->event_exit); } } else { printf(" * ReadFile : %ld\n", nbr_bytes); } } _endthreadex(0); return 0; } void print_last_error(const char *fct) { char *buf; DWORD dw = GetLastError(); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &buf, 0, NULL ); // Display the error message and exit the process printf("%s failed with error %ld: %s\n", fct, dw, buf); LocalFree(buf); } Server * server_new(const char *name) { char buf[256]; Server *svr; HANDLE event; BOOL res; if (!name) return NULL; svr = (Server *)calloc(1,sizeof(Server)); if (!svr) return NULL; snprintf(buf, sizeof(buf), "\\\\.\\pipe\\%s", name); /* * Asynchronuous * block mode */ svr->pipe = CreateNamedPipe(buf, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 512, 512, 5000, NULL); if (!svr->pipe) { print_last_error("CreateNamedPipe"); goto free_svr; } /* * Manual reset * Initial state : non signaled */ event = CreateEvent(NULL, TRUE, FALSE, NULL); if (!event) { print_last_error("CreateEvent"); goto close_pipe; } memset(&svr->ol, 0, sizeof(svr->ol)); svr->ol.hEvent = event; res = ConnectNamedPipe(svr->pipe, &svr->ol); if (res) { print_last_error("ConnectNamedPipe"); goto close_event; } else { DWORD err = GetLastError(); if (err == ERROR_PIPE_CONNECTED) { SetEvent(svr->ol.hEvent); printf("client connected\n"); } else if (err != ERROR_IO_PENDING) { print_last_error("ConnectNamedPipe"); goto close_event; } /* else, we have ERROR_IO_PENDING, so a connection link is pending */ } /* * Manual reset * Initial state : non signaled */ svr->event_exit = CreateEvent(NULL, TRUE, FALSE, NULL); if (!svr->event_exit) { print_last_error("CreateEvent (event exit)"); goto close_event; } /* * Manual reset * Initial state : non signaled */ memset(&svr->ol_read, 0, sizeof(svr->ol_read)); svr->ol_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (!svr->ol_read.hEvent) { print_last_error("CreateEvent (event exit)"); goto close_event_exit; } /* start reading the pipe */ objects[0] = event; objects[1] = svr->event_exit; objects[2] = svr->ol_read.hEvent; return svr; close_event_exit: CloseHandle(svr->event_exit); close_event: CloseHandle(event); close_pipe: CloseHandle(svr->pipe); free_svr: free(svr); return NULL; } void server_del(Server *svr) { if (!svr) return; CloseHandle(svr->event_exit); if (!FlushFileBuffers(svr->pipe)) { print_last_error("FlushFileBuffers"); } if (!DisconnectNamedPipe(svr->pipe)) { print_last_error("DisconnectNamedPipe"); } CloseHandle(svr->ol.hEvent); CloseHandle(svr->pipe); free(svr); } int main() { Server *svr; DWORD ret; DWORD nbr_bytes; BOOL res; svr = server_new("toto"); if (!svr) return -1; printf("waiting for client...\n"); while (1) { ret = WaitForMultipleObjects(3, objects, FALSE, INFINITE); if (ret == WAIT_FAILED) { print_last_error("WaitForMultipleObjects"); goto beach; } printf("WaitForMultipleObjects : %ld\n", ret); if (ret == WAIT_OBJECT_0) { ResetEvent(svr->ol.hEvent); res = GetOverlappedResult(svr->pipe, &svr->ol, &nbr_bytes, FALSE); if (!res) { print_last_error("GetOverlappedResult"); if (!DisconnectNamedPipe(svr->pipe)) { print_last_error("DisconnectNamedPipe"); goto beach; } res = ConnectNamedPipe(svr->pipe, &svr->ol); if (res) { print_last_error("ConnectNamedPipe"); goto beach; } else { DWORD err = GetLastError(); if (err == ERROR_PIPE_CONNECTED) { SetEvent(svr->ol.hEvent); } else if (err != ERROR_IO_PENDING) { print_last_error("ConnectNamedPipe"); goto beach; } /* else, we have ERROR_IO_PENDING, so a connection link is pending */ } } else { printf("client connected (%d)\n", res); /* read pipe */ _beginthreadex(NULL, 0, _read_data_cb, svr, 0, NULL); } } if (ret == (WAIT_OBJECT_0 + 1)) { printf("client connection closed\n"); svr->exit_thread = 1; goto beach; } if (ret == (WAIT_OBJECT_0 + 2)) { ResetEvent(svr->ol_read.hEvent); /* res = GetOverlappedResult(svr->pipe, &svr->ol_read, */ /* &nbr_bytes, TRUE); */ /* if (res) printf(" nbr bytes : %ld\n", nbr_bytes); */ /* else */ /* print_last_error("GetOverlappedResult"); */ } } beach: server_del(svr); return 0; }