nfs4: Add XDR encoder and decoder
Base classes XDR::Stream and classes XDR::WriteStream and XDR::ReadStream are added. They implement encoding and decoding XDR (RFC 4506) streams. All data types used by RPC and NFS4 are supported.
This commit is contained in:
@@ -5,4 +5,5 @@ UsePrivateHeaders kernel ;
|
|||||||
KernelAddon nfs4 :
|
KernelAddon nfs4 :
|
||||||
Connection.cpp
|
Connection.cpp
|
||||||
kernel_interface.cpp
|
kernel_interface.cpp
|
||||||
|
XDR.cpp
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -0,0 +1,326 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Paweł Dziepak, [email protected]
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "XDR.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <ByteOrder.h>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace XDR;
|
||||||
|
|
||||||
|
Stream::Stream(void* buffer, uint32 size)
|
||||||
|
:
|
||||||
|
fBuffer(reinterpret_cast<uint32*>(buffer)),
|
||||||
|
fSize(size),
|
||||||
|
fPosition(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Stream::~Stream()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
Stream::_PositionToSize() const
|
||||||
|
{
|
||||||
|
return fPosition * sizeof(uint32);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
Stream::_RealSize(uint32 size) const
|
||||||
|
{
|
||||||
|
uint32 real_size = size;
|
||||||
|
if (real_size % 4 != 0)
|
||||||
|
real_size = ((real_size >> 2) + 1) << 2;
|
||||||
|
return real_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ReadStream::ReadStream(void* buffer, uint32 size)
|
||||||
|
:
|
||||||
|
Stream(buffer, size),
|
||||||
|
fEOF(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ReadStream::~ReadStream()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
ReadStream::GetInt()
|
||||||
|
{
|
||||||
|
if (_PositionToSize() >= fSize) {
|
||||||
|
fEOF = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_BENDIAN_TO_HOST_INT32(fBuffer[fPosition++]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
ReadStream::GetUInt()
|
||||||
|
{
|
||||||
|
if (_PositionToSize() >= fSize) {
|
||||||
|
fEOF = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_BENDIAN_TO_HOST_INT32(fBuffer[fPosition++]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64
|
||||||
|
ReadStream::GetHyper()
|
||||||
|
{
|
||||||
|
if (_PositionToSize() + sizeof(int64) > fSize) {
|
||||||
|
fEOF = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64* ptr = reinterpret_cast<int64*>(fBuffer + fPosition);
|
||||||
|
fPosition += 2;
|
||||||
|
|
||||||
|
return B_BENDIAN_TO_HOST_INT64(*ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint64
|
||||||
|
ReadStream::GetUHyper()
|
||||||
|
{
|
||||||
|
if (_PositionToSize() + sizeof(uint64) > fSize) {
|
||||||
|
fEOF = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64* ptr = reinterpret_cast<uint64*>(fBuffer + fPosition);
|
||||||
|
fPosition += 2;
|
||||||
|
|
||||||
|
return B_BENDIAN_TO_HOST_INT64(*ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
ReadStream::GetString()
|
||||||
|
{
|
||||||
|
if (_PositionToSize() >= fSize) {
|
||||||
|
fEOF = true;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 size;
|
||||||
|
const void* ptr = GetOpaque(&size);
|
||||||
|
if (ptr == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
char* str = reinterpret_cast<char*>(malloc(size + 1));
|
||||||
|
if (str == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
memcpy(str, ptr, size);
|
||||||
|
str[size] = 0;
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const void*
|
||||||
|
ReadStream::GetOpaque(uint32* size)
|
||||||
|
{
|
||||||
|
if (_PositionToSize() >= fSize) {
|
||||||
|
fEOF = true;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* ptr = NULL;
|
||||||
|
uint32 s = GetUInt();
|
||||||
|
if (s != 0) {
|
||||||
|
ptr = fBuffer + fPosition;
|
||||||
|
if (_PositionToSize() + s <= fSize)
|
||||||
|
fPosition += _RealSize(s) / sizeof(uint32);
|
||||||
|
else {
|
||||||
|
s = fSize - _PositionToSize();
|
||||||
|
fPosition = fSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size != NULL)
|
||||||
|
*size = s;
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WriteStream::WriteStream()
|
||||||
|
:
|
||||||
|
Stream(malloc(kInitialSize), kInitialSize),
|
||||||
|
fError(B_OK)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WriteStream::WriteStream(const WriteStream& x)
|
||||||
|
:
|
||||||
|
Stream(malloc(x.fSize), x.fSize),
|
||||||
|
fError(x.fError)
|
||||||
|
{
|
||||||
|
fPosition = x.fPosition;
|
||||||
|
memcpy(fBuffer, x.fBuffer, fSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WriteStream::~WriteStream()
|
||||||
|
{
|
||||||
|
free(fBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
WriteStream::InsertUInt(Stream::Position pos, uint32 x)
|
||||||
|
{
|
||||||
|
if (pos * sizeof(uint32) >= fSize) {
|
||||||
|
fError = B_BAD_VALUE;
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
fBuffer[pos] = B_HOST_TO_BENDIAN_INT32(x);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
WriteStream::AddInt(int32 x)
|
||||||
|
{
|
||||||
|
status_t err = _CheckResize(sizeof(int32));
|
||||||
|
if (err != B_OK)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
fBuffer[fPosition++] = B_HOST_TO_BENDIAN_INT32(x);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
WriteStream::AddUInt(uint32 x)
|
||||||
|
{
|
||||||
|
status_t err = _CheckResize(sizeof(uint32));
|
||||||
|
if (err != B_OK)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
fBuffer[fPosition++] = B_HOST_TO_BENDIAN_INT32(x);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
WriteStream::AddHyper(int64 x)
|
||||||
|
{
|
||||||
|
status_t err = _CheckResize(sizeof(int64));
|
||||||
|
if (err != B_OK)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
int64* ptr = reinterpret_cast<int64*>(fBuffer + fPosition);
|
||||||
|
*ptr = B_HOST_TO_BENDIAN_INT64(x);
|
||||||
|
fPosition += 2;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
WriteStream::AddUHyper(uint64 x)
|
||||||
|
{
|
||||||
|
status_t err = _CheckResize(sizeof(uint64));
|
||||||
|
if (err != B_OK)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
uint64* ptr = reinterpret_cast<uint64*>(fBuffer + fPosition);
|
||||||
|
*ptr = B_HOST_TO_BENDIAN_INT64(x);
|
||||||
|
fPosition += 2;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
WriteStream::AddString(const char* str, uint32 maxlen)
|
||||||
|
{
|
||||||
|
uint32 len = strlen(str);
|
||||||
|
uint32 size = min_c(maxlen, len);
|
||||||
|
|
||||||
|
return AddOpaque(str, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
WriteStream::AddOpaque(const void *ptr, uint32 size)
|
||||||
|
{
|
||||||
|
uint32 real_size = _RealSize(size);
|
||||||
|
status_t err = _CheckResize(real_size + sizeof(uint32));
|
||||||
|
if (err != B_OK)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
AddUInt(size);
|
||||||
|
memset(fBuffer + fPosition, 0, real_size);
|
||||||
|
memcpy(fBuffer + fPosition, ptr, size);
|
||||||
|
fPosition += real_size / sizeof(int32);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
WriteStream::AddOpaque(const WriteStream& stream)
|
||||||
|
{
|
||||||
|
return AddOpaque(stream.GetBuffer(), stream.GetSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
WriteStream::Append(const WriteStream& stream)
|
||||||
|
{
|
||||||
|
uint32 size = stream.GetSize();
|
||||||
|
status_t err = _CheckResize(size);
|
||||||
|
if (err != B_OK)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
memcpy(fBuffer + fPosition, stream.GetBuffer(), size);
|
||||||
|
fPosition += size / sizeof(int32);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
WriteStream::_CheckResize(uint32 size)
|
||||||
|
{
|
||||||
|
if (_PositionToSize() + size <= fSize)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
uint32 new_size = max_c(fSize * 2, fPosition * sizeof(uint32) + size);
|
||||||
|
|
||||||
|
void* ptr = realloc(fBuffer, new_size);
|
||||||
|
if (ptr == NULL) {
|
||||||
|
fError = B_NO_MEMORY;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
fBuffer = reinterpret_cast<uint32*>(ptr);
|
||||||
|
fSize = new_size;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Paweł Dziepak, [email protected]
|
||||||
|
*/
|
||||||
|
#ifndef XDR_H
|
||||||
|
#define XDR_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace XDR {
|
||||||
|
|
||||||
|
class Stream {
|
||||||
|
public:
|
||||||
|
typedef uint32 Position;
|
||||||
|
|
||||||
|
virtual ~Stream();
|
||||||
|
|
||||||
|
inline const void* GetBuffer() const;
|
||||||
|
inline Position GetCurrent() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Stream(void* buffer, uint32 size);
|
||||||
|
|
||||||
|
inline uint32 _PositionToSize() const;
|
||||||
|
inline uint32 _RealSize(uint32 size) const;
|
||||||
|
|
||||||
|
uint32* fBuffer;
|
||||||
|
uint32 fSize;
|
||||||
|
Position fPosition;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ReadStream : public Stream {
|
||||||
|
public:
|
||||||
|
ReadStream(void* buffer, uint32 size);
|
||||||
|
virtual ~ReadStream();
|
||||||
|
|
||||||
|
inline int GetSize() const;
|
||||||
|
|
||||||
|
int32 GetInt();
|
||||||
|
uint32 GetUInt();
|
||||||
|
int64 GetHyper();
|
||||||
|
uint64 GetUHyper();
|
||||||
|
|
||||||
|
inline bool GetBoolean();
|
||||||
|
|
||||||
|
const char* GetString();
|
||||||
|
|
||||||
|
const void* GetOpaque(uint32* size);
|
||||||
|
|
||||||
|
inline bool IsEOF() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool fEOF;
|
||||||
|
};
|
||||||
|
|
||||||
|
class WriteStream : public Stream {
|
||||||
|
public:
|
||||||
|
WriteStream();
|
||||||
|
WriteStream(const WriteStream& x);
|
||||||
|
virtual ~WriteStream();
|
||||||
|
|
||||||
|
inline int GetSize() const;
|
||||||
|
|
||||||
|
status_t InsertUInt(Stream::Position pos, uint32 x);
|
||||||
|
|
||||||
|
status_t AddInt(int32 x);
|
||||||
|
status_t AddUInt(uint32 x);
|
||||||
|
status_t AddHyper(int64 x);
|
||||||
|
status_t AddUHyper(uint64 x);
|
||||||
|
|
||||||
|
inline status_t AddBoolean(bool x);
|
||||||
|
|
||||||
|
status_t AddString(const char* str, uint32 maxlen);
|
||||||
|
|
||||||
|
status_t AddOpaque(const void* ptr, uint32 size);
|
||||||
|
status_t AddOpaque(const WriteStream& stream);
|
||||||
|
|
||||||
|
status_t Append(const WriteStream& stream);
|
||||||
|
|
||||||
|
inline status_t GetError() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t _CheckResize(uint32 size);
|
||||||
|
|
||||||
|
status_t fError;
|
||||||
|
|
||||||
|
static const uint32 kInitialSize = 64;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline const void*
|
||||||
|
Stream::GetBuffer() const
|
||||||
|
{
|
||||||
|
return fBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Stream::Position
|
||||||
|
Stream::GetCurrent() const
|
||||||
|
{
|
||||||
|
return fPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline int
|
||||||
|
ReadStream::GetSize() const
|
||||||
|
{
|
||||||
|
return fSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
ReadStream::IsEOF() const
|
||||||
|
{
|
||||||
|
return fEOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
ReadStream::GetBoolean()
|
||||||
|
{
|
||||||
|
return GetInt() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline int
|
||||||
|
WriteStream::GetSize() const
|
||||||
|
{
|
||||||
|
return fPosition * sizeof(uint32);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline status_t
|
||||||
|
WriteStream::AddBoolean(bool x)
|
||||||
|
{
|
||||||
|
return AddInt(static_cast<int32>(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline status_t
|
||||||
|
WriteStream::GetError() const
|
||||||
|
{
|
||||||
|
return fError;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace XDR
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XDR_H
|
||||||
|
|
||||||
Reference in New Issue
Block a user