#ifndef STIBCLILIB_H #define STIBCLILIB_H /* ========================================================================== ** * stibclilib.h * * Copyright: * Copyright (C) 2007,2011 by Christopher R. Hertel * * Email: crh@ubiqx.mn.org * * $Id: stibclilib.h 57 2011-06-19 04:27:13Z crh $ * * -------------------------------------------------------------------------- ** * * Description: * Client library for transferring files via MS-BITS and HTTP protocols. * * -------------------------------------------------------------------------- ** * * License: * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * -------------------------------------------------------------------------- ** * * Notes: * This module five main types of objects: * Connection Contexts - These are represented by the stib_Ctx type. * Connection contexts are exported as opaque * pointers, since they are almost entirely * handled within the module. There are * exceptions, of course. At present, the * can be used to extract * the current error status of a connection. * Other exceptions will be introduced as * needed. * * Error class/code sets - There are three sources for the errors that * may be returned by this module. There are * standard system error codes (errno, et. al.), * the special set returned by getaddrinfo(3), * plus our own module-specific error codes. * The type is used to keep track * of the error code itself as well as the * source of the error. The latter provides * context. Function is used * to set the values in a , and * returns a pointer to a * static string describing the error. * * URLs (URIs) - The type is used to hold the * results of parsing an HTTP or HTTPS URI string * (or is it a URL? I don't really understand the * difference). The function * can be used to parse a URI string. * * Message blocks - These are basically Gbfr types (see the Gbfr * module) which are used to compose the BITS * headers. * * Parsed BITS replies - In response to a BITS or HTTP Request, the * server sends a Response message that is * formatted just like any HTTP message would * be formatted. There is a start line with * the status code followed by a series of * header lines (terminated by an empty header * line). After the headers there may be a data * blob. The function will * attempt to and parse the following pieces: * + The Start message and, extracted from that, * the status code returned by the server. * + A linked list of key/value pairs extracted * from the header list. * does not attempt to read * the message body. Use for * that. * * ========================================================================== ** */ #include /* Standard library, for NULL, etc. */ #include /* Standard integer types. */ #include /* Standard boolean type. */ #include "ubi_sLinkList.h" /* Generic singly linked lists. */ #include "Gbfr.h" /* Growable buffer module. */ /* -------------------------------------------------------------------------- ** * Typedefs: * * stib_Ctx - Connection context. This is the STIB equivalent of * the FILE type from . It represents an open * connection to a server, and includes a read buffer. * This is an opaque type. * * stib_errClass - The source of the associated error code. * * stib_errCode - A set of STiB-specific error code values. * Zero (0), of course, is success. The codes indicating * an actual error range from one (1) to stibErrCodeMAX. * This set of error codes is meant to augment the * standard sets provided by and those provided * via the getaddrinfo(3) interface. * * stib_Error - A class/code pair indicating both the source of an * error and the specific error code returned. * * stib_parsedURI - A structure used to hold the results of parsing a URI * string. The URI parser implemented in this module is * fairly simplistic. * * stib_hdrNode - A linked list node containing a key/value pair. * Note that the structure MUST be the * first field of the structure. * * stib_parsedMsg - A BITS/HTTP response message, parsed into a list of * header key/value pairs. This structure does NOT * include the body (data portion) of the message. * Note that the structure MUST be the * first field of the structure. */ typedef void stib_Ctx; /* Connection context. */ typedef enum { stib_errClsNone = 0, /* No error. All okay. It's fine. */ stib_errClsSTiB, /* STiB error class. */ stib_errClsGAI, /* GetAddrInfo error class. */ stib_errClsErrno /* Good ol' errno(3) errors. */ } stib_errClass; typedef enum { stib_errSuccess = 0, /* all okay; worked fine; no problems */ stib_errBadValue, /* invalid value in input */ stib_errMallocFail, /* memory allocation failure */ stib_errEOF, /* end of file */ stib_errNoSession, /* could not establish a server session */ stib_errCodeMAX /* unknown error */ } stib_errCode; typedef struct { stib_errClass class; /* Source of the error. */ int code; /* Error code. */ } stib_Error; typedef struct { bool secure; /* True if https was specified, otherwise false (http). */ char *user; /* Username, if present, or NULL. */ char *pass; /* Password, if present, or NULL. Hopefully NULL. */ char *serv; /* Server identifier (name, IPv4, or IPv6 address). */ char *port; /* Port number to use. Default based upon http/https. */ char *path; /* Path portion of the URI, or NULL if no path was given. */ } stib_parsedURI; typedef struct { ubi_slNode node; /* Linked List node structure. */ char *val; /* Pointer to the value portion. */ char key[1]; /* Array containing the key & value. */ } stib_hdrNode; typedef struct { ubi_slList list; /* Linked list of headers. */ int status; /* Response message status code. */ char start[1]; /* Start Message (see RFC2616). */ } stib_parsedMsg; /* -------------------------------------------------------------------------- ** * Functions: */ void stib_errSetCC( stib_Error *err, const stib_errClass class, const int code ); /* ------------------------------------------------------------------------ ** * Set the error class and code of a stib_Error structure. * * Input: err - A pointer to the error variable to be set, or NULL. * class - The error class. * code - The error code. * * Output: * * Notes: We permit to be NULL because it makes it easy for the * caller to choose to ignore the error codes. If is * NULL, no error code is set and the function just returns. * * ------------------------------------------------------------------------ ** */ const char *stib_errStr( const stib_Error *err ); /* ------------------------------------------------------------------------ ** * Return a pointer to a string describing an error code. * * Input: err - A pointer to a STiB error structure. * * Output: A pointer to a static constant string that describes (in * americlish) the error indicated by the error class/code. * * Notes: The error class indicates the source of the error code, which * may be the getaddrinfo(3) API, an error, or a STiB- * specific error. * * ------------------------------------------------------------------------ ** */ const stib_Error *stib_ctxErr( stib_Ctx *Ctx ); /* ------------------------------------------------------------------------ ** * Return a pointer to the error status of the given connection context. * * Input: Ctx - A pointer to a connection context. * * Output: A pointer to the error status of the context. * * ------------------------------------------------------------------------ ** */ stib_parsedURI *stib_parseURI( const char *uri ); /* ------------------------------------------------------------------------ ** * Parse an HTTP/HTTPS URI string into a parsed URI structure. * * Input: uri - A pointer to a string supposedly containing a URI. * * Output: If the string could not be parsed, this function returns * NULL. Otherwise it returns a pointer to a stib_parsedURI * structure. String fields in the structure will be NULL if * the respective part of the URI was not given. * * Notes: If the return value is not NULL, the memory allocated to the * parsed URI object returned must be freed with a call to * free(3). * * This is a fairly simplistic parser. It handles only * HTTP/HTTPS URIs and does not fill in any default values. * * ------------------------------------------------------------------------ ** */ int stib_addHdr2Block( Gbfr *hdr, char *fmt, ... ); /* ------------------------------------------------------------------------ ** * Add a header line to a buffer. * * Input: hdr - A pointer to the Gbfr buffer structure that holds the * message header as it is being composed. * fmt - A format string. * ... - The variable list of parameters to be merged with the * format string to create the new string. * * Output: The total number of bytes of the resulting data block. * The function returns -1 if the string could not be formed * due to a memory allocation failure. * * Notes: The return value indicates the number of bytes in the composed * message block. There is no terminating NUL (that is, the * composed message is not a C string). The result is a * length-delimited block of bytes. * * ------------------------------------------------------------------------ ** */ stib_Ctx *stib_Connect( const char *server, const char *service, stib_Error *err ); /* ------------------------------------------------------------------------ ** * Create a TCP socket and connect it to the destination server. * * Input: server - The name (or IPv[4|6] address as a string) of the * server to which to connect. * service - The service port, as a string. This may either be * a decimal numeric value (e.g. "8080") or a service * name (e.g."http-alt"). * err - A pointer to a stib_Error structure, or NULL. * * Output: On success, an opaque pointer to a connection context (type * stib_Ctx *). * On error, the return value is NULL. * * Notes: If the function fails to establish a connection and is * not NULL, then will contain an error class/code * indicating the cause of the failure. * * Errors: stib_errClsSTiB/stib_errBadValue * Indicates that at least one of the or * parameters was either NULL or the empty string. * * stib_errClsGAI/ * Indicates an error returned from getaddrinfo(3). See the * getaddrinfo(3) manual page for possible error codes. * * stib_errClsErrno/ * Indicates an error returned either from socket(2) or * connect(2). See errno(3) for a list of possible values. * * ------------------------------------------------------------------------ ** */ void stib_Disconnect( stib_Ctx *Ctx ); /* ------------------------------------------------------------------------ ** * Disconnect the context TCP connection without losing state. * * Input: Ctx - A pointer to the connection context. * * Output: * * Notes: This function is primarily for testing. It closes the socket * connecting the client to the BITS server. The next time a * message is to be sent to the server, the connection should be * automatically re-established. * * ------------------------------------------------------------------------ ** */ int stib_CloseCtx( stib_Ctx *Ctx ); /* ------------------------------------------------------------------------ ** * Close an open STiB connection, freeing all associated memory. * * Input: Ctx - Pointer to the STiB connection context to be closed. * * Output: 0 on success. If the socket (included as part of the * structure) cannot be closed, the system error code is * returned. See close(2) and errno(3). * * ------------------------------------------------------------------------ ** */ int stib_sendBlocks( stib_Ctx *Ctx, ... ); /* ------------------------------------------------------------------------ ** * Send one or more blocks on the connected socket. * * Input: Ctx - A pointer to a STiB context, which is the connection on * which to send the block contents. * ... - A NULL-terminated list of pointers to Gbfrs. * * Output: The total number of bytes sent, or -1 on error. * * Notes: If there is an error sending the blocks, the error code will * be set in . * * Errors: stib_errClsErrno/ * See send(2) for possible error codes. * * ------------------------------------------------------------------------ ** */ void stib_freepMsg( stib_parsedMsg *pMsg ); /* ------------------------------------------------------------------------ ** * Free a previously allocated stib_parsedMsg structure, and header nodes. * * Input: pMsg - A pointer to an allocated and potentially populated * stib_parsedMsg structure. * * Output: * * ------------------------------------------------------------------------ ** */ stib_parsedMsg *stib_recvHeaders( stib_Ctx *Ctx ); /* ------------------------------------------------------------------------ ** * Receive the headers of an HTTP message into a parsed message structure. * * Input: Ctx - A pointer to the connection context on which a * message is expected to be received. * * Output: On error, NULL is returned and the error class/code are set * in . * On success, a pointer to a stib_parsedMsg structure is * returned. The parsed message structure will contain a list * of header key/value pairs, but the message body will NOT be * read. * * Errors: stib_errClsSTiB/stib_errMallocFail * Unable to allocate memory from the heap. * Any error returned by . * See: . * * ------------------------------------------------------------------------ ** */ ssize_t stib_readBody( stib_Ctx *Ctx, unsigned char *bufr, const size_t bsize ); /* ------------------------------------------------------------------------ ** * Read the body of an HTTP/BITS message. * * Input: Ctx - A pointer to the connection context. * bufr - A pointer to a buffer into which received bytes will * be copied. * bsize - The size, in bytes, of . * That is, the maximum number of bytes to be read into * . * * Output: The number of bytes actually read into . * * + If the return value is less than but greater than * zero, then the read was successful and more bytes may be * available. * * + If the return value is zero, then no bytes were read. * This indicates EOF. * * + On error, the function returns -1 and the error code is * stored in the context. Use stib_ctxErr() to retrieve the * error code. * * ------------------------------------------------------------------------ ** */ stib_parsedMsg *stib_Ping( stib_Ctx *Ctx, const char *pathname, const char *agent ); /* ------------------------------------------------------------------------ ** * Perform a BITS Ping operation. * * Input: Ctx - Pointer to an open connection to the server. * pathname - A pathname, required in the BITS_PING start line. * agent - Optional; may be NULL. * Used to identify the user agent making the request. * * Output: A pointer to a stib_parsedMsg structure that will contain the * server's response, if any. * * If the server did not respond, or if an error occurred, this * function will return NULL and will be set with an * appropriate error class and code. Use to * retrieve the error. * * Errors: stib_errClsSTiB/stib_errBadValue * The parameter is either NULL or the empty string. * stib_errClsSTiB, stib_errMallocFail * Temporary storage could not be allocated from the heap. * Any error that can be returned from . * See for additional error codes. * * Notes: The BITS Ping may be used stand-alone or at the start of an * upload. It is also optional as the first packet. With that * in mind, this function does not store the and * strings in the connection context. * * ------------------------------------------------------------------------ ** */ stib_parsedMsg *stib_CreateSession( stib_Ctx *Ctx, const char *pathname, const char *agent, const off_t fsize ); /* ------------------------------------------------------------------------ ** * Create a BITS upload session. * * Input: Ctx - Pointer to an open connection to the server. * pathname - A pointer to a pathname string. This is the * pathname portion of the destination URL. * This value is required in the BITS_POST start line. * agent - Used to identify the user agent making the request. * This value is optional, and may be NULL. * fsize - Size, in bytes, of the file to be transferred. * This value is required, and is used in the BITS * Fragment commands that actually transfer the * chunks of file data. * * Output: A pointer to a stib_parsedMsg structure that will contain the * server's response, if any. * * If the server did not respond, or if some other error occurred, * this function will return NULL and will be set with an * appropriate error class and code. Use to * retrieve the error. * * Errors: stib_errClsSTiB/stib_errBadValue * The parameter is zero, or the parameter * is NULL or the empty string. * stib_errClsSTiB, stib_errMallocFail * Temporary storage could not be allocated from the heap. * Any error that can be returned from . * See for additional error codes. * * Notes: This function creates a BITS session. The and * strings are copied into the connection context * () for use in future calls. * * ------------------------------------------------------------------------ ** */ stib_parsedMsg *stib_Fragment( stib_Ctx *Ctx, const off_t off, const int len, const char *src ); /* ------------------------------------------------------------------------ ** * Send a file fragment to the BITS server. * * Input: Ctx - A pointer to an open connection to the server. * off - Offset, within the file being copied, of the bytes * being sent to the server. * len - Number of bytes to send. * src - Pointer to the block of bytes to be sent. * * Output: A pointer to a stib_parsedMsg structure that will contain the * server's response, if any. * * If the server did not respond, or if some other error occurred, * this function will return NULL and will be set with an * appropriate error class and code. Use to * retrieve the error. * * Errors: stib_errClsSTiB/stib_errBadValue * The value of is either zero or less, or would cause * the total number of bytes written to exceed the file size * given in the parameter to . * stib_errClsSTiB/stib_errMallocFail * Temporary storage could not be allocated from the heap. * Any error that can be returned from . * See for additional error codes. * * Notes: Fragments can only be sent over a session previously * established using . * * ------------------------------------------------------------------------ ** */ stib_parsedMsg *stib_CancelSession( stib_Ctx *Ctx ); /* ------------------------------------------------------------------------ ** * Cancel an in-progress BITS upload session. * * Input: Ctx - The connection context of the session to be cancelled. * * Output: A pointer to a stib_parsedMsg structure that will contain the * server's response, if any. * * If the server did not respond, or if some other error occurred, * this function will return NULL and will be set with an * appropriate error class and code. Use to * retrieve the error. * * Errors: stib_errClsSTiB/stib_errMallocFail * Temporary storage could not be allocated from the heap. * Any error that can be returned from . * See for additional error codes. * * Notes: If the server fails to handle the cancel, and returns an error * code in the range 500..599, the client is expected to re-send * the Cancel-Session request unless the server has specified * that the error is BG_E_SESSION_NOT_FOUND (0x8020001F). * See: http://msdn.microsoft.com/en-us/library/aa362710.aspx * * ------------------------------------------------------------------------ ** */ stib_parsedMsg *stib_CloseSession( stib_Ctx *Ctx ); /* ------------------------------------------------------------------------ ** * Close a completed BITS upload session. * * Input: Ctx - The connection context of the session to be closed. * * Output: A pointer to a stib_parsedMsg structure that will contain the * server's response, if any. * * If the server did not respond, or if some other error occurred, * this function will return NULL and will be set with an * appropriate error class and code. Use to * retrieve the error. * * Errors: stib_errClsSTiB/stib_errMallocFail * Temporary storage could not be allocated from the heap. * Any error that can be returned from . * See for additional error codes. * * ------------------------------------------------------------------------ ** */ stib_parsedMsg *stib_Get( stib_Ctx *Ctx, const char *pathname, const char *agent, const off_t off, const uint len, const bool BCE ); /* ------------------------------------------------------------------------ ** * Download a file using the HTTP[S] GET command. * * Input: Ctx - A pointer to a connection context structure. * pathname - A pointer to a pathname string. This is the * pathname portion of the URL, indicating the * remote resource (file) to be retrieved. * This value is required in the GET start line. * agent - Used to identify the user agent making the request. * This value is optional, and may be NULL. * off - For Range requests, this is the offset within * the source file at which our request range begins. * len - For Range requests, this is the number of bytes we * are requesting. * BCE - If true, request BranchCache peerdist encoding. * * Output: A pointer to a stib_parsedMsg structure that will contain the * server's response, if any. * * If the request was successful (2xx), the message body can be * retrieved using the function. * * If both and are zero, then the "Range:" header * will not be sent and this will be a normal GET command. If * either or are non-zero, the "Range" header will * be used to request a portion of the content. If is * non-zero and is zero, then the request will be for * the range starting at through to the end of the content. * * ------------------------------------------------------------------------ ** */ char const *stib_Info( void ); /* ------------------------------------------------------------------------ ** * Return a module information string. * * Input: * * Output: A pointer to a constant, static string that provides some * basic information about this module. * * ------------------------------------------------------------------------ ** */ /* ========================================================================== */ #endif /* STIBCLILIB_H */