VOID InstanceThread (LPVOID lpvParam) { CHAR chRequest[BUFSIZE]; CHAR chReply[BUFSIZE]; DWORD cbBytesRead, cbReplyBytes, cbWritten; BOOL fSuccess; HANDLE hPipe; hPipe = (HANDLE)lpvParam; while (1) { fSuccess = ReadFile(hPipe, chRequest, BUFSIZE, &cbBytesRead, NULL); if (!fSuccess || cbBytesRead == 0) break; GetAnswerToRequest(chRequest, chReply, &cbReplyBytes); fSuccess = WriteFile(hPipe, chReply, cbReplyBytes, &cbWritten, NULL); if (!fSuccess || cbReplyBytes != cbWritten) break; } FlushFileBuffers(hPipe); DisconnectNamedPipe(hPipe); CloseHandle(hPipe); }
void WINAPI CompletedReadRoutine(DWORD dwErr,DWORD cbBytesRead,LPOVERLAPPED lpOverLap){ LPPIPEINST lpPipeInst; BOOL fWrite = FALSE; lpPipeInst = (LPPIPEINST) lpOverLap; if ((dwErr == 0) && (cbBytesRead != 0)){ GetAnswerToRequest(lpPipeInst); fWrite = WriteFileEx(lpPipeInst->hPipeInst,lpPipeInst->chReply, lpPipeInst->cbToWrite,(LPOVERLAPPED) lpPipeInst, (LPOVERLAPPED_COMPLETION_ROUTINE) CompletedWriteRoutine); } if (!fWrite) DisconnectAndClose(lpPipeInst); }
DWORD ReadClient() { while(!loopstop) { if(startread) { while(ReadFile(hPipe, chRequest, BUFSIZE, &cbBytesRead, NULL) >0) { GetAnswerToRequest(chRequest); Sleep(20); } Sleep(100); SendToPipe(0, 0); } else { Sleep(500); } } return 0; }
DWORD WINAPI InstanceThread(LPVOID lpvParam) { ATLTRACE("InstanceThread started\n"); TGITCacheResponse response; DWORD cbBytesRead, cbWritten; BOOL fSuccess; CAutoFile hPipe; // The thread's parameter is a handle to a pipe instance. hPipe = lpvParam; InterlockedIncrement(&nThreadCount); while (bRun) { // Read client requests from the pipe. TGITCacheRequest request; fSuccess = ReadFile( hPipe, // handle to pipe &request, // buffer to receive data sizeof(request), // size of buffer &cbBytesRead, // number of bytes read NULL); // not overlapped I/O if (! fSuccess || cbBytesRead == 0) { DisconnectNamedPipe(hPipe); ATLTRACE("Instance thread exited\n"); InterlockedDecrement(&nThreadCount); if (nThreadCount == 0) PostMessage(hWnd, WM_CLOSE, 0, 0); return 1; } DWORD responseLength; GetAnswerToRequest(&request, &response, &responseLength); // Write the reply to the pipe. fSuccess = WriteFile( hPipe, // handle to pipe &response, // buffer to write from responseLength, // number of bytes to write &cbWritten, // number of bytes written NULL); // not overlapped I/O if (! fSuccess || responseLength != cbWritten) { DisconnectNamedPipe(hPipe); ATLTRACE("Instance thread exited\n"); InterlockedDecrement(&nThreadCount); if (nThreadCount == 0) PostMessage(hWnd, WM_CLOSE, 0, 0); return 1; } } // Flush the pipe to allow the client to read the pipe's contents // before disconnecting. Then disconnect the pipe, and close the // handle to this pipe instance. FlushFileBuffers(hPipe); DisconnectNamedPipe(hPipe); ATLTRACE("Instance thread exited\n"); InterlockedDecrement(&nThreadCount); if (nThreadCount == 0) PostMessage(hWnd, WM_CLOSE, 0, 0); return 0; }
void* SocketHandler(void* lp){ int *csock = (int*)lp; char pchRequest[BUFSIZ]; char pchReply[BUFSIZ]; DWORD cbBytesRead = 0, cbReplyBytes = 0; /*char buffer[1024]; int buffer_len = 1024;*/ //int bytecount; memset(pchRequest, 0, BUFSIZ); if((cbBytesRead = recv(*csock, pchRequest, BUFSIZ, 0)) == (DWORD)-1){ fprintf(stderr, "Error receiving data %d\n", errno); close(*csock); free(csock); return 0; } printf("Received bytes %d\nReceived string \"%s\"\n", cbBytesRead, pchRequest); //strcat(buffer, " SERVER ECHO"); pchRequest[cbBytesRead] = '\0'; // check for Exit-Message if(0 == strcmp(pchRequest, szExitMessage)) { printf("Received Exit-Message, pinging Server to stop it.\n"); stop = true; close(*csock); free(csock); // create a socket connection so that the server comes out of the accept() call pingServerSocket(); return 0; } // Print verbose messages. In production code, this should be for debugging only. //printf("InstanceThread created, receiving and processing messages, GLE=%d\n", GetLastError()); /*for(DWORD i = 0;i < cbBytesRead+1;i++) { printf("%i/%c ", pchRequest[i], pchRequest[i]); } printf("\n");*/ char tag[BUFSIZE]; // look for the tag in the sent data char* pos = strchr(pchRequest, '|'); // if we do not find the pipe, there is no tag information if(pos != NULL) { strncpy(tag, pchRequest, pos-pchRequest); tag[pos-pchRequest] = '\0'; strcpy(pchRequest, pos+1); pchRequest[cbBytesRead - (pos-pchRequest+1)] = '\0'; //printf("Having %d, cutting down to %d: %s\n", cbBytesRead, cbBytesRead - (pos-pchRequest+1), pchRequest); } //printf("After tagging: %s\n", pchRequest); // only set the tag if we have one if(pos != NULL && pos > pchRequest) { _tprintf(TEXT("Found tag: %s, GLE=%d.\n"), tag, GetLastError()); DYNATRACE_SET_TAG_FROM_STRING(tag); // retrieve and set tag DYNATRACE_START_SERVER_PUREPATH(); // start server-side PurePath } /* does not work... else { // start normal purepath if we DYNATRACE_START_PUREPATH(); }*/ ssize_t cbWritten = 0; { // create a block for auto-node-capture to work correctly here DYNATRACE_AUTO_NODE_CAPTURE(DYNATRACE_CAPTURE << REPLACEMENT << cbBytesRead); // Process the incoming message. GetAnswerToRequest(pchRequest, pchReply, &cbReplyBytes); _tprintf( TEXT("Handled data, returning: %s (%d), GLE=%d\n"), pchReply, cbReplyBytes, GetLastError()); if((cbWritten = send(*csock, pchReply, cbReplyBytes, 0))== -1){ fprintf(stderr, "Error sending data %d\n", errno); close(*csock); free(csock); return 0; } } if(pos != NULL && pos > pchRequest) { DYNATRACE_END_SERVER_PUREPATH(); // end server-side PurePath } /* does not work... based on scoping!! else { DYNATRACE_EXIT(); }*/ if (/*!fSuccess ||*/ cbReplyBytes != (DWORD)cbWritten) { _tprintf(TEXT("InstanceThread WriteFile failed, GLE=%d.\n"), GetLastError()); close(*csock); free(csock); return 0; } printf("Sent bytes %d\n", (int)cbWritten); close(*csock); free(csock); return 0; }
int main(void) { //printf("SHARE %d\n", *KMotionLocal.sharePtr); /* SJH - modified to listen to a TCP socket in addition to the unix domain (local) socket. Listens at port KMOTION_PORT (defined in KMotionDLL.h). FIXME: need to make this an argc/argv parameter. */ #ifdef _DEAMON //daemonize2(); daemonize(); #endif //http://robertoacevedo.net/blog/2012/12/03/socket-server/ pthread_attr_t attr; // Thread attribute pthread_attr_init(&attr); // Creating thread attributes pthread_attr_setschedpolicy(&attr, SCHED_FIFO); // FIFO scheduling for threads pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); // Don't want threads (particualrly main) // waiting on each other openlog("KMotionServer", LOG_PID|LOG_CONS, LOG_USER); syslog(LOG_ERR, "KMotionServer started "); int tcp_socket; int main_socket; int client_socket; unsigned int t; struct sockaddr_un local, remote; struct sockaddr_in tlocal, tremote; fd_set rfds; int retval; socklen_t len; bool select_timedout; if ((main_socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { perrorExit("socket"); } if ((tcp_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perrorExit("tcp socket"); } if (strlen(SOCK_PATH) >= sizeof(local.sun_path)) { perrorExit("path too long!"); } local.sun_family = AF_UNIX; strcpy(local.sun_path, SOCK_PATH); int unlink_err; if((unlink_err = unlink(local.sun_path))){ logError("unlink"); } //http://idletechnology.blogspot.se/2011/12/unix-domain-sockets-on-osx.html #ifdef __APPLE__ local.sun_len = sizeof(local); if (bind(main_socket, (struct sockaddr *)&local, SUN_LEN(&local)) == -1) { #else len = strlen(local.sun_path) + sizeof(local.sun_family); if (bind(main_socket, (struct sockaddr *)&local, len) == -1) { #endif perrorExit("bind"); } tlocal.sin_family = AF_INET; tlocal.sin_port = htons(KMOTION_PORT); tlocal.sin_addr.s_addr = INADDR_ANY; len = sizeof(tlocal); if (bind(tcp_socket, (struct sockaddr *)&tlocal, len) == -1) { perrorExit("tcp bind"); } if (listen(main_socket, 5) == -1) { perrorExit("listen"); } if (listen(tcp_socket, 5) == -1) { perrorExit("tcp listen"); } for (int i=0; i<MAX_BOARDS; i++) ConsolePipeHandle[i]=0; // The main loop creates an instance of the named pipe and // then waits for a client to connect to it. When the client // connects, a thread is created to handle communications // with that client, and the loop is repeated. //pthread_t ct = pthread_self(); //printf("Thread %.8x %.8x: Current thread\n", ct); select_timedout = false; for (;;) { FD_ZERO(&rfds); FD_SET(main_socket, &rfds); FD_SET(tcp_socket, &rfds); if(!select_timedout){ syslog(LOG_ERR,"Main Thread. Waiting for a connection...\n"); } struct timeval timeout; // Initialize the timeout data structure. timeout.tv_sec = 1; timeout.tv_usec = 0; retval = select(tcp_socket+1, &rfds, NULL, NULL, &timeout); select_timedout = retval == 0; if (retval < 0){ perrorExit("select"); } else if(select_timedout){ //If exit() is executed in the processs that started the server we never get here //Hence the reference counting from KMotionDLl.nInstances must be made. if (nClients <= 0) break; // nobody left - terminate server if (KMotionDLL.nInstances() < 2) break; // nobody left - terminate server continue; //timeout } else if (FD_ISSET(main_socket, &rfds)) { t = sizeof(remote); client_socket = accept(main_socket, (struct sockaddr *)&remote, &t); } else if (FD_ISSET(tcp_socket, &rfds)) { t = sizeof(tremote); client_socket = accept(tcp_socket, (struct sockaddr *)&tremote, &t); if (client_socket >= 0) { int flag = 1; setsockopt(client_socket, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag)); } } else { // select() man page indicates possibility that there is nothing really there continue; } if (client_socket < 0) { perrorExit("Main Thread. accept"); } else { //struct timeval tv; //tv.tv_sec = 5; /* 30 Secs Timeout */ //setsockopt(client_socket, SOL_SOCKET, SO_RCVTIMEO,(struct timeval *)&tv,sizeof(struct timeval)); syslog(LOG_ERR,"Main Thread. Connected descriptor %d %s\n", client_socket, FD_ISSET(tcp_socket, &rfds) ? "(tcp)" : "(local)"); nClients++; syslog(LOG_ERR,"Main Thread. Spawning worker\n"); pthread_t thr; // initialize data to pass to thread thdata data; data.file_desc = client_socket; if(pthread_create(&thr, &attr, &InstanceThread, (void *) &data)) { MyErrExit("Main Thread. pthread_create"); } } } closelog(); syslog(LOG_ERR,"Main Thread. Closing server\n"); exit(EXIT_SUCCESS); } //http://www.amparo.net/ce155/thread-ex.html void * InstanceThread(void *ptr){ thdata *data = (thdata*) ptr; int thread_socket = data->file_desc; //pthread_t ct = pthread_self(); //printf("Thread %.8x %.8x: Current thread\n", ct); syslog(LOG_ERR,"The ID of this of this thread is: %ld\n", syscall(SYS_gettid/*224*/)); syslog(LOG_ERR,"Worker Thread. Nr of Clients when entered %d", nClients); //vsyslog(LOG_INFO, "Inside Thread %d\n", thread_socket); syslog(LOG_ERR, "Worker Thread. Inside Thread %d\n", thread_socket); char chRequest[BUFSIZE]; char chReply[BUFSIZE]; unsigned short cbReplyBytes; int cbBytesRead, cbWritten; // SJH - messages to/from client must now be prefixed with 2-byte length word (except for ACK 0xAA from client // in response to console or error messages). This allows working over // network with SOCK_STREAM sockets where message boundaries are likely to be broken. Even with Unix // domain sockets, this is safer. unsigned short msglen; unsigned short len; enum { RD_LEN, RD_MSG } state; state = RD_LEN; len = 0; msglen = sizeof(msglen); bool cont = true; while(cont) { cbBytesRead = recv(thread_socket, chRequest + len, msglen - len, 0); if (cbBytesRead <= 0) { if (cbBytesRead < 0){ logError("Worker Thread. recv"); } else { syslog(LOG_ERR,"Worker Thread. received 0 bytes"); } break; } len += cbBytesRead; switch (state) { case RD_LEN: if (len == msglen) { memcpy(&msglen, chRequest, sizeof(msglen)); state = RD_MSG; len = 0; if (msglen > sizeof(chRequest)) { // Too long to possibly fit in buffer. This should not happen unless client bad. syslog(LOG_ERR,"Worker Thread. Message prefix %hu too long", msglen); cont = false; continue; } } continue; case RD_MSG: if (len == msglen) { cbBytesRead = len; msglen = sizeof(msglen); state = RD_LEN; len = 0; break; // from switch and process this msg } continue; } GetAnswerToRequest(chRequest, cbBytesRead, chReply+sizeof(msglen), &cbReplyBytes, thread_socket); memcpy(chReply, &cbReplyBytes, sizeof(msglen)); cbReplyBytes += sizeof(msglen); cbWritten = send(thread_socket, chReply, cbReplyBytes, 0); if (cbWritten < 0 || cbReplyBytes != cbWritten) { if (cbWritten < 0){ logError("Worker Thread. send"); } else { syslog(LOG_ERR,"Worker Thread. %d bytes written != %d bytes sent\n",cbWritten,cbReplyBytes); } break; } } syslog(LOG_ERR,"Worker Thread. Exiting thread %d", thread_socket); // Flush the pipe to allow the client to read the pipe's contents // before disconnecting. Then disconnect the pipe, and close the // handle to this pipe instance. // FlushFileBuffers(thread_socket); // DisconnectNamedPipe(thread_socket); // CloseHandle(thread_socket); if(shutdown(thread_socket,SHUT_RDWR)< 0){ logError("thread socket shutdown"); } close(thread_socket); syslog(LOG_ERR,"Worker Thread. Nr of clients left %d", --nClients); pthread_exit(0); return 0; }
int _tmain(VOID) { DWORD i, dwWait, cbRet, dwErr; BOOL fSuccess; LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe"); // The initial loop creates several instances of a named pipe // along with an event object for each instance. An // overlapped ConnectNamedPipe operation is started for // each instance. for (i = 0; i < INSTANCES; i++) { // Create an event object for this instance. hEvents[i] = CreateEvent( NULL, // default security attribute TRUE, // manual-reset event TRUE, // initial state = signaled NULL); // unnamed event object if (hEvents[i] == NULL) { printf("CreateEvent failed with %d.\n", GetLastError()); return 0; } Pipe[i].oOverlap.hEvent = hEvents[i]; Pipe[i].hPipeInst = CreateNamedPipe( lpszPipename, // pipe name PIPE_ACCESS_DUPLEX | // read/write access FILE_FLAG_OVERLAPPED, // overlapped mode PIPE_TYPE_MESSAGE | // message-type pipe PIPE_READMODE_MESSAGE | // message-read mode PIPE_WAIT, // blocking mode INSTANCES, // number of instances BUFSIZE*sizeof(TCHAR), // output buffer size BUFSIZE*sizeof(TCHAR), // input buffer size PIPE_TIMEOUT, // client time-out NULL); // default security attributes if (Pipe[i].hPipeInst == INVALID_HANDLE_VALUE) { printf("CreateNamedPipe failed with %d.\n", GetLastError()); return 0; } // Call the subroutine to connect to the new client Pipe[i].fPendingIO = ConnectToNewClient( Pipe[i].hPipeInst, &Pipe[i].oOverlap); Pipe[i].dwState = Pipe[i].fPendingIO ? CONNECTING_STATE : // still connecting READING_STATE; // ready to read } while (1) { // Wait for the event object to be signaled, indicating // completion of an overlapped read, write, or // connect operation. dwWait = WaitForMultipleObjects( INSTANCES, // number of event objects hEvents, // array of event objects FALSE, // does not wait for all INFINITE); // waits indefinitely // dwWait shows which pipe completed the operation. i = dwWait - WAIT_OBJECT_0; // determines which pipe if (i < 0 || i > (INSTANCES - 1)) { printf("Index out of range.\n"); return 0; } // Get the result if the operation was pending. if (Pipe[i].fPendingIO) { fSuccess = GetOverlappedResult( Pipe[i].hPipeInst, // handle to pipe &Pipe[i].oOverlap, // OVERLAPPED structure &cbRet, // bytes transferred FALSE); // do not wait switch (Pipe[i].dwState) { // Pending connect operation case CONNECTING_STATE: if (! fSuccess) { printf("Error %d.\n", GetLastError()); return 0; } Pipe[i].dwState = READING_STATE; break; // Pending read operation case READING_STATE: if (! fSuccess || cbRet == 0) { DisconnectAndReconnect(i); continue; } Pipe[i].cbRead = cbRet; Pipe[i].dwState = WRITING_STATE; break; // Pending write operation case WRITING_STATE: if (! fSuccess || cbRet != Pipe[i].cbToWrite) { DisconnectAndReconnect(i); continue; } Pipe[i].dwState = READING_STATE; break; default: { printf("Invalid pipe state.\n"); return 0; } } } // The pipe state determines which operation to do next. switch (Pipe[i].dwState) { // READING_STATE: // The pipe instance is connected to the client // and is ready to read a request from the client. case READING_STATE: fSuccess = ReadFile( Pipe[i].hPipeInst, Pipe[i].chRequest, BUFSIZE*sizeof(TCHAR), &Pipe[i].cbRead, &Pipe[i].oOverlap); // The read operation completed successfully. if (fSuccess && Pipe[i].cbRead != 0) { Pipe[i].fPendingIO = FALSE; Pipe[i].dwState = WRITING_STATE; continue; } // The read operation is still pending. dwErr = GetLastError(); if (! fSuccess && (dwErr == ERROR_IO_PENDING)) { Pipe[i].fPendingIO = TRUE; continue; } // An error occurred; disconnect from the client. DisconnectAndReconnect(i); break; // WRITING_STATE: // The request was successfully read from the client. // Get the reply data and write it to the client. case WRITING_STATE: GetAnswerToRequest(&Pipe[i]); fSuccess = WriteFile( Pipe[i].hPipeInst, Pipe[i].chReply, Pipe[i].cbToWrite, &cbRet, &Pipe[i].oOverlap); // The write operation completed successfully. if (fSuccess && cbRet == Pipe[i].cbToWrite) { Pipe[i].fPendingIO = FALSE; Pipe[i].dwState = READING_STATE; continue; } // The write operation is still pending. dwErr = GetLastError(); if (! fSuccess && (dwErr == ERROR_IO_PENDING)) { Pipe[i].fPendingIO = TRUE; continue; } // An error occurred; disconnect from the client. DisconnectAndReconnect(i); break; default: { printf("Invalid pipe state.\n"); return 0; } } } return 0; }
DWORD WINAPI InstanceThread(LPVOID lpvParam) // This routine is a thread processing function to read from and reply to a client // via the open pipe connection passed from the main loop. Note this allows // the main loop to continue executing, potentially creating more threads of // of this procedure to run concurrently, depending on the number of incoming // client connections. { HANDLE hHeap = GetProcessHeap(); char* pchRequest = (char*) HeapAlloc(hHeap, 0, BUFSIZE * sizeof(char)); char* pchReply = (char*) HeapAlloc(hHeap, 0, BUFSIZE * sizeof(char)); DWORD cbBytesRead = 0, cbReplyBytes = 0, cbWritten = 0; BOOL fSuccess = FALSE; HANDLE hPipe = NULL; // Do some extra error checking since the app will keep running even if this // thread fails. if (lpvParam == NULL) { printf( "\nERROR - Pipe Server Failure:\n"); printf( " InstanceThread got an unexpected NULL value in lpvParam.\n"); printf( " InstanceThread exitting.\n"); if (pchReply != NULL) HeapFree(hHeap, 0, pchReply); if (pchRequest != NULL) HeapFree(hHeap, 0, pchRequest); return (DWORD)-1; } if (pchRequest == NULL) { printf( "\nERROR - Pipe Server Failure:\n"); printf( " InstanceThread got an unexpected NULL heap allocation.\n"); printf( " InstanceThread exitting.\n"); if (pchReply != NULL) HeapFree(hHeap, 0, pchReply); return (DWORD)-1; } if (pchReply == NULL) { printf( "\nERROR - Pipe Server Failure:\n"); printf( " InstanceThread got an unexpected NULL heap allocation.\n"); printf( " InstanceThread exitting.\n"); if (pchRequest != NULL) HeapFree(hHeap, 0, pchRequest); return (DWORD)-1; } // Print verbose messages. In production code, this should be for debugging only. printf("InstanceThread created, receiving and processing messages.\n"); // The thread's parameter is a handle to a pipe object instance. hPipe = (HANDLE) lpvParam; // Loop until done reading while (1) { // Read client requests from the pipe. This simplistic code only allows messages // up to BUFSIZE characters in length. fSuccess = ReadFile( hPipe, // handle to pipe pchRequest, // buffer to receive data BUFSIZE*sizeof(TCHAR), // size of buffer &cbBytesRead, // number of bytes read NULL); // not overlapped I/O if (!fSuccess || cbBytesRead == 0) { if (GetLastError() == ERROR_BROKEN_PIPE) { _tprintf(TEXT("InstanceThread: client disconnected.\n"), GetLastError()); } else { _tprintf(TEXT("InstanceThread ReadFile failed, GLE=%d.\n"), GetLastError()); } break; } // Process the incoming message. GetAnswerToRequest(pchRequest, pchReply, &cbReplyBytes); // Write the reply to the pipe. fSuccess = WriteFile( hPipe, // handle to pipe pchReply, // buffer to write from cbReplyBytes, // number of bytes to write &cbWritten, // number of bytes written NULL); // not overlapped I/O if (!fSuccess || cbReplyBytes != cbWritten) { _tprintf(TEXT("InstanceThread WriteFile failed, GLE=%d.\n"), GetLastError()); break; } } // Flush the pipe to allow the client to read the pipe's contents // before disconnecting. Then disconnect the pipe, and close the // handle to this pipe instance. FlushFileBuffers(hPipe); DisconnectNamedPipe(hPipe); CloseHandle(hPipe); HeapFree(hHeap, 0, pchRequest); HeapFree(hHeap, 0, pchReply); printf("InstanceThread exitting.\n"); terminateSelf(); return 1; }
unsigned int __stdcall InstanceThread(LPVOID lpvParam) { CCrashReportThread crashthread; CTraceToOutputDebugString::Instance()(__FUNCTION__ ": InstanceThread started\n"); TSVNCacheResponse response; DWORD cbBytesRead, cbWritten; CAutoFile hPipe; // The thread's parameter is a handle to a pipe instance. hPipe = std::move((HANDLE) lpvParam); while (bRun) { // Read client requests from the pipe. TSVNCacheRequest request; BOOL fSuccess = ReadFile( hPipe, // handle to pipe &request, // buffer to receive data sizeof(request), // size of buffer &cbBytesRead, // number of bytes read NULL); // not overlapped I/O if (! fSuccess || cbBytesRead == 0) { DisconnectNamedPipe(hPipe); CTraceToOutputDebugString::Instance()(__FUNCTION__ ": Instance thread exited\n"); return 1; } // sanitize request: // * Make sure the string properly 0-terminated // by resetting overlong paths to the empty string // * Set all trailing chars to 0. // * Clear unknown flags // This is more or less paranoia code but maybe something // is feeding garbage into our queue. for (size_t i = MAX_PATH+1; (i > 0) && (request.path[i-1] != 0); --i) request.path[i-1] = 0; size_t pathLength = wcslen (request.path); SecureZeroMemory ( request.path + pathLength , sizeof (request.path) - pathLength * sizeof (TCHAR)); request.flags &= TSVNCACHE_FLAGS_MASK; // process request DWORD responseLength; GetAnswerToRequest(&request, &response, &responseLength); // Write the reply to the pipe. fSuccess = WriteFile( hPipe, // handle to pipe &response, // buffer to write from responseLength, // number of bytes to write &cbWritten, // number of bytes written NULL); // not overlapped I/O if (! fSuccess || responseLength != cbWritten) { DisconnectNamedPipe(hPipe); CTraceToOutputDebugString::Instance()(__FUNCTION__ ": Instance thread exited\n"); return 1; } } // Flush the pipe to allow the client to read the pipe's contents // before disconnecting. Then disconnect the pipe, and close the // handle to this pipe instance. FlushFileBuffers(hPipe); DisconnectNamedPipe(hPipe); CTraceToOutputDebugString::Instance()(__FUNCTION__ ": Instance thread exited\n"); return 0; }
int PipeManager(LPTSTR lpszPipename, void __cdecl GetAnswerToRequest(LPPIPEINST pipe)) { DWORD i, dwWait, cbRet, dwErr; BOOL fSuccess; char pTemp[121]; // The initial loop creates several instances of a named pipe // along with an event object for each instance. An // overlapped ConnectNamedPipe operation is started for // each instance. for (i = 0; i < INSTANCES; i++) { // create named pipe Pipe[i].sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)malloc(SECURITY_DESCRIPTOR_MIN_LENGTH); if (!InitializeSecurityDescriptor(Pipe[i].sa.lpSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION)) { sprintf_s(pTemp, 120, "PipeManager: InitializeSecurityDescriptor failed, error code = %d", GetLastError()); WriteLog(pTemp); return 0; } if (!SetSecurityDescriptorDacl(Pipe[i].sa.lpSecurityDescriptor, TRUE, (PACL)0, FALSE)) { sprintf_s(pTemp, 120, "PipeManager: SetSecurityDescriptorDacl failed, error code = %d", GetLastError()); WriteLog(pTemp); return 0; } Pipe[i].sa.nLength = sizeof Pipe[i].sa; Pipe[i].sa.bInheritHandle = TRUE; // Create an event object for this instance. hEvents[i] = CreateEvent( NULL, // default security attribute TRUE, // manual-reset event TRUE, // initial state = signaled NULL); // unnamed event object if (hEvents[i] == NULL) { sprintf_s(pTemp, 120, "PipeManager: CreateEvent failed with %d.\n", GetLastError()); WriteLog(pTemp); return 0; } Pipe[i].oOverlap.hEvent = hEvents[i]; Pipe[i].hPipeInst = CreateNamedPipe( lpszPipename, // pipe name PIPE_ACCESS_DUPLEX | // read/write access FILE_FLAG_OVERLAPPED, // overlapped mode PIPE_TYPE_MESSAGE | // message-type pipe PIPE_READMODE_MESSAGE | // message-read mode PIPE_WAIT, // blocking mode INSTANCES, // number of instances BUFSIZE*sizeof(TCHAR), // output buffer size BUFSIZE*sizeof(TCHAR), // input buffer size PIPE_TIMEOUT, // client time-out &Pipe[i].sa); // the security attributes if (Pipe[i].hPipeInst == INVALID_HANDLE_VALUE) { sprintf_s(pTemp, 120, "PipeManager: CreateNamedPipe failed with %d.\n", GetLastError()); WriteLog(pTemp); return 0; } // Call the subroutine to connect to the new client Pipe[i].fPendingIO = ConnectToNewClient( Pipe[i].hPipeInst, &Pipe[i].oOverlap); Pipe[i].dwState = Pipe[i].fPendingIO ? CONNECTING_STATE : // still connecting READING_STATE; // ready to read } // Create an event object used to signal that PipeManager shuld exit. hEvents[INSTANCES] = CreateEvent( NULL, // default security attribute TRUE, // manual-reset event FALSE, // initial state = not signaled NULL); // unnamed event object if (hEvents[INSTANCES] == NULL) { sprintf_s(pTemp, 120, "PipeManager: CreateEvent failed with %d.\n", GetLastError()); WriteLog(pTemp); return 0; } while (true) { // Wait for the event object to be signaled, indicating // completion of an overlapped read, write, or // connect operation. dwWait = WaitForMultipleObjects( (INSTANCES +1), // number of event objects hEvents, // array of event objects FALSE, // does not wait for all INFINITE); // waits indefinitely // dwWait shows which pipe completed the operation. i = dwWait - WAIT_OBJECT_0; // determines which pipe // If this was the exit PipeManager event, we exits the loop. if (i == INSTANCES) { break; } // Chack the range if (i < 0 || i > (INSTANCES - 1)) { sprintf_s(pTemp, 120, "PipeManager: Index (%d) out of range. 0..%d\n", i, INSTANCES); WriteLog(pTemp); return 0; } // Get the result if the operation was pending. if (Pipe[i].fPendingIO) { fSuccess = GetOverlappedResult( Pipe[i].hPipeInst, // handle to pipe &Pipe[i].oOverlap, // OVERLAPPED structure &cbRet, // bytes transferred FALSE); // do not wait switch (Pipe[i].dwState) { // Pending connect operation case CONNECTING_STATE: if (! fSuccess) { sprintf_s(pTemp, 120, "PipeManager, Pipe error %d.\n", GetLastError()); WriteLog(pTemp); return 0; } Pipe[i].dwState = READING_STATE; break; // Pending read operation case READING_STATE: if (! fSuccess || cbRet == 0) { DisconnectAndReconnect(i); continue; } Pipe[i].cbRead = cbRet; Pipe[i].dwState = WRITING_STATE; break; // Pending write operation case WRITING_STATE: if (! fSuccess || cbRet != Pipe[i].cbToWrite) { DisconnectAndReconnect(i); continue; } Pipe[i].dwState = READING_STATE; break; default: { sprintf_s(pTemp, 120, "PipeManager: Invalid pipe state.\n"); WriteLog(pTemp); return 0; } } } // The pipe state determines which operation to do next. switch (Pipe[i].dwState) { // READING_STATE: // The pipe instance is connected to the client // and is ready to read a request from the client. case READING_STATE: fSuccess = ReadFile( Pipe[i].hPipeInst, Pipe[i].chRequest, BUFSIZE*sizeof(TCHAR), &Pipe[i].cbRead, &Pipe[i].oOverlap); // The read operation completed successfully. if (fSuccess && Pipe[i].cbRead != 0) { Pipe[i].fPendingIO = FALSE; Pipe[i].dwState = WRITING_STATE; continue; } // The read operation is still pending. dwErr = GetLastError(); if (! fSuccess && (dwErr == ERROR_IO_PENDING)) { Pipe[i].fPendingIO = TRUE; continue; } // An error occurred; disconnect from the client. DisconnectAndReconnect(i); break; // WRITING_STATE: // The request was successfully read from the client. // Get the reply data and write it to the client. case WRITING_STATE: GetAnswerToRequest(&Pipe[i]); //make it a valid string. ++Pipe[i].cbToWrite; Pipe[i].chReply[Pipe[i].cbToWrite] = '\0'; fSuccess = WriteFile( Pipe[i].hPipeInst, Pipe[i].chReply, Pipe[i].cbToWrite, &cbRet, &Pipe[i].oOverlap); // The write operation completed successfully. if (fSuccess && cbRet == Pipe[i].cbToWrite) { Pipe[i].fPendingIO = FALSE; Pipe[i].dwState = READING_STATE; Pipe[i].cbToWrite = 0; //All data is writen continue; } // The write operation is still pending. dwErr = GetLastError(); if (! fSuccess && (dwErr == ERROR_IO_PENDING)) { Pipe[i].fPendingIO = TRUE; continue; } else { sprintf_s(pTemp, 120, "PipeManager: WRITING_STATE error 0x%x.\n", dwErr); WriteLog(pTemp); } // An error occurred; disconnect from the client. DisconnectAndReconnect(i); break; default: { sprintf_s(pTemp, 120, "PipeManager: Invalid pipe state.\n"); WriteLog(pTemp); return 0; } } } return 0; }