medfall

A super great game engine
Log | Files | Refs

http.cc (1925B)


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include <errno.h>
      5 
      6 #include <string>
      7 
      8 #include "intrinsics.h"
      9 #include "array.h"
     10 #include "platform_io.h"
     11 #include "platform_network.h"
     12 #include "http.h"
     13 
     14 GetResult http_get( const NetAddress & addr, const char * host, const char * path, std::string * body, HttpProgressCallback progress_cb, void * cb_data ) {
     15 	TCPSocket sock;
     16 	if( !net_new_tcp( &sock, addr, NET_BLOCKING ) ) {
     17 		return GET_ERROR_CANT_CONNECT;
     18 	}
     19 	defer { net_destroy( &sock ); };
     20 
     21 	// TODO: should just be a dynamic string
     22 	char request[ 1024 ];
     23 	size_t request_len = ggformat( request, sizeof( request ),
     24 		"GET {} HTTP/1.1\r\n"
     25 		"Host: {}\r\n"
     26 		"Connection: close\r\n"
     27 		"User-Agent: medfall\r\n"
     28 		// "Range: bytes=%llu-\r\n"
     29 		"\r\n\r\n", path, host );
     30 	ASSERT( request_len <= sizeof( request ) - 1 );
     31 
     32 	if( !net_send( sock, request, request_len ) ) {
     33 		return GET_ERROR_DISCONNECTED;
     34 	}
     35 
     36 	std::string response;
     37 	while( true ) {
     38 		char buf[ BUFSIZ ];
     39 		size_t bytes_read;
     40 		TCPRecvResult ok = net_recv( sock, buf, sizeof( buf ), &bytes_read, 10000 );
     41 		if( ok == TCP_TIMEOUT ) return GET_ERROR_TIMEOUT;
     42 		if( ok == TCP_ERROR ) return GET_ERROR_DISCONNECTED;
     43 		if( ok == TCP_CLOSED ) break;
     44 
     45 		response.append( buf, bytes_read );
     46 
     47 		if( progress_cb != NULL ) {
     48 			progress_cb( response.size(), cb_data );
     49 		}
     50 	}
     51 
     52 	// HTTP/1.1 200 OK
     53 	// 0123456789
     54 	std::string response_code = response.substr( 9, 3 );
     55 	if( response_code == "400" ) return GET_ERROR_HTTP_BAD_REQUEST;
     56 	if( response_code == "404" ) return GET_ERROR_HTTP_NOT_FOUND;
     57 	if( response_code == "500" ) return GET_ERROR_HTTP_INTERNAL_SERVER_ERROR;
     58 	if( response_code != "200" ) return GET_ERROR_HTTP_OTHER;
     59 
     60 	size_t body_start = response.find( "\r\n\r\n" );
     61 	if( body_start == std::string::npos ) {
     62 		return GET_ERROR_HTTP_OTHER;
     63 	}
     64 
     65 	body->append( response, body_start + strlen( "\r\n\r\n" ), std::string::npos );
     66 
     67 	return GET_OK;
     68 }