HRESULT CNktDvTransportEngine::SendMsg(__in DWORD dwPid, __inout NKT_DV_TMSG_COMMON *lpMsg, __in SIZE_T nMsgSize) { CNktDvShutdownAutoLock cSdLock(&cShutdownMtx); CConnectionAutoRef cConnAutoRef; CConnection *lpConn; CNktDvTransportOverlapped *lpOvr; HRESULT hRes; if (lpMsg == NULL) return E_POINTER; if (nMsgSize < sizeof(NKT_DV_TMSG_COMMON) || nMsgSize > NKT_DV_TRANSPORT_MAX_DATA_SIZE) return E_INVALIDARG; { CNktDvAutoCancellableFastMutex cLock(this, &cShutdownMtx); if (cLock.IsLockHeld() == FALSE || cShutdownMtx.IsShuttingDown() != FALSE) return NKT_DVERR_Cancelled; if (cShutdownMtx.IsSystemActive() == FALSE) return E_FAIL; //not initialized //find connection cConnAutoRef.Attach(lpConn = FindConnectionAndAddRef(dwPid), FALSE); if (lpConn == NULL) return NKT_DVERR_NotFound; NKT_DEBUGPRINTLNA(Nektra::dlTransport, ("%lu) TransportEngine[SendMsg]: Pid=%lu, Code=%lu, Id=%lu", ::GetTickCount(), dwPid, lpMsg->dwMsgCode & (~NKT_DV_TMSG_CODE_CALLBACK), lpMsg->dwMsgId & (~NKT_DV_TMSG_ID_CALLBACK))); } { CNktAutoFastMutex cConnAutoLock(lpConn); if (lpConn->nState != XSTATE_Connected) return E_FAIL; //not initialized //get a free buffer lpOvr = lpConn->GetBuffer(); if (lpOvr == NULL) return E_OUTOFMEMORY; //fill buffer nktMemCopy(lpOvr->sMsg.aBuf, lpMsg, nMsgSize); //do write prepare lpOvr->dwType = XTYPE_WriteRequest; lpOvr->nOrder = NktInterlockedIncrement(&(lpConn->nNextWriteOrder)); lpOvr->dwWrittenBytes = (DWORD)nMsgSize; lpConn->AddBufferToRwList(lpOvr); hRes = S_OK; if (::PostQueuedCompletionStatus(lpConn->hIocpCopy, 0, (ULONG_PTR)lpConn, &(lpOvr->sOvr)) == FALSE) hRes = NKT_HRESULT_FROM_LASTERROR(); } if (FAILED(hRes)) { lpConn->FreeBuffer(lpOvr); return hRes; } //done lpConn->AddRef(); NKT_DEBUGPRINTLNA(Nektra::dlTransport, ("%lu) TransportEngine[SendMsg]: Pid=%lu, Ovr=%IXh", ::GetTickCount(), dwPid, lpOvr)); return S_OK; }
VOID CNktDvTransportEngine::WorkerThreadProc(__in SIZE_T nIndex) { CConnection *lpConn; LPOVERLAPPED _lpOvr; CNktDvTransportOverlapped *lpOvr; HRESULT hRes; HANDLE hEventCopy; BOOL b, bReadPending; DWORD dwNumberOfBytes, dwWritten; lpCallback->TEC_WorkerThreadStarted(); //---- for (;;) { lpConn = NULL; lpOvr = NULL; b = ::GetQueuedCompletionStatus(hIOCP, &dwNumberOfBytes, (PULONG_PTR)&lpConn, &_lpOvr, INFINITE); if (lpConn == NULL) { break; //a completion key of 0 is posted to the iocp to request us to shut down... } hRes = (b != FALSE) ? S_OK : NKT_HRESULT_FROM_LASTERROR(); { CConnectionAutoRef cConnAutoRef(lpConn); lpOvr = CNktDvTransportOverlapped::ClassFromOverlapped(_lpOvr); bReadPending = FALSE; if (_lpOvr != NULL) { switch (lpOvr->dwType) { case XTYPE_Read: lpOvr->dwReadedBytes = dwNumberOfBytes; //add to read queue if (SUCCEEDED(hRes)) { lpConn->AddBufferInSortedReadedQueue(lpOvr); hRes = lpConn->SendReadPacket(); //setup read-ahead } NKT_DEBUGPRINTLNA(Nektra::dlTransport, ("%lu) TransportEngine[ReadCompleted]: Ovr=%IXh, " "hRes=%08X", ::GetTickCount(), lpOvr, hRes)); bReadPending = TRUE; break; case XTYPE_WriteRequest: { CNktAutoFastMutex cLock(lpConn); if (SUCCEEDED(hRes)) lpConn->AddBufferInSortedToWriteQueue(lpOvr); while (SUCCEEDED(hRes) && cShutdownMtx.IsSystemActive() != FALSE && cShutdownMtx.IsShuttingDown() == FALSE) { //get next sequenced block to write lpOvr = lpConn->GetBufferFromSortedToWriteQueue(lpConn->nNextWriteOrderToProcess); if (lpOvr == NULL) break; if (lpOvr->dwType != XTYPE_Discard) { lpConn->AddBufferToRwList(lpOvr); //do real write lpOvr->dwType = XTYPE_Write; if (lpOvr->sMsg.sMsgCommon.hProcessedEvent != NULL) { if (::DuplicateHandle(::GetCurrentProcess(), (HANDLE)(lpOvr->sMsg.sMsgCommon.hProcessedEvent), lpConn->hAgentProc, &hEventCopy, 0, FALSE, DUPLICATE_SAME_ACCESS) != FALSE) lpOvr->sMsg.sMsgCommon.hProcessedEvent = NKT_PTR_2_ULONGLONG(hEventCopy); else hRes = NKT_HRESULT_FROM_LASTERROR(); } if (SUCCEEDED(hRes)) { if (::WriteFile(lpConn->hPipe, &(lpOvr->sMsg), lpOvr->dwWrittenBytes, &dwWritten, &(lpOvr->sOvr)) == FALSE) { hRes = NKT_HRESULT_FROM_LASTERROR(); if (hRes == NKT_HRESULT_FROM_WIN32(ERROR_IO_PENDING)) hRes = S_OK; } } if (SUCCEEDED(hRes)) lpConn->AddRef(); else lpConn->FreeBuffer(lpOvr); NKT_DEBUGPRINTLNA(Nektra::dlTransport, ("%lu) TransportEngine[Write]: Ovr=%IXh, " "hRes=%08X", ::GetTickCount(), lpOvr, hRes)); } else { lpConn->FreeBuffer(lpOvr); } NktInterlockedIncrement(&(lpConn->nNextWriteOrderToProcess)); } } break; case XTYPE_Write: if (SUCCEEDED(hRes) && lpOvr->dwWrittenBytes != dwNumberOfBytes) hRes = NKT_HRESULT_FROM_WIN32(ERROR_WRITE_FAULT); NKT_DEBUGPRINTLNA(Nektra::dlTransport, ("%lu) TransportEngine[WriteCompleted]: Ovr=%IXh, " "hRes=%08X", ::GetTickCount(), lpOvr, hRes)); lpConn->FreeBuffer(lpOvr); break; case XTYPE_Discard: lpConn->FreeBuffer(lpOvr); break; default: NKT_ASSERT(FALSE); lpConn->FreeBuffer(lpOvr); break; } } else { hRes = NKT_DVERR_InvalidTransportData; } if (SUCCEEDED(hRes) && bReadPending != FALSE) { while (SUCCEEDED(hRes) && cShutdownMtx.IsSystemActive() != FALSE && cShutdownMtx.IsShuttingDown() == FALSE) { //get next sequenced block readed lpOvr = lpConn->GetBufferFromSortedReadedQueue(lpConn->nNextReadOrderToProcess); if (lpOvr == NULL) break; hRes = DispatchReadedMessage(lpConn, lpOvr); NktInterlockedIncrement(&(lpConn->nNextReadOrderToProcess)); } } if (FAILED(hRes)) { if (cShutdownMtx.IsSystemActive() != FALSE && cShutdownMtx.IsShuttingDown() == FALSE) lpCallback->TEC_OnTransportError(this, lpConn->dwPid, hRes); DisconnectAgent(lpConn->dwPid); } lpConn->Release(); } } //---- lpCallback->TEC_WorkerThreadEnded(); return; }
HRESULT CNktDvTransportEngine::SendBigPacketMsg(__out LPDWORD lpdwBigPacketId, __in DWORD dwPid, __in LPCVOID lpData, __in SIZE_T nDataSize) { CNktDvShutdownAutoLock cSdLock(&cShutdownMtx); CConnectionAutoRef cConnAutoRef; CConnection *lpConn; CNktDvTransportOverlapped *lpOvr; NKT_DV_TMSG_BIGDATA *lpMsgBd; HRESULT hRes; SIZE_T nThisBlockLen; DWORD dwOrderNo; const BYTE *s; if (lpdwBigPacketId == NULL) return E_POINTER; if (nDataSize < 1) return E_INVALIDARG; { CNktDvAutoCancellableFastMutex cLock(this, &cShutdownMtx); if (cLock.IsLockHeld() == FALSE || cShutdownMtx.IsShuttingDown() != FALSE) return NKT_DVERR_Cancelled; if (cShutdownMtx.IsSystemActive() == FALSE) return E_FAIL; //not initialized //find connection cConnAutoRef.Attach(lpConn = FindConnectionAndAddRef(dwPid), FALSE); if (lpConn == NULL) return NKT_DVERR_NotFound; NKT_DEBUGPRINTLNA(Nektra::dlTransport, ("%lu) TransportEngine[SendBigPacketMsg]: Pid=%lu, Size=%Iu", ::GetTickCount(), dwPid, nDataSize)); } //process the message { CNktAutoFastMutex cConnAutoLock(lpConn); if (lpConn->nState != XSTATE_Connected) return E_FAIL; //not initialized } //NOTE: Ensure that thread sending big packets is the same that later will send // the real message containing the packet id to avoid writing problems s = (const BYTE *)lpData; *lpdwBigPacketId = lpConn->cBigData->GetNextBuildId(); for (dwOrderNo=1; nDataSize>0; dwOrderNo++) { //get a free buffer lpOvr = lpConn->GetBuffer(); if (lpOvr == NULL) return E_OUTOFMEMORY; //build message with data lpMsgBd = (NKT_DV_TMSG_BIGDATA*)&(lpOvr->sMsg.sMsgCommon); hRes = NktDvTransportInitMessage(lpMsgBd, NKT_DV_TMSG_CODE_BigData, GetNextMsgId(), NULL, NULL); if (FAILED(hRes)) { lpConn->FreeBuffer(lpOvr); return hRes; } lpMsgBd->sBdHeader.dwThreadId = 0; lpMsgBd->sBdHeader.dwId = *lpdwBigPacketId; lpMsgBd->sBdHeader.dwOrderNo = dwOrderNo; if ((nThisBlockLen=nDataSize) > sizeof(lpMsgBd->aData)) nThisBlockLen = sizeof(lpMsgBd->aData); lpMsgBd->sBdHeader.dwDataLen = (DWORD)nThisBlockLen; nktMemCopy(lpMsgBd->aData, s, nThisBlockLen); //do write prepare lpOvr->dwType = XTYPE_WriteRequest; lpOvr->nOrder = NktInterlockedIncrement(&(lpConn->nNextWriteOrder)); lpOvr->dwWrittenBytes = (DWORD)(sizeof(lpOvr->sMsg.sMsgCommon) + sizeof(lpMsgBd->sBdHeader) + nThisBlockLen); lpConn->AddBufferToRwList(lpOvr); if (::PostQueuedCompletionStatus(lpConn->hIocpCopy, 0, (ULONG_PTR)lpConn, &(lpOvr->sOvr)) == FALSE) { hRes = NKT_HRESULT_FROM_LASTERROR(); lpConn->FreeBuffer(lpOvr); return hRes; } //done lpConn->AddRef(); //advance source data s += nThisBlockLen; nDataSize -= nThisBlockLen; NKT_DEBUGPRINTLNA(Nektra::dlTransport, ("%lu) TransportEngine[SendBigPacketMsg]: Pid=%lu, Ovr=%IXh, " "Id=%lu, Order=%lu, Size=%lu", ::GetTickCount(), dwPid, lpOvr, *lpdwBigPacketId, dwOrderNo, (DWORD)nThisBlockLen)); } NKT_DEBUGPRINTLNA(Nektra::dlTransport, ("%lu) TransportEngine[SendBigPacketMsg]: Pid=%lu", ::GetTickCount(), dwPid)); return S_OK; }