TcpOptions Deserialize should return zero if a deserialization error happens

This commit is contained in:
Tommaso Pecorella
2014-09-09 09:44:37 +02:00
parent b6d33fd296
commit 0950f7f943
9 changed files with 154 additions and 91 deletions

View File

@@ -377,8 +377,12 @@ TcpHeader::Deserialize (Buffer::Iterator start)
uint8_t kind = i.PeekU8 ();
Ptr<TcpOption> op = TcpOption::CreateOption (kind);
optionLen -= op->Deserialize (i);
i.Next (op->GetSerializedSize ());
uint32_t optionSize;
optionSize = op->Deserialize (i);
NS_ASSERT_MSG (optionSize, "Unable to Deserialize an Option of Kind " << int (kind) << ", sorry.");
optionLen -= optionSize;
i.Next (optionSize);
if (op->GetKind () != TcpOption::END)
{

View File

@@ -83,7 +83,7 @@ TcpOptionEnd::Deserialize (Buffer::Iterator start)
if (readKind != GetKind ())
{
NS_LOG_WARN ("Malformed END option");
return 1;
return 0;
}
return GetSerializedSize ();
@@ -153,7 +153,7 @@ TcpOptionNOP::Deserialize (Buffer::Iterator start)
if (readKind != GetKind ())
{
NS_LOG_WARN ("Malformed NOP option");
return 1;
return 0;
}
return GetSerializedSize ();
@@ -225,7 +225,7 @@ TcpOptionMSS::Deserialize (Buffer::Iterator start)
if (readKind != GetKind ())
{
NS_LOG_WARN ("Malformed MSS option");
return 1;
return 0;
}
uint8_t size = i.ReadU8 ();
@@ -261,6 +261,8 @@ NS_OBJECT_ENSURE_REGISTERED (TcpOptionUnknown);
TcpOptionUnknown::TcpOptionUnknown ()
: TcpOption ()
{
m_kind = 0xFF;
m_size = 0;
}
TcpOptionUnknown::~TcpOptionUnknown ()
@@ -292,15 +294,21 @@ TcpOptionUnknown::Print (std::ostream &os) const
uint32_t
TcpOptionUnknown::GetSerializedSize (void) const
{
return 0;
return m_size;
}
void
TcpOptionUnknown::Serialize (Buffer::Iterator start) const
TcpOptionUnknown::Serialize (Buffer::Iterator i) const
{
NS_LOG_WARN ("Can't Serialize an Unknown Tcp Option");
if (m_size == 0)
{
NS_LOG_WARN ("Can't Serialize an Unknown Tcp Option");
return;
}
(void) start;
i.WriteU8 (GetKind ());
i.WriteU8 (GetSerializedSize ());
i.Write (m_content, m_size-2);
}
uint32_t
@@ -308,28 +316,21 @@ TcpOptionUnknown::Deserialize (Buffer::Iterator start)
{
Buffer::Iterator i = start;
uint8_t readKind = i.ReadU8 ();
NS_LOG_WARN ("Trying to Deserialize an Unknown Option of Kind=" << readKind);
m_kind = i.ReadU8 ();
NS_LOG_WARN ("Trying to Deserialize an Unknown Option of Kind " << int (m_kind));
uint8_t size = i.ReadU8 ();
m_size = i.ReadU8 ();
NS_ASSERT_MSG ((m_size >= 2) && (m_size < 40), "Unable to parse an Unknown Option of Kind " << int (m_kind) << " with apparent size " << int (m_size));
if (size < 2)
{
return 0;
}
i.Read (m_content, m_size-2);
for (uint8_t j = 2; j < size; ++j)
{
i.ReadU8 ();
}
return static_cast<uint32_t> (size);
return m_size;
}
uint8_t
TcpOptionUnknown::GetKind (void) const
{
return 100;
return m_kind;
}
} // namespace ns3

View File

@@ -25,7 +25,7 @@
namespace ns3 {
/**
* Defines the TCP option of kind 0 (end of option list) as in RFC793
* Defines the TCP option of kind 0 (end of option list) as in \RFC{793}
*/
class TcpOptionEnd : public TcpOption
{
@@ -33,6 +33,10 @@ public:
TcpOptionEnd ();
virtual ~TcpOptionEnd ();
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId (void);
virtual TypeId GetInstanceTypeId (void) const;
@@ -46,7 +50,7 @@ public:
};
/**
* Defines the TCP option of kind 1 (no operation) as in RFC793
* Defines the TCP option of kind 1 (no operation) as in \RFC{793}
*/
class TcpOptionNOP : public TcpOption
{
@@ -54,6 +58,10 @@ public:
TcpOptionNOP ();
virtual ~TcpOptionNOP ();
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId (void);
virtual TypeId GetInstanceTypeId (void) const;
@@ -66,7 +74,7 @@ public:
};
/**
* Defines the TCP option of kind 2 (maximum segment size) as in RFC793
* Defines the TCP option of kind 2 (maximum segment size) as in \RFC{793}
*/
class TcpOptionMSS : public TcpOption
{
@@ -74,6 +82,10 @@ public:
TcpOptionMSS ();
virtual ~TcpOptionMSS ();
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId (void);
virtual TypeId GetInstanceTypeId (void) const;
@@ -84,14 +96,26 @@ public:
virtual uint8_t GetKind (void) const;
virtual uint32_t GetSerializedSize (void) const;
/**
* \brief Get the Maximum Segment Size stored in the Option
* \return The Maximum Segment Size
*/
uint16_t GetMSS (void) const;
/**
* \brief Set the Maximum Segment Size stored in the Option
* \param mss The Maximum Segment Size
*/
void SetMSS (uint16_t mss);
protected:
uint16_t m_mss; // maximum segment size
uint16_t m_mss; //!< maximum segment size
};
/**
* \brief An unknown tcp option
* \brief An unknown TCP option.
*
* An unknown option can be deserialized and (only if deserialized previously)
* serialized again.
*/
class TcpOptionUnknown : public TcpOption
{
@@ -99,6 +123,10 @@ public:
TcpOptionUnknown ();
virtual ~TcpOptionUnknown ();
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId (void);
virtual TypeId GetInstanceTypeId (void) const;
@@ -108,6 +136,12 @@ public:
virtual uint8_t GetKind (void) const;
virtual uint32_t GetSerializedSize (void) const;
private:
uint8_t m_kind; //!< The unknown option kind
uint32_t m_size; //!< The unknown option size
uint8_t m_content[40]; //!< The option data
};
} // namespace ns3

View File

@@ -84,7 +84,7 @@ TcpOptionTS::Deserialize (Buffer::Iterator start)
if (readKind != GetKind ())
{
NS_LOG_WARN ("Malformed Timestamp option");
return 1;
return 0;
}
uint8_t size = i.ReadU8 ();

View File

@@ -27,7 +27,7 @@
namespace ns3 {
/**
* Defines the TCP option of kind 8 (timestamp option) as in RFC1323
* Defines the TCP option of kind 8 (timestamp option) as in \RFC{1323}
*/
class TcpOptionTS : public TcpOption
@@ -36,6 +36,10 @@ public:
TcpOptionTS ();
virtual ~TcpOptionTS ();
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId (void);
virtual TypeId GetInstanceTypeId (void) const;
@@ -46,9 +50,25 @@ public:
virtual uint8_t GetKind (void) const;
virtual uint32_t GetSerializedSize (void) const;
/**
* \brief Get the timestamp stored in the Option
* \return the timestamp
*/
uint32_t GetTimestamp (void) const;
/**
* \brief Get the timestamp echo stored in the Option
* \return the timestamp echo
*/
uint32_t GetEcho (void) const;
/**
* \brief Set the timestamp stored in the Option
* \param ts the timestamp
*/
void SetTimestamp (uint32_t ts);
/**
* \brief Set the timestamp echo stored in the Option
* \param ts the timestamp echo
*/
void SetEcho (uint32_t ts);
/**
@@ -79,8 +99,8 @@ public:
static Time ElapsedTimeFromTsValue (uint32_t echoTime);
protected:
uint32_t m_timestamp; // local timestamp
uint32_t m_echo; // echo timestamp
uint32_t m_timestamp; //!< local timestamp
uint32_t m_echo; //!< echo timestamp
};
} // namespace ns3

View File

@@ -83,7 +83,7 @@ TcpOptionWinScale::Deserialize (Buffer::Iterator start)
if (readKind != GetKind ())
{
NS_LOG_WARN ("Malformed Window Scale option");
return 1;
return 0;
}
uint8_t size = i.ReadU8 ();
NS_ASSERT (size == 3);

View File

@@ -27,14 +27,14 @@
namespace ns3 {
/**
* \brief Defines the TCP option of kind 3 (window scale option) as in RFC1323
* \brief Defines the TCP option of kind 3 (window scale option) as in \RFC{1323}
*
* For more efficient use of high bandwidth networks, a larger TCP window size
* may be used. The TCP window size field controls the flow of data and its
* value is limited to between 2 and 65,535 bytes.
*
* Since the size field cannot be expanded, a scaling factor is used.
* The TCP window scale option, as defined in RFC 1323, is an option used
* The TCP window scale option, as defined in \RFC{1323}, is an option used
* to increase the maximum window size from 65,535 bytes to 1 gigabyte.
* Scaling up to larger window sizes is a part of what is necessary for TCP Tuning.
*
@@ -48,61 +48,21 @@ namespace ns3 {
class TcpOptionWinScale : public TcpOption
{
public:
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId (void);
virtual TypeId GetInstanceTypeId (void) const;
/**
* \brief Create the option
*
* The scale is initialized with a 0U value.
*/
TcpOptionWinScale ();
/**
* \brief Deconstructor
*/
virtual ~TcpOptionWinScale ();
/**
* \brief Print the option to a ostream
*
* Only the window scale (uint8_t) is printed out.
*
* \param os Stream to which print the option to
*/
virtual void Print (std::ostream &os) const;
/**
* \brief Serialize the option to a Buffer
*
* The option writes three U8: kind, length, and the scale.
*
* \param start Buffer::Iterator to which write to
*/
virtual void Serialize (Buffer::Iterator start) const;
/**
* \brief Deserialize the option from a Buffer
*
* The option read two U8: length, and the scale. Kind SHOULD be read
* before call this method.
*
* \param start Buffer::Iterator to which read from
*/
virtual uint32_t Deserialize (Buffer::Iterator start);
/**
* \brief Get the kind value for this option
*
* \return Fixed value, TcpOption::WINSCALE
*/
virtual uint8_t GetKind (void) const;
/**
* \brief Get the serialized size of the option
*
* \return Fixed value, 3
*/
virtual uint32_t GetSerializedSize (void) const;
/**
@@ -114,7 +74,7 @@ public:
/**
* \brief Set the scale option
*
* The scale option SHOULD be <= 14 (as RFC).
* The scale option SHOULD be <= 14 (as \RFC{1323}).
*
* \param scale Scale factor
*/

View File

@@ -74,7 +74,7 @@ TcpOption::CreateOption (uint8_t kind)
{ TcpOption::WINSCALE, TcpOptionWinScale::GetTypeId () }
};
for (unsigned int i = 0; i < sizeof(toTid) / sizeof(kindToTid); ++i)
for (unsigned int i = 0; i < sizeof (toTid) / sizeof (kindToTid); ++i)
{
if (toTid[i].kind == kind)
{

View File

@@ -37,28 +37,72 @@ public:
TcpOption ();
virtual ~TcpOption ();
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId (void);
virtual TypeId GetInstanceTypeId (void) const;
/**
* The option Kind, as defined in the respective RFCs.
*/
enum Kind
{
END = 0,
NOP = 1,
MSS = 2,
WINSCALE = 3,
SACK_PERM = 4,
SACK = 5,
TS = 8
END = 0, //!< END
NOP = 1, //!< NOP
MSS = 2, //!< MSS
WINSCALE = 3, //!< WINSCALE
SACK_PERM = 4,//!< SACK_PERM
SACK = 5, //!< SACK
TS = 8 //!< TS
};
/**
* \brief Print the Option contents
* \param os the output stream
*/
virtual void Print (std::ostream &os) const = 0;
/**
* \brief Serialize the Option to a buffer iterator
* \param start the buffer iterator
*/
virtual void Serialize (Buffer::Iterator start) const = 0;
/**
* \brief Deserialize the Option from a buffer iterator
* \param start the buffer iterator
* \returns the number of deserialized bytes
*/
virtual uint32_t Deserialize (Buffer::Iterator start) = 0;
virtual uint8_t GetKind (void) const = 0; // Get the `kind' (as in RFC793) of this option
virtual uint32_t GetSerializedSize (void) const = 0; // Get the total length of this option, >= 1
/**
* \brief Get the `kind' (as in \RFC{793}) of this option
* \return the Option Kind
*/
virtual uint8_t GetKind (void) const = 0;
/**
* \brief Returns number of bytes required for Option
* serialization.
*
* \returns number of bytes required for Option
* serialization
*/
virtual uint32_t GetSerializedSize (void) const = 0;
static Ptr<TcpOption> CreateOption (uint8_t kind); // Factory method for all options
/**
* \brief Creates an option
* \param kind the option kind
* \return the requested option or an ns3::UnknownOption if the option is not supported
*/
static Ptr<TcpOption> CreateOption (uint8_t kind);
/**
* \brief Check if the option is implemented
* \param kind the Option kind
* \return true if the option is known
*/
static bool IsKindKnown (uint8_t kind);
};