windows-nt/Source/XPSP1/NT/com/rpc/runtime/trans/common/httprts.cxx
2020-09-26 16:20:57 +08:00

5119 lines
128 KiB
C++

/*++
Copyright (C) Microsoft Corporation, 2001
Module Name:
HttpRTS.cxx
Abstract:
HTTP2 RTS packets support functions.
Author:
KamenM 09-07-01 Created
Revision History:
--*/
#include <precomp.hxx>
#include <HttpRTS.hxx>
const int TunnelSettingsCommandTypeSizes[LAST_RTS_COMMAND + 1] =
{
sizeof(ULONG), // tsctReceiveWindowSize
sizeof(FlowControlAck), // tsctFlowControlAck
sizeof(ULONG), // tsctConnectionTimeout
sizeof(ChannelSettingCookie), // tsctCookie
sizeof(ULONG), // tsctChannelLifetime
sizeof(ULONG), // tsctClientKeepalive
sizeof(ULONG), // tsctVersion
0, // tsctEmpty
sizeof(ULONG), // tsctPadding - size is variable. This is only for the conformance count
0, // tsctNANCE - no operands
0, // tsctANCE - no operands
sizeof(ChannelSettingClientAddress), // tsctClientAddress
sizeof(ChannelSettingCookie), // tsctAssociationGroupId
sizeof(ULONG), // tsctDestination
sizeof(ULONG) // tsctPingTrafficSentNotify
};
const int ClientAddressSizes[] =
{
FIELD_OFFSET(ChannelSettingClientAddress, u) + sizeof(SOCKADDR_IN),
FIELD_OFFSET(ChannelSettingClientAddress, u) + sizeof(SOCKADDR_IN6)
};
BYTE *ValidateRTSPacketCommon (
IN BYTE *Packet,
IN ULONG PacketLength
)
/*++
Routine Description:
Validates the common portions of an RTS packet.
Arguments:
Packet - the packet to be validated.
PacketLength - the length of the packet.
Return Value:
A pointer to the location after the common part if successful.
NULL is validation failed.
--*/
{
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
if (PacketLength < BaseRTSSizeAndPadding)
{
ASSERT(0);
return NULL;
}
if (RTS->common.frag_length != (unsigned short) PacketLength)
{
ASSERT(0);
return NULL;
}
if ( (RTS->common.rpc_vers != OSF_RPC_V20_VERS)
|| (RTS->common.rpc_vers_minor > OSF_RPC_V20_VERS_MINOR))
{
ASSERT(0);
return NULL;
}
if (RTS->common.pfc_flags != (PFC_FIRST_FRAG | PFC_LAST_FRAG))
{
ASSERT(0);
return NULL;
}
if (RTS->common.drep[0] != NDR_LITTLE_ENDIAN)
{
ASSERT(0);
return NULL;
}
if ((RTS->common.auth_length != 0)
|| (RTS->common.call_id != 0))
{
ASSERT(0);
return NULL;
}
return (Packet + BaseRTSSizeAndPadding);
}
RPC_STATUS CheckPacketForForwarding (
IN BYTE *Packet,
IN ULONG PacketLength,
IN ForwardDestinations CurrentLocation
)
/*++
Routine Description:
Checks whether a packet needs forwarding, and if yes,
patches up the protocol version if it is present.
Arguments:
Packet - the packet to be validated.
PacketLength - the length of the packet.
CurrentLocation - the current location we're in. This is how
this routine knows whether to forward.
Return Value:
RPC_S_OK for success (means the packet is for us)
RPC_P_PACKET_NEEDS_FORWARDING - success, but packet is not for us
RPC_S_PROTOCOL_ERROR - packet is garbled and cannot be processed
--*/
{
BYTE *CurrentPosition;
ULONG CurrentLength;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
TunnelSettingsCommand *CurrentCommand;
int i;
BOOL ForwardingNeeded;
ULONG *ProtocolPosition;
CurrentPosition = ValidateRTSPacketCommon(Packet,
PacketLength);
if (CurrentPosition == NULL)
return RPC_S_PROTOCOL_ERROR;
ForwardingNeeded = FALSE;
ProtocolPosition = NULL;
CurrentLength = CurrentPosition - Packet;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
for (i = 0; i < RTS->NumberOfSettingCommands; i ++)
{
// check if there is enough to read the command after this
CurrentLength += BaseRTSCommandSize;
if (CurrentLength > PacketLength)
return RPC_S_PROTOCOL_ERROR;
if (CurrentCommand->CommandType == tsctDestination)
{
CurrentLength += SIZE_OF_RTS_CMD_AND_PADDING(tsctDestination);
if (CurrentLength > PacketLength)
return RPC_S_PROTOCOL_ERROR;
if (CurrentCommand->u.Destination == CurrentLocation)
return RPC_S_OK;
ForwardingNeeded = TRUE;
// if we have found the protocol as well, we're done - break
// out of here
if (ProtocolPosition)
break;
}
else if (CurrentCommand->CommandType == tsctVersion)
{
CurrentLength += SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion);
if (CurrentLength > PacketLength)
return RPC_S_PROTOCOL_ERROR;
ProtocolPosition = &CurrentCommand->u.Version;
// if we have already found the destination as well, we're done -
// get out of here
if (ForwardingNeeded)
break;
}
else
{
if (CurrentCommand->CommandType > LAST_RTS_COMMAND)
return RPC_S_PROTOCOL_ERROR;
CurrentLength += SIZE_OF_RTS_CMD_AND_PADDING(CurrentCommand->CommandType);
}
CurrentCommand = (TunnelSettingsCommand *)(Packet + CurrentLength);
}
if (ForwardingNeeded)
{
if (ProtocolPosition)
*ProtocolPosition = HTTP2ProtocolVersion;
return RPC_P_PACKET_NEEDS_FORWARDING;
}
return RPC_S_OK;
}
BOOL UntrustedIsPingPacket (
IN BYTE *Packet,
IN ULONG PacketLength
)
/*++
Routine Description:
Checks if a packet coming from an untrusted source is a
ping packet.
Arguments:
Packet - the packet to be validated.
PacketLength - the length of the packet.
Return Value:
non-zero if it is a valid ping packet.
zero if it is a valid non-ping packet or if it is an
invalid packet.
--*/
{
BYTE *CurrentPosition;
rpcconn_tunnel_settings *RTS;
CurrentPosition = ValidateRTSPacketCommon(Packet,
PacketLength);
if (CurrentPosition == NULL)
return FALSE;
RTS = (rpcconn_tunnel_settings *)Packet;
return (RTS->Flags & RTS_FLAG_PING);
}
BOOL IsEchoPacket (
IN BYTE *Packet,
IN ULONG PacketLength
)
/*++
Routine Description:
Checks if a packet is an echo packet.
Arguments:
Packet - the packet to be validated.
PacketLength - the length of the packet.
Return Value:
non-zero if it is a valid echo packet.
zero if it is a valid non-echo packet or if it is an
invalid packet.
--*/
{
BYTE *CurrentPosition;
rpcconn_tunnel_settings *RTS;
CurrentPosition = ValidateRTSPacketCommon(Packet,
PacketLength);
if (CurrentPosition == NULL)
return FALSE;
RTS = (rpcconn_tunnel_settings *)Packet;
return (RTS->Flags & RTS_FLAG_ECHO);
}
BOOL IsOtherCmdPacket (
IN BYTE *Packet,
IN ULONG PacketLength
)
/*++
Routine Description:
Checks if a packet coming from an untrusted source is a
other cmd packet.
Arguments:
Packet - the packet to be validated.
PacketLength - the length of the packet.
Return Value:
non-zero if it is a valid other cmd packet.
zero if it is not a valid other cmd packet.
--*/
{
BYTE *CurrentPosition;
rpcconn_tunnel_settings *RTS;
CurrentPosition = ValidateRTSPacketCommon(Packet,
PacketLength);
if (CurrentPosition == NULL)
return FALSE;
RTS = (rpcconn_tunnel_settings *)Packet;
return (RTS->Flags & RTS_FLAG_OTHER_CMD);
}
HTTP2SendContext *AllocateAndInitializePingPacket (
void
)
/*++
Routine Description:
Allocates and initializes an RTS ping packet
Arguments:
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
0
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = RTS_FLAG_PING;
RTS->NumberOfSettingCommands = 0;
}
return SendContext;
}
HTTP2SendContext *AllocateAndInitializePingPacketWithSize (
IN ULONG TotalPacketSize
)
/*++
Routine Description:
Allocates and initializes an RTS ping packet padding
the packet until a certain size.
Arguments:
TotalPacketSize - the total desired size of the packet.
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
BOOL UseEmpty;
ULONG ExtraSize;
// the size of empty must be 0 for the calculation below to work
ASSERT(SIZE_OF_RTS_CMD_AND_PADDING(tsctEmpty) == 0);
ASSERT(TotalPacketSize >= BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 1
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctEmpty));
// reduce the TotalPacketSize to the size of the actual padding
// We subtract the base packet size + the padding command itself
TotalPacketSize -= BaseRTSCommandSize * 1
+ BaseRTSSizeAndPadding;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 1
+ TotalPacketSize
);
if (SendContext)
{
// if we were required to use larger size, we'll use the padding.
// if it was smaller, we'll use the empty command
if (TotalPacketSize >= SIZE_OF_RTS_CMD_AND_PADDING(tsctPadding))
{
TotalPacketSize -= SIZE_OF_RTS_CMD_AND_PADDING(tsctPadding);
UseEmpty = FALSE;
}
else
{
TotalPacketSize -= SIZE_OF_RTS_CMD_AND_PADDING(tsctEmpty);
UseEmpty = TRUE;
}
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = RTS_FLAG_PING;
RTS->NumberOfSettingCommands = 1;
CurrentCommand = RTS->Cmd;
if (UseEmpty)
{
// set empty command
CurrentCommand->CommandType = tsctEmpty;
}
else
{
// set padding command
CurrentCommand->CommandType = tsctPadding;
CurrentCommand->u.ConformanceCount = TotalPacketSize;
CurrentCommand = SkipCommand(CurrentCommand, tsctPadding);
// clean out the padding bytes
RpcpMemorySet(CurrentCommand, 0, TotalPacketSize);
}
}
return SendContext;
}
RPC_STATUS ParseAndFreePingPacket (
IN BYTE *Packet,
IN ULONG PacketLength
)
/*++
Routine Description:
Parses and frees a ping packet.
N.B.: UntrustedIsPingPacket must have
already been called and returned non-zero
for this function to be used.
Arguments:
Packet - the packet to be validated.
PacketLength - the length of the packet.
Return Value:
RPC_S_OK for success
RPC_S_PROTOCOL_ERROR for garbled packet
--*/
{
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
RPC_STATUS RpcStatus;
if (RTS->NumberOfSettingCommands != 0)
goto AbortAndExit;
if (RTS->Flags != RTS_FLAG_PING)
goto AbortAndExit;
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
RpcFreeBuffer(Packet);
return RpcStatus;
}
ULONG GetD1_A1TotalLength (
void
)
/*++
Routine Description:
Calculates the length of a D1/A1 RTS packet
Arguments:
Return Value:
The length of the D1/A1 RTS packet.
--*/
{
return (BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 4
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctReceiveWindowSize)
);
}
HTTP2SendContext *AllocateAndInitializeEmptyRTS (
void
)
/*++
Routine Description:
Allocates and initializes an empty RTS packet
Arguments:
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 1
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = 0;
RTS->NumberOfSettingCommands = 1;
CurrentCommand = RTS->Cmd;
// set empty command
CurrentCommand->CommandType = tsctEmpty;
}
return SendContext;
}
RPC_STATUS ParseEmptyRTS (
IN BYTE *Packet,
IN ULONG PacketLength
)
/*++
Routine Description:
Parses an empty RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 1
;
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 1)
goto AbortAndExit;
if (RTS->Flags != 0)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// verify empty
if (CurrentCommand->CommandType != tsctEmpty)
goto AbortAndExit;
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
return RpcStatus;
}
RPC_STATUS ParseAndFreeEmptyRTS (
IN BYTE *Packet,
IN ULONG PacketLength
)
/*++
Routine Description:
Parses and frees an empty RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
RPC_STATUS RpcStatus;
RpcStatus = ParseEmptyRTS(Packet,
PacketLength
);
RpcFreeBuffer(Packet);
return RpcStatus;
}
HTTP2SendContext *AllocateAndInitializeEmptyRTSWithDestination (
IN ForwardDestinations Destination
)
/*++
Routine Description:
Allocates and initializes an empty RTS packet
Arguments:
Destination - where to forward this to.
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 1
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctDestination)
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = 0;
RTS->NumberOfSettingCommands = 1;
CurrentCommand = RTS->Cmd;
// set destination
CurrentCommand->CommandType = tsctDestination;
CurrentCommand->u.Destination = Destination;
}
return SendContext;
}
RPC_STATUS ParseEmptyRTSWithDestination (
IN BYTE *Packet,
IN ULONG PacketLength,
IN ForwardDestinations ExpectedDestination
)
/*++
Routine Description:
Parses an empty RTS packet with destination
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
ExpectedDestination - the destination code for this location (client)
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 1
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctDestination)
;
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 1)
goto AbortAndExit;
if (RTS->Flags != 0)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// verify destination
if (CurrentCommand->CommandType != tsctDestination)
goto AbortAndExit;
if (ExpectedDestination != CurrentCommand->u.Destination)
goto AbortAndExit;
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
return RpcStatus;
}
RPC_STATUS ParseAndFreeEmptyRTSWithDestination (
IN BYTE *Packet,
IN ULONG PacketLength,
IN ForwardDestinations ExpectedDestination
)
/*++
Routine Description:
Parses and frees an empty RTS packet with destination
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
ExpectedDestination - the destination code for this location (client)
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
RPC_STATUS RpcStatus;
RpcStatus = ParseEmptyRTSWithDestination (Packet,
PacketLength,
ExpectedDestination
);
RpcFreeBuffer(Packet);
return RpcStatus;
}
HTTP2SendContext *AllocateAndInitializeD1_A1 (
IN ULONG ProtocolVersion,
IN HTTP2Cookie *ConnectionCookie,
IN HTTP2Cookie *ChannelCookie,
IN ULONG ClientReceiveWindow
)
/*++
Routine Description:
Allocates and initializes a D1/A1 RTS packet
Arguments:
ProtocolVersion - the version of the HTTP tunnelling protocol
ConnectionCookie - the connection cookie
ChannelCookie - the channel cookie
ClientReceiveWindow - the client receive window
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 4
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctReceiveWindowSize)
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = 0;
RTS->NumberOfSettingCommands = 4;
CurrentCommand = RTS->Cmd;
// set version
CurrentCommand->CommandType = tsctVersion;
CurrentCommand->u.Version = ProtocolVersion;
CurrentCommand = SkipCommand(CurrentCommand, tsctVersion);
// set connection cookie
CurrentCommand->CommandType = tsctCookie;
RpcpMemoryCopy(CurrentCommand->u.Cookie.Cookie, ConnectionCookie->GetCookie(), COOKIE_SIZE_IN_BYTES);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// set channel cookie
CurrentCommand->CommandType = tsctCookie;
RpcpMemoryCopy(CurrentCommand->u.Cookie.Cookie, ChannelCookie->GetCookie(), COOKIE_SIZE_IN_BYTES);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// set client receive window
CurrentCommand->CommandType = tsctReceiveWindowSize;
CurrentCommand->u.ReceiveWindowSize = ClientReceiveWindow;
}
return SendContext;
}
RPC_STATUS ParseAndFreeD1_A1 (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT ULONG *ProtocolVersion,
OUT HTTP2Cookie *ConnectionCookie,
OUT HTTP2Cookie *ChannelCookie,
OUT ULONG *ClientReceiveWindow
)
/*++
Routine Description:
Parses and frees a D1/A1 RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
ProtocolVersion - the version of the HTTP tunnelling protocol
ConnectionCookie - the connection cookie
ChannelCookie - the channel cookie
ClientReceiveWindow - the client receive window
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 4
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctReceiveWindowSize);
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 4)
goto AbortAndExit;
if (RTS->Flags != 0)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// get version
if (CurrentCommand->CommandType != tsctVersion)
goto AbortAndExit;
*ProtocolVersion = CurrentCommand->u.Version;
CurrentCommand = SkipCommand(CurrentCommand, tsctVersion);
// get connection cookie
if (CurrentCommand->CommandType != tsctCookie)
goto AbortAndExit;
ConnectionCookie->SetCookie((BYTE *)CurrentCommand->u.Cookie.Cookie);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// get channel cookie
if (CurrentCommand->CommandType != tsctCookie)
goto AbortAndExit;
ChannelCookie->SetCookie((BYTE *)CurrentCommand->u.Cookie.Cookie);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// get client receive window
if (CurrentCommand->CommandType != tsctReceiveWindowSize)
goto AbortAndExit;
*ClientReceiveWindow = CurrentCommand->u.ReceiveWindowSize;
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
RpcFreeBuffer(Packet);
return RpcStatus;
}
HTTP2SendContext *AllocateAndInitializeD1_A2 (
IN ULONG ProtocolVersion,
IN HTTP2Cookie *ConnectionCookie,
IN HTTP2Cookie *ChannelCookie,
IN ULONG ChannelLifetime,
IN ULONG ProxyReceiveWindow
)
/*++
Routine Description:
Allocates and initializes a D1/A2 RTS packet
Arguments:
ProtocolVersion - the version of the HTTP tunnelling protocol
ConnectionCookie - the connection cookie
ChannelCookie - the channel cookie
ChannelLifetime - the lifetime of the channel
ProxyReceiveWindow - the proxy receive window
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 5
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctChannelLifetime)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctReceiveWindowSize)
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = RTS_FLAG_OUT_CHANNEL;
RTS->NumberOfSettingCommands = 5;
CurrentCommand = RTS->Cmd;
// set version
CurrentCommand->CommandType = tsctVersion;
CurrentCommand->u.Version = ProtocolVersion;
CurrentCommand = SkipCommand(CurrentCommand, tsctVersion);
// set connection cookie
CurrentCommand->CommandType = tsctCookie;
RpcpMemoryCopy(CurrentCommand->u.Cookie.Cookie, ConnectionCookie->GetCookie(), COOKIE_SIZE_IN_BYTES);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// set channel cookie
CurrentCommand->CommandType = tsctCookie;
RpcpMemoryCopy(CurrentCommand->u.Cookie.Cookie, ChannelCookie->GetCookie(), COOKIE_SIZE_IN_BYTES);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// set channel lifetime
CurrentCommand->CommandType = tsctChannelLifetime;
CurrentCommand->u.ChannelLifetime = ChannelLifetime;
CurrentCommand = SkipCommand(CurrentCommand, tsctChannelLifetime);
// set proxy receive window
CurrentCommand->CommandType = tsctReceiveWindowSize;
CurrentCommand->u.ReceiveWindowSize = ProxyReceiveWindow;
}
return SendContext;
}
RPC_STATUS ParseD1_A2 (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT ULONG *ProtocolVersion,
OUT HTTP2Cookie *ConnectionCookie,
OUT HTTP2Cookie *ChannelCookie,
OUT ULONG *ChannelLifetime,
OUT ULONG *ProxyReceiveWindow
)
/*++
Routine Description:
Parses D1/A2 RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
ProtocolVersion - the version of the HTTP tunnelling protocol
ConnectionCookie - the connection cookie
ChannelCookie - the channel cookie
ChannelLifetime - the lifetime of the channel
ProxyReceiveWindow - the proxy receive window
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 5
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctChannelLifetime)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctReceiveWindowSize);
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 5)
goto AbortAndExit;
if (RTS->Flags != RTS_FLAG_OUT_CHANNEL)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// get version
if (CurrentCommand->CommandType != tsctVersion)
goto AbortAndExit;
*ProtocolVersion = CurrentCommand->u.Version;
CurrentCommand = SkipCommand(CurrentCommand, tsctVersion);
// get connection cookie
if (CurrentCommand->CommandType != tsctCookie)
goto AbortAndExit;
ConnectionCookie->SetCookie((BYTE *)CurrentCommand->u.Cookie.Cookie);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// get channel cookie
if (CurrentCommand->CommandType != tsctCookie)
goto AbortAndExit;
ChannelCookie->SetCookie((BYTE *)CurrentCommand->u.Cookie.Cookie);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// get channel lifetime
if (CurrentCommand->CommandType != tsctChannelLifetime)
goto AbortAndExit;
*ChannelLifetime = CurrentCommand->u.ChannelLifetime;
CurrentCommand = SkipCommand(CurrentCommand, tsctChannelLifetime);
// get proxy receive window
if (CurrentCommand->CommandType != tsctReceiveWindowSize)
goto AbortAndExit;
*ProxyReceiveWindow = CurrentCommand->u.ReceiveWindowSize;
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
return RpcStatus;
}
HTTP2SendContext *AllocateAndInitializeD1_B1 (
IN ULONG ProtocolVersion,
IN HTTP2Cookie *ConnectionCookie,
IN HTTP2Cookie *ChannelCookie,
IN ULONG ChannelLifetime,
IN ULONG ClientKeepAliveInterval,
IN HTTP2Cookie *AssociationGroupId
)
/*++
Routine Description:
Allocates and initializes a D1/B1 RTS packet
Arguments:
ProtocolVersion - the version of the HTTP tunnelling protocol
ConnectionCookie - the connection cookie
ChannelCookie - the channel cookie
ChannelLifetime - the lifetime of the channel
ClientKeepAliveInterval - the client receive window
AssociationGroupId - the association group id
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 6
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctChannelLifetime)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctClientKeepalive)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctAssociationGroupId)
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = 0;
RTS->NumberOfSettingCommands = 6;
CurrentCommand = RTS->Cmd;
// set version
CurrentCommand->CommandType = tsctVersion;
CurrentCommand->u.Version = ProtocolVersion;
CurrentCommand = SkipCommand(CurrentCommand, tsctVersion);
// set connection cookie
CurrentCommand->CommandType = tsctCookie;
RpcpMemoryCopy(CurrentCommand->u.Cookie.Cookie, ConnectionCookie->GetCookie(), COOKIE_SIZE_IN_BYTES);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// set channel cookie
CurrentCommand->CommandType = tsctCookie;
RpcpMemoryCopy(CurrentCommand->u.Cookie.Cookie, ChannelCookie->GetCookie(), COOKIE_SIZE_IN_BYTES);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// set channel lifetime
CurrentCommand->CommandType = tsctChannelLifetime;
CurrentCommand->u.ChannelLifetime = ChannelLifetime;
CurrentCommand = SkipCommand(CurrentCommand, tsctChannelLifetime);
// set client receive window
CurrentCommand->CommandType = tsctClientKeepalive;
CurrentCommand->u.ClientKeepalive = ClientKeepAliveInterval;
CurrentCommand = SkipCommand(CurrentCommand, tsctClientKeepalive);
// set association group id
CurrentCommand->CommandType = tsctAssociationGroupId;
RpcpMemoryCopy(CurrentCommand->u.AssociationGroupId.Cookie, AssociationGroupId->GetCookie(), COOKIE_SIZE_IN_BYTES);
}
return SendContext;
}
RPC_STATUS ParseAndFreeD1_B1 (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT ULONG *ProtocolVersion,
OUT HTTP2Cookie *ConnectionCookie,
OUT HTTP2Cookie *ChannelCookie,
OUT ULONG *ChannelLifetime,
OUT HTTP2Cookie *AssociationGroupId,
OUT ULONG *ClientKeepAliveInterval
)
/*++
Routine Description:
Parses and frees a D1/B1 RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
ProtocolVersion - on output, the version of the HTTP tunnelling protocol
Success only.
ConnectionCookie - on output, the connection cookie. Success only.
ChannelCookie - on output, the channel cookie. Success only.
ChannelLifetime - on output, the lifetime of the channel. Success only.
AssociationGroupId - on output, the client association group id.
Success only.
ClientKeepAliveInterval - on output, the client receive window.
Success only.
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 6
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctChannelLifetime)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctClientKeepalive)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctAssociationGroupId)
;
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 6)
goto AbortAndExit;
if (RTS->Flags != 0)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// get version
if (CurrentCommand->CommandType != tsctVersion)
goto AbortAndExit;
*ProtocolVersion = CurrentCommand->u.Version;
CurrentCommand = SkipCommand(CurrentCommand, tsctVersion);
// get connection cookie
if (CurrentCommand->CommandType != tsctCookie)
goto AbortAndExit;
ConnectionCookie->SetCookie((BYTE *)CurrentCommand->u.Cookie.Cookie);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// get channel cookie
if (CurrentCommand->CommandType != tsctCookie)
goto AbortAndExit;
ChannelCookie->SetCookie((BYTE *)CurrentCommand->u.Cookie.Cookie);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// get channel lifetime
if (CurrentCommand->CommandType != tsctChannelLifetime)
goto AbortAndExit;
*ChannelLifetime = CurrentCommand->u.ChannelLifetime;
CurrentCommand = SkipCommand(CurrentCommand, tsctChannelLifetime);
// get client keep alive
if (CurrentCommand->CommandType != tsctClientKeepalive)
goto AbortAndExit;
*ClientKeepAliveInterval = CurrentCommand->u.ClientKeepalive;
CurrentCommand = SkipCommand(CurrentCommand, tsctClientKeepalive);
// get association group id
if (CurrentCommand->CommandType != tsctAssociationGroupId)
goto AbortAndExit;
AssociationGroupId->SetCookie((BYTE *)CurrentCommand->u.AssociationGroupId.Cookie);
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
RpcFreeBuffer(Packet);
return RpcStatus;
}
HTTP2SendContext *AllocateAndInitializeD1_B2 (
IN ULONG ProtocolVersion,
IN HTTP2Cookie *ConnectionCookie,
IN HTTP2Cookie *ChannelCookie,
IN ULONG ReceiveWindowSize,
IN ULONG ConnectionTimeout,
IN HTTP2Cookie *AssociationGroupId,
IN ChannelSettingClientAddress *ClientAddress
)
/*++
Routine Description:
Allocates and initializes a D1/B2 RTS packet
Arguments:
ProtocolVersion - the version of the HTTP tunnelling protocol
ConnectionCookie - the connection cookie
ChannelCookie - the channel cookie
ReceiveWindowSize - the receive window size of the in proxy
ConnectionTimeout - connection timeout of the in proxy
ClientAddress - client address of the client as seen by the in proxy
AssociationGroupId - the association group id
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 7
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctReceiveWindowSize)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctConnectionTimeout)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctAssociationGroupId)
+ ClientAddressSizes[ClientAddress->AddressType]
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = RTS_FLAG_IN_CHANNEL;
RTS->NumberOfSettingCommands = 7;
CurrentCommand = RTS->Cmd;
// set version
CurrentCommand->CommandType = tsctVersion;
CurrentCommand->u.Version = ProtocolVersion;
CurrentCommand = SkipCommand(CurrentCommand, tsctVersion);
// set connection cookie
CurrentCommand->CommandType = tsctCookie;
RpcpMemoryCopy(CurrentCommand->u.Cookie.Cookie, ConnectionCookie->GetCookie(), COOKIE_SIZE_IN_BYTES);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// set channel cookie
CurrentCommand->CommandType = tsctCookie;
RpcpMemoryCopy(CurrentCommand->u.Cookie.Cookie, ChannelCookie->GetCookie(), COOKIE_SIZE_IN_BYTES);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// set receive window size
CurrentCommand->CommandType = tsctReceiveWindowSize;
CurrentCommand->u.ReceiveWindowSize = ReceiveWindowSize;
CurrentCommand = SkipCommand(CurrentCommand, tsctReceiveWindowSize);
// set connection timeout
CurrentCommand->CommandType = tsctConnectionTimeout;
CurrentCommand->u.ConnectionTimeout = ConnectionTimeout;
CurrentCommand = SkipCommand(CurrentCommand, tsctConnectionTimeout);
// set association group id
CurrentCommand->CommandType = tsctAssociationGroupId;
RpcpMemoryCopy(CurrentCommand->u.AssociationGroupId.Cookie, AssociationGroupId->GetCookie(), COOKIE_SIZE_IN_BYTES);
CurrentCommand = SkipCommand(CurrentCommand, tsctAssociationGroupId);
// set client address.
CurrentCommand->CommandType = tsctClientAddress;
CurrentCommand->u.ClientAddress.AddressType = ClientAddress->AddressType;
RpcpMemorySet(&CurrentCommand->u, 0, ClientAddressSizes[ClientAddress->AddressType]);
if (ClientAddress->AddressType == catIPv4)
{
RpcpCopyIPv4Address((SOCKADDR_IN *)ClientAddress->u.IPv4Address,
(SOCKADDR_IN *) CurrentCommand->u.ClientAddress.u.IPv4Address);
}
else
{
RpcpCopyIPv6Address((SOCKADDR_IN6 *)ClientAddress->u.IPv4Address,
(SOCKADDR_IN6 *) CurrentCommand->u.ClientAddress.u.IPv4Address);
}
}
return SendContext;
}
RPC_STATUS ParseD1_B2 (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT ULONG *ProtocolVersion,
OUT HTTP2Cookie *ConnectionCookie,
OUT HTTP2Cookie *ChannelCookie,
OUT ULONG *ReceiveWindowSize,
OUT ULONG *ConnectionTimeout,
OUT HTTP2Cookie *AssociationGroupId,
OUT ChannelSettingClientAddress *ClientAddress
)
/*++
Routine Description:
Parses a D1/B2 RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
ProtocolVersion - the version of the HTTP tunnelling protocol
ConnectionCookie - the connection cookie
ChannelCookie - the channel cookie
ReceiveWindowSize - the receive window size of the in proxy
ConnectionTimeout - connection timeout of the in proxy
AssociationGroupId - the association group id
ClientAddress - client address of the client as seen by the in proxy
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 7
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctReceiveWindowSize)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctConnectionTimeout)
+ FIELD_OFFSET(ChannelSettingClientAddress, u) // check for enough space to read the
// address type
;
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 7)
goto AbortAndExit;
if (RTS->Flags != RTS_FLAG_IN_CHANNEL)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// get version
if (CurrentCommand->CommandType != tsctVersion)
goto AbortAndExit;
*ProtocolVersion = CurrentCommand->u.Version;
CurrentCommand = SkipCommand(CurrentCommand, tsctVersion);
// get connection cookie
if (CurrentCommand->CommandType != tsctCookie)
goto AbortAndExit;
ConnectionCookie->SetCookie((BYTE *)CurrentCommand->u.Cookie.Cookie);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// get channel cookie
if (CurrentCommand->CommandType != tsctCookie)
goto AbortAndExit;
ChannelCookie->SetCookie((BYTE *)CurrentCommand->u.Cookie.Cookie);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// get receive window size
if (CurrentCommand->CommandType != tsctReceiveWindowSize)
goto AbortAndExit;
*ReceiveWindowSize = CurrentCommand->u.ReceiveWindowSize;
CurrentCommand = SkipCommand(CurrentCommand, tsctReceiveWindowSize);
// get connection timeout
if (CurrentCommand->CommandType != tsctConnectionTimeout)
goto AbortAndExit;
*ConnectionTimeout = CurrentCommand->u.ConnectionTimeout;
CurrentCommand = SkipCommand(CurrentCommand, tsctConnectionTimeout);
if (CurrentCommand->CommandType != tsctAssociationGroupId)
goto AbortAndExit;
AssociationGroupId->SetCookie((BYTE *)CurrentCommand->u.AssociationGroupId.Cookie);
CurrentCommand = SkipCommand(CurrentCommand, tsctAssociationGroupId);
// get client address. Note that we have checked the length only up to
// the address type. Everything after that must be validated separately
if (CurrentCommand->CommandType != tsctClientAddress)
goto AbortAndExit;
ClientAddress->AddressType = CurrentCommand->u.ClientAddress.AddressType;
// We have already calculated the size of the AddressType field. Add the
// size for the body of the client address
MemorySize +=
ClientAddressSizes[ClientAddress->AddressType]
- FIELD_OFFSET(ChannelSettingClientAddress, u);
if (PacketLength < MemorySize)
goto AbortAndExit;
if (ClientAddress->AddressType == catIPv4)
{
RpcpCopyIPv4Address((SOCKADDR_IN *)CurrentCommand->u.ClientAddress.u.IPv4Address,
(SOCKADDR_IN *)ClientAddress->u.IPv4Address);
}
else
{
RpcpCopyIPv6Address((SOCKADDR_IN6 *)CurrentCommand->u.ClientAddress.u.IPv4Address,
(SOCKADDR_IN6 *)ClientAddress->u.IPv4Address);
}
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
return RpcStatus;
}
RPC_STATUS GetFirstServerPacketType (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT HTTP2FirstServerPacketType *PacketType
)
/*++
Routine Description:
Determines the type of the first server packet.
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
PacketType - one of the members of the enumeration
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
rpcconn_tunnel_settings *RTS;
if (PacketLength < BaseRTSSizeAndPadding)
return RPC_S_PROTOCOL_ERROR;
RTS = (rpcconn_tunnel_settings *)Packet;
if (RTS->Flags & RTS_FLAG_OUT_CHANNEL)
{
if (RTS->Flags & RTS_FLAG_RECYCLE_CHANNEL)
*PacketType = http2fsptD4_A4;
else
*PacketType = http2fsptD1_A2;
return RPC_S_OK;
}
else if (RTS->Flags & RTS_FLAG_IN_CHANNEL)
{
if (RTS->Flags & RTS_FLAG_RECYCLE_CHANNEL)
*PacketType = http2fsptD2_A2;
else
*PacketType = http2fsptD1_B2;
return RPC_S_OK;
}
else
return RPC_S_PROTOCOL_ERROR;
}
RPC_STATUS GetClientOpenedPacketType (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT HTTP2ClientOpenedPacketType *PacketType
)
/*++
Routine Description:
Determines the type of the packet in client opened (or one of
the opened states)
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
PacketType - one of the members of the enumeration
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
rpcconn_tunnel_settings *RTS;
if (PacketLength < BaseRTSSizeAndPadding)
return RPC_S_PROTOCOL_ERROR;
RTS = (rpcconn_tunnel_settings *)Packet;
// here we expect D2/A4, D3/A4, D4/A2, D4/A6, D5/A6
// and D5/B3
if (RTS->Flags & RTS_FLAG_RECYCLE_CHANNEL)
{
*PacketType = http2coptD4_A2;
}
else if (RTS->Flags & RTS_FLAG_OUT_CHANNEL)
{
*PacketType = http2coptD4_A6;
}
else if (RTS->Flags & RTS_FLAG_EOF)
{
// D5/B3 has the EOF flag
*PacketType = http2coptD5_B3;
}
else if (IsD4_A10(Packet, PacketLength))
{
// D4/A10 is an ANCE packet.
*PacketType = http2coptD4_A10;
}
else if (IsD5_A6(Packet, PacketLength, fdClient))
{
// D5/A6 is an ANCE packet with forward destination.
*PacketType = http2coptD5_A6;
}
else if (IsD2_A4OrD3_A4(Packet, PacketLength))
{
*PacketType = http2coptD2_A4;
}
else
{
*PacketType = http2coptD3_A4;
}
return RPC_S_OK;
}
RPC_STATUS GetServerOpenedPacketType (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT HTTP2ServerOpenedPacketType *PacketType
)
/*++
Routine Description:
Determines the type of the packet in server opened (or one of
the opened states)
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
PacketType - one of the members of the enumeration
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
rpcconn_tunnel_settings *RTS;
if (PacketLength < BaseRTSSizeAndPadding)
return RPC_S_PROTOCOL_ERROR;
RTS = (rpcconn_tunnel_settings *)Packet;
// here we expect D2/A6, D2/B1, D3/A2, D4/A8 and D5/A8
if (RTS->Flags & RTS_FLAG_OUT_CHANNEL)
{
// D4/A8 and D5/A8 are differentiated by state only
*PacketType = http2soptD4_A8orD5_A8;
}
else if (IsEmptyRTS (Packet, PacketLength))
{
*PacketType = http2soptD2_B1;
}
else
{
*PacketType = http2soptD2_A6orD3_A2;
}
return RPC_S_OK;
}
RPC_STATUS GetOtherCmdPacketType (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT HTTP2OtherCmdPacketType *PacketType
)
/*++
Routine Description:
Determines the type of a packet containing other cmd flag
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
PacketType - one of the members of the enumeration
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
rpcconn_tunnel_settings *RTS;
if (PacketLength < BaseRTSSizeAndPadding)
return RPC_S_PROTOCOL_ERROR;
RTS = (rpcconn_tunnel_settings *)Packet;
// right now we only expect KeepAliveChange
*PacketType = http2ocptKeepAliveChange;
return RPC_S_OK;
}
RPC_STATUS GetServerOutChannelOtherCmdPacketType (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT HTTP2ServerOutChannelOtherCmdPacketType *PacketType
)
/*++
Routine Description:
Determines the type of a packet containing other cmd flag
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
PacketType - one of the members of the enumeration
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
// tsctPingTrafficSentNotify is shorter than tsctFlowControlAck
// This is how we differentiate them
ASSERT(SIZE_OF_RTS_CMD_AND_PADDING(tsctFlowControlAck)
> SIZE_OF_RTS_CMD_AND_PADDING(tsctPingTrafficSentNotify));
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 1
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctFlowControlAck)
;
if (PacketLength < MemorySize)
*PacketType = http2sococptPingTrafficSentNotify;
else
*PacketType = http2sococptFlowControl;
return RPC_S_OK;
}
const char *ResponseHeaderFragment1 = "HTTP/1.1 200 Success\r\nContent-Type:application/rpc\r\nContent-Length:";
const int ResponseHeaderFragment1Length = 67; // length of "HTTP/1.1 200 Success\r\nContent-Type:application/rpc\r\nContent-Length:"
const char *ResponseHeaderFragment2 = "\r\n\r\n";
const int ResponseHeaderFragment2Length = 4; // length of "\r\n\r\n"
HTTP2SendContext *AllocateAndInitializeResponseHeader (
void
)
/*++
Routine Description:
Allocates and initializes the out channel response header.
Arguments:
Return Value:
The allocated and initialized send context on success. NULL on
failure.
--*/
{
ULONG MemorySize;
char *Buffer;
char *OriginalBuffer;
HTTP2SendContext *SendContext;
MemorySize = ResponseHeaderFragment1Length
+ DefaultChannelLifetimeStringLength
+ ResponseHeaderFragment2Length
;
Buffer = (char *)RpcAllocateBuffer(HTTPSendContextSizeAndPadding + MemorySize);
if (Buffer == NULL)
return NULL;
OriginalBuffer = Buffer;
SendContext = (HTTP2SendContext *)Buffer;
Buffer += HTTPSendContextSizeAndPadding;
#if DBG
SendContext->ListEntryUsed = FALSE;
#endif
SendContext->maxWriteBuffer = MemorySize;
SendContext->pWriteBuffer = (BUFFER)Buffer;
SendContext->TrafficType = http2ttRaw;
SendContext->u.SyncEvent = NULL;
SendContext->Flags = 0;
SendContext->UserData = 0;
RpcpMemoryCopy(Buffer, ResponseHeaderFragment1, ResponseHeaderFragment1Length);
Buffer += ResponseHeaderFragment1Length;
RpcpMemoryCopy(Buffer, DefaultChannelLifetimeString, DefaultChannelLifetimeStringLength);
Buffer += DefaultChannelLifetimeStringLength;
RpcpMemoryCopy(Buffer, ResponseHeaderFragment2, ResponseHeaderFragment2Length);
return (HTTP2SendContext *)OriginalBuffer;
}
HTTP2SendContext *AllocateAndInitializeD1_A3 (
IN ULONG ProxyConnectionTimeout
)
/*++
Routine Description:
Allocates and initializes an D1_A3 packet.
Arguments:
ProxyConnectionTimeout - the proxy connection timeout.
Return Value:
The allocated and initialized send context on success. NULL on
failure.
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 1
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctReceiveWindowSize)
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->NumberOfSettingCommands = 1;
CurrentCommand = RTS->Cmd;
// set connection timeout
CurrentCommand->CommandType = tsctConnectionTimeout;
CurrentCommand->u.ConnectionTimeout = ProxyConnectionTimeout;
}
return SendContext;
}
RPC_STATUS ParseAndFreeD1_A3 (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT ULONG *ProxyConnectionTimeout
)
/*++
Routine Description:
Parses and frees a D1/A3 RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
ProxyConnectionTimeout - the proxy connection timeout is returned
here (success only).
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 1
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctConnectionTimeout);
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 1)
goto AbortAndExit;
if (RTS->Flags != 0)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// get connection timeout
if (CurrentCommand->CommandType != tsctConnectionTimeout)
goto AbortAndExit;
*ProxyConnectionTimeout = CurrentCommand->u.ConnectionTimeout;
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
RpcFreeBuffer(Packet);
return RpcStatus;
}
HTTP2SendContext *AllocateAndInitializeD1_B3 (
IN ULONG ReceiveWindowSize,
IN ULONG UpdatedProtocolVersion
)
/*++
Routine Description:
Allocates and initializes an D1_B3 packet.
Arguments:
ReceiveWindowSize - the server receive window size.
UpdatedProtocolVersion - the updated protocol version.
Return Value:
The allocated and initialized send context on success. NULL on
failure.
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 2
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctReceiveWindowSize)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->NumberOfSettingCommands = 2;
CurrentCommand = RTS->Cmd;
// set receive window
CurrentCommand->CommandType = tsctReceiveWindowSize;
CurrentCommand->u.ConnectionTimeout = ReceiveWindowSize;
CurrentCommand = SkipCommand(CurrentCommand, tsctReceiveWindowSize);
// set version
CurrentCommand->CommandType = tsctVersion;
CurrentCommand->u.Version = UpdatedProtocolVersion;
}
return SendContext;
}
RPC_STATUS ParseAndFreeD1_B3 (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT ULONG *ReceiveWindowSize,
OUT ULONG *UpdatedProtocolVersion
)
/*++
Routine Description:
Parses and frees a D1/A3 RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
ReceiveWindowSize - the receive window size is returned
here (success only).
UpdatedProtocolVersion - the updated protocol version from the
server (success only)
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 2
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctReceiveWindowSize)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
;
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 2)
goto AbortAndExit;
if (RTS->Flags != 0)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// get receive window
if (CurrentCommand->CommandType != tsctReceiveWindowSize)
goto AbortAndExit;
*ReceiveWindowSize = CurrentCommand->u.ConnectionTimeout;
CurrentCommand = SkipCommand(CurrentCommand, tsctReceiveWindowSize);
// get version
if (CurrentCommand->CommandType != tsctVersion)
goto AbortAndExit;
*UpdatedProtocolVersion = CurrentCommand->u.Version;
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
RpcFreeBuffer(Packet);
return RpcStatus;
}
HTTP2SendContext *AllocateAndInitializeD1_C1 (
IN ULONG UpdatedProtocolVersion,
IN ULONG InProxyReceiveWindowSize,
IN ULONG InProxyConnectionTimeout
)
/*++
Routine Description:
Allocates and initializes a D1_C1 packet.
Arguments:
UpdatedProtocolVersion - the updated protocol version.
InProxyReceiveWindowSize - the in proxy receive window size.
InProxyConnectionTimeout - the in proxy connection timeout
Return Value:
The allocated and initialized send context on success. NULL on
failure.
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 3
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctReceiveWindowSize)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctConnectionTimeout)
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->NumberOfSettingCommands = 3;
CurrentCommand = RTS->Cmd;
// set version
CurrentCommand->CommandType = tsctVersion;
CurrentCommand->u.Version = UpdatedProtocolVersion;
CurrentCommand = SkipCommand(CurrentCommand, tsctVersion);
// set receive window
CurrentCommand->CommandType = tsctReceiveWindowSize;
CurrentCommand->u.ReceiveWindowSize = InProxyReceiveWindowSize;
CurrentCommand = SkipCommand(CurrentCommand, tsctReceiveWindowSize);
// set connection timeout
CurrentCommand->CommandType = tsctConnectionTimeout;
CurrentCommand->u.ConnectionTimeout = InProxyConnectionTimeout;
}
return SendContext;
}
RPC_STATUS ParseD1_C1 (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT ULONG *UpdatedProtocolVersion,
OUT ULONG *InProxyReceiveWindowSize,
OUT ULONG *InProxyConnectionTimeout
)
/*++
Routine Description:
Parses a D1_C1 packet.
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
UpdatedProtocolVersion - the updated protocol version.
InProxyReceiveWindowSize - the in proxy receive window size.
InProxyConnectionTimeout - the in proxy connection timeout
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 3
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctReceiveWindowSize)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctConnectionTimeout)
;
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 3)
goto AbortAndExit;
if (RTS->Flags != 0)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// get version
if (CurrentCommand->CommandType != tsctVersion)
goto AbortAndExit;
*UpdatedProtocolVersion = CurrentCommand->u.Version;
CurrentCommand = SkipCommand(CurrentCommand, tsctVersion);
// get receive window
if (CurrentCommand->CommandType != tsctReceiveWindowSize)
goto AbortAndExit;
*InProxyReceiveWindowSize = CurrentCommand->u.ReceiveWindowSize;
CurrentCommand = SkipCommand(CurrentCommand, tsctReceiveWindowSize);
// get connection timeout
if (CurrentCommand->CommandType != tsctConnectionTimeout)
goto AbortAndExit;
*InProxyConnectionTimeout = CurrentCommand->u.ConnectionTimeout;
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
return RpcStatus;
}
RPC_STATUS ParseAndFreeD1_C2 (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT ULONG *UpdatedProtocolVersion,
OUT ULONG *InProxyReceiveWindowSize,
OUT ULONG *InProxyConnectionTimeout
)
/*++
Routine Description:
Parses and frees a D1_C2 packet.
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
UpdatedProtocolVersion - the updated protocol version.
InProxyReceiveWindowSize - the in proxy receive window size.
InProxyConnectionTimeout - the in proxy connection timeout
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
RPC_STATUS RpcStatus;
// D1/C1 has the same format as D1/C2
RpcStatus = ParseD1_C1(Packet,
PacketLength,
UpdatedProtocolVersion,
InProxyReceiveWindowSize,
InProxyConnectionTimeout
);
RpcFreeBuffer(Packet);
return RpcStatus;
}
HTTP2SendContext *AllocateAndInitializeD2_A1 (
IN ULONG ProtocolVersion,
IN HTTP2Cookie *ConnectionCookie,
IN HTTP2Cookie *OldChannelCookie,
IN HTTP2Cookie *NewChannelCookie
)
/*++
Routine Description:
Allocates and initializes a D2/A1 RTS packet
Arguments:
ProtocolVersion - the version of the HTTP tunnelling protocol
ConnectionCookie - the connection cookie
OldChannelCookie - the old channel cookie
NewChannelCookie - the new channel cookie
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 4
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = RTS_FLAG_RECYCLE_CHANNEL;
RTS->NumberOfSettingCommands = 4;
CurrentCommand = RTS->Cmd;
// set version
CurrentCommand->CommandType = tsctVersion;
CurrentCommand->u.Version = ProtocolVersion;
CurrentCommand = SkipCommand(CurrentCommand, tsctVersion);
// set connection cookie
CurrentCommand->CommandType = tsctCookie;
RpcpMemoryCopy(CurrentCommand->u.Cookie.Cookie, ConnectionCookie->GetCookie(), COOKIE_SIZE_IN_BYTES);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// set old channel cookie
CurrentCommand->CommandType = tsctCookie;
RpcpMemoryCopy(CurrentCommand->u.Cookie.Cookie, OldChannelCookie->GetCookie(), COOKIE_SIZE_IN_BYTES);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// set new channel cookie
CurrentCommand->CommandType = tsctCookie;
RpcpMemoryCopy(CurrentCommand->u.Cookie.Cookie, NewChannelCookie->GetCookie(), COOKIE_SIZE_IN_BYTES);
}
return SendContext;
}
RPC_STATUS ParseAndFreeD2_A1 (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT ULONG *ProtocolVersion,
OUT HTTP2Cookie *ConnectionCookie,
OUT HTTP2Cookie *OldChannelCookie,
OUT HTTP2Cookie *NewChannelCookie
)
/*++
Routine Description:
Parses and frees a D2/A1 RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
ProtocolVersion - on output, the version of the HTTP tunnelling protocol
Success only.
ConnectionCookie - on output, the connection cookie. Success only.
OldChannelCookie - on output, the old channel cookie. Success only.
NewChannelCookie - on output, the new channel cookie. Success only.
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 4
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
;
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 4)
goto AbortAndExit;
if (RTS->Flags != RTS_FLAG_RECYCLE_CHANNEL)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// get version
if (CurrentCommand->CommandType != tsctVersion)
goto AbortAndExit;
*ProtocolVersion = CurrentCommand->u.Version;
CurrentCommand = SkipCommand(CurrentCommand, tsctVersion);
// get connection cookie
if (CurrentCommand->CommandType != tsctCookie)
goto AbortAndExit;
ConnectionCookie->SetCookie((BYTE *)CurrentCommand->u.Cookie.Cookie);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// get new channel cookie
if (CurrentCommand->CommandType != tsctCookie)
goto AbortAndExit;
OldChannelCookie->SetCookie((BYTE *)CurrentCommand->u.Cookie.Cookie);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// get old channel cookie
if (CurrentCommand->CommandType != tsctCookie)
goto AbortAndExit;
NewChannelCookie->SetCookie((BYTE *)CurrentCommand->u.Cookie.Cookie);
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
RpcFreeBuffer(Packet);
return RpcStatus;
}
HTTP2SendContext *AllocateAndInitializeD2_A2 (
IN ULONG ProtocolVersion,
IN HTTP2Cookie *ConnectionCookie,
IN HTTP2Cookie *OldChannelCookie,
IN HTTP2Cookie *NewChannelCookie,
IN ULONG ReceiveWindowSize,
IN ULONG ConnectionTimeout
)
/*++
Routine Description:
Allocates and initializes a D2/A2 RTS packet
Arguments:
ProtocolVersion - the version of the HTTP tunnelling protocol
ConnectionCookie - the connection cookie
OldChannelCookie - the old channel cookie
NewChannelCookie - the new channel cookie
ReceiveWindowSize - the receive window size of the in proxy
ConnectionTimeout - connection timeout of the in proxy
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 6
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctReceiveWindowSize)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctConnectionTimeout)
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = RTS_FLAG_IN_CHANNEL | RTS_FLAG_RECYCLE_CHANNEL;
RTS->NumberOfSettingCommands = 6;
CurrentCommand = RTS->Cmd;
// set version
CurrentCommand->CommandType = tsctVersion;
CurrentCommand->u.Version = ProtocolVersion;
CurrentCommand = SkipCommand(CurrentCommand, tsctVersion);
// set connection cookie
CurrentCommand->CommandType = tsctCookie;
RpcpMemoryCopy(CurrentCommand->u.Cookie.Cookie, ConnectionCookie->GetCookie(), COOKIE_SIZE_IN_BYTES);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// set old channel cookie
CurrentCommand->CommandType = tsctCookie;
RpcpMemoryCopy(CurrentCommand->u.Cookie.Cookie, OldChannelCookie->GetCookie(), COOKIE_SIZE_IN_BYTES);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// set new channel cookie
CurrentCommand->CommandType = tsctCookie;
RpcpMemoryCopy(CurrentCommand->u.Cookie.Cookie, NewChannelCookie->GetCookie(), COOKIE_SIZE_IN_BYTES);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// set receive window size
CurrentCommand->CommandType = tsctReceiveWindowSize;
CurrentCommand->u.ReceiveWindowSize = ReceiveWindowSize;
CurrentCommand = SkipCommand(CurrentCommand, tsctReceiveWindowSize);
// set connection timeout
CurrentCommand->CommandType = tsctConnectionTimeout;
CurrentCommand->u.ConnectionTimeout = ConnectionTimeout;
}
return SendContext;
}
RPC_STATUS ParseD2_A2 (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT ULONG *ProtocolVersion,
OUT HTTP2Cookie *ConnectionCookie,
OUT HTTP2Cookie *OldChannelCookie,
OUT HTTP2Cookie *NewChannelCookie,
OUT ULONG *ReceiveWindowSize,
OUT ULONG *ConnectionTimeout
)
/*++
Routine Description:
Parses a D1/B2 RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
ProtocolVersion - the version of the HTTP tunnelling protocol
ConnectionCookie - the connection cookie
OldChannelCookie - the old channel cookie
NewChannelCookie - the new channel cookie
ReceiveWindowSize - the receive window size of the in proxy
ConnectionTimeout - connection timeout of the in proxy
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 6
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctReceiveWindowSize)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctConnectionTimeout)
;
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 6)
goto AbortAndExit;
if (RTS->Flags != (RTS_FLAG_IN_CHANNEL | RTS_FLAG_RECYCLE_CHANNEL))
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// get version
if (CurrentCommand->CommandType != tsctVersion)
goto AbortAndExit;
*ProtocolVersion = CurrentCommand->u.Version;
CurrentCommand = SkipCommand(CurrentCommand, tsctVersion);
// get connection cookie
if (CurrentCommand->CommandType != tsctCookie)
goto AbortAndExit;
ConnectionCookie->SetCookie((BYTE *)CurrentCommand->u.Cookie.Cookie);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// get old channel cookie
if (CurrentCommand->CommandType != tsctCookie)
goto AbortAndExit;
OldChannelCookie->SetCookie((BYTE *)CurrentCommand->u.Cookie.Cookie);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// get new channel cookie
if (CurrentCommand->CommandType != tsctCookie)
goto AbortAndExit;
NewChannelCookie->SetCookie((BYTE *)CurrentCommand->u.Cookie.Cookie);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// get receive window size
if (CurrentCommand->CommandType != tsctReceiveWindowSize)
goto AbortAndExit;
*ReceiveWindowSize = CurrentCommand->u.ReceiveWindowSize;
CurrentCommand = SkipCommand(CurrentCommand, tsctReceiveWindowSize);
// get connection timeout
if (CurrentCommand->CommandType != tsctConnectionTimeout)
goto AbortAndExit;
*ConnectionTimeout = CurrentCommand->u.ConnectionTimeout;
CurrentCommand = SkipCommand(CurrentCommand, tsctConnectionTimeout);
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
return RpcStatus;
}
HTTP2SendContext *AllocateAndInitializeD2_A3 (
IN ForwardDestinations Destination,
IN ULONG ProtocolVersion,
IN ULONG ReceiveWindowSize,
IN ULONG ConnectionTimeout
)
/*++
Routine Description:
Allocates and initializes a D2/A3 RTS packet
Arguments:
Destination - where to forward this to.
ProtocolVersion - the version of the HTTP tunnelling protocol
ReceiveWindowSize - the receive window size of the in proxy
ConnectionTimeout - connection timeout of the in proxy
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 4
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctDestination)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctReceiveWindowSize)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctConnectionTimeout)
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = 0;
RTS->NumberOfSettingCommands = 4;
CurrentCommand = RTS->Cmd;
// set destination
CurrentCommand->CommandType = tsctDestination;
CurrentCommand->u.Destination = Destination;
CurrentCommand = SkipCommand(CurrentCommand, tsctDestination);
// set version
CurrentCommand->CommandType = tsctVersion;
CurrentCommand->u.Version = ProtocolVersion;
CurrentCommand = SkipCommand(CurrentCommand, tsctVersion);
// set receive window size
CurrentCommand->CommandType = tsctReceiveWindowSize;
CurrentCommand->u.ReceiveWindowSize = ReceiveWindowSize;
CurrentCommand = SkipCommand(CurrentCommand, tsctReceiveWindowSize);
// set connection timeout
CurrentCommand->CommandType = tsctConnectionTimeout;
CurrentCommand->u.ConnectionTimeout = ConnectionTimeout;
}
return SendContext;
}
RPC_STATUS ParseAndFreeD2_A4 (
IN BYTE *Packet,
IN ULONG PacketLength,
IN ForwardDestinations ExpectedDestination,
OUT ULONG *ProtocolVersion,
OUT ULONG *ReceiveWindowSize,
OUT ULONG *ConnectionTimeout
)
/*++
Routine Description:
Parses and frees a D2/A4 RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
ExpectedDestination - the destination code for this location (client)
ProtocolVersion - the version of the HTTP tunnelling protocol
ReceiveWindowSize - the receive window size of the in proxy
ConnectionTimeout - connection timeout of the in proxy
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 4
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctDestination)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctReceiveWindowSize)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctConnectionTimeout)
;
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 4)
goto AbortAndExit;
if (RTS->Flags != 0)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// verify destination
if (CurrentCommand->CommandType != tsctDestination)
goto AbortAndExit;
if (ExpectedDestination != CurrentCommand->u.Destination)
goto AbortAndExit;
CurrentCommand = SkipCommand(CurrentCommand, tsctDestination);
// get version
if (CurrentCommand->CommandType != tsctVersion)
goto AbortAndExit;
*ProtocolVersion = CurrentCommand->u.Version;
CurrentCommand = SkipCommand(CurrentCommand, tsctVersion);
// get receive window size
if (CurrentCommand->CommandType != tsctReceiveWindowSize)
goto AbortAndExit;
*ReceiveWindowSize = CurrentCommand->u.ReceiveWindowSize;
CurrentCommand = SkipCommand(CurrentCommand, tsctReceiveWindowSize);
// get connection timeout
if (CurrentCommand->CommandType != tsctConnectionTimeout)
goto AbortAndExit;
*ConnectionTimeout = CurrentCommand->u.ConnectionTimeout;
CurrentCommand = SkipCommand(CurrentCommand, tsctConnectionTimeout);
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
RpcFreeBuffer(Packet);
return RpcStatus;
}
HTTP2SendContext *AllocateAndInitializeD2_A5 (
IN HTTP2Cookie *NewChannelCookie
)
/*++
Routine Description:
Allocates and initializes a D2/A5 RTS packet
Arguments:
NewChannelCookie - the new channel cookie
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 1
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = 0;
RTS->NumberOfSettingCommands = 1;
CurrentCommand = RTS->Cmd;
// set new channel cookie
CurrentCommand->CommandType = tsctCookie;
RpcpMemoryCopy(CurrentCommand->u.Cookie.Cookie, NewChannelCookie->GetCookie(), COOKIE_SIZE_IN_BYTES);
}
return SendContext;
}
RPC_STATUS ParseD2_A5 (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT HTTP2Cookie *NewChannelCookie
)
/*++
Routine Description:
Parses a D2/A5 RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
NewChannelCookie - the new channel cookie
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 1
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
;
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 1)
goto AbortAndExit;
if (RTS->Flags != 0)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// get new channel cookie
if (CurrentCommand->CommandType != tsctCookie)
goto AbortAndExit;
NewChannelCookie->SetCookie((BYTE *)CurrentCommand->u.Cookie.Cookie);
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
return RpcStatus;
}
RPC_STATUS ParseAndFreeD2_A6 (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT HTTP2Cookie *NewChannelCookie
)
/*++
Routine Description:
Parses and frees a D2/A6 RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
NewChannelCookie - the new channel cookie
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
RPC_STATUS RpcStatus;
// D2/A6 is the same as D2/A5
RpcStatus = ParseD2_A5(Packet,
PacketLength,
NewChannelCookie);
RpcFreeBuffer(Packet);
return RpcStatus;
}
HTTP2SendContext *AllocateAndInitializeD2_B2 (
IN ULONG ServerReceiveWindow
)
/*++
Routine Description:
Allocates and initializes a D2/B2 RTS packet
Arguments:
ServerReceiveWindow - the server receive window
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 1
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctReceiveWindowSize)
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = 0;
RTS->NumberOfSettingCommands = 1;
CurrentCommand = RTS->Cmd;
// set server receive window
CurrentCommand->CommandType = tsctReceiveWindowSize;
CurrentCommand->u.ReceiveWindowSize = ServerReceiveWindow;
}
return SendContext;
}
RPC_STATUS ParseAndFreeD2_B2 (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT ULONG *ServerReceiveWindow
)
/*++
Routine Description:
Parses and frees a D2/B2 RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
ServerReceiveWindow - the server receive window
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 1
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctReceiveWindowSize);
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 1)
goto AbortAndExit;
if (RTS->Flags != 0)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// get server receive window
if (CurrentCommand->CommandType != tsctReceiveWindowSize)
goto AbortAndExit;
*ServerReceiveWindow = CurrentCommand->u.ReceiveWindowSize;
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
RpcFreeBuffer(Packet);
return RpcStatus;
}
HTTP2SendContext *AllocateAndInitializeD4_A3 (
IN ULONG ProtocolVersion,
IN HTTP2Cookie *ConnectionCookie,
IN HTTP2Cookie *OldChannelCookie,
IN HTTP2Cookie *NewChannelCookie,
IN ULONG ClientReceiveWindow
)
/*++
Routine Description:
Allocates and initializes a D4/A3 RTS packet
Arguments:
ProtocolVersion - the version of the HTTP tunnelling protocol
ConnectionCookie - the connection cookie
OldChannelCookie - the old channel cookie
NewChannelCookie - the new channel cookie
ClientReceiveWindow - the client receive window
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 5
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctReceiveWindowSize)
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = RTS_FLAG_RECYCLE_CHANNEL;
RTS->NumberOfSettingCommands = 5;
CurrentCommand = RTS->Cmd;
// set version
CurrentCommand->CommandType = tsctVersion;
CurrentCommand->u.Version = ProtocolVersion;
CurrentCommand = SkipCommand(CurrentCommand, tsctVersion);
// set connection cookie
CurrentCommand->CommandType = tsctCookie;
RpcpMemoryCopy(CurrentCommand->u.Cookie.Cookie, ConnectionCookie->GetCookie(), COOKIE_SIZE_IN_BYTES);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// set old channel cookie
CurrentCommand->CommandType = tsctCookie;
RpcpMemoryCopy(CurrentCommand->u.Cookie.Cookie, OldChannelCookie->GetCookie(), COOKIE_SIZE_IN_BYTES);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// set new channel cookie
CurrentCommand->CommandType = tsctCookie;
RpcpMemoryCopy(CurrentCommand->u.Cookie.Cookie, NewChannelCookie->GetCookie(), COOKIE_SIZE_IN_BYTES);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// set client receive window
CurrentCommand->CommandType = tsctReceiveWindowSize;
CurrentCommand->u.ReceiveWindowSize = ClientReceiveWindow;
}
return SendContext;
}
RPC_STATUS ParseAndFreeD4_A2 (
IN BYTE *Packet,
IN ULONG PacketLength
)
/*++
Routine Description:
Parses and frees a D4/A2 packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 1
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctDestination)
;
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 1)
goto AbortAndExit;
if (RTS->Flags != RTS_FLAG_RECYCLE_CHANNEL)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// verify destination
if (CurrentCommand->CommandType != tsctDestination)
goto AbortAndExit;
if (fdClient != CurrentCommand->u.Destination)
goto AbortAndExit;
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
RpcFreeBuffer(Packet);
return RpcStatus;
}
ULONG GetD4_A3TotalLength (
void
)
/*++
Routine Description:
Calculates the length of a D1/A1 RTS packet
Arguments:
Return Value:
The length of the D1/A1 RTS packet.
--*/
{
return (BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 5
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctReceiveWindowSize)
);
}
ULONG GetD4_A11TotalLength (
void
)
/*++
Routine Description:
Calculates the length of a D4/A11 RTS packet
Arguments:
Return Value:
The length of the D4/A11 RTS packet.
--*/
{
return (BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 1
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctANCE)
);
}
RPC_STATUS ParseD4_A3 (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT ULONG *ProtocolVersion,
OUT HTTP2Cookie *ConnectionCookie,
OUT HTTP2Cookie *OldChannelCookie,
OUT HTTP2Cookie *NewChannelCookie,
OUT ULONG *ClientReceiveWindow
)
/*++
Routine Description:
Parses and frees a D1/A1 RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
ProtocolVersion - the version of the HTTP tunnelling protocol
ConnectionCookie - the connection cookie
OldChannelCookie - the old channel cookie
NewChannelCookie - the new channel cookie
ClientReceiveWindow - the client receive window
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 5
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctReceiveWindowSize);
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 5)
goto AbortAndExit;
if (RTS->Flags != RTS_FLAG_RECYCLE_CHANNEL)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// get version
if (CurrentCommand->CommandType != tsctVersion)
goto AbortAndExit;
*ProtocolVersion = CurrentCommand->u.Version;
CurrentCommand = SkipCommand(CurrentCommand, tsctVersion);
// get connection cookie
if (CurrentCommand->CommandType != tsctCookie)
goto AbortAndExit;
ConnectionCookie->SetCookie((BYTE *)CurrentCommand->u.Cookie.Cookie);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// get old channel cookie
if (CurrentCommand->CommandType != tsctCookie)
goto AbortAndExit;
OldChannelCookie->SetCookie((BYTE *)CurrentCommand->u.Cookie.Cookie);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// get new channel cookie
if (CurrentCommand->CommandType != tsctCookie)
goto AbortAndExit;
NewChannelCookie->SetCookie((BYTE *)CurrentCommand->u.Cookie.Cookie);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// get client receive window
if (CurrentCommand->CommandType != tsctReceiveWindowSize)
goto AbortAndExit;
*ClientReceiveWindow = CurrentCommand->u.ReceiveWindowSize;
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
return RpcStatus;
}
RPC_STATUS ParseAndFreeD4_A3 (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT ULONG *ProtocolVersion,
OUT HTTP2Cookie *ConnectionCookie,
OUT HTTP2Cookie *OldChannelCookie,
OUT HTTP2Cookie *NewChannelCookie,
OUT ULONG *ClientReceiveWindow
)
/*++
Routine Description:
Parses and frees a D1/A1 RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
ProtocolVersion - the version of the HTTP tunnelling protocol
ConnectionCookie - the connection cookie
OldChannelCookie - the old channel cookie
NewChannelCookie - the new channel cookie
ClientReceiveWindow - the client receive window
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
RPC_STATUS RpcStatus;
RpcStatus = ParseD4_A3 (Packet,
PacketLength,
ProtocolVersion,
ConnectionCookie,
OldChannelCookie,
NewChannelCookie,
ClientReceiveWindow
);
RpcFreeBuffer(Packet);
return RpcStatus;
}
HTTP2SendContext *AllocateAndInitializeD4_A4 (
IN ULONG ProtocolVersion,
IN HTTP2Cookie *ConnectionCookie,
IN HTTP2Cookie *OldChannelCookie,
IN HTTP2Cookie *NewChannelCookie,
IN ULONG ChannelLifetime,
IN ULONG ProxyReceiveWindow,
IN ULONG ProxyConnectionTimeout
)
/*++
Routine Description:
Allocates and initializes a D4/A4 RTS packet
Arguments:
ProtocolVersion - the version of the HTTP tunnelling protocol
ConnectionCookie - the connection cookie
OldChannelCookie - the old channel cookie
NewChannelCookie - the new channel cookie
ChannelLifetime - the lifetime of the channel
ProxyReceiveWindow - the proxy receive window
ProxyConnectionTimeout - the proxy connection timeout
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 7
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctChannelLifetime)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctReceiveWindowSize)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctConnectionTimeout)
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = RTS_FLAG_RECYCLE_CHANNEL | RTS_FLAG_OUT_CHANNEL;
RTS->NumberOfSettingCommands = 7;
CurrentCommand = RTS->Cmd;
// set version
CurrentCommand->CommandType = tsctVersion;
CurrentCommand->u.Version = ProtocolVersion;
CurrentCommand = SkipCommand(CurrentCommand, tsctVersion);
// set connection cookie
CurrentCommand->CommandType = tsctCookie;
RpcpMemoryCopy(CurrentCommand->u.Cookie.Cookie, ConnectionCookie->GetCookie(), COOKIE_SIZE_IN_BYTES);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// set old channel cookie
CurrentCommand->CommandType = tsctCookie;
RpcpMemoryCopy(CurrentCommand->u.Cookie.Cookie, OldChannelCookie->GetCookie(), COOKIE_SIZE_IN_BYTES);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// set new channel cookie
CurrentCommand->CommandType = tsctCookie;
RpcpMemoryCopy(CurrentCommand->u.Cookie.Cookie, NewChannelCookie->GetCookie(), COOKIE_SIZE_IN_BYTES);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// set channel lifetime
CurrentCommand->CommandType = tsctChannelLifetime;
CurrentCommand->u.ChannelLifetime = ChannelLifetime;
CurrentCommand = SkipCommand(CurrentCommand, tsctChannelLifetime);
// set proxy receive window
CurrentCommand->CommandType = tsctReceiveWindowSize;
CurrentCommand->u.ReceiveWindowSize = ProxyReceiveWindow;
CurrentCommand = SkipCommand(CurrentCommand, tsctReceiveWindowSize);
// set proxy connection timeout
CurrentCommand->CommandType = tsctConnectionTimeout;
CurrentCommand->u.ConnectionTimeout = ProxyConnectionTimeout;
}
return SendContext;
}
RPC_STATUS ParseD4_A4 (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT ULONG *ProtocolVersion,
OUT HTTP2Cookie *ConnectionCookie,
OUT HTTP2Cookie *OldChannelCookie,
OUT HTTP2Cookie *NewChannelCookie,
OUT ULONG *ChannelLifetime,
OUT ULONG *ProxyReceiveWindow,
OUT ULONG *ProxyConnectionTimeout
)
/*++
Routine Description:
Parses and frees a D1/A1 RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
ProtocolVersion - the version of the HTTP tunnelling protocol
ConnectionCookie - the connection cookie
OldChannelCookie - the old channel cookie
NewChannelCookie - the new channel cookie
ChannelLifetime - the lifetime of the channel
ProxyReceiveWindow - the proxy receive window
ProxyConnectionTimeout - the proxy connection timeout
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 7
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctChannelLifetime)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctReceiveWindowSize)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctConnectionTimeout)
;
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 7)
goto AbortAndExit;
if (RTS->Flags != (RTS_FLAG_RECYCLE_CHANNEL | RTS_FLAG_OUT_CHANNEL))
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// get version
if (CurrentCommand->CommandType != tsctVersion)
goto AbortAndExit;
*ProtocolVersion = CurrentCommand->u.Version;
CurrentCommand = SkipCommand(CurrentCommand, tsctVersion);
// get connection cookie
if (CurrentCommand->CommandType != tsctCookie)
goto AbortAndExit;
ConnectionCookie->SetCookie((BYTE *)CurrentCommand->u.Cookie.Cookie);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// get old channel cookie
if (CurrentCommand->CommandType != tsctCookie)
goto AbortAndExit;
OldChannelCookie->SetCookie((BYTE *)CurrentCommand->u.Cookie.Cookie);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// get new channel cookie
if (CurrentCommand->CommandType != tsctCookie)
goto AbortAndExit;
NewChannelCookie->SetCookie((BYTE *)CurrentCommand->u.Cookie.Cookie);
CurrentCommand = SkipCommand(CurrentCommand, tsctCookie);
// get channel lifetime
if (CurrentCommand->CommandType != tsctChannelLifetime)
goto AbortAndExit;
*ChannelLifetime = CurrentCommand->u.ChannelLifetime;
CurrentCommand = SkipCommand(CurrentCommand, tsctChannelLifetime);
// get proxy receive window
if (CurrentCommand->CommandType != tsctReceiveWindowSize)
goto AbortAndExit;
*ProxyReceiveWindow = CurrentCommand->u.ReceiveWindowSize;
CurrentCommand = SkipCommand(CurrentCommand, tsctReceiveWindowSize);
// get proxy connection timeout
if (CurrentCommand->CommandType != tsctConnectionTimeout)
goto AbortAndExit;
*ProxyConnectionTimeout = CurrentCommand->u.ConnectionTimeout;
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
return RpcStatus;
}
HTTP2SendContext *AllocateAndInitializeD4_A5 (
IN ForwardDestinations Destination,
IN ULONG ProtocolVersion,
IN ULONG ConnectionTimeout
)
/*++
Routine Description:
Allocates and initializes a D4/A5 RTS packet
Arguments:
Destination - where to forward this to.
ProtocolVersion - the version of the HTTP tunnelling protocol
ConnectionTimeout - connection timeout of the out proxy
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 3
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctDestination)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctConnectionTimeout)
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = RTS_FLAG_OUT_CHANNEL;
RTS->NumberOfSettingCommands = 3;
CurrentCommand = RTS->Cmd;
// set destination
CurrentCommand->CommandType = tsctDestination;
CurrentCommand->u.Destination = Destination;
CurrentCommand = SkipCommand(CurrentCommand, tsctDestination);
// set version
CurrentCommand->CommandType = tsctVersion;
CurrentCommand->u.Version = ProtocolVersion;
CurrentCommand = SkipCommand(CurrentCommand, tsctVersion);
// set connection timeout
CurrentCommand->CommandType = tsctConnectionTimeout;
CurrentCommand->u.ConnectionTimeout = ConnectionTimeout;
}
return SendContext;
}
RPC_STATUS ParseAndFreeD4_A6 (
IN BYTE *Packet,
IN ULONG PacketLength,
IN ForwardDestinations ExpectedDestination,
OUT ULONG *ProtocolVersion,
OUT ULONG *ConnectionTimeout
)
/*++
Routine Description:
Parses and frees a D4/A6 RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
ExpectedDestination - the destination code for this location (client)
ProtocolVersion - the version of the HTTP tunnelling protocol
ConnectionTimeout - connection timeout of the out proxy
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 3
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctDestination)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctVersion)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctConnectionTimeout)
;
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 3)
goto AbortAndExit;
if (RTS->Flags != RTS_FLAG_OUT_CHANNEL)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// verify destination
if (CurrentCommand->CommandType != tsctDestination)
goto AbortAndExit;
if (ExpectedDestination != CurrentCommand->u.Destination)
goto AbortAndExit;
CurrentCommand = SkipCommand(CurrentCommand, tsctVersion);
// get version
if (CurrentCommand->CommandType != tsctVersion)
goto AbortAndExit;
*ProtocolVersion = CurrentCommand->u.Version;
CurrentCommand = SkipCommand(CurrentCommand, tsctVersion);
// get connection timeout
if (CurrentCommand->CommandType != tsctConnectionTimeout)
goto AbortAndExit;
*ConnectionTimeout = CurrentCommand->u.ConnectionTimeout;
CurrentCommand = SkipCommand(CurrentCommand, tsctConnectionTimeout);
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
RpcFreeBuffer(Packet);
return RpcStatus;
}
HTTP2SendContext *AllocateAndInitializeD4_A7 (
IN ForwardDestinations Destination,
IN HTTP2Cookie *NewChannelCookie
)
/*++
Routine Description:
Allocates and initializes a D4/A7 RTS packet
Arguments:
Destination - the destination for the packet.
NewChannelCookie - the new channel cookie
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 2
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctDestination)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = RTS_FLAG_OUT_CHANNEL;
RTS->NumberOfSettingCommands = 2;
CurrentCommand = RTS->Cmd;
// set destination
CurrentCommand->CommandType = tsctDestination;
CurrentCommand->u.Destination = Destination;
CurrentCommand = SkipCommand(CurrentCommand, tsctDestination);
// set new channel cookie
CurrentCommand->CommandType = tsctCookie;
RpcpMemoryCopy(CurrentCommand->u.Cookie.Cookie, NewChannelCookie->GetCookie(), COOKIE_SIZE_IN_BYTES);
}
return SendContext;
}
RPC_STATUS ParseAndFreeD4_A8 (
IN BYTE *Packet,
IN ULONG PacketLength,
IN ForwardDestinations ExpectedDestination,
OUT HTTP2Cookie *NewChannelCookie
)
/*++
Routine Description:
Parses a D2/A5 RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
NewChannelCookie - the new channel cookie
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 2
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctCookie)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctDestination)
;
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 2)
goto AbortAndExit;
if (RTS->Flags != RTS_FLAG_OUT_CHANNEL)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// verify destination
if (CurrentCommand->CommandType != tsctDestination)
goto AbortAndExit;
if (ExpectedDestination != CurrentCommand->u.Destination)
goto AbortAndExit;
CurrentCommand = SkipCommand(CurrentCommand, tsctDestination);
// get new channel cookie
if (CurrentCommand->CommandType != tsctCookie)
goto AbortAndExit;
NewChannelCookie->SetCookie((BYTE *)CurrentCommand->u.Cookie.Cookie);
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
RpcFreeBuffer(Packet);
return RpcStatus;
}
HTTP2SendContext *AllocateAndInitializeD4_A9 (
void
)
/*++
Routine Description:
Allocates and initializes a D4/A9 RTS packet
Arguments:
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 1
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctANCE)
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = 0;
RTS->NumberOfSettingCommands = 1;
CurrentCommand = RTS->Cmd;
// set ANCE command
CurrentCommand->CommandType = tsctANCE;
}
return SendContext;
}
RPC_STATUS ParseD4_A9 (
IN BYTE *Packet,
IN ULONG PacketLength
)
/*++
Routine Description:
Parses a D4/A10 RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 1
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctANCE)
;
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 1)
goto AbortAndExit;
if (RTS->Flags != 0)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// verify ANCE
if (CurrentCommand->CommandType != tsctANCE)
goto AbortAndExit;
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
return RpcStatus;
}
RPC_STATUS ParseAndFreeD4_A9 (
IN BYTE *Packet,
IN ULONG PacketLength
)
/*++
Routine Description:
Parses and frees a D4/A10 RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
RPC_STATUS RpcStatus;
RpcStatus = ParseD4_A10(Packet,
PacketLength
);
RpcFreeBuffer(Packet);
return RpcStatus;
}
HTTP2SendContext *AllocateAndInitializeD5_A5 (
IN ForwardDestinations Destination
)
/*++
Routine Description:
Allocates and initializes a D4/A9 RTS packet
Arguments:
Destination - destination for forwarding
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 2
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctDestination)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctANCE)
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = 0;
RTS->NumberOfSettingCommands = 2;
CurrentCommand = RTS->Cmd;
// set destination
CurrentCommand->CommandType = tsctDestination;
CurrentCommand->u.Destination = Destination;
CurrentCommand = SkipCommand(CurrentCommand, tsctDestination);
// set empty command
CurrentCommand->CommandType = tsctANCE;
}
return SendContext;
}
RPC_STATUS ParseD5_A6 (
IN BYTE *Packet,
IN ULONG PacketLength,
IN ForwardDestinations ExpectedDestination
)
/*++
Routine Description:
Parses a D5/A6 RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
ExpectedDestination - the destination code for the target location (client)
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 2
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctDestination)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctANCE)
;
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 2)
goto AbortAndExit;
if (RTS->Flags != 0)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// verify destination
if (CurrentCommand->CommandType != tsctDestination)
goto AbortAndExit;
if (ExpectedDestination != CurrentCommand->u.Destination)
goto AbortAndExit;
CurrentCommand = SkipCommand(CurrentCommand, tsctDestination);
// verify ANCE
if (CurrentCommand->CommandType != tsctANCE)
goto AbortAndExit;
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
return RpcStatus;
}
RPC_STATUS ParseAndFreeD5_A6 (
IN BYTE *Packet,
IN ULONG PacketLength,
IN ForwardDestinations ExpectedDestination
)
/*++
Routine Description:
Parses and frees a D5/A5 RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
ExpectedDestination - the destination code for this location (client)
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
RPC_STATUS RpcStatus;
RpcStatus = ParseD5_A6(Packet,
PacketLength,
ExpectedDestination
);
RpcFreeBuffer(Packet);
return RpcStatus;
}
HTTP2SendContext *AllocateAndInitializeD5_B1orB2 (
IN BOOL IsAckOrNak
)
/*++
Routine Description:
Allocates and initializes a D5/B1 or D5/B2 RTS packet
Arguments:
IsAckOrNack - non-zero if this is an ACK and D5/B1 needs
to go out. If 0, this is a NACK and D5/B2 will go out.
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
ASSERT(SIZE_OF_RTS_CMD_AND_PADDING(tsctANCE) == SIZE_OF_RTS_CMD_AND_PADDING(tsctNANCE));
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 1
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctANCE)
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = 0;
RTS->NumberOfSettingCommands = 1;
CurrentCommand = RTS->Cmd;
// set ANCE or NANCE command
if (IsAckOrNak)
CurrentCommand->CommandType = tsctANCE;
else
CurrentCommand->CommandType = tsctNANCE;
}
return SendContext;
}
RPC_STATUS ParseAndFreeD5_B1orB2 (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT BOOL *IsAckOrNak
)
/*++
Routine Description:
Parses and frees a D5/B1 or D2/B2 RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
IsAckOrNak - if success, on output it will contain
non-zero if the packet was ACK (ANCE or D5/B1)
or zero if the packet was NACK (NANCE or D5/B2)
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 1
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctANCE)
;
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 1)
goto AbortAndExit;
if (RTS->Flags != 0)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// verify ANCE
if (CurrentCommand->CommandType == tsctANCE)
*IsAckOrNak = TRUE;
else if (CurrentCommand->CommandType == tsctNANCE)
*IsAckOrNak = FALSE;
else
goto AbortAndExit;
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
RpcFreeBuffer(Packet);
return RpcStatus;
}
RPC_STATUS ParseAndFreeD5_B3 (
IN BYTE *Packet,
IN ULONG PacketLength
)
/*++
Routine Description:
Parses and frees a D5/B3 RTS packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 1
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctANCE)
;
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 1)
goto AbortAndExit;
if (RTS->Flags != RTS_FLAG_EOF)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// verify ANCE
if (CurrentCommand->CommandType != tsctANCE)
goto AbortAndExit;
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
RpcFreeBuffer(Packet);
return RpcStatus;
}
HTTP2SendContext *AllocateAndInitializeKeepAliveChangePacket (
IN ULONG NewKeepAliveInterval
)
/*++
Routine Description:
Allocates and initializes a keep alive change packet.
Arguments:
NewKeepAliveInterval - the new keep alive interval in
milliseconds
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 1
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctClientKeepalive)
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = RTS_FLAG_OTHER_CMD;
RTS->NumberOfSettingCommands = 1;
CurrentCommand = RTS->Cmd;
// set destination
CurrentCommand->CommandType = tsctClientKeepalive;
CurrentCommand->u.ClientKeepalive = NewKeepAliveInterval;
}
return SendContext;
}
RPC_STATUS ParseAndFreeKeepAliveChangePacket (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT ULONG *NewKeepAliveInterval
)
/*++
Routine Description:
Parses and frees a keep alive change packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
NewKeepAliveInterval - the new keep alive interval
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 1
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctClientKeepalive)
;
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 1)
goto AbortAndExit;
if (RTS->Flags != RTS_FLAG_OTHER_CMD)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// get new client keep alive
if (CurrentCommand->CommandType != tsctClientKeepalive)
goto AbortAndExit;
*NewKeepAliveInterval = CurrentCommand->u.ClientKeepalive;
if ((*NewKeepAliveInterval < MinimumClientNewKeepAliveInterval)
&& (*NewKeepAliveInterval != 0))
goto AbortAndExit;
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
RpcFreeBuffer(Packet);
return RpcStatus;
}
HTTP2SendContext *AllocateAndInitializeFlowControlAckPacket (
IN ULONG BytesReceivedForAck,
IN ULONG WindowForAck,
IN HTTP2Cookie *CookieForChannel
)
/*++
Routine Description:
Allocates and initializes a flow control ack packet
Arguments:
BytesReceivedForAck - the bytes received at the time the
ack was issued.
WindowForAck - the available window at the time the ack was
issued.
CookieForChannel - the cookie of the channel we ack to.
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 1
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctFlowControlAck)
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = RTS_FLAG_OTHER_CMD;
RTS->NumberOfSettingCommands = 1;
CurrentCommand = RTS->Cmd;
// set ack command
CurrentCommand->CommandType = tsctFlowControlAck;
CurrentCommand->u.Ack.BytesReceived = BytesReceivedForAck;
CurrentCommand->u.Ack.AvailableWindow = WindowForAck;
RpcpMemoryCopy(CurrentCommand->u.Ack.ChannelCookie.Cookie, CookieForChannel->GetCookie(), COOKIE_SIZE_IN_BYTES);
}
return SendContext;
}
HTTP2SendContext *AllocateAndInitializeFlowControlAckPacketWithDestination (
IN ForwardDestinations Destination,
IN ULONG BytesReceivedForAck,
IN ULONG WindowForAck,
IN HTTP2Cookie *CookieForChannel
)
/*++
Routine Description:
Allocates and initializes a flow control ack packet with a forward
destination
Arguments:
Destination - the destination to which to forward the packet
BytesReceivedForAck - the bytes received at the time the
ack was issued.
WindowForAck - the available window at the time the ack was
issued.
CookieForChannel - the cookie of the channel we ack to.
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 2
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctDestination)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctFlowControlAck)
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = RTS_FLAG_OTHER_CMD;
RTS->NumberOfSettingCommands = 2;
CurrentCommand = RTS->Cmd;
// set destination
CurrentCommand->CommandType = tsctDestination;
CurrentCommand->u.Destination = Destination;
CurrentCommand = SkipCommand(CurrentCommand, tsctDestination);
// set ack command
CurrentCommand->CommandType = tsctFlowControlAck;
CurrentCommand->u.Ack.BytesReceived = BytesReceivedForAck;
CurrentCommand->u.Ack.AvailableWindow = WindowForAck;
RpcpMemoryCopy(CurrentCommand->u.Ack.ChannelCookie.Cookie, CookieForChannel->GetCookie(), COOKIE_SIZE_IN_BYTES);
}
return SendContext;
}
RPC_STATUS ParseAndFreeFlowControlAckPacket (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT ULONG *BytesReceivedForAck,
OUT ULONG *WindowForAck,
OUT HTTP2Cookie *CookieForChannel
)
/*++
Routine Description:
Parses and frees a flow control ack packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
BytesReceivedForAck - the bytes received at the time the
ack was issued.
WindowForAck - the available window at the time the ack was
issued.
CookieForChannel - the cookie of the channel we received ack for.
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 1
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctFlowControlAck)
;
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 1)
goto AbortAndExit;
if (RTS->Flags != RTS_FLAG_OTHER_CMD)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// get ack values
if (CurrentCommand->CommandType != tsctFlowControlAck)
goto AbortAndExit;
*BytesReceivedForAck = CurrentCommand->u.Ack.BytesReceived;
*WindowForAck = CurrentCommand->u.Ack.AvailableWindow;
CookieForChannel->SetCookie((BYTE *)CurrentCommand->u.Ack.ChannelCookie.Cookie);
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
RpcFreeBuffer(Packet);
return RpcStatus;
}
RPC_STATUS ParseAndFreeFlowControlAckPacketWithDestination (
IN BYTE *Packet,
IN ULONG PacketLength,
IN ForwardDestinations ExpectedDestination,
OUT ULONG *BytesReceivedForAck,
OUT ULONG *WindowForAck,
OUT HTTP2Cookie *CookieForChannel
)
/*++
Routine Description:
Parses and frees a flow control ack packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
Destination - the expected destination
BytesReceivedForAck - the bytes received at the time the
ack was issued.
WindowForAck - the available window at the time the ack was
issued.
CookieForChannel - the cookie of the channel we received ack for.
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
RPC_STATUS RpcStatus;
RpcStatus = ParseFlowControlAckPacketWithDestination (
Packet,
PacketLength,
ExpectedDestination,
BytesReceivedForAck,
WindowForAck,
CookieForChannel
);
RpcFreeBuffer(Packet);
return RpcStatus;
}
RPC_STATUS ParseFlowControlAckPacketWithDestination (
IN BYTE *Packet,
IN ULONG PacketLength,
IN ForwardDestinations ExpectedDestination,
OUT ULONG *BytesReceivedForAck,
OUT ULONG *WindowForAck,
OUT HTTP2Cookie *CookieForChannel
)
/*++
Routine Description:
Parses a flow control ack packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
Destination - the expected destination
BytesReceivedForAck - the bytes received at the time the
ack was issued.
WindowForAck - the available window at the time the ack was
issued.
CookieForChannel - the cookie of the channel we received ack for.
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 2
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctDestination)
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctFlowControlAck)
;
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 2)
goto AbortAndExit;
if (RTS->Flags != RTS_FLAG_OTHER_CMD)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// verify destination
if (CurrentCommand->CommandType != tsctDestination)
goto AbortAndExit;
if (ExpectedDestination != CurrentCommand->u.Destination)
goto AbortAndExit;
CurrentCommand = SkipCommand(CurrentCommand, tsctDestination);
// get ack values
if (CurrentCommand->CommandType != tsctFlowControlAck)
goto AbortAndExit;
*BytesReceivedForAck = CurrentCommand->u.Ack.BytesReceived;
*WindowForAck = CurrentCommand->u.Ack.AvailableWindow;
CookieForChannel->SetCookie((BYTE *)CurrentCommand->u.Ack.ChannelCookie.Cookie);
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
return RpcStatus;
}
HTTP2SendContext *AllocateAndInitializePingTrafficSentNotifyPacket (
IN ULONG PingTrafficSentBytes
)
/*++
Routine Description:
Allocates and initializes a ping traffic sent packet
Arguments:
PingTrafficSentBytes - the number of bytes sent in ping traffic
Return Value:
The allocated send context or NULL for out-of-memory
--*/
{
HTTP2SendContext *SendContext;
TunnelSettingsCommand *CurrentCommand;
rpcconn_tunnel_settings *RTS;
SendContext = AllocateAndInitializeRTSPacket(
BaseRTSCommandSize * 1
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctPingTrafficSentNotify)
);
if (SendContext)
{
RTS = GetRTSPacketFromSendContext(SendContext);
RTS->Flags = RTS_FLAG_OTHER_CMD;
RTS->NumberOfSettingCommands = 1;
CurrentCommand = RTS->Cmd;
// set ping traffic sent
CurrentCommand->CommandType = tsctPingTrafficSentNotify;
CurrentCommand->u.PingTrafficSent = PingTrafficSentBytes;
}
return SendContext;
}
RPC_STATUS ParseAndFreePingTrafficSentNotifyPacket (
IN BYTE *Packet,
IN ULONG PacketLength,
OUT ULONG *PingTrafficSentBytes
)
/*++
Routine Description:
Parses a ping traffic sent packet
Arguments:
Packet - the packet received.
PacketLength - the length of the packet
PingTrafficSentBytes - the number of bytes sent in ping traffic
Return Value:
RPC_S_OK if the packet was successfully parsed and RPC_S_PROTOCOL_ERROR
otherwise.
--*/
{
ULONG MemorySize;
rpcconn_tunnel_settings *RTS = (rpcconn_tunnel_settings *)Packet;
BYTE *CurrentPosition;
TunnelSettingsCommand *CurrentCommand;
RPC_STATUS RpcStatus;
MemorySize = BaseRTSSizeAndPadding
+ BaseRTSCommandSize * 1
+ SIZE_OF_RTS_CMD_AND_PADDING(tsctPingTrafficSentNotify)
;
if (PacketLength < MemorySize)
goto AbortAndExit;
CurrentPosition = ValidateRTSPacketCommon(Packet, PacketLength);
if (CurrentPosition == NULL)
goto AbortAndExit;
if (RTS->NumberOfSettingCommands != 1)
goto AbortAndExit;
if (RTS->Flags != RTS_FLAG_OTHER_CMD)
goto AbortAndExit;
CurrentCommand = (TunnelSettingsCommand *)CurrentPosition;
// get ping traffic sent values
if (CurrentCommand->CommandType != tsctPingTrafficSentNotify)
goto AbortAndExit;
*PingTrafficSentBytes = CurrentCommand->u.PingTrafficSent;
RpcStatus = RPC_S_OK;
goto CleanupAndExit;
AbortAndExit:
RpcStatus = RPC_S_PROTOCOL_ERROR;
CleanupAndExit:
RpcFreeBuffer(Packet);
return RpcStatus;
}