QString QAutoGenDialog::GetFileParameter(const QString & strParam, const QString & strFilename, unsigned int iVehicle)
{
	std::map<QString, std::vector<QString> >::iterator iterFileData = m_mapFileData.find(strFilename);
	if (iterFileData == m_mapFileData.end())
	{
		QFile fileData(strFilename);
		if (fileData.exists() && fileData.open(QIODevice::ReadOnly | QIODevice::Text))
		{
			Q3TextStream streamData(&fileData);
			QString strLine;
			iterFileData = m_mapFileData.insert(std::pair<QString, std::vector<QString> >(strFilename, std::vector<QString>())).first;
			while (!(strLine = streamData.readLine()).isNull())
			{
				strLine = strLine.stripWhiteSpace();
				if (strLine.isEmpty())
					continue;
				iterFileData->second.push_back(strLine);
			}
			fileData.close();
		}
	}
	if (iterFileData == m_mapFileData.end())
		return "";
	else
		return iterFileData->second[iVehicle % iterFileData->second.size()];
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
bool RifEclipseUserDataParserTools::isFixedWidthHeader(const std::string& lines)
{
    std::stringstream streamData(lines);

    std::vector<std::string> headerLines = RifEclipseUserDataParserTools::findValidHeaderLines(streamData);
    if (headerLines.size() > 1)
    {
        std::vector<size_t> firstLine = RifEclipseUserDataParserTools::columnIndexForWords(headerLines[0]);

        for (auto line : headerLines)
        {
            std::vector<size_t> columnIndicesForLine = RifEclipseUserDataParserTools::columnIndexForWords(line);
            for (auto index : columnIndicesForLine)
            {
                if (std::find(firstLine.begin(), firstLine.end(), index) == firstLine.end())
                {
                    return false;
                }
            }
        }

        return true;
    }

    return false;
}
示例#3
0
BOOL CFileStreamParser::OpenFile(LPCTSTR szFile)
{
	CloseFile();

	m_hFileStream = ::CreateFile(szFile,
		GENERIC_READ,
		FILE_SHARE_READ,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);

	if (m_hFileStream != INVALID_HANDLE_VALUE)
	{
		_tcscpy(m_szFilename, szFile);

		std::auto_ptr<BYTE> streamData(new BYTE[ MAX_FRAME_LENGTH ]);
		memset(streamData.get(), 0, MAX_FRAME_LENGTH);
		FRAME_HEADER fh;
		INT nRet = GetOneFrame(streamData.get(), &fh);
		if (nRet <= 0)
		{
			nRet = GetOneFrame(streamData.get(), &fh);
			if ( nRet <= 0)
			{
				m_nFirstFrameTime = 0;
				m_nLastFrameTime = 0;
				return TRUE;
			}
		}
		m_nFirstFrameTime = htonl(fh.FrameTime);
		dwFileSize = GetFileSize();
		DWORD dwMovePos = dwFileSize-100;
		DWORD dwCurPos = 0;
		if (dwMovePos > 0 && INVALID_SET_FILE_POINTER != (dwCurPos = ::SetFilePointer(m_hFileStream, dwMovePos, 0, FILE_BEGIN)))
		{
			nRet = GetOneFrame(streamData.get(), &fh);
			while((nRet <= 0 && (dwMovePos - 100)) > 0 ||
				(nRet > 0 && (fh.FrameRate != 25 || fh.FrameType == 10)))
			{
				dwMovePos -= 100;
				if (INVALID_SET_FILE_POINTER == (dwCurPos = ::SetFilePointer(m_hFileStream, dwMovePos, 0, FILE_BEGIN)))
					break;
				nRet = GetOneFrame(streamData.get(), &fh);
			}
			if (nRet > 0)
			{
				m_nLastFrameTime = htonl(fh.FrameTime);
			}
		}
		::SetFilePointer(m_hFileStream, 0, 0, FILE_BEGIN);
		return TRUE;
	}
	return FALSE;
}
示例#4
0
static void TestPDFStream(skiatest::Reporter* reporter) {
    char streamBytes[] = "Test\nFoo\tBar";
    SkAutoTUnref<SkMemoryStream> streamData(new SkMemoryStream(
        streamBytes, strlen(streamBytes), true));
    SkAutoTUnref<SkPDFStream> stream(new SkPDFStream(streamData.get()));
    SimpleCheckObjectOutput(
        reporter, stream.get(),
        "<</Length 12\n>> stream\nTest\nFoo\tBar\nendstream");
    stream->insert("Attribute", new SkPDFInt(42))->unref();
    SimpleCheckObjectOutput(reporter, stream.get(),
                            "<</Length 12\n/Attribute 42\n>> stream\n"
                                "Test\nFoo\tBar\nendstream");

    if (SkFlate::HaveFlate()) {
        char streamBytes2[] = "This is a longer string, so that compression "
                              "can do something with it. With shorter strings, "
                              "the short circuit logic cuts in and we end up "
                              "with an uncompressed string.";
        SkAutoDataUnref streamData2(SkData::NewWithCopy(streamBytes2,
                                                        strlen(streamBytes2)));
        SkAutoTUnref<SkPDFStream> stream(new SkPDFStream(streamData2.get()));

        SkDynamicMemoryWStream compressedByteStream;
        SkFlate::Deflate(streamData2.get(), &compressedByteStream);
        SkAutoDataUnref compressedData(compressedByteStream.copyToData());

        // Check first without compression.
        SkDynamicMemoryWStream expectedResult1;
        expectedResult1.writeText("<</Length 167\n>> stream\n");
        expectedResult1.writeText(streamBytes2);
        expectedResult1.writeText("\nendstream");
        SkAutoDataUnref expectedResultData1(expectedResult1.copyToData());
        CheckObjectOutput(reporter, stream.get(),
                          (const char*) expectedResultData1->data(),
                          expectedResultData1->size(), true, false);

        // Then again with compression.
        SkDynamicMemoryWStream expectedResult2;
        expectedResult2.writeText("<</Filter /FlateDecode\n/Length 116\n"
                                 ">> stream\n");
        expectedResult2.write(compressedData->data(), compressedData->size());
        expectedResult2.writeText("\nendstream");
        SkAutoDataUnref expectedResultData2(expectedResult2.copyToData());
        CheckObjectOutput(reporter, stream.get(),
                          (const char*) expectedResultData2->data(),
                          expectedResultData2->size(), true, true);
    }
}
HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReadFileFragment(
    void const** fragmentStart,
    UINT64 fileOffset,
    UINT64 fragmentSize,
    void** fragmentContext)
{
    // The loader is responsible for doing a bounds check.
    UINT64 fileSize;
    this->GetFileSize(&fileSize);
    if (fileOffset > fileSize || fragmentSize > fileSize - fileOffset) {
        *fragmentStart = NULL;
        *fragmentContext = NULL;
        return E_FAIL;
    }

    if (!SkTFitsIn<size_t>(fileOffset + fragmentSize)) {
        return E_FAIL;
    }

    const void* data = fStream->getMemoryBase();
    if (NULL != data) {
        *fragmentStart = static_cast<BYTE const*>(data) + static_cast<size_t>(fileOffset);
        *fragmentContext = NULL;

    } else {
        //May be called from multiple threads.
        SkAutoMutexAcquire ama(fStreamMutex);

        *fragmentStart = NULL;
        *fragmentContext = NULL;

        if (!fStream->rewind()) {
            return E_FAIL;
        }
        if (fStream->skip(static_cast<size_t>(fileOffset)) != fileOffset) {
            return E_FAIL;
        }
        SkAutoTMalloc<uint8_t> streamData(static_cast<size_t>(fragmentSize));
        if (fStream->read(streamData.get(), static_cast<size_t>(fragmentSize)) != fragmentSize) {
            return E_FAIL;
        }

        *fragmentStart = streamData.get();
        *fragmentContext = streamData.detach();
    }
    return S_OK;
}
示例#6
0
static void TestPDFStream(skiatest::Reporter* reporter) {
    char streamBytes[] = "Test\nFoo\tBar";
    SkAutoTDelete<SkMemoryStream> streamData(new SkMemoryStream(
        streamBytes, strlen(streamBytes), true));
    SkAutoTUnref<SkPDFStream> stream(new SkPDFStream(streamData.get()));
    ASSERT_EMIT_EQ(reporter,
                   *stream,
                   "<</Length 12>> stream\nTest\nFoo\tBar\nendstream");
    stream->insertInt("Attribute", 42);
    ASSERT_EMIT_EQ(reporter,
                   *stream,
                   "<</Length 12\n/Attribute 42>> stream\n"
                   "Test\nFoo\tBar\nendstream");

    {
        char streamBytes2[] = "This is a longer string, so that compression "
                              "can do something with it. With shorter strings, "
                              "the short circuit logic cuts in and we end up "
                              "with an uncompressed string.";
        SkAutoDataUnref streamData2(SkData::NewWithCopy(streamBytes2,
                                                        strlen(streamBytes2)));
        SkAutoTUnref<SkPDFStream> stream(new SkPDFStream(streamData2.get()));

        SkDynamicMemoryWStream compressedByteStream;
        SkDeflateWStream deflateWStream(&compressedByteStream);
        deflateWStream.write(streamBytes2, strlen(streamBytes2));
        deflateWStream.finalize();

        SkDynamicMemoryWStream expected;
        expected.writeText("<</Filter /FlateDecode\n/Length 116>> stream\n");
        compressedByteStream.writeToStream(&expected);
        compressedByteStream.reset();
        expected.writeText("\nendstream");
        SkAutoDataUnref expectedResultData2(expected.copyToData());
        SkString result = emit_to_string(*stream);
        ASSERT_EQL(reporter,
                   result,
                   (const char*)expectedResultData2->data(),
                   expectedResultData2->size());
    }
}
示例#7
0
/** Activates XMLterm and instantiates LineTerm;
 * called at the the end of Init page loading.
 */
NS_IMETHODIMP mozXMLTerminal::Activate(void)
{
  nsresult result = NS_OK;

#if 0
  // TEMPORARY: Testing mozIXMLTermStream
  nsAutoString streamData(  "<HTML><HEAD><TITLE>Stream Title</TITLE>"
                            "<SCRIPT language='JavaScript'>"
                            "function clik(){ dump('click\\n');return(false);}"
                            "</SCRIPT></HEAD>"
                            "<BODY><B>Stream Body "
                            "<SPAN STYLE='color: blue' onClick='return clik();'>Clik</SPAN></B><BR>"
"<TABLE WIDTH=720><TR><TD WIDTH=700 BGCOLOR=maroon>&nbsp;</TABLE>"
                            "<BR>ABCD<BR>EFGH<BR>JKLM<BR>"
                            "</BODY></HTML>" );

  nsCOMPtr<mozIXMLTermStream> stream;
  result = NS_NewXMLTermStream(getter_AddRefs(stream));
  if (NS_FAILED(result)) {
    XMLT_ERROR("mozXMLTerminal::Activate: Failed to create stream\n");
    return result;
  }

  nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocShell);
  if (!docShell)
    return NS_ERROR_FAILURE;

  nsCOMPtr<nsIDOMWindowInternal> outerDOMWindow;
  result = mozXMLTermUtils::ConvertDocShellToDOMWindow(docShell,
                                              getter_AddRefs(outerDOMWindow));

  if (NS_FAILED(result) || !outerDOMWindow) {
    XMLT_ERROR("mozXMLTerminal::Activate: Failed to convert docshell\n");
    return NS_ERROR_FAILURE;
  }

  result = stream->Open(outerDOMWindow, "iframet", "chrome://dummy",
                        "text/html", 800);
  if (NS_FAILED(result)) {
    XMLT_ERROR("mozXMLTerminal::Activate: Failed to open stream\n");
    return result;
  }

  result = stream->Write(streamData.get());
  if (NS_FAILED(result)) {
    XMLT_ERROR("mozXMLTerminal::Activate: Failed to write to stream\n");
    return result;
  }

  result = stream->Close();
  if (NS_FAILED(result)) {
    XMLT_ERROR("mozXMLTerminal::Activate: Failed to close stream\n");
    return result;
  }

#endif

  XMLT_LOG(mozXMLTerminal::Activate,20,("\n"));

  if (!mInitialized)
    return NS_ERROR_NOT_INITIALIZED;

  PR_ASSERT(mDocShell != nsnull);

  if ((mDOMDocument != nsnull) || (mPresShell != nsnull))
    return NS_ERROR_FAILURE;

  nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocShell);
  if (!docShell)
    return NS_ERROR_FAILURE;

  // Get reference to presentation shell
  nsCOMPtr<nsPresContext> presContext;
  result = docShell->GetPresContext(getter_AddRefs(presContext));
  if (NS_FAILED(result) || !presContext)
    return NS_ERROR_FAILURE;

  nsCOMPtr<nsIPresShell> presShell;
  result = docShell->GetPresShell(getter_AddRefs(presShell));
  if (NS_FAILED(result) || !presShell)
    return NS_ERROR_FAILURE;

  // Get reference to DOMDocument
  nsIDocument *document = presShell->GetDocument();
  if (!document)
    return NS_ERROR_FAILURE;

  nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(document);
  if (!domDoc)
    return NS_ERROR_FAILURE;

  // Save weak references to presentation shell and DOMDocument
  mPresShell   = do_GetWeakReference(presShell); // weak ref
  mDOMDocument = do_GetWeakReference(domDoc);    // weak ref

  // Show caret
  ShowCaret();

  // Determine current screen dimensions
  PRInt32 nRows, nCols, xPixels, yPixels;
  result = ScreenSize(&nRows, &nCols, &xPixels, &yPixels);
  if (NS_FAILED(result))
    return result;

  // The above call does not return the correct screen dimensions.
  // (because rendering is still in progress?)
  // As a workaround, explicitly set screen dimensions
  nRows = 24;
  nCols = 80;
  xPixels = 0;
  yPixels = 0;

  // Instantiate and initialize XMLTermSession object
  mXMLTermSession = new mozXMLTermSession();

  if (!mXMLTermSession) {
    return NS_ERROR_OUT_OF_MEMORY;
  }

  result = mXMLTermSession->Init(this, presShell, domDoc, nRows, nCols);
  if (NS_FAILED(result)) {
    XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to initialize XMLTermSession\n");
    return NS_ERROR_FAILURE;
  }

  // Instantiate LineTerm  
  XMLT_LOG(mozXMLTerminal::Activate,22,
           ("instantiating lineterm, nRows=%d, nCols=%d\n", nRows, nCols));
  mLineTermAux = do_CreateInstance(MOZLINETERM_CONTRACTID, &result);
  if (NS_FAILED(result)) {
    XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to instantiate LineTermAux\n");
    return result;
  }

  // Open LineTerm to execute command
  // Non-owning reference to this; delete LineTerm before deleting self
  PRInt32 options = 0;

  XMLT_LOG(mozXMLTerminal::Activate,22,("Opening LineTerm\n"));
  nsCOMPtr<nsIObserver> anObserver = this;
#ifdef NO_CALLBACK
  anObserver = nsnull;
#endif
  nsAutoString cookie;
  result = mLineTermAux->OpenAux(mCommand.get(),
                                 mInitInput.get(),
                                 mPromptExpr.get(),
                                 options, LTERM_DETERMINE_PROCESS,
                                 nRows, nCols, xPixels, yPixels,
                                 domDoc, anObserver, cookie);

  if (NS_FAILED(result)) {
    XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to open LineTermAux\n");
    return result;
  }
  XMLT_LOG(mozXMLTerminal::Activate,22,("Opened LineTerm\n"));

  // Save cookie
  mCookie = cookie;

  // Get the DOM event receiver for document
  nsCOMPtr<nsIDOMEventReceiver> eventReceiver;
  result = domDoc->QueryInterface(NS_GET_IID(nsIDOMEventReceiver),
                                        getter_AddRefs(eventReceiver));
  if (NS_FAILED(result)) {
    XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to get DOM receiver\n");
    return result;
  }

  // Create a key listener
  result = NS_NewXMLTermKeyListener(getter_AddRefs(mKeyListener), this);
  if (NS_OK != result) {
    XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to get key listener\n");
    return result;
  }

  // Register the key listener with the DOM event receiver
  result = eventReceiver->AddEventListenerByIID(mKeyListener,
                                                NS_GET_IID(nsIDOMKeyListener));

  if (NS_FAILED(result)) {
    XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to register key listener\n");
    return result;
  }

  // Create a text listener
  result = NS_NewXMLTermTextListener(getter_AddRefs(mTextListener), this);
  if (NS_OK != result) {
    XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to get text listener\n");
    return result;
  }

  // Register the text listener with the DOM event receiver
  result = eventReceiver->AddEventListenerByIID(mTextListener,
                                                NS_GET_IID(nsIDOMTextListener));
  if (NS_FAILED(result)) {
    XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to register text listener\n");
    return result;
  }

  // Create a mouse listener
  result = NS_NewXMLTermMouseListener(getter_AddRefs(mMouseListener), this);
  if (NS_OK != result) {
    XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to get mouse listener\n");
    return result;
  }

  // Register the mouse listener with the DOM event receiver
  result = eventReceiver->AddEventListenerByIID(mMouseListener,
                                                NS_GET_IID(nsIDOMMouseListener));
  if (NS_FAILED(result)) {
    XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to register mouse listener\n");
    return result;
  }

  // Create a drag listener
  result = NS_NewXMLTermDragListener(getter_AddRefs(mDragListener), this);
  if (NS_OK != result) {
    XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to get drag listener\n");
    return result;
  }

  // Register the drag listener with the DOM event receiver
  result = eventReceiver->AddEventListenerByIID(mDragListener,
                                                NS_GET_IID(nsIDOMDragListener));
  if (NS_FAILED(result)) {
    XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to register drag listener\n");
    return result;
  }

  return NS_OK;
}
示例#8
0
void TcpReassembly::checkOutOfOrderFragments(TcpReassemblyData* tcpReassemblyData, int sideIndex, bool cleanWholeFragList)
{
	bool foundSomething = false;

	do
	{
		LOG_DEBUG("Starting first iteration of checkOutOfOrderFragments - looking for fragments that match the current sequence or have smaller sequence");

		int index = 0;
		foundSomething = false;

		do
		{
			index = 0;
			foundSomething = false;

			// first fragment list iteration - go over the whole fragment list and see if can find fragments that match the current sequence
			// or have smaller sequence but have big enough payload to get new data
			while (index < (int)tcpReassemblyData->twoSides[sideIndex].tcpFragmentList.size())
			{
				TcpFragment* curTcpFrag = tcpReassemblyData->twoSides[sideIndex].tcpFragmentList.at(index);

				// if fragment sequence matches the current sequence
				if (curTcpFrag->sequence == tcpReassemblyData->twoSides[sideIndex].sequence)
				{
					// update sequence
					tcpReassemblyData->twoSides[sideIndex].sequence += curTcpFrag->dataLength;
					if (curTcpFrag->data != NULL)
					{
						LOG_DEBUG("Found an out-of-order packet matching to the current sequence with size %d on side %d. Pulling it out of the list and sending the data to the callback", (int)curTcpFrag->dataLength, sideIndex);

						// send new data to callback

						if (m_OnMessageReadyCallback != NULL)
						{
							TcpStreamData streamData(curTcpFrag->data, curTcpFrag->dataLength, tcpReassemblyData->connData);
							streamData.setDeleteDataOnDestruction(false);
							m_OnMessageReadyCallback(sideIndex, streamData, m_UserCookie);
						}
					}


					// remove fragment from list
					tcpReassemblyData->twoSides[sideIndex].tcpFragmentList.erase(tcpReassemblyData->twoSides[sideIndex].tcpFragmentList.begin() + index);

					foundSomething = true;

					continue;
				}

				// if fragment sequence has lower sequence than the current sequence
				if (curTcpFrag->sequence < tcpReassemblyData->twoSides[sideIndex].sequence)
				{
					// check if it still has new data
					uint32_t newSequence = curTcpFrag->sequence + curTcpFrag->dataLength;

					// it has new data
					if (newSequence > tcpReassemblyData->twoSides[sideIndex].sequence)
					{
						// calculate the delta new data size
						uint32_t newLength = tcpReassemblyData->twoSides[sideIndex].sequence - curTcpFrag->sequence;

						LOG_DEBUG("Found a fragment in the out-of-order list which its sequence is lower than expected but its payload is long enough to contain new data. "
							"Calling the callback with the new data. Fragment size is %d on side %d, new data size is %d", (int)curTcpFrag->dataLength, sideIndex, (int)(curTcpFrag->dataLength - newLength));

						// update current sequence with the delta new data size
						tcpReassemblyData->twoSides[sideIndex].sequence += curTcpFrag->dataLength - newLength;

						// send only the new data to the callback
						if (m_OnMessageReadyCallback != NULL)
						{
							TcpStreamData streamData(curTcpFrag->data + newLength, curTcpFrag->dataLength - newLength, tcpReassemblyData->connData);
							streamData.setDeleteDataOnDestruction(false);
							m_OnMessageReadyCallback(sideIndex, streamData, m_UserCookie);
						}

						foundSomething = true;
					}
					else
					{
						LOG_DEBUG("Found a fragment in the out-of-order list which doesn't contain any new data, ignoring it. Fragment size is %d on side %d", (int)curTcpFrag->dataLength, sideIndex);
					}

					// delete fragment from list
					tcpReassemblyData->twoSides[sideIndex].tcpFragmentList.erase(tcpReassemblyData->twoSides[sideIndex].tcpFragmentList.begin() + index);

					continue;
				}

				//if got to here it means the fragment has higher sequence than current sequence, increment index and continue
				index++;
			}

			// if managed to find new segment, do the search all over again
		} while (foundSomething);


		// if got here it means we're left only with fragments that have higher sequence than current sequence. This means out-of-order packets or
		// missing data. If we don't want to clear the frag list yet, assume it's out-of-order and return
		if (!cleanWholeFragList)
			return;

		LOG_DEBUG("Starting second  iteration of checkOutOfOrderFragments - handle missing data");

		// second fragment list iteration - now we're left only with fragments that have higher sequence than current sequence. This means missing data.
		// Search for the fragment with the closest sequence to the current one

		uint32_t closestSequence = 0xffffffff;
		int closestSequenceFragIndex = -1;
		index = 0;

		while (index < (int)tcpReassemblyData->twoSides[sideIndex].tcpFragmentList.size())
		{
			// extract segment at current index
			TcpFragment* curTcpFrag = tcpReassemblyData->twoSides[sideIndex].tcpFragmentList.at(index);

			// check if its sequence is closer than current closest sequence
			if (curTcpFrag->sequence < closestSequence)
			{
				closestSequence = curTcpFrag->sequence;
				closestSequenceFragIndex = index;
			}

			index++;
		}

		// this means fragment list is not empty at this stage
		if (closestSequenceFragIndex > -1)
		{
			// get the fragment with the closest sequence
			TcpFragment* curTcpFrag = tcpReassemblyData->twoSides[sideIndex].tcpFragmentList.at(closestSequenceFragIndex);

			// calculate number of missing bytes
			uint32_t missingDataLen = curTcpFrag->sequence - tcpReassemblyData->twoSides[sideIndex].sequence;

			// update sequence
			tcpReassemblyData->twoSides[sideIndex].sequence = curTcpFrag->sequence + curTcpFrag->dataLength;
			if (curTcpFrag->data != NULL)
			{
				// send new data to callback
				if (m_OnMessageReadyCallback != NULL)
				{
					// prepare missing data text
					std::string missingDataTextStr = prepareMissingDataMessage(missingDataLen);

					// add missing data text to the data that will be sent to the callback. This means that the data will look something like:
					// "[xx bytes missing]<original_data>"
					size_t dataWithMissingDataTextLen = missingDataTextStr.length() + curTcpFrag->dataLength;
					uint8_t* dataWithMissingDataText = new uint8_t[dataWithMissingDataTextLen];
					memcpy(dataWithMissingDataText, missingDataTextStr.c_str(), missingDataTextStr.length());
					memcpy(dataWithMissingDataText + missingDataTextStr.length(), curTcpFrag->data, curTcpFrag->dataLength);

					//TcpStreamData streamData(curTcpFrag->data, curTcpFrag->dataLength, tcpReassemblyData->connData);
					//streamData.setDeleteDataOnDestruction(false);
					TcpStreamData streamData(dataWithMissingDataText, dataWithMissingDataTextLen, tcpReassemblyData->connData);
					m_OnMessageReadyCallback(sideIndex, streamData, m_UserCookie);

					LOG_DEBUG("Found missing data on side %d: %d byte are missing. Sending the closest fragment which is in size %d + missing text message which size is %d",
						sideIndex, missingDataLen, (int)curTcpFrag->dataLength, (int)missingDataTextStr.length());
				}
			}

			// remove fragment from list
			tcpReassemblyData->twoSides[sideIndex].tcpFragmentList.erase(tcpReassemblyData->twoSides[sideIndex].tcpFragmentList.begin() + closestSequenceFragIndex);

			LOG_DEBUG("Calling checkOutOfOrderFragments again from the start");

			// call the method again from the start to do the whole search again (both iterations). 
			// the stop condition is when the list is empty (so closestSequenceFragIndex == -1)
			foundSomething = true;
		}

	} while (foundSomething);
}
示例#9
0
void TcpReassembly::reassemblePacket(Packet& tcpData)
{
	// get IP layer
	Layer* ipLayer = NULL;
	if (tcpData.isPacketOfType(IPv4))
		ipLayer = (Layer*)tcpData.getLayerOfType<IPv4Layer>();
	else if (tcpData.isPacketOfType(IPv6))
		ipLayer = (Layer*)tcpData.getLayerOfType<IPv6Layer>();

	if (ipLayer == NULL)
		return;

	// Ignore non-TCP packets
	TcpLayer* tcpLayer = tcpData.getLayerOfType<TcpLayer>();
	if (tcpLayer == NULL)
		return;

	// Ignore the packet if it's an ICMP packet that has a TCP layer
    // Several ICMP messages (like "destination unreachable") have TCP data as part of the ICMP message.
	// This is not real TCP data and packet can be ignored
	if (tcpData.isPacketOfType(ICMP))
	{
		LOG_DEBUG("Packet is of type ICMP so TCP data is probably  part of the ICMP message. Ignoring this packet");
		return;
	}

	// calculate the TCP payload size
	size_t tcpPayloadSize = tcpLayer->getLayerPayloadSize();

	// calculate if this packet has FIN or RST flags
	bool isFin = (tcpLayer->getTcpHeader()->finFlag == 1);
	bool isRst = (tcpLayer->getTcpHeader()->rstFlag == 1);
	bool isFinOrRst = isFin || isRst;

	// ignore ACK packets or TCP packets with no payload (except for SYN, FIN or RST packets which we'll later need)
	if (tcpPayloadSize == 0 && tcpLayer->getTcpHeader()->synFlag == 0 && !isFinOrRst)
		return;

	// if the actual TCP payload is smaller than the value written in IPV4's "total length" field then adjust tcpPayloadSize to avoid buffer overflow
	if (tcpLayer->getLayerPayloadSize() < tcpPayloadSize)
	{
		LOG_DEBUG("Got a packet where actual TCP payload size is smaller then the value written in IPv4's 'total length' header. Adjusting tcpPayloadSize to avoid buffer overflow");
		tcpPayloadSize = tcpLayer->getLayerPayloadSize();
	}


	TcpReassemblyData* tcpReassemblyData = NULL;

	// calculate flow key for this packet
	uint32_t flowKey = hash5Tuple(&tcpData);

	// if this packet belongs to a connection that was already closed (for example: data packet that comes after FIN), ignore it
	if (m_ClosedConnectionList.find(flowKey) != m_ClosedConnectionList.end())
	{
		LOG_DEBUG("Ignoring packet of already closed flow [0x%X]", flowKey);
		return;
	}

	// calculate packet's source and dest IP address
	IPAddress* srcIP = NULL;
	IPAddress* dstIP = NULL;
	IPv4Address srcIP4Addr = IPv4Address::Zero;
	IPv6Address srcIP6Addr = IPv6Address::Zero;
	IPv4Address dstIP4Addr = IPv4Address::Zero;
	IPv6Address dstIP6Addr = IPv6Address::Zero;
	if (ipLayer->getProtocol() == IPv4)
	{
		srcIP4Addr = ((IPv4Layer*)ipLayer)->getSrcIpAddress();
		srcIP = &srcIP4Addr;
		dstIP4Addr = ((IPv4Layer*)ipLayer)->getDstIpAddress();
		dstIP = &dstIP4Addr;
	}
	else if (ipLayer->getProtocol() == IPv6)
	{
		srcIP6Addr = ((IPv6Layer*)ipLayer)->getSrcIpAddress();
		srcIP = &srcIP6Addr;
		dstIP6Addr = ((IPv6Layer*)ipLayer)->getDstIpAddress();
		dstIP = &dstIP6Addr;
	}

	// find the connection in the connection map
	std::map<uint32_t, TcpReassemblyData*>::iterator iter = m_ConnectionList.find(flowKey);
	if (iter == m_ConnectionList.end())
	{
		// if it's a packet of a new connection, create a TcpReassemblyData object and add it to the active connection list
		tcpReassemblyData = new TcpReassemblyData();
		tcpReassemblyData->connData.setSrcIpAddress(srcIP);
		tcpReassemblyData->connData.setDstIpAddress(dstIP);
		tcpReassemblyData->connData.srcPort = ntohs(tcpLayer->getTcpHeader()->portSrc);
		tcpReassemblyData->connData.dstPort = ntohs(tcpLayer->getTcpHeader()->portDst);
		tcpReassemblyData->connData.flowKey = flowKey;

		m_ConnectionList[flowKey] = tcpReassemblyData;

		m_ConnectionInfo.push_back(tcpReassemblyData->connData);

		// fire connection start callback
		if (m_OnConnStart != NULL)
			m_OnConnStart(tcpReassemblyData->connData, m_UserCookie);
	}
	else // connection already exists
		tcpReassemblyData = iter->second;

	int sideIndex = -1;
	bool first = false;

	// calculate packet's source port
	uint16_t srcPort = tcpLayer->getTcpHeader()->portSrc;

	// if this is a new connection and it's the first packet we see on that connection
	if (tcpReassemblyData->numOfSides == 0)
	{
		LOG_DEBUG("Setting side for new connection");

		// open the first side of the connection, side index is 0
		sideIndex = 0;
		tcpReassemblyData->twoSides[sideIndex].setSrcIP(srcIP);
		tcpReassemblyData->twoSides[sideIndex].srcPort = srcPort;
		tcpReassemblyData->numOfSides++;
		first = true;
	}
	// if there is already one side in this connection (which will be at side index 0)
	else if (tcpReassemblyData->numOfSides == 1)
	{
		// check if packet belongs to that side
		if (tcpReassemblyData->twoSides[0].srcIP->equals(srcIP) && tcpReassemblyData->twoSides[0].srcPort == srcPort)
		{
			sideIndex = 0;
		}
		else
		{
			// this means packet belong to the second side which doesn't yet exist. Open a second side with side index 1
			LOG_DEBUG("Setting second side of a connection");
			sideIndex = 1;
			tcpReassemblyData->twoSides[sideIndex].setSrcIP(srcIP);
			tcpReassemblyData->twoSides[sideIndex].srcPort = srcPort;
			tcpReassemblyData->numOfSides++;
			first = true;
		}
	}
	// if there are already 2 sides open for this connection
	else if (tcpReassemblyData->numOfSides == 2)
	{
		// check if packet matches side 0
		if (tcpReassemblyData->twoSides[0].srcIP->equals(srcIP) && tcpReassemblyData->twoSides[0].srcPort == srcPort)
		{
			sideIndex = 0;
		}
		// check if packet matches side 1
		else if (tcpReassemblyData->twoSides[1].srcIP->equals(srcIP) && tcpReassemblyData->twoSides[1].srcPort == srcPort)
		{
			sideIndex = 1;
		}
		// packet doesn't match either side. This case doesn't make sense but it's handled anyway. Packet will be ignored
		else
		{
			LOG_ERROR("Error occurred - packet doesn't match either side of the connection!!");
			return;
		}
	}
	// there are more than 2 side - this case doesn't make sense and shouldn't happen, but handled anyway. Packet will be ignored
	else
	{
		LOG_ERROR("Error occurred - connection has more than 2 sides!!");
		return;
	}

	// if this side already got FIN or RST packet before, ignore this packet as this side is considered closed
	if (tcpReassemblyData->twoSides[sideIndex].gotFinOrRst)
	{
		LOG_DEBUG("Got a packet after FIN or RST were already seen on this side (%d). Ignoring this packet", sideIndex);
		return;
	}

	// handle FIN/RST packets that don't contain additional TCP data
	if (isFinOrRst && tcpPayloadSize == 0)
	{
		LOG_DEBUG("Got FIN or RST packet without data on side %d", sideIndex);

		handleFinOrRst(tcpReassemblyData, sideIndex, flowKey);
		return;
	}

	// check if this packet contains data from a different side than the side seen before.
	// If this is the case then treat the out-of-order packet list as missing data and send them to the user (callback) together with an indication that some data was missing.
	// Why? because a new packet from the other side means the previous message was probably already received and a new message is starting.
	// In this case out-of-order packets are probably actually missing data
	// For example: let's assume these are HTTP messages. If we're seeing the first packet of a response this means the server has already received the full request and is now starting
	// to send the response. So if we still have out-of-order packets from the request it probably means that some packets were lost during the capture. So we don't expect the client to
	// continue sending packets of the previous request, so we'll treat the out-of-order packets as missing data
	//
	// I'm aware that there are edge cases where the situation I described above is not true, but at some point we must clean the out-of-order packet list to avoid memory leak.
	// I decided to do what Wireshark does and clean this list when starting to see a message from the other side
	if (!first && tcpPayloadSize > 0 && tcpReassemblyData->prevSide != -1 && tcpReassemblyData->prevSide != sideIndex &&
			tcpReassemblyData->twoSides[tcpReassemblyData->prevSide].tcpFragmentList.size() > 0)
	{
		LOG_DEBUG("Seeing a first data packet from a different side. Previous side was %d, current side is %d", tcpReassemblyData->prevSide, sideIndex);
		checkOutOfOrderFragments(tcpReassemblyData, tcpReassemblyData->prevSide, true);
	}
	tcpReassemblyData->prevSide = sideIndex;

	// extract sequence value from packet
	uint32_t sequence = ntohl(tcpLayer->getTcpHeader()->sequenceNumber);

	// if it's the first packet we see on this side of the connection
	if (first)
	{
		LOG_DEBUG("First data from this side of the connection");

		// set initial sequence
		tcpReassemblyData->twoSides[sideIndex].sequence = sequence + tcpPayloadSize;
		if (tcpLayer->getTcpHeader()->synFlag != 0)
			tcpReassemblyData->twoSides[sideIndex].sequence++;

		// send data to the callback
		if (tcpPayloadSize != 0 && m_OnMessageReadyCallback != NULL)
		{
			TcpStreamData streamData(tcpLayer->getLayerPayload(), tcpPayloadSize, tcpReassemblyData->connData);
			streamData.setDeleteDataOnDestruction(false);
			m_OnMessageReadyCallback(sideIndex, streamData, m_UserCookie);
		}

		// handle case where this packet is FIN or RST (although it's unlikely)
		if (isFinOrRst)
			handleFinOrRst(tcpReassemblyData, sideIndex, flowKey);

		// return - nothing else to do here
		return;
	}

	// if packet sequence is smaller than expected - this means that part or all of the TCP data is being re-transmitted
	if (sequence < tcpReassemblyData->twoSides[sideIndex].sequence)
	{
		LOG_DEBUG("Found new data with the sequence lower than expected");

		// calculate the sequence after this packet to see if this TCP payload contains also new data
		uint32_t newSequence = sequence + tcpPayloadSize;

		// this means that some of payload is new
		if (newSequence > tcpReassemblyData->twoSides[sideIndex].sequence)
		{
			// calculate the size of the new data
			uint32_t newLength = tcpReassemblyData->twoSides[sideIndex].sequence - sequence;

			LOG_DEBUG("Although sequence is lower than expected payload is long enough to contain new data. Calling the callback with the new data");

			// update the sequence for this side to include the new data that was seen
			tcpReassemblyData->twoSides[sideIndex].sequence += tcpPayloadSize - newLength;

			// send only the new data to the callback
			if (m_OnMessageReadyCallback != NULL)
			{
				TcpStreamData streamData(tcpLayer->getLayerPayload() + newLength, tcpPayloadSize - newLength, tcpReassemblyData->connData);
				streamData.setDeleteDataOnDestruction(false);
				m_OnMessageReadyCallback(sideIndex, streamData, m_UserCookie);
			}
		}

		// handle case where this packet is FIN or RST
		if (isFinOrRst)
			handleFinOrRst(tcpReassemblyData, sideIndex, flowKey);

		// return - nothing else to do here
		return;
	}

	// if packet sequence is exactly as expected - this is the "good" case and the most common one
	else if (sequence == tcpReassemblyData->twoSides[sideIndex].sequence)
	{
		// if TCP data size is 0 - nothing to do
		if (tcpPayloadSize == 0)
		{
			LOG_DEBUG("Payload length is 0, doing nothing");

			// handle case where this packet is FIN or RST
			if (isFinOrRst)
				handleFinOrRst(tcpReassemblyData, sideIndex, flowKey);

			return;
		}

		LOG_DEBUG("Found new data with expected sequence. Calling the callback");

		// update the sequence for this side to include TCP data from this packet
		tcpReassemblyData->twoSides[sideIndex].sequence += tcpPayloadSize;

		// if this is a SYN packet - add +1 to the sequence
		if (tcpLayer->getTcpHeader()->synFlag != 0)
			tcpReassemblyData->twoSides[sideIndex].sequence++;

		// send the data to the callback
		if (m_OnMessageReadyCallback != NULL)
		{
			TcpStreamData streamData(tcpLayer->getLayerPayload(), tcpPayloadSize, tcpReassemblyData->connData);
			streamData.setDeleteDataOnDestruction(false);
			m_OnMessageReadyCallback(sideIndex, streamData, m_UserCookie);
		}

		//while (checkOutOfOrderFragments(tcpReassemblyData, sideIndex)) {}

		// now that we've seen new data, go over the list of out-of-order packets and see if one or more of them fits now
		checkOutOfOrderFragments(tcpReassemblyData, sideIndex, false);

		// handle case where this packet is FIN or RST
		if (isFinOrRst)
			handleFinOrRst(tcpReassemblyData, sideIndex, flowKey);

		// return - nothing else to do here
		return;
	}

	// this case means sequence size of the packet is higher than expected which means the packet is out-of-order or some packets were lost (missing data).
	// we don't know which of the 2 cases it is at this point so we just add this data to the out-of-order packet list
	else
	{
		// if TCP data size is 0 - nothing to do
		if (tcpPayloadSize == 0)
		{
			LOG_DEBUG("Payload length is 0, doing nothing");

			// handle case where this packet is FIN or RST
			if (isFinOrRst)
				handleFinOrRst(tcpReassemblyData, sideIndex, flowKey);

			return;
		}

		// create a new TcpFragment, copy the TCP data to it and add this packet to the the out-of-order packet list
		TcpFragment* newTcpFrag = new TcpFragment();
		newTcpFrag->data = new uint8_t[tcpPayloadSize];
		newTcpFrag->dataLength = tcpPayloadSize;
		newTcpFrag->sequence = sequence;
		memcpy(newTcpFrag->data, tcpLayer->getLayerPayload(), tcpPayloadSize);
		tcpReassemblyData->twoSides[sideIndex].tcpFragmentList.pushBack(newTcpFrag);

		LOG_DEBUG("Found out-of-order packet and added a new TCP fragment with size %d to the out-of-order list of side %d", (int)tcpPayloadSize, sideIndex);

		// handle case where this packet is FIN or RST
		if (isFinOrRst)
		{
			handleFinOrRst(tcpReassemblyData, sideIndex, flowKey);
			return;
		}

	}
}