Previous: Steps in Implementing an Insecure HTTP Client, Up: Implementing an Insecure HTTP Client [Index]
This is the full code listing for the Insecure HTTP Client.
1 /** 2 * This test utility does simple (non-encrypted) HTTP 3 */ 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <errno.h> 8 #include <string.h> 9 #include <sys/types.h> 10 #include <netdb.h> 11 #include <sys/socket.h> 12 #include <netinet/in.h> 13 #include <unistd.h> 14 15 #define HTTP_PORT 80 16 #define BUFFER_SIZE 255 17 #define MAX_GET_COMMAND 255 18 19 /** 20 * Accept a well-formed URL (e.g. http://www.company.com/index.html) and return 21 * pointers to the host part and the path part. Note that this function 22 * modifies the uri itself as well. It returns 0 on success, -1 if the URL is 23 * found to be malformed in any way. 24 */ 25 26 int parse_url( char *uri, char **host, char **path ) 27 { 28 char *pos; 29 30 pos = strstr( uri, "//" ); 31 32 if ( !pos ) 33 { 34 return -1; 35 } 36 37 *host = pos + 2; 38 39 pos = strchr( *host, '/' ); 40 41 if ( !pos ) 42 { 43 *path = NULL; 44 } 45 else 46 { 47 *pos = '\0'; 48 *path = pos + 1; 49 } 50 51 return 0; 52 } 53 54 /** 55 * Format and send an HTTP get command. The return value will be 0 on 56 * success, -1 on failure, with errno set appropriately. The caller 57 * must then retrieve the response. 58 */ 59 60 int http_get( int connection, const char *path, const char *host ) 61 { 62 static char get_command[ MAX_GET_COMMAND ]; 63 64 sprintf( get_command, "GET /%s HTTP/1.1\r\n", path ); 65 if ( send( connection, get_command, strlen( get_command ), 0 ) == -1 ) 66 { 67 return -1; 68 } 69 70 sprintf( get_command, "Host: %s\r\n", host ); 71 if ( send( connection, get_command, strlen( get_command ), 0 ) == -1 ) 72 { 73 return -1; 74 } 75 76 sprintf( get_command, "Connection: close\r\n\r\n" ); 77 if ( send( connection, get_command, strlen( get_command ), 0 ) == -1 ) 78 { 79 return -1; 80 } 81 82 return 0; 83 } 84 85 /** 86 * Receive all data available on a connection and dump it to stdout 87 */ 88 89 void display_result( int connection ) 90 { 91 int received = 0; 92 93 static char recv_buf[ BUFFER_SIZE + 1 ]; 94 95 while ( ( received = recv( connection, recv_buf, BUFFER_SIZE, 0 ) ) > 0 ) 96 { 97 recv_buf[ received ] = '\0'; 98 printf( "%s", recv_buf ); 99 } 100 101 printf( "\n" ); 102 } 103 104 /** 105 * Simple command-line HTTP client. 106 */ 107 108 int main( int argc, char *argv[ ] ) 109 { 110 int client_connection; 111 char *host, *path; 112 struct hostent *host_name; 113 struct sockaddr_in host_address; 114 115 if ( argc < 2 ) 116 { 117 fprintf( stderr, "Usage: %s: <URL>\n", argv[ 0 ] ); 118 return 1; 119 } 120 121 if ( parse_url( argv[ 1 ], &host, &path ) == -1 ) 122 { 123 fprintf( stderr, "Error - malformed URL '%s . \n", argv[ 1 ] ); 124 return 1; 125 } 126 127 printf( "Conecting to host '%s'\n", host ); 128 129 // Step 1: open a socket connection on http port with the destination host 130 131 client_connection = socket( PF_INET, SOCK_STREAM, 0 ); 132 133 if ( !client_connection ) 134 { 135 perror( "Unable to create a local socket" ); 136 return 2; 137 } 138 139 host_name = gethostbyname( host ); 140 141 if ( !host_name ) 142 { 143 perror( "Error in name resolution" ); 144 return 3; 145 } 146 147 host_address.sin_family = AF_INET; 148 host_address.sin_port = htons( HTTP_PORT ); 149 memcpy( &host_address.sin_addr, host_name->h_addr_list[ 0 ], 150 sizeof( struct in_addr ) ); 151 152 if ( connect( client_connection, ( struct sockaddr * ) &host_address, 153 sizeof( host_address ) ) == -1 ) 154 { 155 perror( "Unable to connect to host" ); 156 return 4; 157 } 158 159 printf( "Retrieving document: '%s'\n", path ); 160 161 // Step 2: Issue a GET command 162 163 http_get( client_connection, path, host ); 164 165 display_result( client_connection ); 166 167 printf( "Shutting down.\n" ); 168 169 if (close( client_connection ) == -1 ) 170 { 171 perror( "Error closing client connection" ); 172 return 5; 173 } 174 175 return 0; 176 } 177