/*----------------------------------------------------------------------+ | NPT_RingBuffer::Read +----------------------------------------------------------------------*/ NPT_Result NPT_RingBuffer::Read(void* buffer, NPT_Size byte_count) { if (m_Closed) return NPT_ERROR_READ_FAILED; if (byte_count == 0) return NPT_SUCCESS; if (m_In > m_Out) { if (buffer) NPT_CopyMemory(buffer, m_Out, byte_count); m_Out += byte_count; if (m_Out == m_Data.end) m_Out = m_Data.start; } else { unsigned int chunk = (unsigned int)(m_Data.end - m_Out); if (chunk >= byte_count) chunk = byte_count; if (buffer) NPT_CopyMemory(buffer, m_Out, chunk); m_Out += chunk; if (m_Out == m_Data.end) m_Out = m_Data.start; if (chunk != byte_count) { if (buffer) { NPT_CopyMemory(((char*)buffer)+chunk, m_Out, byte_count-chunk); } m_Out += byte_count-chunk; if (m_Out == m_Data.end) m_Out = m_Data.start; } } return NPT_SUCCESS; }
/*----------------------------------------------------------------------+ | NPT_RingBuffer::Write +----------------------------------------------------------------------*/ NPT_Result NPT_RingBuffer::Write(const void* buffer, NPT_Size byte_count) { if (m_Closed) return NPT_ERROR_WRITE_FAILED; if (byte_count == 0) return NPT_SUCCESS; if (m_In < m_Out) { if (buffer) NPT_CopyMemory(m_In, buffer, byte_count); m_In += byte_count; if (m_In == m_Data.end) m_In = m_Data.start; } else { unsigned int chunk = (unsigned int)(m_Data.end - m_In); if (chunk >= byte_count) chunk = byte_count; if (buffer) NPT_CopyMemory(m_In, buffer, chunk); m_In += chunk; if (m_In == m_Data.end) m_In = m_Data.start; if (chunk != byte_count) { if (buffer) { NPT_CopyMemory(m_In, ((const char*)buffer)+chunk, byte_count-chunk); } m_In += byte_count-chunk; if (m_In == m_Data.end) m_In = m_Data.start; } } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | NPT_MemoryStream::Read +---------------------------------------------------------------------*/ NPT_Result NPT_MemoryStream::Read(void* buffer, NPT_Size bytes_to_read, NPT_Size* bytes_read) { // check for shortcut if (bytes_to_read == 0) { if (bytes_read) *bytes_read = 0; return NPT_SUCCESS; } // clip to what's available NPT_Size available = m_Buffer.GetDataSize(); if (m_ReadOffset+bytes_to_read > available) { bytes_to_read = available-m_ReadOffset; } // copy the data if (bytes_to_read) { NPT_CopyMemory(buffer, (void*)(((char*)m_Buffer.UseData())+m_ReadOffset), bytes_to_read); m_ReadOffset += bytes_to_read; } if (bytes_read) *bytes_read = bytes_to_read; return bytes_to_read?NPT_SUCCESS:NPT_ERROR_EOS; }
/*---------------------------------------------------------------------- | NPT_BufferedInputStream::SetBufferSize +---------------------------------------------------------------------*/ NPT_Result NPT_BufferedInputStream::SetBufferSize(NPT_Size size, bool force /* = false */) { if (m_Buffer.data != NULL) { // we already have a buffer if (m_Buffer.size < size || force) { // the current buffer is too small or we want to move // existing data to the beginning of the buffer, reallocate NPT_Byte* buffer = new NPT_Byte[size]; if (buffer == NULL) return NPT_ERROR_OUT_OF_MEMORY; // copy existing data NPT_Size need_to_copy = m_Buffer.valid - m_Buffer.offset; if (need_to_copy) { NPT_CopyMemory((void*)buffer, m_Buffer.data+m_Buffer.offset, need_to_copy); } // use the new buffer delete[] m_Buffer.data; m_Buffer.data = buffer; m_Buffer.valid -= m_Buffer.offset; m_Buffer.offset = 0; } } m_Buffer.size = size; return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | NPT_DataBuffer::NPT_DataBuffer +---------------------------------------------------------------------*/ NPT_DataBuffer::NPT_DataBuffer(const void* data, NPT_Size data_size, bool copy) : m_BufferIsLocal(copy), m_Buffer(copy?(data_size?new NPT_Byte[data_size]:NULL):reinterpret_cast<NPT_Byte*>(const_cast<void*>(data))), m_BufferSize(data_size), m_DataSize(data_size) { if (copy && data_size) NPT_CopyMemory(m_Buffer, data, data_size); }
/*---------------------------------------------------------------------- | NPT_DataBuffer::NPT_DataBuffer +---------------------------------------------------------------------*/ NPT_DataBuffer::NPT_DataBuffer(const NPT_DataBuffer& other) : m_BufferIsLocal(true), m_Buffer(NULL), m_BufferSize(other.m_DataSize), m_DataSize(other.m_DataSize) { if (m_BufferSize) { m_Buffer = new NPT_Byte[m_BufferSize]; NPT_CopyMemory(m_Buffer, other.m_Buffer, m_BufferSize); } }
/*---------------------------------------------------------------------- | NPT_DataBuffer::SetData +---------------------------------------------------------------------*/ NPT_Result NPT_DataBuffer::SetData(const NPT_Byte* data, NPT_Size size) { if (size > m_BufferSize) { if (m_BufferIsLocal) { NPT_CHECK(ReallocateBuffer(size)); } else { return NPT_ERROR_INVALID_STATE; } } if (data) NPT_CopyMemory(m_Buffer, data, size); m_DataSize = size; return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_OutputDatagramStream::Write +---------------------------------------------------------------------*/ NPT_Result PLT_OutputDatagramStream::Write(const void* buffer, NPT_Size bytes_to_write, NPT_Size* bytes_written /* = NULL */) { // calculate if we need to increase the buffer NPT_Int32 overflow = bytes_to_write - m_Buffer.GetBufferSize() + m_Buffer.GetDataSize(); if (overflow > 0) { m_Buffer.Reserve(m_Buffer.GetBufferSize() + overflow); } // copy data in place at the end of what we have there already NPT_CopyMemory(m_Buffer.UseData() + m_Buffer.GetDataSize(), buffer, bytes_to_write); m_Buffer.SetDataSize(m_Buffer.GetDataSize() + bytes_to_write); if (bytes_written) *bytes_written = bytes_to_write; return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | NPT_MemoryStream::Write +---------------------------------------------------------------------*/ NPT_Result NPT_MemoryStream::Write(const void* data, NPT_Size bytes_to_write, NPT_Size* bytes_written) { NPT_CHECK(m_Buffer.Reserve(m_WriteOffset+bytes_to_write)); NPT_CopyMemory(m_Buffer.UseData()+m_WriteOffset, data, bytes_to_write); m_WriteOffset += bytes_to_write; if (m_WriteOffset > m_Buffer.GetDataSize()) { m_Buffer.SetDataSize(m_WriteOffset); } if (bytes_written) *bytes_written = bytes_to_write; return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | NPT_DataBuffer::operator= +---------------------------------------------------------------------*/ NPT_DataBuffer& NPT_DataBuffer::operator=(const NPT_DataBuffer& copy) { // do nothing if we're assigning to ourselves if (this != ©) { Clear(); m_BufferIsLocal = true; m_BufferSize = copy.m_BufferSize; m_DataSize = copy.m_DataSize; if (m_BufferSize) { m_Buffer = new NPT_Byte[m_BufferSize]; NPT_CopyMemory(m_Buffer, copy.m_Buffer, m_BufferSize); } } return *this; }
/*---------------------------------------------------------------------- | NPT_BufferedInputStream::Peek +---------------------------------------------------------------------*/ NPT_Result NPT_BufferedInputStream::Peek(void* buffer, NPT_Size bytes_to_read, NPT_Size* bytes_read) { NPT_Result result = NPT_SUCCESS; NPT_Size buffered; NPT_Size new_size = m_Buffer.size?m_Buffer.size:NPT_BUFFERED_BYTE_STREAM_DEFAULT_SIZE; // check for a possible shortcut if (bytes_to_read == 0) return NPT_SUCCESS; // compute how much is buffered buffered = m_Buffer.valid-m_Buffer.offset; if (bytes_to_read > buffered && buffered < new_size && !m_Eos) { // we need more data than what we have // switch to unbuffered mode and resize to force relocation // of data to the beginning of the buffer SetBufferSize(new_size, true); // fill up the end of the buffer result = FillBuffer(); // continue even if it failed buffered = m_Buffer.valid; } // make sure we're returning what we can if (bytes_to_read > buffered) bytes_to_read = buffered; // get what we can from the buffer NPT_CopyMemory(buffer, m_Buffer.data + m_Buffer.offset, bytes_to_read); if (bytes_read) *bytes_read = bytes_to_read; if (result == NPT_ERROR_EOS) { m_Eos = true; if (bytes_to_read != 0) { // we have reached the end of the stream, but we have read // some chars, so do not return EOS now return NPT_SUCCESS; } } return result; }
/*---------------------------------------------------------------------- | NPT_TlsInputStream::Read +---------------------------------------------------------------------*/ NPT_Result NPT_TlsInputStream::Read(void* buffer, NPT_Size bytes_to_read, NPT_Size* bytes_read) { // setup default values if (bytes_read) *bytes_read = 0; // quick check for edge case if (bytes_to_read == 0) return NPT_SUCCESS; // read a new record if we don't have one cached if (m_RecordCacheData == NULL) { int ssl_result; do { ssl_result = ssl_read(m_Session->m_SSL, &m_RecordCacheData); } while (ssl_result == 0); if (ssl_result < 0) { return NPT_Tls_MapResult(ssl_result); } m_RecordCacheSize = ssl_result; } // we now have data in cache if (bytes_to_read > m_RecordCacheSize) { // read at most what's in the cache bytes_to_read = m_RecordCacheSize; } NPT_CopyMemory(buffer, m_RecordCacheData, bytes_to_read); if (bytes_read) *bytes_read = bytes_to_read; // update the record cache m_RecordCacheSize -= bytes_to_read; if (m_RecordCacheSize == 0) { // nothing left in the cache m_RecordCacheData = NULL; } else { // move the cache pointer m_RecordCacheData += bytes_to_read; } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_InputDatagramStream::Read +---------------------------------------------------------------------*/ NPT_Result PLT_InputDatagramStream::Read(void* buffer, NPT_Size bytes_to_read, NPT_Size* bytes_read /*= 0*/) { NPT_Result res = NPT_SUCCESS; if (bytes_read) *bytes_read = 0; // always try to read from socket if needed even if bytes_to_read is 0 if (m_Buffer.GetDataSize() == 0) { // read data into it now NPT_SocketAddress addr; res = m_Socket->Receive(m_Buffer, &addr); // update info m_Socket->GetInfo(m_Info); m_Info.remote_address = addr; NPT_LOG_FINE_1("PLT_InputDatagramStream received %d", m_Buffer.GetDataSize()); } if (bytes_to_read == 0) return res; if (NPT_SUCCEEDED(res)) { NPT_Size available = m_Buffer.GetDataSize()-(NPT_Size)m_BufferOffset; NPT_Size _bytes_to_read = bytes_to_read<available?bytes_to_read:available; NPT_CopyMemory(buffer, m_Buffer.UseData()+m_BufferOffset, _bytes_to_read); m_BufferOffset += _bytes_to_read; if (bytes_read) *bytes_read = _bytes_to_read; // read buffer entirety, reset for next time if (m_BufferOffset == m_Buffer.GetDataSize()) { m_BufferOffset = 0; m_Buffer.SetDataSize(0); } NPT_LOG_FINE_3("PLT_InputDatagramStream requested %d, consumed %d, left %d", bytes_to_read, _bytes_to_read, m_Buffer.GetDataSize()); } return res; }
/*---------------------------------------------------------------------- | NPT_DataBuffer::ReallocateBuffer +---------------------------------------------------------------------*/ NPT_Result NPT_DataBuffer::ReallocateBuffer(NPT_Size size) { // check that the existing data fits if (m_DataSize > size) return NPT_ERROR_INVALID_PARAMETERS; // allocate a new buffer NPT_Byte* newBuffer = new NPT_Byte[size]; // copy the contents of the previous buffer, if any if (m_Buffer && m_DataSize) { NPT_CopyMemory(newBuffer, m_Buffer, m_DataSize); } // destroy the previous buffer delete[] m_Buffer; // use the new buffer m_Buffer = newBuffer; m_BufferSize = size; return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | TestBlockCiphers +---------------------------------------------------------------------*/ static int TestBlockCiphers() { NPT_BlockCipher* cipher = NULL; NPT_UInt8 b0[16]; NPT_UInt8 k1[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; NPT_UInt8 pt1[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; NPT_UInt8 ct1[16] = { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a }; NPT_Result result; result = NPT_BlockCipher::Create(NPT_BlockCipher::AES_128, NPT_BlockCipher::ENCRYPT, k1, 16, cipher); SHOULD_SUCCEED(result); SHOULD_EQUAL(cipher->GetBlockSize(), 16); result = cipher->ProcessBlock(pt1, b0); SHOULD_SUCCEED(result); SHOULD_EQUAL_MEM(b0, ct1, 16); delete cipher; result = NPT_BlockCipher::Create(NPT_BlockCipher::AES_128, NPT_BlockCipher::DECRYPT, k1, 16, cipher); SHOULD_SUCCEED(result); SHOULD_EQUAL(cipher->GetBlockSize(), 16); result = cipher->ProcessBlock(ct1, b0); SHOULD_SUCCEED(result); SHOULD_EQUAL_MEM(b0, pt1, 16); delete cipher; NPT_UInt8 key[16]; NPT_CopyMemory(key, k1, 16); for (unsigned int i=0; i<100; i++) { NPT_BlockCipher* encrypter; NPT_BlockCipher* decrypter; result = NPT_BlockCipher::Create(NPT_BlockCipher::AES_128, NPT_BlockCipher::ENCRYPT, key, 16, encrypter); result = NPT_BlockCipher::Create(NPT_BlockCipher::AES_128, NPT_BlockCipher::DECRYPT, key, 16, decrypter); NPT_UInt8 mem1[16]; NPT_UInt8 mem2[16]; NPT_UInt8 mem3[16]; NPT_SetMemory(mem1, 0, 16); for (unsigned int j=0; j<1000; j++) { encrypter->ProcessBlock(mem1, mem2); decrypter->ProcessBlock(mem2, mem3); SHOULD_EQUAL_MEM(mem1, mem3, 16); NPT_CopyMemory(mem1, mem2, 16); } delete encrypter; delete decrypter; NPT_CopyMemory(key, mem1, 16); } return 0; }
/*---------------------------------------------------------------------- | NPT_BufferedInputStream::Read +---------------------------------------------------------------------*/ NPT_Result NPT_BufferedInputStream::Read(void* buffer, NPT_Size bytes_to_read, NPT_Size* bytes_read) { NPT_Result result = NPT_SUCCESS; NPT_Size total_read = 0; NPT_Size buffered; // check for a possible shortcut if (bytes_to_read == 0) return NPT_SUCCESS; // skip a newline char if needed if (m_SkipNewline) { m_SkipNewline = false; result = Read(buffer, 1, NULL); if (NPT_FAILED(result)) goto done; NPT_Byte c = *(NPT_Byte*)buffer; if (c != '\n') { buffer = (void*)((NPT_Byte*)buffer+1); --bytes_to_read; total_read = 1; } } // compute how much is buffered buffered = m_Buffer.valid-m_Buffer.offset; if (bytes_to_read > buffered) { // there is not enough in the buffer, take what's there if (buffered) { NPT_CopyMemory(buffer, m_Buffer.data + m_Buffer.offset, buffered); buffer = (void*)((NPT_Byte*)buffer+buffered); m_Buffer.offset += buffered; bytes_to_read -= buffered; total_read += buffered; goto done; } // read the rest from the source if (m_Buffer.size == 0) { // unbuffered mode, read directly into the supplied buffer if (m_Buffer.data != NULL) ReleaseBuffer(); // cleanup if necessary NPT_Size local_read = 0; result = m_Source->Read(buffer, bytes_to_read, &local_read); if (NPT_SUCCEEDED(result)) { total_read += local_read; } goto done; } else { // refill the buffer result = FillBuffer(); if (NPT_FAILED(result)) goto done; buffered = m_Buffer.valid; if (bytes_to_read > buffered) bytes_to_read = buffered; } } // get what we can from the buffer if (bytes_to_read) { NPT_CopyMemory(buffer, m_Buffer.data + m_Buffer.offset, bytes_to_read); m_Buffer.offset += bytes_to_read; total_read += bytes_to_read; } done: m_Position += total_read; if (bytes_read) *bytes_read = total_read; if (result == NPT_ERROR_EOS) { m_Eos = true; if (total_read != 0) { // we have reached the end of the stream, but we have read // some chars, so do not return EOS now return NPT_SUCCESS; } } return result; }