BOOL CreateAndConnectInstance(LPOVERLAPPED lpoOverlap) { if (!(hdPipe = CreateNamedPipe(pipeName,PIPE_ACCESS_DUPLEX |FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,BUFSIZE*sizeof(TCHAR),BUFSIZE*sizeof(TCHAR), PIPE_TIMEOUT,NULL))) return 0*(printf("CreateNamedPipe failed with %ld.\n", GetLastError())); return ConnectToNewClient(hdPipe, lpoOverlap); }
VOID Server::DisconnectAndReconnect(DWORD pipe_number) { // Disconnect the pipe instance. if (! DisconnectNamedPipe(Pipe_[pipe_number].hPipeInst)) { // TODO: Убрать (заменить) логирование. printf("DisconnectNamedPipe failed with %d.\n", GetLastError()); Pipe_[pipe_number].dwState = STATE::errored; } Pipe_[pipe_number].dwState = STATE::undefined; // Call a subroutine to connect to the new client. ConnectToNewClient(pipe_number); }
VOID DisconnectAndReconnect(DWORD i) { // Disconnect the pipe instance. if (! DisconnectNamedPipe(Pipe[i].hPipeInst) ) { printf("DisconnectNamedPipe failed with %d.\n", GetLastError()); } // Call a 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 }
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; } } } }
DWORD Server::Start_Helper(VOID) { // Предотвращение повторного запуска. hServerIsUp_Mutex = CreateMutexA(NULL, FALSE, SERVER_IS_WORKING_MUTEX_GUID); if ((hServerIsUp_Mutex == NULL) || (GetLastError() == ERROR_ALREADY_EXISTS)) { CLOSE_HANDLE(hServerIsUp_Mutex); return ERROR_ALREADY_EXISTS; } DWORD i; // The initial loop creates several S_PIPES_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 < S_PIPES_INSTANCES; i++) { // Create an event object for this instance. CREATE_EVENT__SIGNALED(hPipes_Events_[i], t_string(TEXT("!!!!!_") + t_to_string(i)).c_str()); if (hPipes_Events_[i] == NULL) { return GetLastError(); } Pipe_[i].oOverlap.hEvent = hPipes_Events_[i]; Pipe_[i].hPipeInst = CreateNamedPipe( PipeName_.c_str(), // 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 S_PIPES_INSTANCES, // number of S_PIPES_INSTANCES BUFSIZE*sizeof(TCHAR), // output buffer size BUFSIZE*sizeof(TCHAR), // input buffer size S_PIPE_TIMEOUT, // client time-out NULL // default security attributes ); if (Pipe_[i].hPipeInst == INVALID_HANDLE_VALUE) { return GetLastError(); } // Call the subroutine to connect to the new client if (DWORD connect_to_new_client_result = ConnectToNewClient(i) != ERROR_SUCCESS) { return connect_to_new_client_result; } } // stop-event CREATE_EVENT__UNSIGNALED(hPipes_Events_[S_EVENT_STOP], TEXT("")); // stop-server-event CREATE_EVENT__UNSIGNALED(hPipes_Events_[S_EVENT_STOP_SERVER], TEXT(STOP_SERVER_EVENT_GUID)); for (DWORD counter = 0; counter < S_EVENTS_; counter++ ) { CREATE_EVENT__UNSIGNALED(hS_Events_[counter], TEXT("")); } //TODO_URGENT: инициализировать S_EVENTS_ InitializeCriticalSection(&csReadPipe_); for (DWORD counter = 0; counter < S_PIPES_INSTANCES; counter++) { InitializeCriticalSection(&Pipe_[counter].csWritePipe); } StartMainThread(); eState_ = STATE::started; return ERROR_SUCCESS; }
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; }