You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
576 lines
9.0 KiB
576 lines
9.0 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
buffsock.cxx
|
|
|
|
Abstract:
|
|
|
|
Implements the BUFFERED_SOCKET class.
|
|
|
|
Author:
|
|
|
|
Keith Moore (keithmo) 02-Dec-1996
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "precomp.hxx"
|
|
#pragma hdrstop
|
|
|
|
|
|
//
|
|
// Private constants.
|
|
//
|
|
|
|
#define BUFFER_LENGTH 4096 // bytes
|
|
|
|
#define ALLOC_MEM(cb) (PVOID)::LocalAlloc(LPTR, (cb))
|
|
#define FREE_MEM(p) (VOID)::LocalFree((HLOCAL)(p))
|
|
|
|
|
|
//
|
|
// Private types.
|
|
//
|
|
|
|
|
|
//
|
|
// Private globals.
|
|
//
|
|
|
|
LONG BUFFERED_SOCKET::m_InitCount = -1;
|
|
|
|
|
|
//
|
|
// Private prototypes.
|
|
//
|
|
|
|
|
|
//
|
|
// Public functions.
|
|
//
|
|
|
|
|
|
BUFFERED_SOCKET::BUFFERED_SOCKET()
|
|
{
|
|
|
|
m_Socket = INVALID_SOCKET;
|
|
m_Buffer = NULL;
|
|
m_BufferLength = 0;
|
|
m_BytesAvailable = NULL;
|
|
m_Offset = 0;
|
|
m_Initialized = FALSE;
|
|
|
|
} // BUFFERED_SOCKET::BUFFERED_SOCKET()
|
|
|
|
|
|
BUFFERED_SOCKET::~BUFFERED_SOCKET()
|
|
{
|
|
|
|
if( m_Socket != INVALID_SOCKET ) {
|
|
|
|
::closesocket( m_Socket );
|
|
|
|
}
|
|
|
|
if( m_Buffer != NULL ) {
|
|
|
|
FREE_MEM( m_Buffer );
|
|
|
|
}
|
|
|
|
if( ::InterlockedDecrement( &BUFFERED_SOCKET::m_InitCount ) == -1 ) {
|
|
|
|
::WSACleanup();
|
|
|
|
}
|
|
|
|
} // BUFFERED_SOCKET::~BUFFERED_SOCKET()
|
|
|
|
|
|
INT
|
|
BUFFERED_SOCKET::InitializeClient(
|
|
LPSTR HostName,
|
|
USHORT Port
|
|
)
|
|
{
|
|
|
|
LPHOSTENT hostent;
|
|
INT result;
|
|
SOCKADDR_IN addr;
|
|
|
|
result = CommonInitialize();
|
|
|
|
if( result != 0 ) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
addr.sin_family = AF_INET;
|
|
addr.sin_port = htons( Port );
|
|
addr.sin_addr.s_addr = ::inet_addr( HostName );
|
|
|
|
if( addr.sin_addr.s_addr == INADDR_NONE ) {
|
|
|
|
hostent = ::gethostbyname( HostName );
|
|
|
|
if( hostent == NULL ) {
|
|
|
|
return ::WSAGetLastError();
|
|
|
|
}
|
|
|
|
addr.sin_addr.s_addr = *(PULONG)hostent->h_addr_list[0];
|
|
|
|
}
|
|
|
|
return InitializeClient( &addr );
|
|
|
|
} // BUFFERED_SOCKET::InitializeClient
|
|
|
|
|
|
INT
|
|
BUFFERED_SOCKET::InitializeClient(
|
|
LPSOCKADDR_IN HostAddress
|
|
)
|
|
{
|
|
|
|
INT result;
|
|
|
|
result = CommonInitialize();
|
|
|
|
if( result != 0 ) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
if( m_Socket == INVALID_SOCKET ) {
|
|
|
|
m_Socket = ::socket(
|
|
AF_INET,
|
|
SOCK_STREAM,
|
|
0
|
|
);
|
|
|
|
if( m_Socket == INVALID_SOCKET ) {
|
|
|
|
return ::WSAGetLastError();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( ::connect(
|
|
m_Socket,
|
|
(SOCKADDR *)HostAddress,
|
|
sizeof(*HostAddress)
|
|
) == SOCKET_ERROR ) {
|
|
|
|
return ::WSAGetLastError();
|
|
|
|
}
|
|
|
|
return InitializeClient( m_Socket );
|
|
|
|
} // BUFFERED_SOCKET::InitializeClient
|
|
|
|
|
|
INT
|
|
BUFFERED_SOCKET::InitializeClient(
|
|
SOCKET Socket
|
|
)
|
|
{
|
|
|
|
INT result;
|
|
|
|
result = CommonInitialize();
|
|
|
|
if( result != 0 ) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
m_Socket = Socket;
|
|
|
|
return 0;
|
|
|
|
} // BUFFERED_SOCKET::InitializeClient
|
|
|
|
|
|
INT
|
|
BUFFERED_SOCKET::InitializeServer(
|
|
USHORT Port
|
|
)
|
|
{
|
|
|
|
INT result;
|
|
SOCKET tmpSocket;
|
|
SOCKADDR_IN addr;
|
|
|
|
result = CommonInitialize();
|
|
|
|
if( result != 0 ) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
tmpSocket = ::socket(
|
|
AF_INET,
|
|
SOCK_STREAM,
|
|
0
|
|
);
|
|
|
|
if( tmpSocket == INVALID_SOCKET ) {
|
|
|
|
return ::WSAGetLastError();
|
|
|
|
}
|
|
|
|
addr.sin_family = AF_INET;
|
|
addr.sin_port = htons( Port );
|
|
addr.sin_addr.s_addr = INADDR_ANY;
|
|
|
|
result = ::bind(
|
|
tmpSocket,
|
|
(SOCKADDR *)&addr,
|
|
sizeof(addr)
|
|
);
|
|
|
|
if( result == SOCKET_ERROR ) {
|
|
|
|
result = ::WSAGetLastError();
|
|
::closesocket( tmpSocket );
|
|
return result;
|
|
|
|
}
|
|
|
|
result = ::listen(
|
|
tmpSocket,
|
|
1
|
|
);
|
|
|
|
if( result == SOCKET_ERROR ) {
|
|
|
|
result = ::WSAGetLastError();
|
|
::closesocket( tmpSocket );
|
|
return result;
|
|
|
|
}
|
|
|
|
m_Socket = ::accept(
|
|
tmpSocket,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if( m_Socket == INVALID_SOCKET ) {
|
|
|
|
result = ::WSAGetLastError();
|
|
::closesocket( tmpSocket );
|
|
return result;
|
|
|
|
}
|
|
|
|
::closesocket( tmpSocket );
|
|
return 0;
|
|
|
|
} // BUFFERED_SOCKET::InitializeClient
|
|
|
|
|
|
INT
|
|
BUFFERED_SOCKET::Send(
|
|
PVOID Buffer,
|
|
LPDWORD BufferLength
|
|
)
|
|
{
|
|
|
|
INT result;
|
|
|
|
result = ::send(
|
|
m_Socket,
|
|
(CHAR *)Buffer,
|
|
(INT)*BufferLength,
|
|
0
|
|
);
|
|
|
|
if( result == SOCKET_ERROR ) {
|
|
|
|
return ::WSAGetLastError();
|
|
|
|
}
|
|
|
|
*BufferLength = (DWORD)result;
|
|
return 0;
|
|
|
|
} // BUFFERED_SOCKET::Send
|
|
|
|
|
|
INT
|
|
BUFFERED_SOCKET::Recv(
|
|
PVOID Buffer,
|
|
LPDWORD BufferLength
|
|
)
|
|
{
|
|
|
|
INT result;
|
|
|
|
result = ::recv(
|
|
m_Socket,
|
|
(CHAR *)Buffer,
|
|
(INT)*BufferLength,
|
|
0
|
|
);
|
|
|
|
if( result == SOCKET_ERROR ) {
|
|
|
|
return ::WSAGetLastError();
|
|
|
|
}
|
|
|
|
*BufferLength = (DWORD)result;
|
|
return 0;
|
|
|
|
} // BUFFERED_SOCKET::Recv
|
|
|
|
|
|
INT
|
|
BUFFERED_SOCKET::SendFrame(
|
|
PVOID Buffer,
|
|
LPDWORD BufferLength
|
|
)
|
|
{
|
|
|
|
INT result;
|
|
WSABUF buffers[2];
|
|
|
|
buffers[0].len = sizeof(DWORD);
|
|
buffers[0].buf = (CHAR *)BufferLength;
|
|
buffers[1].len = *BufferLength;
|
|
buffers[1].buf = (CHAR *)Buffer;
|
|
|
|
result = ::WSASend(
|
|
m_Socket,
|
|
buffers,
|
|
2,
|
|
BufferLength,
|
|
0,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if( result == SOCKET_ERROR ) {
|
|
|
|
return ::WSAGetLastError();
|
|
|
|
}
|
|
|
|
*BufferLength -= sizeof(DWORD);
|
|
return 0;
|
|
|
|
} // BUFFERED_SOCKET::SendFrame
|
|
|
|
|
|
INT
|
|
BUFFERED_SOCKET::RecvFrame(
|
|
PVOID Buffer,
|
|
LPDWORD BufferLength
|
|
)
|
|
{
|
|
|
|
INT result;
|
|
DWORD frameLength;
|
|
|
|
result = BufferedRecv( &frameLength, sizeof(frameLength) );
|
|
|
|
if( result != 0 ) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
if( frameLength > *BufferLength ) {
|
|
|
|
return WSAEMSGSIZE;
|
|
|
|
}
|
|
|
|
result = BufferedRecv( Buffer, frameLength );
|
|
|
|
if( result != 0 ) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
*BufferLength = frameLength;
|
|
return 0;
|
|
|
|
} // BUFFERED_SOCKET::RecvFrom
|
|
|
|
|
|
INT
|
|
BUFFERED_SOCKET::SendBlob(
|
|
PIIS_CRYPTO_BLOB Blob
|
|
)
|
|
{
|
|
|
|
DWORD length;
|
|
|
|
length = IISCryptoGetBlobLength( Blob );
|
|
|
|
return SendFrame(
|
|
(PVOID)Blob,
|
|
&length
|
|
);
|
|
|
|
} // BUFFERED_SOCKET::SendFrame
|
|
|
|
|
|
INT
|
|
BUFFERED_SOCKET::RecvBlob(
|
|
PIIS_CRYPTO_BLOB * ppBlob
|
|
)
|
|
{
|
|
|
|
INT result;
|
|
DWORD blobLength;
|
|
PIIS_CRYPTO_BLOB blob;
|
|
|
|
result = BufferedRecv( &blobLength, sizeof(blobLength) );
|
|
|
|
if( result != 0 ) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
blob = (PIIS_CRYPTO_BLOB)ALLOC_MEM(blobLength);
|
|
|
|
if( blob == NULL ) {
|
|
|
|
return WSAENOBUFS;
|
|
|
|
}
|
|
|
|
result = BufferedRecv( blob, blobLength );
|
|
|
|
if( result != 0 ) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
*ppBlob = blob;
|
|
return 0;
|
|
|
|
} // BUFFERED_SOCKET::RecvFrom
|
|
|
|
|
|
//
|
|
// Private functions.
|
|
//
|
|
|
|
|
|
INT
|
|
BUFFERED_SOCKET::BufferedRecv(
|
|
PVOID Buffer,
|
|
DWORD BufferLength
|
|
)
|
|
{
|
|
|
|
PCHAR buffer = (PCHAR)Buffer;
|
|
DWORD bytesToCopy;
|
|
INT result;
|
|
|
|
while( BufferLength > 0 ) {
|
|
|
|
if( m_BytesAvailable == 0 ) {
|
|
|
|
m_BytesAvailable = m_BufferLength;
|
|
result = Recv( m_Buffer, &m_BytesAvailable );
|
|
|
|
if( result != 0 ) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
if( m_BytesAvailable == 0 ) {
|
|
|
|
return WSAEMSGSIZE;
|
|
|
|
}
|
|
|
|
m_Offset = 0;
|
|
|
|
}
|
|
|
|
bytesToCopy = min( m_BytesAvailable, BufferLength );
|
|
|
|
memcpy(
|
|
buffer,
|
|
(PCHAR)m_Buffer + m_Offset,
|
|
bytesToCopy
|
|
);
|
|
|
|
m_Offset += bytesToCopy;
|
|
m_BytesAvailable -= bytesToCopy;
|
|
BufferLength -= bytesToCopy;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
} // BUFFERED_SOCKET::BufferedRecv
|
|
|
|
|
|
INT
|
|
BUFFERED_SOCKET::CommonInitialize()
|
|
{
|
|
|
|
INT result = 0;
|
|
WSADATA data;
|
|
|
|
if( m_Initialized ) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if( m_Buffer == NULL ) {
|
|
|
|
m_Buffer = ALLOC_MEM( BUFFER_LENGTH );
|
|
|
|
if( m_Buffer == NULL ) {
|
|
|
|
return WSAENOBUFS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_BufferLength = BUFFER_LENGTH;
|
|
m_BytesAvailable = 0;
|
|
m_Offset = 0;
|
|
|
|
if( ::InterlockedIncrement( &BUFFERED_SOCKET::m_InitCount ) == 0 ) {
|
|
|
|
result = ::WSAStartup( 0x0202, &data );
|
|
|
|
}
|
|
|
|
m_Initialized = ( result == 0 );
|
|
|
|
return result;
|
|
|
|
} // BUFFERED_SOCKET::CommonInitialize
|
|
|
|
|