HTTP SDK
From GameSpy SDK
HTTP SDK
Overview
The GameSpy HTTP SDK (GHTTP) is a library for downloading files or other data from HTTP servers. Simply make a request, and the library will connect to the server and download the requested file using the HTTP 1.1 protocol. GHTTP also supports uploading (posting) files or other data to HTTP servers. The SDK is written in standard ANSI C and has been tested on Win32, Unix, Mac, and consoles. The library has been designed to be easy to use, fast, and memory efficient (particularly useful on console systems with tight memory requirements). Just include all of the source files in your project, and you can start easily downloading data from web servers.
The SDK also includes two samples. ghttpc is a simple ANSI C sample that makes some requests, then waits for them to complete. ghttpmfc is a Windows MFC sample that provides a GUI for experimenting with the SDK.
The rest of this document presents a simple, step-by-step set of instructions for using GHTTP. See the main ghttp.h header file for more detailed information on each function.
File Manifest
The following files should be included with this package. If any of the files are missing, please contact devsupport@gamespy.com.
- File
- Description
- ghttp.h
- GameSpy HTTP header (all user functions are prototyped here)
- ghttpMain.c, h
- The main entry point for all GHTTP functions
- ghttpBuffer.c,h
- Code for buffering of incoming and outgoing data
- ghttpCallbacks.c,h
- Code for calling callbacks
- ghttpCommon.c,h
- Common utility code
- ghttpConnection.c,h
- This code manages all current connections
- ghttpPost.c,h
- Code for managing and procesing posts (uploads)
- ghttpProcess.c,h
- Code for processing requests (based on type and state)
- nonport.c,h
- Platform-specific code
- /ghttpc/
- ANSI-C sample
- /ghttpmfc/
- Windows MFC sample
Implementation
Step 1: Startup
To initialize the GHTTP SDK, call ghttpStartup. This can be called multiple times. There must, however, be a matching ghttpCleanup for each call. Note: it will be called automatically if a request function is called first.
Step 2: Make A Request
Once the library has been started up, its ready to start making requests. This is done by passing a URL to a GHTTP function, which then contacts the appropriate HTTP server, makes a request, then possibly downloads a file (or other resource).
There are five types of request, each of which has a basic function and an extended function: get, save, stream, head, and post.
- get
- The "get" type of function simply downloads the file into memory. This memory can be provided by the application, or it can be allocated by the library.
- save
- The "save" type of function saves the file directly to disk. The filename to save it as is passed into the request function.
- stream
- The "stream" type of function doesn't store the file at all. It calls an application-provided callback whenever part of the file is received from the server, and the application can then do what it wants with the data.
- head
- The "head" type of function is used when an application wants the headers that would normally be returned as part of a "get" request, but without actually getting the file.
- post
- The "post" type of function is used solely to post data, ignoring any possible body returned by the server (response status and headers can still be checked). The get, save, and stream types can also optionally post data.
get
GHTTPRequest ghttpGet ( const char * URL, GHTTPBool blocking, ghttpCompletedCallback completedCallback, void * param ); GHTTPRequest ghttpGetEx ( const char * URL, const char * headers, char * buffer, int bufferSize, GHTTPPost post, GHTTPBool throttle, GHTTPBool blocking, ghttpProgressCallback progressCallback, ghttpCompletedCallback completedCallback, void * param );
- URL
- This is the URL for the file (i.e., "http://host.domain[:port]/path/filename").
- headers
- If not NULL, this is a string containing extra headers to send with the request.
- buffer
- The buffer to download to. If NULL, one will be allocated by the library.
- bufferSize
- If buffer is not NULL, the size of the buffer. If buffer is NULL, this should be 0.
- post
- If not NULL, post this object along with the request.
- throttle
- If GHTTPTrue, throttle this request's download speed.
- blocking
- If GHTTPTrue, the request function won't return until the request has finished.
- progressCallback
- If not NULL, gets called whenever the download progresses.
- completedCallback
- If not NULL, gets called when the download is completed (successfully or not).
- param
- This is optional user-data that will be passed into the callbacks.
save
GHTTPRequest ghttpSave ( const char * URL, const char * filename, GHTTPBool blocking, ghttpCompletedCallback completedCallback, void * param ); GHTTPRequest ghttpSaveEx ( const char * URL, const char * filename, const char * headers, GHTTPPost post, GHTTPBool throttle, GHTTPBool blocking, ghttpProgressCallback progressCallback, ghttpCompletedCallback completedCallback, void * param );
- URL
- This is the URL for the file (i.e., "http://host.domain[:port]/path/filename").
- filename
- The filename to save the file as. Cannot be NULL.
- headers
- If not NULL, this is a string containing extra headers to send with the request.
- post
- If not NULL, post this object along with the request.
- throttle
- If GHTTPTrue, throttle this request's download speed.
- blocking
- If GHTTPTrue, the request function won't return until the request has finished.
- progressCallback
- If not NULL, gets called whenever the download progresses.
- completedCallback
- If not NULL, gets called when the download is completed (successfully or not).
- param
- This is optional user-data that will be passed into the callbacks.
stream
GHTTPRequest ghttpStream ( const char * URL, GHTTPBool blocking, ghttpProgressCallback progressCallback, ghttpCompletedCallback completedCallback, void * param ); GHTTPRequest ghttpStreamEx ( const char * URL, const char * headers, GHTTPPost post, GHTTPBool throttle, GHTTPBool blocking, ghttpProgressCallback progressCallback, ghttpCompletedCallback completedCallback, void * param );
- URL
- This is the URL for the file (i.e., "http://host.domain[:port]/path/filename").
- headers
- If not NULL, this is a string containing extra headers to send with the request.
- post
- If not NULL, post this object along with the request.
- throttle
- If GHTTPTrue, throttle this request's download speed.
- blocking
- If GHTTPTrue, the request function won't return until the request has finished.
- progressCallback
- If not NULL, gets called whenever the download progresses.
- completedCallback
- If not NULL, gets called when the download is completed (successfully or not).
- param
- This is optional user-data that will be passed into the callbacks.
head
GHTTPRequest ghttpHead ( const char * URL, GHTTPBool blocking, ghttpCompletedCallback completedCallback, void * param ); GHTTPRequest ghttpHeadEx ( const char * URL, const char * headers, GHTTPBool throttle, GHTTPBool blocking, ghttpProgressCallback progressCallback, ghttpCompletedCallback completedCallback, void * param );
- URL
- This is the URL for the file (i.e., "http://host.domain[:port]/path/filename").
- headers
- If not NULL, this is a string containing extra headers to send with the request.
- throttle
- If GHTTPTrue, throttle this request's download speed.
- blocking
- If GHTTPTrue, the request function won't return until the request has finished.
- progressCallback
- If not NULL, gets called whenever the download progresses.
- completedCallback
- If not NULL, gets called when the download is completed (successfully or not).
- param
- This is optional user-data that will be passed into the callbacks.
post
GHTTPRequest ghttpPost ( const char * URL, GHTTPPost post, GHTTPBool blocking, ghttpCompletedCallback completedCallback, void * param ); GHTTPRequest ghttpPostEx ( const char * URL, const char * headers, GHTTPPost post, GHTTPBool throttle, GHTTPBool blocking, ghttpProgressCallback progressCallback, ghttpCompletedCallback completedCallback, void * param );
- URL
- This is the URL for the file (i.e., "http://host.domain[:port]/path/filename").
- headers
- If not NULL, this is a string containing extra headers to send with the request.
- post
- The object to post with the request. Cannot be NULL.
- throttle
- If GHTTPTrue, throttle this request's download speed.
- blocking
- If GHTTPTrue, the request function won't return until the request has finished.
- progressCallback
- If not NULL, gets called whenever the download progresses.
- completedCallback
- If not NULL, gets called when the download is completed (successfully or not).
- param
- This is optional user-data that will be passed into the callbacks.
Step 2: Wait For Callbacks
Any application that uses GHTTP in non-blocking mode (sets the blocking paramater to GHTTPFalse) needs to call ghttpThink to let the library do any necessary processing. This call will process any current requests and call any callbacks if necessary. It will typically be called in the application's main loop. While it can be called as little as a few times a second, it should be called closer to 10-20 times a second. If downloading larger files, it may be desirable to call it even more often, to ensure that incoming buffers are emptied to make room for more incoming data.
Threads note: Making GHTTP requests concurrently from multiple threads is currently only supported under Win32. When using GHTTP from multiple threads, instead of calling ghttpThink, use ghttpRequestThink for each individual request. This allows that request's callback to be called from within the same thread in which it was started.
There are two callback types used by GHTTP: the "progress" callback, and the "completed" callback. The progress callback, if provided, gets called when the state of the request changes and when file data is received from the server.
typedef enum
{
GHTTPSocketInit,
GHTTPHostLookup,
GHTTPLookupPending,
GHTTPConnecting,
GHTTPSendingRequest,
GHTTPPosting,
GHTTPWaiting,
GHTTPReceivingStatus,
GHTTPReceivingHeaders,
GHTTPReceivingFile
} GHTTPState;
typedef void (* ghttpProgressCallback)
(
GHTTPRequest request,
GHTTPState state,
const char * buffer,
int bufferLen,
int bytesReceived,
int totalSize,
void * param
);
- request
- This is the same request identifier returned by the request function.
- state
- The current state of the request.
- buffer
- For get requests, the file so far. For save and stream, the most recent data received.
- Header data is not passed into this callback. This will only be the actual file.
- If state != GHTTPReceivingFile, this will be NULL.
- bufferLen
- The length of the data in buffer (buffer is also NUL-terminated).
- If buffer is NULL, this will be 0.
- bytesRecieved
- If GHTTPTrue, the request function won't return until the request has finished.
- totalSize
- If not NULL, gets called whenever the download progresses.
- param
- This is optional user-data that will be passed into the callbacks.
Note: the state usually moves forward by one state at a time (i.e., GHTTPSocketInit -> GHTTPHostLookup). However, it will move from GHTTPReceivingHeaders back to GHTTPSocketInit if the request has been redirected, it will skip GHTTPPosting if not posting data, and it will move from GHTTPReceivingHeaders back to GHTTPReceivingStatus if it gets a 100-Continue status (this typically only happens while posting).
The completed callback gets called when the request is completed:
typedef enum
{
GHTTPSuccess,
GHTTPOutOfMemory,
GHTTPBufferOverflow,
GHTTPParseURLFailed,
GHTTPHostLookupFailed,
GHTTPSocketFailed,
GHTTPConnectFailed,
GHTTPBadResponse,
GHTTPRequestRejected,
GHTTPUnauthorized,
GHTTPForbidden,
GHTTPFileNotFound,
GHTTPServerError,
GHTTPFileWriteFailed,
GHTTPFileReadFailed
) GHTTPResult;
typedef GHTTPBool (* ghttpCompletedCallback)
(
GHTTPRequest request,
GHTTPResult result,
char * buffer,
int bufferLen,
void * param
);
- request
- This is the same request identifier returned by the request function.
- result
- The result of the request.
- buffer
- If a get request, this is the entire file in memory. Otherwise, NULL.
- bufferLen
- The length of the file (even if not a get request).
- param
- This is optional user-data that will be passed into the callbacks.
The return value can be ignored if this is not a get request. For a get request, return GHTTPTrue to have the buffer's memory freed. If GHTTPFalse is returned, it is the responsibility of the application to free the memory.
Step 4: Cleanup
When the application is done using GHTTP, call ghttpCleanup to free any resources it is using. This call can also be used if GHTTP will not be used for a while, and the application wishes to free up resources. If it is called while requests are pending, they will be cancelled, and the completed callback will not be called.
Posting
GHTTPPost objects are used to post (upload) data along with a request. They can be used to upload simple string data, and they can be used to upload files. This allows for a range of uses, from posting to web forums to uploading custom skins. GHTTPPost objects can be passed to ghttpGetEx, ghttpSaveEx, and ghttpStreamEx to upload data and then receive a response from the server, or they can be passed to ghttpPost and ghttpPostEx to just upload data without getting a response.
ghttpNewPost is used to create a new GHTTPPost object. To add data to it, use ghttpPostAddString, ghttpPostAddFileFromDisk, and ghttpPostAddFileFromMemory. Once an object is setup, it can be used in a request. An application must not modify a GHTTPPost object that is in the process of being used in a request. By default, the object will be automatically freed after being used. However, the same object can be used in multiple requests by calling ghttpPostSetAutoFree and setting the autoFree paramater to GHTTPFalse. When done using the object, free it with ghttpFreePost (or set autoFree back to GHTTPTrue before using it for the last time). ghttpPostSetCallback can be used to setup a callback to be called whenever data is uploaded, which allows an application to monitor the progress of the upload in terms of both bytes and objects uploaded.
If only strings are being uploaded as part of a request, then it will be done using the "application/x-www-form/urlencoded" content type. If files are also being uploaded (either from disk or memory), then the post will use the "multipart/form-data" content type.
Miscellaneous
If throttling is enabled for a request, the download speed will be limited. To customize the throttle speed, use ghttpThrottleSettings. To change a requests throttle setting after it has been started, use ghttpSetThrottle".
There is a known bug with Windows CE that causes it to return the wrong address when looking up certain DNS names (specifically, those with CNAME records). An example of a host name that CE will not handle correctly is "www.cnn.com".
GHTTP can handle HTTP redirection. If the server sends a response with a 3xx status code, and the new location is given, GHTTP will then attempt to open the new URL. The current state of the request will go from GHTTPReceivingHeaders to GHTTPSocketInit.
A current request can be cancelled by passing its GHTTPRequest identifier (returned from the request function) to ghttpCancelRequest. The completed callback will not be called for this request.
The current state of a request can be obtained at any time with ghttpGetState.
If the state of a request has passed GHTTPReceivingStatus, then ghttpGetResponseStatus can be used to get both the status code and status string returned by the HTTP server.
If the request has passed the GHTTPReceivingHeaders state, then ghttpGetHeaders can be called to get the headers returned by the server.
ghttpGetURL can be called to get the URL being retrieved by the request. If the request has been redirected, the URL returned will be the new URL, not the one passed into the request function.
All requests can be forwarded to a web proxy by passing a proxy's address to ghttpSetProxy.
UNICODE Support
The GameSpy SDKs support an optional UNICODE interface for widestring applications. To use this interface, first define the symbol "GSI_UNICODE". Then, use widestrings wherever ANSI strings were previously called for. When in doubt, please refer to the header files for specific function declarations.
Although the GameSpy SDK interfaces support UNICODE parameters, some items may be stripped of their extra UNICODE information. These items include: nickname, email address, and URL strings. You may pass in widestring values, but they will first be converted to their ANSI counterparts before transmission.