VOID Server::MainThread_Helper(VOID) { DWORD dwPipeIndex; DWORD dwWait; DWORD dwRet; BOOL bSuccess; while (1) { // Wait for the event object to be signaled, indicating // completion of an overlapped read, write, or // connect operation. _tprintf(TEXT("ReadThread_Helper: Before WaitForMultipleObjects\n")); dwWait = WaitForMultipleObjects ( S_PIPES_EVENTS, // number of event objects hPipes_Events_, // array of event objects FALSE, // does not wait for all INFINITE // waits indefinitely ); // TODO: Убрать (заменить) логирование. _tprintf(TEXT("ReadThread_Helper: After WaitForMultipleObjects\n")); dwPipeIndex = dwWait - WAIT_OBJECT_0; // determines which pipe if (dwPipeIndex < 0 || dwPipeIndex > (S_PIPES_EVENTS - 2)) // (S_PIPES_EVENTS - 2)б т.к. последний евент - указание завершить рботу. { // TODO: Убрать (заменить) логирование. _tprintf(TEXT("ReadThread_Helper: Index out of range.\n")); //TODO_URGENT: возвращать значение. Кому??? //return ERROR_INVALID_INDEX; return; } ResetEvent(hPipes_Events_[dwPipeIndex]); if (Pipe_[dwPipeIndex].dwState == STATE::connected) { bSuccess = GetOverlappedResult ( Pipe_[dwPipeIndex].hPipeInst, // handle to pipe &Pipe_[dwPipeIndex].oOverlap, // OVERLAPPED structure &dwRet, // bytes transferred FALSE // do not wait ); if (bSuccess) { Pipe_[dwPipeIndex].cbRead = dwRet; // TODO: Если размер S_GlobalReadBuffer_ достиг максимума, // ждем операцию чтения, в буфер не читаем. // Сохранить прочитанное (если оно есть) и продолжить чтение. if (Pipe_[dwPipeIndex].cbRead != 0) { EnterCriticalSection(&csReadPipe_); GlobalReadBuffer_.push(std::pair<DWORD, t_string>(dwPipeIndex, Pipe_[dwPipeIndex].chRequest)); _tprintf(TEXT("\nAfter PUSH: Buffer: #%5d %s\n"), GlobalReadBuffer_.front().first, GlobalReadBuffer_.front().second.c_str()); _tprintf(TEXT( "After PUSH: Pipe: #%5d %s\n"), dwPipeIndex, ((t_string)Pipe_[dwPipeIndex].chRequest).c_str()); //if (S_GlobalReadBuffer_.front().second != Pipe_[dwPipeIndex].chRequest) //{ // Sleep(1); //} // Сигнализируем о том, что произошло чтение. SetEvent(hS_Events_[S_EVENT_READING_FINISHED]); LeaveCriticalSection(&csReadPipe_); } else { // TODO: Обработать случай, если cbRead == 0; printf("cbRead = 0\n"); } } else { //// TODO: Убрать (заменить) логирование. //_tprintf(TEXT("ReadThread_Helper: Error %d.\n"), GetLastError()); //return; // TODO: Убрать (заменить) логирование. _tprintf(TEXT("ReadThread_Helper: Error %d.\n"), GetLastError()); DisconnectAndReconnect(dwPipeIndex); continue; } } else { bSuccess = GetOverlappedResult ( Pipe_[dwPipeIndex].hPipeInst, // handle to pipe &Pipe_[dwPipeIndex].oOverlap, // OVERLAPPED structure &dwRet, // bytes transferred FALSE // do not wait ); if (!bSuccess) { Sleep(1); } Pipe_[dwPipeIndex].dwState = STATE::connected; } bSuccess = ReadFile ( Pipe_[dwPipeIndex].hPipeInst, // pipe handle Pipe_[dwPipeIndex].chRequest, // buffer to receive reply BUFSIZE*sizeof(TCHAR), // size of buffer &Pipe_[dwPipeIndex].cbRead, // number of bytes read &Pipe_[dwPipeIndex].oOverlap // overlapped ); } }
void NamedPipeServer::run() { DWORD i, dwWait, cbRet, dwErr; BOOL fSuccess; QByteArray response; std::string s; DWORD r = scrobSubPipeName( &s ); if (r != 0) throw std::runtime_error( formatWin32Error( r ) ); QString const name = QString::fromStdString( s ); // 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; } Pipe[i].oOverlap.hEvent = hEvents[i]; Pipe[i].hPipeInst = CreateNamedPipe( (const wchar_t *)name.utf16(), // 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; } // 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; } // 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; } 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; } } } // 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: response = emit lineReady( QString::fromUtf8( (char*)Pipe[i].chRequest, Pipe[i].cbRead ) ).toUtf8(); StringCchCopy( Pipe[i].chReply, BUFSIZE, (LPCTSTR)response.data() ); Pipe[i].cbToWrite = response.size(); 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; } } } }
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; }