Beispiel #1
0
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;
}
Beispiel #2
0
CNktDvTransportEngine::CConnection* CNktDvTransportEngine::FindConnectionAndAddRef(__in DWORD dwPid)
{
  TNktLnkLst<CConnection>::Iterator it;
  CConnection *lpConn;

  //find process
  for (lpConn=it.Begin(cConnList); lpConn!=NULL; lpConn=it.Next())
  {
    if (dwPid == lpConn->dwPid)
    {
      lpConn->AddRef();
      return lpConn;
    }
  }
  return NULL;
}
Beispiel #3
0
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;
}
Beispiel #4
0
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;
}