577 lines
9.0 KiB
C++
577 lines
9.0 KiB
C++
/*++
|
||
|
||
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
|
||
|
||
|