Example #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;
}
Example #2
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;
}