Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* gcc -g -Wall -o server.exe server5.c */
- #include <stdio.h>
- #include <windows.h>
- #include <process.h>
- #define BUFSIZE 512
- HANDLE objects[2];
- typedef struct
- {
- HANDLE pipe;
- HANDLE event_exit;
- OVERLAPPED ol;
- OVERLAPPED ol_read;
- DWORD read_count;
- int exit_thread;
- HANDLE iocp_read;
- /* in normal struct */
- void *data;
- int size;
- } Server;
- void print_last_error(const char *fct);
- static void
- _svr_data_append(Server *svr, void *data, size_t size)
- {
- if (!svr->data)
- {
- svr->data = malloc(size);
- if (!svr->data)
- return;
- memcpy(svr->data, data, size);
- svr->size = size;
- }
- else
- {
- void *tmp;
- tmp = realloc(svr->data, svr->size + size);
- if (tmp)
- {
- svr->data = tmp;
- memcpy(svr->data + svr->size, data, size);
- svr->size += size;
- }
- }
- {
- char *buf;
- buf = malloc(svr->size + 1);
- memcpy(buf, svr->data, svr->size);
- buf[svr->size] = 0;
- printf("msg (%d -> %02d) : %s\n", (int)size, (int)svr->size, buf);
- free(buf);
- }
- }
- static unsigned int __stdcall
- _read_data_cb(void *data)
- {
- #define READ_BUFSIZE 5
- char buf[READ_BUFSIZE];
- Server *svr;
- DWORD nbr_bytes = 0;
- BOOL res;
- BOOL pending = FALSE;
- ULONG_PTR key;
- LPOVERLAPPED lpol;
- svr = (Server *)data;
- while (!svr->exit_thread)
- {
- res = ReadFile(svr->pipe, buf, sizeof(buf),
- &nbr_bytes, &svr->ol_read);
- if (res)
- {
- printf("ReadFile 1\n");
- _svr_data_append(svr, buf, nbr_bytes);
- do {
- res = ReadFile(svr->pipe, buf, sizeof(buf),
- &nbr_bytes, &svr->ol_read);
- if (res)
- {
- printf("ReadFile 2\n");
- _svr_data_append(svr, buf, nbr_bytes);
- }
- else
- {
- DWORD err = GetLastError();
- if (err == ERROR_IO_PENDING)
- {
- printf("ReadFile2: ERROR_IO_PENDING\n");
- pending = TRUE;
- }
- else if (err == ERROR_SUCCESS)
- {
- printf(" * success\n");
- continue;
- }
- else if (err == ERROR_BROKEN_PIPE)
- {
- printf(" * broken pipe\n");
- SetEvent(svr->event_exit);
- }
- else
- {
- printf(" * unexpected error %ld\n", err);
- SetEvent(svr->event_exit);
- }
- break;
- }
- } while (1);
- }
- else
- {
- DWORD err = GetLastError();
- if (err == ERROR_IO_PENDING)
- {
- printf("ReadFile1: ERROR_IO_PENDING\n");
- pending = TRUE;
- }
- else if (err == ERROR_SUCCESS)
- {
- printf(" * success\n");
- continue;
- }
- else if (err == ERROR_BROKEN_PIPE)
- {
- printf(" * broken pipe\n");
- SetEvent(svr->event_exit);
- }
- else
- {
- printf(" * unexpected error %ld\n", err);
- SetEvent(svr->event_exit);
- }
- }
- if (pending)
- {
- res = GetQueuedCompletionStatus(svr->iocp_read, &nbr_bytes, &key, &lpol, INFINITE);
- printf("GQCIOS %d %d %p\n", (int)nbr_bytes, (int)key, lpol);
- if (res && lpol)
- {
- res = ReadFile(svr->pipe, buf, sizeof(buf),
- &nbr_bytes, &svr->ol_read);
- if (res)
- {
- pending = FALSE;
- printf("ReadFile 3\n");
- _svr_data_append(svr, buf, nbr_bytes);
- }
- else
- {
- DWORD err = GetLastError();
- if (err == ERROR_IO_PENDING)
- {
- printf("ReadFile3: ERROR_IO_PENDING\n");
- }
- }
- }
- else
- {
- DWORD err = GetLastError();
- print_last_error("GetQueuedCompletionStatus");
- if (err == ERROR_IO_PENDING)
- {
- pending = TRUE;
- }
- }
- }
- }
- printf("ending thread...\n");
- _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;
- HANDLE iocp;
- ULONG_PTR key = 0xff;
- 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;
- }
- /*
- * ConnectNamedPipe() event
- * 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;
- objects[0] = svr->ol.hEvent;
- 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 */
- }
- /*
- * Exit event
- * Manual reset
- * Initial state : non signaled
- */
- event = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (!event)
- {
- print_last_error("CreateEvent (event exit)");
- goto close_event;
- }
- svr->event_exit = event;
- objects[1] = svr->event_exit;
- /*
- * ReadFile() event
- * Manual reset
- * Initial state : non signaled
- */
- event = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (!event)
- {
- print_last_error("CreateEvent (event exit)");
- goto close_event_exit;
- }
- memset(&svr->ol_read, 0, sizeof(svr->ol_read));
- svr->ol_read.hEvent = event;
- iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
- if (!iocp)
- {
- print_last_error("CreateIoCompletionPort");
- goto close_event_exit;
- }
- svr->iocp_read = CreateIoCompletionPort(svr->pipe, iocp, key, 1);
- if (!svr->iocp_read)
- {
- print_last_error("CreateIoCompletionPort");
- goto close_event_exit;
- }
- 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(2, 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))
- {
- }
- }
- beach:
- server_del(svr);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement