// Implementation of WSock
#include <stdio.h>
#ifndef GLOBAL_DECL
#include "global.h" // Global data types and variables
#endif
// Needed for some versions of compiler:
// enum bool { false, true };
// Constructor - Initialise WinSock and Bind Socket
wsock::wsock(config* setts)
{
settings = setts;
crlf[0] = 13;
crlf[1] = 10;
crlf[2] = 13;
crlf[3] = 10;
crlf[4] = NULL;
error[0] = NULL;
// Set timeout and retry settings
timeout_val = settings -> timeout; // Timeout in seconds
retry_val = settings -> retries;
// Set proxy settings
use_proxy = settings -> use_proxy;
strcpy(proxy_addr, settings -> proxy_addr);
proxy_port = settings -> proxy_port;
wsock::initialise();
}
// Initialise Winsock
void wsock::initialise()
{
WORD requested;
WSADATA data;
int wserror;
requested = MAKEWORD( 2, 0 );
wserror = WSAStartup( requested, &data );
if ( wserror != 0 )
{
strcpy( error, "ERROR - Couldn't find a WinSock DLL." );
}
// Confirm that the WinSock DLL supports 2.0.
if ( LOBYTE( data.wVersion ) != 2 ||
HIBYTE( data.wVersion ) != 0 )
{
strcpy( error, "ERROR - Couldn't find a usable WinSock DLL." );
WSACleanup();
}
}
// Destructor - Close socket and shut down Winsock
wsock::~wsock()
{
WSACleanup();
}
// Check that domain is valid
bool wsock::check_valid( char* address )
{
LPHOSTENT host_info; // Information about host
if ( ( serv_addr.sin_addr.s_addr = inet_addr( address ) ) == INADDR_NONE)
if ( ( host_info = gethostbyname( address ) ) == NULL )
{
strcpy( error, "ERROR - Server does not have a DNS entry." );
return false;
}
else
{
if (use_proxy)
if ( ( host_info = gethostbyname( proxy_addr ) ) == NULL )
{
strcpy( error, "ERROR - Proxy Server does not have a DNS entry." );
return false;
}
memcpy ( &( serv_addr.sin_addr ), host_info -> h_addr,
host_info -> h_length );
}
return true;
}
// Create and bind socket
bool wsock::create_socket( void )
{
SOCKADDR_IN cli_addr; // Client address
// Set up client-side address
cli_addr.sin_family = AF_INET;
cli_addr.sin_port = 0;
cli_addr.sin_addr.s_addr = INADDR_ANY;
// Create socket
my_socket = socket ( AF_INET, SOCK_STREAM, 0 );
if ( my_socket == INVALID_SOCKET )
{
strcpy( error, "ERROR - Couldn't create socket." );
return false;
}
// Bind socket to client address
if ( bind ( my_socket, (LPSOCKADDR) &cli_addr,
sizeof( cli_addr ) ) == SOCKET_ERROR )
{
strcpy( error, "ERROR - Unable to bind socket." );
return false;
}
return true;
}
// Connect to server
bool wsock::make_connection( void )
{
serv_addr.sin_family = AF_INET;
if (use_proxy)
serv_addr.sin_port = htons( proxy_port );
else
serv_addr.sin_port = htons( 80 );
if ( connect ( my_socket, (LPSOCKADDR) &serv_addr,
sizeof( serv_addr ) ) == SOCKET_ERROR )
{
strcpy( error, "ERROR - Unable to connect to server." );
return false;
}
return true;
}
bool wsock::get_page( char* address, char* fname )
{
char domain_name[100]; // Just the domain part of address
int characters; // Number of characters in domain
char command[200]; // Command to send to server
// Create socket and bind it locally
if ( !wsock::create_socket() )
return false;
// Seperate domain name from user input
sscanf( address, "http://%s", domain_name );
characters = strcspn( domain_name, "/" );
domain_name[characters] = NULL;
if ( !wsock::check_valid( domain_name ) ) // Check that domain is valid
return false;
if ( !wsock::make_connection() ) // Connect to server
return false;
// Create string to send to server
strcpy( command, "GET " );
strcat( command, address );
strcat( command, " HTTP/1.0" );
strcat( command, crlf );
if ( !wsock::send_command( command ) ) // Send a string to the server
return false;
wsock::get_reply( fname ); // Get reply from server
closesocket( my_socket );
return true;
}
// Send a string to the server
bool wsock::send_command( char* command )
{
char* ptr; // Pointer to current position in string
int bytes_sent; // # of bytes sent
int length; // Length of string to send
ptr = command;
length = strlen( command );
do
{
bytes_sent = send ( my_socket, ptr, length, 0 );
if ( bytes_sent == SOCKET_ERROR )
{
strcpy( error, "ERROR - Error while sending data." );
return false;
}
ptr += bytes_sent;
length -= bytes_sent;
} while ( length > 0 );
return true;
}
// Get the reply from the server
bool wsock::get_reply( char* fname )
{
char character; // Character recieved
char prev_chars[5]; // Previous characters received
int bytes_rcvd; // # of bytes received
int result; // Result of select statement
fd_set iadd_set; // Set of sockets used in select
timeval timeout; // Timeout variable
FILE *fp; // File pointer
bool is_header; // true if receiving header, else false
int retries; // Retries remaining
int loop;
FD_ZERO ( &iadd_set ); // Initialise empty set of ports
FD_SET ( my_socket, &iadd_set ); // Add to set of sockets
timeout.tv_sec = timeout_val; // Set timeout value
timeout.tv_usec = 0;
retries = retry_val; // Set number of retries
is_header = true; // Receiving header flag
do
{
result = select ( 0, &iadd_set, 0, 0, &timeout );
} while ((result == 0) && (retries-- > 0));
if (result != 0)
{
// Open file to save downloaded data to
if ( ( fp = fopen(fname, "w") ) == NULL )
{
strcpy( error, "ERROR - Unable to create file." );
return false;
}
// Receive a character from server
bytes_rcvd = recv ( my_socket, &character, 1, 0 );
while ( bytes_rcvd != 0 )
{
// Buffer characters and check if at end of header
for ( loop=0; loop<3; loop++)
prev_chars[loop] = prev_chars[loop+1];
prev_chars[3] = character;
prev_chars[4] = NULL;
if ( !strcmp(prev_chars, crlf) )
is_header = false;
if ( !is_header ) // Not In header
fputc( character, fp );
if ( bytes_rcvd == SOCKET_ERROR )
{
strcpy( error, "ERROR - Error while receiving data." );
return false;
}
// Receive a character from server
bytes_rcvd = recv ( my_socket, &character, 1, 0 );
}
fclose( fp ); // Close file
}
else
{
strcpy( error, "ERROR - Connection timed out." );
return false;
}
return true;
}
syntax highlighted by Code2HTML, v. 0.8.11