diff options
author | Bryan Ischo <bryan@ischo.com> | 2008-07-10 21:12:21 +0000 |
---|---|---|
committer | Bryan Ischo <bryan@ischo.com> | 2008-07-10 21:12:21 +0000 |
commit | c0535eabe25706904711f1453e724e659b93318c (patch) | |
tree | 55e2a2acc6fbc71e4c1a55489aaeed7f2cc919e2 /inc | |
parent | e9e38ab98e38b35725d85cbe6101bfbbd34d1418 (diff) | |
download | ceph-libs3-c0535eabe25706904711f1453e724e659b93318c.tar.gz |
* Work in progress - reorganized alot, completed list bucket, create bucket,
delete bucket, test bucket
Diffstat (limited to 'inc')
-rw-r--r-- | inc/error_parser.h | 80 | ||||
-rw-r--r-- | inc/libs3.h | 14 | ||||
-rw-r--r-- | inc/private.h | 409 | ||||
-rw-r--r-- | inc/request.h | 191 | ||||
-rw-r--r-- | inc/request_context.h | 39 | ||||
-rw-r--r-- | inc/response_headers_handler.h | 62 | ||||
-rw-r--r-- | inc/simplexml.h | 74 | ||||
-rw-r--r-- | inc/string_buffer.h | 105 | ||||
-rw-r--r-- | inc/util.h | 90 |
9 files changed, 648 insertions, 416 deletions
diff --git a/inc/error_parser.h b/inc/error_parser.h new file mode 100644 index 0000000..9252fba --- /dev/null +++ b/inc/error_parser.h @@ -0,0 +1,80 @@ +/** ************************************************************************** + * error_parser.h + * + * Copyright 2008 Bryan Ischo <bryan@ischo.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program 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 General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the + * + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + ************************************************************************** **/ + +#ifndef ERROR_PARSER_H +#define ERROR_PARSER_H + +#include "libs3.h" +#include "simplexml.h" +#include "string_buffer.h" + + +#define EXTRA_DETAILS_SIZE 8 + +typedef struct ErrorParser +{ + // This is the S3ErrorDetails that this ErrorParser fills in from the + // data that it parses + S3ErrorDetails s3ErrorDetails; + + // This is the error XML parser + SimpleXml errorXmlParser; + + // Set to 1 after the first call to add + int errorXmlParserInitialized; + + // Used to buffer the S3 Error Code as it is read in + string_buffer(code, 1024); + + // Used to buffer the S3 Error Message as it is read in + string_buffer(message, 1024); + + // Used to buffer the S3 Error Resource as it is read in + string_buffer(resource, 1024); + + // Used to buffer the S3 Error Further Details as it is read in + string_buffer(furtherDetails, 1024); + + // The extra details; we support up to EXTRA_DETAILS_SIZE of them + S3NameValue extraDetails[EXTRA_DETAILS_SIZE]; + + // This is the buffer from which the names and values used in extraDetails + // are allocated + string_multibuffer(extraDetailsNamesValues, EXTRA_DETAILS_SIZE * 1024); +} ErrorParser; + + +// Always call this +void error_parser_initialize(ErrorParser *errorParser); + +S3Status error_parser_add(ErrorParser *errorParser, char *buffer, + int bufferSize); + +void error_parser_convert_status(ErrorParser *errorParser, S3Status *status); + +// Always call this +void error_parser_deinitialize(ErrorParser *errorParser); + + +#endif /* ERROR_PARSER_H */ diff --git a/inc/libs3.h b/inc/libs3.h index af5c79d..190cf8d 100644 --- a/inc/libs3.h +++ b/inc/libs3.h @@ -598,7 +598,7 @@ typedef S3Status (S3ResponseHeadersCallback)(const S3ResponseHeaders *headers, typedef void (S3ResponseCompleteCallback)(S3Status status, int httpResponseCode, - S3ErrorDetails *errorDetails, + const S3ErrorDetails *errorDetails, void *callbackData); @@ -921,9 +921,9 @@ void S3_list_service(S3Protocol protocol, const char *accessKeyId, * be set to the name of the geographic location of S3 bucket, or will * be left as a zero-length string if no location was available. **/ -void S3_test_bucket(S3Protocol protocol, const char *accessKeyId, - const char *secretAccessKey, const char *bucketName, - int locationConstraintReturnSize, +void S3_test_bucket(S3Protocol protocol, S3UriStyle uriStyle, + const char *accessKeyId, const char *secretAccessKey, + const char *bucketName, int locationConstraintReturnSize, char *locationConstraintReturn, S3RequestContext *requestContext, S3ResponseHandler *handler, void *callbackData); @@ -962,9 +962,9 @@ void S3_create_bucket(S3Protocol protocol, const char *accessKeyId, * @param bucketName is the name of the bucket to be deleted * @return S3Status ??? **/ -void S3_delete_bucket(S3Protocol protocol, const char *accessKeyId, - const char *secretAccessKey, const char *bucketName, - S3RequestContext *requestContext, +void S3_delete_bucket(S3Protocol protocol, S3UriStyle uriStyle, + const char *accessKeyId, const char *secretAccessKey, + const char *bucketName, S3RequestContext *requestContext, S3ResponseHandler *handler, void *callbackData); diff --git a/inc/private.h b/inc/private.h deleted file mode 100644 index 2ce88d9..0000000 --- a/inc/private.h +++ /dev/null @@ -1,409 +0,0 @@ -/** ************************************************************************** - * private.h - * - * Copyright 2008 Bryan Ischo <bryan@ischo.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program 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 General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the - * - * Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - ************************************************************************** **/ - -#ifndef PRIVATE_H -#define PRIVATE_H - -#include <curl/curl.h> -#include <curl/multi.h> -#include "libs3.h" - - -// As specified in S3 documntation -#define META_HEADER_NAME_PREFIX "x-amz-meta-" -#define HOSTNAME "s3.amazonaws.com" - - -// Derived from S3 documentation - -// This is the maximum number of x-amz-meta- headers that could be included in -// a request to S3. The smallest meta header is" x-amz-meta-n: v". Since S3 -// doesn't count the ": " against the total, the smallest amount of data to -// count for a header would be the length of "x-amz-meta-nv". -#define MAX_META_HEADER_COUNT \ - (S3_MAX_META_HEADER_SIZE / (sizeof(META_HEADER_NAME_PREFIX "nv") - 1)) - -// This is the maximum number of bytes needed in a "compacted meta header" -// buffer, which is a buffer storing all of the compacted meta headers. -#define COMPACTED_META_HEADER_BUFFER_SIZE \ - (MAX_META_HEADER_COUNT * sizeof(META_HEADER_NAME_PREFIX "n: v")) - -// Maximum url encoded key size; since every single character could require -// URL encoding, it's 3 times the size of a key (since each url encoded -// character takes 3 characters: %NN) -#define MAX_URLENCODED_KEY_SIZE (3 * S3_MAX_KEY_SIZE) - -// This is the maximum size of a URI that could be passed to S3: -// https://s3.amazonaws.com/${BUCKET}/${KEY}?acl -// 255 is the maximum bucket length -#define MAX_URI_SIZE \ - ((sizeof("https://" HOSTNAME "/") - 1) + 255 + 1 + \ - MAX_URLENCODED_KEY_SIZE + (sizeof("?torrent" - 1)) + 1) - -// Maximum size of a canonicalized resource -#define MAX_CANONICALIZED_RESOURCE_SIZE \ - (1 + 255 + 1 + MAX_URLENCODED_KEY_SIZE + (sizeof("?torrent") - 1) + 1) - - -// Describes a type of HTTP request (these are our supported HTTP "verbs") -typedef enum -{ - HttpRequestTypeGET, - HttpRequestTypeHEAD, - HttpRequestTypePUT, - HttpRequestTypeCOPY, - HttpRequestTypeDELETE -} HttpRequestType; - - -// Simple XML callback. -// -// elementPath: is the full "path" of the element; i.e. -// <foo><bar><baz>data</baz><bar><foo> would have 'data' in the element -// foo/bar/baz. -// -// Return of anything other than S3StatusOK causes the calling -// simplexml_add() function to immediately stop and return the status. -// -// data is passed in as 0 on end of element -typedef S3Status (SimpleXmlCallback)(const char *elementPath, const char *data, - int dataLen, void *callbackDatao); - -typedef struct SimpleXml -{ - void *xmlParser; - - SimpleXmlCallback *callback; - - void *callbackData; - - char elementPath[512]; - - int elementPathLen; - - S3Status status; -} SimpleXml; - - -// This completely describes a request. A RequestParams is not required to be -// allocated from the heap and its lifetime is not assumed to extend beyond -// the lifetime of the function to which it has been passed. -typedef struct RequestParams -{ - // The following are supplied --------------------------------------------- - - // Request type, affects the HTTP verb used - HttpRequestType httpRequestType; - // Protocol to use for request - S3Protocol protocol; - // URI style to use for request - S3UriStyle uriStyle; - // Bucket name, if any - const char *bucketName; - // Key, if any - const char *key; - // Query params - ready to append to URI (i.e. ?p1=v1?p2=v2) - const char *queryParams; - // sub resource, like ?acl, ?location, ?torrent - const char *subResource; - // AWS Access Key ID - const char *accessKeyId; - // AWS Secret Access Key - const char *secretAccessKey; - // Request headers - const S3RequestHeaders *requestHeaders; - // Response handler callback - S3ResponseHandler *handler; - // The callbacks to make for the data payload of the response - union { - S3ListServiceCallback *listServiceCallback; - S3ListBucketCallback *listBucketCallback; - S3PutObjectCallback *putObjectCallback; - S3GetObjectCallback *getObjectCallback; - } u; - // Response handler callback data - void *callbackData; - // The write callback to be called by curl, if needed; req will be passed - // in as the Request structure for this request - size_t (*curlWriteCallback)(void *data, size_t s, size_t n, void *req); - // The read callback to be called by curl, if needed; req will be passed - // in as the Request structure for this request - size_t (*curlReadCallback)(void *data, size_t s, size_t n, void *req); - // This is the number of bytes that will be provided by the read callback, - // if the read callback is set - int64_t readSize; - - - // The following are computed --------------------------------------------- - - // All x-amz- headers, in normalized form (i.e. NAME: VALUE, no other ws) - char *amzHeaders[MAX_META_HEADER_COUNT + 2]; // + 2 for acl and date - // The number of x-amz- headers - int amzHeadersCount; - // Storage for amzHeaders (the +256 is for x-amz-acl and x-amz-date) - char amzHeadersRaw[COMPACTED_META_HEADER_BUFFER_SIZE + 256 + 1]; - // Canonicalized x-amz- headers - char canonicalizedAmzHeaders[COMPACTED_META_HEADER_BUFFER_SIZE + 256 + 1]; - // URL-Encoded key - char urlEncodedKey[MAX_URLENCODED_KEY_SIZE + 1]; - // Canonicalized resource - char canonicalizedResource[MAX_CANONICALIZED_RESOURCE_SIZE + 1]; - // Cache-Control header (or empty) - char cacheControlHeader[128]; - // Content-Type header (or empty) - char contentTypeHeader[128]; - // Content-MD5 header (or empty) - char md5Header[128]; - // Content-Disposition header (or empty) - char contentDispositionHeader[128]; - // Content-Encoding header (or empty) - char contentEncodingHeader[128]; - // Expires header (or empty) - char expiresHeader[128]; - // Authorization header - char authorizationHeader[128]; -} RequestParams; - - -typedef struct ListServiceXmlCallbackData -{ - char ownerId[256]; - int ownerIdLen; - - char ownerDisplayName[256]; - int ownerDisplayNameLen; - - char bucketName[256]; - int bucketNameLen; - - char creationDate[128]; - int creationDateLen; -} ListServiceXmlCallbackData; - - -typedef struct ListBucketXmlCallbackData -{ - -} ListBucketXmlCallbackData; - - -// This is the stuff associated with a request that needs to be on the heap -// (and thus live while a curl_multi is in use). -typedef struct Request -{ - // True if this request has already been used - int used; - - // The status of this Request, as will be reported to the user via the - // complete callback - S3Status status; - - // The CURL structure driving the request - CURL *curl; - - // The HTTP headers to use for the curl request - struct curl_slist *headers; - - // libcurl requires that the uri be stored outside of the curl handle - char uri[MAX_URI_SIZE + 1]; - - // The callback data to pass to all of the callbacks - void *callbackData; - - // responseHeaders.{requestId,requestId2,contentType,server,eTag} get - // copied into here. We allow 128 bytes for each header, plus \0 term. - char responseHeaderStrings[5 * 129]; - - // The length thus far of responseHeaderStrings - int responseHeaderStringsLen; - - // responseHeaders.metaHeaders strings get copied into here - char responseMetaHeaderStrings[COMPACTED_META_HEADER_BUFFER_SIZE]; - - // The length thus far of metaHeaderStrings - int responseMetaHeaderStringsLen; - - // Response meta headers - S3NameValue responseMetaHeaders[MAX_META_HEADER_COUNT]; - - // Callback to make when headers are available - S3ResponseHeadersCallback *headersCallback; - - // The structure to pass to the headers callback - S3ResponseHeaders responseHeaders; - - // This is set to nonzero after the haders callback has been made - int headersCallbackMade; - - // The HTTP response code that S3 sent back for this request - int httpResponseCode; - - // This is the write callback that the user of the request wants to have - // called back when data is available. - size_t (*curlWriteCallback)(void *data, size_t s, size_t n, void *req); - - // This is the read callback that the user of the request wants to have - // called back when data is to be written. - size_t (*curlReadCallback)(void *data, size_t s, size_t n, void *req); - - // The callback to make when the response has been completely handled - S3ResponseCompleteCallback *completeCallback; - - // This is nonzero if the error XML parser has been initialized - int errorXmlParserInitialized; - - // This is the error XML parser - SimpleXml errorXmlParser; - - // If S3 did send an XML error, this is the parsed form of it - S3ErrorDetails s3ErrorDetails; - - // These are the buffers used to store the S3Error values - char s3ErrorCode[1024]; - int s3ErrorCodeLen; - - // These are the buffers used to store the S3Error values - char s3ErrorMessage[1024]; - int s3ErrorMessageLen; - - // These are the buffers used to store the S3Error values - char s3ErrorResource[1024]; - int s3ErrorResourceLen; - - // These are the buffers used to store the S3Error values - char s3ErrorFurtherDetails[1024]; - int s3ErrorFurtherDetailsLen; - - // The extra details; we support up to 8 of them - S3NameValue s3ErrorExtraDetails[8]; - // This is the buffer from which the names used in s3ErrorExtraDetails - // are allocated - char s3ErrorExtraDetailsNames[512]; - // And this is the length of each element of s3ErrorExtraDetailsNames - int s3ErrorExtraDetailsNamesLen; - // These are the buffers of values in the s3ErrorExtraDetails. They - // are kept separate so that they can be individually appended to. - char s3ErrorExtraDetailsValues[8][1024]; - // And these are the individual lengths of each of each element of - // s3ErrorExtraDetailsValues - int s3ErrorExtraDetailsValuesLens[8]; - - // The following fields are used by the S3 functions themselves, not - // the request code. - - // xxx rewrite all of this stuff, it's ugly. Do the following: - // * Define request as a self-contained API similar to what it is now, - // but supporting only get object and put object callbacks - // * Make the S3 functions that have to do XML parsing allocate their - // own callback data, that does the XML parsing, and then passes the - // parsed data on - // - // Alternately, something like: - // - // - An API for preparing a CURL handle to issue an S3 request - // - Separate APIs for handling response data - // - The S3 functions tie all of these together, with their own callbacks - // for parsing XML data if necessary - // - // In either case, break the Request structure up into separate structures - // with their own APIs (response header parsing, error parsing, etc), - // and compose them here, instead of having everything stuck into this - // structure directly, which is ugly. - - // The callbacks to make for the data payload of the response - union { - S3ListServiceCallback *listServiceCallback; - S3ListBucketCallback *listBucketCallback; - S3PutObjectCallback *putObjectCallback; - S3GetObjectCallback *getObjectCallback; - } callback; - - // The data to use during the xml callback - union { - ListServiceXmlCallbackData listServiceXmlCallbackData; - ListBucketXmlCallbackData listBucketXmlCallbackData; - } data; - - // The XML parser that the write callback will use if it needs it - SimpleXml dataXmlParser; - - // Whoever initializes dataXmlParser has to set this to 1 - int dataXmlParserInitialized; -} Request; - - -struct S3RequestContext -{ - CURLM *curlm; - - int count; -}; - - -// Mutex functions ------------------------------------------------------------ - -// Create a mutex. Returns 0 if none could be created. -struct S3Mutex *mutex_create(); - -// Lock a mutex -void mutex_lock(struct S3Mutex *mutex); - -// Unlock a mutex -void mutex_unlock(struct S3Mutex *mutex); - -// Destroy a mutex -void mutex_destroy(struct S3Mutex *mutex); - - -// Request functions -// ---------------------------------------------------------------------------- - -// Initialize the API -S3Status request_api_initialize(const char *userAgentInfo); - -// Deinitialize the API -void request_api_deinitialize(); - -// Perform a request; if context is 0, performs the request immediately; -// otherwise, sets it up to be performed by context. -void request_perform(RequestParams *params, S3RequestContext *context); - -// Called by the internal request code or internal request context code when a -// curl has finished the request -void request_finish(Request *request, S3Status status); - - -// Simple XML parsing -// ---------------------------------------------------------------------------- - -S3Status simplexml_initialize(SimpleXml *simpleXml, - SimpleXmlCallback *callback, void *callbackData); - -S3Status simplexml_add(SimpleXml *simpleXml, const char *data, int dataLen); - - -void simplexml_deinitialize(SimpleXml *simpleXml); - - -#endif /* PRIVATE_H */ diff --git a/inc/request.h b/inc/request.h new file mode 100644 index 0000000..e63f162 --- /dev/null +++ b/inc/request.h @@ -0,0 +1,191 @@ +/** ************************************************************************** + * request.h + * + * Copyright 2008 Bryan Ischo <bryan@ischo.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program 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 General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the + * + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + ************************************************************************** **/ + +#ifndef REQUEST_H +#define REQUEST_H + +#include "libs3.h" +#include "error_parser.h" +#include "response_headers_handler.h" +#include "util.h" + +/** + * Any return value other than S3StatusOK will stop the request processing + * immediately + **/ +typedef S3Status (RequestHeadersCallback) + (const S3ResponseHeaders *responseHeaders, void *callbackData); + +/** + * As a 'read' function: + * - Fill [buffer] with up to [bufferSize] bytes, return the number of + * bytes actually filled; returning 0 means EOF. + * + * As a 'write' function: + * - [bufferSize] bytes are supplied in [buffer]. Return anything other + * than [bufferSize] to stop the request processing immediately + **/ +typedef int (RequestDataCallback) + (char *buffer, int bufferSize, void *callbackData); + +/** + **/ +typedef void (RequestCompleteCallback) + (S3Status requestStatus, int httpResponseCode, + const S3ErrorDetails *s3ErrorDetails, void *callbackData); + + +// Describes a type of HTTP request (these are our supported HTTP "verbs") +typedef enum +{ + HttpRequestTypeGET, + HttpRequestTypeHEAD, + HttpRequestTypePUT, + HttpRequestTypeCOPY, + HttpRequestTypeDELETE +} HttpRequestType; + + +// This completely describes a request. A RequestParams is not required to be +// allocated from the heap and its lifetime is not assumed to extend beyond +// the lifetime of the function to which it has been passed. +typedef struct RequestParams +{ + // Request type, affects the HTTP verb used + HttpRequestType httpRequestType; + + // Protocol to use for request + S3Protocol protocol; + + // URI style to use for request + S3UriStyle uriStyle; + + // Bucket name, if any + const char *bucketName; + + // Key, if any + const char *key; + + // Query params - ready to append to URI (i.e. ?p1=v1?p2=v2) + const char *queryParams; + + // sub resource, like ?acl, ?location, ?torrent + const char *subResource; + + // AWS Access Key ID + const char *accessKeyId; + + // AWS Secret Access Key + const char *secretAccessKey; + + // Request headers + const S3RequestHeaders *requestHeaders; + + // Callback to be made when headers are available. May not be called. + RequestHeadersCallback *headersCallback; + + // Callback to be made to supply data to send to S3. May not be called. + RequestDataCallback *toS3Callback; + + // Number of bytes total that readCallback will supply + int64_t toS3CallbackTotalSize; + + // Callback to be made that supplies data read from S3. May not be called. + RequestDataCallback *fromS3Callback; + + // Callback to be made when request is complete. This will *always* be + // called. + RequestCompleteCallback *completeCallback; + + // Data passed to the callbacks + void *callbackData; +} RequestParams; + + +// This is the stuff associated with a request that needs to be on the heap +// (and thus live while a curl_multi is in use). +typedef struct Request +{ + // The status of this Request, as will be reported to the user via the + // complete callback + S3Status status; + + // The HTTP headers to use for the curl request + struct curl_slist *headers; + + // The CURL structure driving the request + CURL *curl; + + // libcurl requires that the uri be stored outside of the curl handle + char uri[MAX_URI_SIZE + 1]; + + // The HTTP response code that S3 sent back for this request + int httpResponseCode; + + // Callback to be made when headers are available. May not be called. + RequestHeadersCallback *headersCallback; + + // Callback to be made to supply data to send to S3. May not be called. + RequestDataCallback *toS3Callback; + + // Callback to be made that supplies data read from S3. May not be called. + RequestDataCallback *fromS3Callback; + + // Callback to be made when request is complete. This will *always* be + // called. + RequestCompleteCallback *completeCallback; + + // Data passed to the callbacks + void *callbackData; + + // Handler of response headers + ResponseHeadersHandler responseHeadersHandler; + + // This is set to nonzero after the haders callback has been made + int headersCallbackMade; + + // Parser of errors + ErrorParser errorParser; +} Request; + + +// Request functions +// ---------------------------------------------------------------------------- + +// Initialize the API +S3Status request_api_initialize(const char *userAgentInfo); + +// Deinitialize the API +void request_api_deinitialize(); + +// Perform a request; if context is 0, performs the request immediately; +// otherwise, sets it up to be performed by context. +void request_perform(const RequestParams *params, S3RequestContext *context); + +// Called by the internal request code or internal request context code when a +// curl has finished the request +void request_finish(Request *request); + + +#endif /* REQUEST_H */ diff --git a/inc/request_context.h b/inc/request_context.h new file mode 100644 index 0000000..0d9d8b3 --- /dev/null +++ b/inc/request_context.h @@ -0,0 +1,39 @@ +/** ************************************************************************** + * request_context.h + * + * Copyright 2008 Bryan Ischo <bryan@ischo.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program 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 General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the + * + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + ************************************************************************** **/ + +#ifndef REQUEST_CONTEXT_H +#define REQUEST_CONTEXT_H + +#include "libs3.h" + + +struct S3RequestContext +{ + CURLM *curlm; + + int count; +}; + + +#endif /* REQUEST_CONTEXT_H */ diff --git a/inc/response_headers_handler.h b/inc/response_headers_handler.h new file mode 100644 index 0000000..817a1fc --- /dev/null +++ b/inc/response_headers_handler.h @@ -0,0 +1,62 @@ +/** ************************************************************************** + * response_haeders_handler.h + * + * Copyright 2008 Bryan Ischo <bryan@ischo.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program 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 General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the + * + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + ************************************************************************** **/ + +#ifndef RESPONSE_HEADERS_HANDLER_H +#define RESPONSE_HEADERS_HANDLER_H + +#include "libs3.h" +#include "string_buffer.h" +#include "util.h" + + +typedef struct ResponseHeadersHandler +{ + // The structure to pass to the headers callback. This is filled in by + // the ResponseHeadersHandler from the headers added to it. + S3ResponseHeaders responseHeaders; + + // Set to 1 after the done call has been made + int done; + + // copied into here. We allow 128 bytes for each header, plus \0 term. + string_multibuffer(responseHeaderStrings, 5 * 129); + + // responseHeaders.metaHeaders strings get copied into here + string_multibuffer(responseMetaHeaderStrings, + COMPACTED_META_HEADER_BUFFER_SIZE); + + // Response meta headers + S3NameValue responseMetaHeaders[MAX_META_HEADER_COUNT]; +} ResponseHeadersHandler; + + +void response_headers_handler_initialize(ResponseHeadersHandler *handler); + +void response_headers_handler_add(ResponseHeadersHandler *handler, + char *data, int dataLen); + +void response_headers_handler_done(ResponseHeadersHandler *handler, + CURL *curl); + +#endif /* RESPONSE_HEADERS_HANDLER_H */ diff --git a/inc/simplexml.h b/inc/simplexml.h new file mode 100644 index 0000000..d9b5981 --- /dev/null +++ b/inc/simplexml.h @@ -0,0 +1,74 @@ +/** ************************************************************************** + * simplexml.h + * + * Copyright 2008 Bryan Ischo <bryan@ischo.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program 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 General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the + * + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + ************************************************************************** **/ + +#ifndef SIMPLEXML_H +#define SIMPLEXML_H + +#include "libs3.h" + + +// Simple XML callback. +// +// elementPath: is the full "path" of the element; i.e. +// <foo><bar><baz>data</baz><bar><foo> would have 'data' in the element +// foo/bar/baz. +// +// Return of anything other than S3StatusOK causes the calling +// simplexml_add() function to immediately stop and return the status. +// +// data is passed in as 0 on end of element +typedef S3Status (SimpleXmlCallback)(const char *elementPath, const char *data, + int dataLen, void *callbackData); + +typedef struct SimpleXml +{ + void *xmlParser; + + SimpleXmlCallback *callback; + + void *callbackData; + + char elementPath[512]; + + int elementPathLen; + + S3Status status; +} SimpleXml; + + +// Simple XML parsing +// ---------------------------------------------------------------------------- + +// Always call this, even if the simplexml doesn't end up being used +S3Status simplexml_initialize(SimpleXml *simpleXml, + SimpleXmlCallback *callback, void *callbackData); + +S3Status simplexml_add(SimpleXml *simpleXml, const char *data, int dataLen); + + +// Always call this +void simplexml_deinitialize(SimpleXml *simpleXml); + + +#endif /* SIMPLEXML_H */ diff --git a/inc/string_buffer.h b/inc/string_buffer.h new file mode 100644 index 0000000..1deeb51 --- /dev/null +++ b/inc/string_buffer.h @@ -0,0 +1,105 @@ +/** ************************************************************************** + * string_buffer.h + * + * Copyright 2008 Bryan Ischo <bryan@ischo.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program 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 General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the + * + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + ************************************************************************** **/ + +#ifndef STRING_BUFFER_H +#define STRING_BUFFER_H + +#include <stdio.h> + + +// Declare a string_buffer with the given name of the given maximum length +#define string_buffer(name, len) \ + char name[len + 1]; \ + int name##Len + + +// Initialize a string_buffer +#define string_buffer_initialize(sb) \ + do { \ + sb[0] = 0; \ + sb##Len = 0; \ + } while (0) + + +// Append [len] bytes of [str] to [sb], setting [all_fit] to 1 if it fit, and +// 0 if it did not +#define string_buffer_append(sb, str, len, all_fit) \ + do { \ + sb##Len += snprintf(&(sb[sb##Len]), sizeof(sb) - sb##Len - 1, \ + "%.*s", len, str); \ + if (sb##Len > (sizeof(sb) - 1)) { \ + sb##Len = sizeof(sb) - 1; \ + all_fit = 0; \ + } \ + else { \ + all_fit = 1; \ + } \ + } while (0) + + +// Declare a string multibuffer with the given name of the given maximum size +#define string_multibuffer(name, size) \ + char name[size]; \ + int name##Size + + +// Initialize a string_multibuffer +#define string_multibuffer_initialize(smb) \ + do { \ + smb##Size = 0; \ + } while (0) + + +// Evaluates to the current string within the string_multibuffer +#define string_multibuffer_current(smb) \ + &(smb[smb##Size]) + + +// Adds a new string to the string_multibuffer +#define string_multibuffer_add(smb, str, len, all_fit) \ + do { \ + smb##Size += (snprintf(&(smb[smb##Size]), \ + sizeof(smb) - smb##Size, \ + "%.*s", len, str) + 1); \ + if (smb##Size > sizeof(smb)) { \ + smb##Size = sizeof(smb); \ + all_fit = 0; \ + } \ + else { \ + all_fit = 1; \ + } \ + } while (0) + + +// Appends to the current string in the string_multibuffer. There must be a +// current string, meaning that string_multibuffer_add must have been called +// at least once for this string_multibuffer. +#define string_multibuffer_append(smb, str, len, all_fit) \ + do { \ + smb##Size--; \ + string_multibuffer_add(smb, str, len, all_fit); \ + } while (0) + + +#endif /* STRING_BUFFER_H */ diff --git a/inc/util.h b/inc/util.h new file mode 100644 index 0000000..c56f3cc --- /dev/null +++ b/inc/util.h @@ -0,0 +1,90 @@ +/** ************************************************************************** + * util.h + * + * Copyright 2008 Bryan Ischo <bryan@ischo.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program 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 General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the + * + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + ************************************************************************** **/ + +#ifndef UTIL_H +#define UTIL_H + +#include <curl/curl.h> +#include <curl/multi.h> +#include "libs3.h" + + +// As specified in S3 documntation +#define META_HEADER_NAME_PREFIX "x-amz-meta-" +#define HOSTNAME "s3.amazonaws.com" + + +// Derived from S3 documentation + +// This is the maximum number of x-amz-meta- headers that could be included in +// a request to S3. The smallest meta header is" x-amz-meta-n: v". Since S3 +// doesn't count the ": " against the total, the smallest amount of data to +// count for a header would be the length of "x-amz-meta-nv". +#define MAX_META_HEADER_COUNT \ + (S3_MAX_META_HEADER_SIZE / (sizeof(META_HEADER_NAME_PREFIX "nv") - 1)) + +// This is the maximum number of bytes needed in a "compacted meta header" +// buffer, which is a buffer storing all of the compacted meta headers. +#define COMPACTED_META_HEADER_BUFFER_SIZE \ + (MAX_META_HEADER_COUNT * sizeof(META_HEADER_NAME_PREFIX "n: v")) + +// Maximum url encoded key size; since every single character could require +// URL encoding, it's 3 times the size of a key (since each url encoded +// character takes 3 characters: %NN) +#define MAX_URLENCODED_KEY_SIZE (3 * S3_MAX_KEY_SIZE) + +// This is the maximum size of a URI that could be passed to S3: +// https://s3.amazonaws.com/${BUCKET}/${KEY}?acl +// 255 is the maximum bucket length +#define MAX_URI_SIZE \ + ((sizeof("https://" HOSTNAME "/") - 1) + 255 + 1 + \ + MAX_URLENCODED_KEY_SIZE + (sizeof("?torrent" - 1)) + 1) + +// Maximum size of a canonicalized resource +#define MAX_CANONICALIZED_RESOURCE_SIZE \ + (1 + 255 + 1 + MAX_URLENCODED_KEY_SIZE + (sizeof("?torrent") - 1) + 1) + + +// Mutex functions ----------------------------------------------------------- + +// Create a mutex. Returns 0 if none could be created. +struct S3Mutex *mutex_create(); + +// Lock a mutex +void mutex_lock(struct S3Mutex *mutex); + +// Unlock a mutex +void mutex_unlock(struct S3Mutex *mutex); + +// Destroy a mutex +void mutex_destroy(struct S3Mutex *mutex); + + +// Utilities ----------------------------------------------------------------- + +// Returns 0 on success, nonzero on failure +int parseIso8601Time(const char *str, time_t *secondsReturn, int *millisReturn); + + +#endif /* UTIL_H */ |