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; }
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; }