summaryrefslogtreecommitdiff
path: root/inc
diff options
context:
space:
mode:
authorBryan Ischo <bryan@ischo.com>2008-07-10 21:12:21 +0000
committerBryan Ischo <bryan@ischo.com>2008-07-10 21:12:21 +0000
commitc0535eabe25706904711f1453e724e659b93318c (patch)
tree55e2a2acc6fbc71e4c1a55489aaeed7f2cc919e2 /inc
parente9e38ab98e38b35725d85cbe6101bfbbd34d1418 (diff)
downloadceph-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.h80
-rw-r--r--inc/libs3.h14
-rw-r--r--inc/private.h409
-rw-r--r--inc/request.h191
-rw-r--r--inc/request_context.h39
-rw-r--r--inc/response_headers_handler.h62
-rw-r--r--inc/simplexml.h74
-rw-r--r--inc/string_buffer.h105
-rw-r--r--inc/util.h90
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 */