diff options
author | Bryan Ischo <bryan@ischo.com> | 2008-07-01 12:08:57 +0000 |
---|---|---|
committer | Bryan Ischo <bryan@ischo.com> | 2008-07-01 12:08:57 +0000 |
commit | ea132819c17f169c68b4c2ac5993c857a53bded7 (patch) | |
tree | c01a327012cdecf51276c530c0083546c7432872 /inc | |
parent | fb76cb2d8fe580babd63c4b45826faa9fe9c8a19 (diff) | |
download | ceph-libs3-ea132819c17f169c68b4c2ac5993c857a53bded7.tar.gz |
* Checkpoint work in progress
Diffstat (limited to 'inc')
-rw-r--r-- | inc/libs3.h | 37 | ||||
-rw-r--r-- | inc/private.h | 180 |
2 files changed, 141 insertions, 76 deletions
diff --git a/inc/libs3.h b/inc/libs3.h index 41db7ee..d27bcf5 100644 --- a/inc/libs3.h +++ b/inc/libs3.h @@ -55,13 +55,13 @@ ************************************************************************** **/ /** - * S3_MAX_KEY_LENGTH is the maximum length of keys that Amazon S3 supports. + * S3_MAX_KEY_SIZE is the maximum size of keys that Amazon S3 supports. **/ -#define S3_MAX_KEY_LENGTH 1024 +#define S3_MAX_KEY_SIZE 1024 /** - * S3_MAX_META_HEADERS_SIZE is the maximum number of bytes that all - * x-amz-meta headers passed to Amazon S3 is allowed to contain + * S3_MAX_META_HEADERS_SIZE is the maximum number of bytes allowed for + * x-amz-meta header names and values in any request passed to Amazon S3 **/ #define S3_MAX_META_HEADER_SIZE 2048 @@ -226,7 +226,7 @@ typedef enum * updated. Each canned ACL has a predefined value when expanded to a full * set of S3 ACL Grants. **/ -typedef enum S3CannedAcl +typedef enum { S3CannedAclNone = 0, /* private */ S3CannedAclRead = 1, /* public-read */ @@ -235,6 +235,17 @@ typedef enum S3CannedAcl } S3CannedAcl; +/** + * S3MetaDataDirective identifies what the S3 service should do with an + * object's metadata when the object is copied. + **/ +typedef enum +{ + S3MetaDataDirectiveCopy = 0, + S3MetaDataDirectiveReplace = 1 +} S3MetaDataDirective; + + /** ************************************************************************** * Data Types ************************************************************************** **/ @@ -479,10 +490,24 @@ typedef struct S3RequestHeaders /** * This identifies the "canned ACL" that should be used for this object. * The default (0) gives only the owner of the object access to it. + * This value is ignored for all operations except put_object and + * copy_object. **/ S3CannedAcl cannedAcl; /** - * This is the number of headers in the metaHeaders field + * For copy operations, this identifies the source object; must be + * of the form /source_bucket/source_key. This value is ignored for all + * operations except copy_object. + **/ + const char *sourceObject; + /** + * For copy operations, this gives the metadata directive. This value is + * ignored for all operations except copy_object. + **/ + S3MetaDataDirective metaDataDirective; + /** + * This is the number of headers in the metaHeaders field. Ignored and + * assumed to be 0, for all except put_object and copy_object operations. **/ int metaHeadersCount; /** diff --git a/inc/private.h b/inc/private.h index 6514043..5640313 100644 --- a/inc/private.h +++ b/inc/private.h @@ -36,26 +36,112 @@ // Derived from S3 documentation -// The maximum number of x-amz-meta headers that the user can supply is -// limited by the fact that every x-amz-meta header must be of the form: -// x-amz-meta-${NAME}: ${VALUE} -// where NAME and VALUE must be at least 1 character long, so the shortest -// x-amz-meta header would be: -// x-amz-meta-n: v -// So we take the S3's total limit of 2K and divide it by the length of that + +// 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 "n: v"))) -// Now the total that we allow for all x-amz- headers includes the ones that -// we additionally add, which is x-amz-acl and x-amz-date -// 256 bytes will be more than enough to cover those -#define MAX_AMZ_HEADER_SIZE (S3_MAX_META_HEADER_SIZE + 256) + (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) -#define MAX_CANONICALIZED_RESOURCE_SIZE (S3_MAX_KEY_LENGTH + 1024) +// 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) -#define MAX_URLENCODED_KEY_SIZE (3 * S3_MAX_KEY_LENGTH) +// Maximum size of a canonicalized resource +#define MAX_CANONICALIZED_RESOURCE_SIZE \ + (1 + 255 + 1 + MAX_URLENCODED_KEY_SIZE + (sizeof("?torrent") - 1) + 1) -// This is the data associated with a request, and is set in the private data -// of the curl request + +// 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 +{ + // 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; + // Response handler callback data + void *callbackData; + + // 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]; + // 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]; + // Uri + char uri[MAX_URI_SIZE + 1]; +} 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 { // True if this request has already been used @@ -64,22 +150,19 @@ typedef struct Request // The CURL structure driving the request CURL *curl; - // The headers that will be sent to S3 - 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.metaHeaders strings get copied into here. Since S3 - // supports a max of 2K for all values and keys, limiting to 2K here is - // sufficient - char responseMetaHeaderStrings[S3_MAX_META_HEADER_SIZE]; + // responseHeaders.metaHeaders strings get copied into here + char responseMetaHeaderStrings[COMPACTED_META_HEADER_BUFFER_SIZE]; // The length thus far of metaHeaderStrings int responseMetaHeaderStringsLen; - // The maximum number of meta headers possible is: - // 2K / strlen("x-amz-meta-a:\0\0") + // Response meta headers S3MetaHeader responseMetaHeaders[MAX_META_HEADER_COUNT]; // Callback stuff --------------------------------------------------------- @@ -148,9 +231,9 @@ S3Status request_api_initialize(const char *userAgentInfo); void request_api_deinitialize(); // Get a Request that has been initialized, except for the data payload -// callback pointer -S3Status request_get(S3ResponseHandler *handler, void *callbackData, - Request **requestReturn); +// callback pointer, and is ready to execute via request_multi_add or +// request_easy_perform +S3Status request_get(RequestParams *params, Request **requestReturn); // Release a Request that is no longer needed void request_release(Request *request); @@ -166,48 +249,5 @@ void request_easy_perform(Request *request); // releases the request void request_finish(Request *request, S3Status status); -typedef struct XAmzHeaders -{ - int count; - char *headers[MAX_META_HEADER_COUNT]; - char headers_raw[MAX_AMZ_HEADER_SIZE]; -} XAmzHeaders; - -// Composes the entire list of x-amz- headers, which includes all x-amz-meta- -// headers and any other headers. Each one is guaranteed to be of the form: -// [HEADER]: [VALUE] -// Where HEADER and VALUE have no whitespace in them, and they are separated -// by exactly ": " -// There may be duplicate x-amz-meta- headers returned -// All header names will be lower cased -S3Status request_compose_x_amz_headers(XAmzHeaders *xAmzHeaders, - const S3RequestHeaders *requestHeaders); - -// buffer must be at least MAX_URLENCODED_KEY_SIZE bytes -void request_encode_key(char *buffer, const char *key); - - -// Authorization functions -// ------------------------------------------------------------ - -// Canonicalizes the given x-amz- headers into the given buffer with the -// given bufferSize. buffer must be at least S3_MAX_AMZ_HEADER_SIZE bytes. -void canonicalize_amz_headers(char *buffer, const XAmzHeaders *xAmzHeaders); - -// Canonicalizes a resource into buffer; buffer must be at least -// MAX_CANONICALIZED_RESOURCE_SIZE bytes long. subResource is one of: -// "acl", "location", "logging", and "torrent" -void canonicalize_resource(char *buffer, S3UriStyle uriStyle, - const char *bucketName, - const char *encodedKey, const char *subResource); - -S3Status auth_header_snprintf(char *buffer, int bufferSize, - const char *accessKeyId, - const char *secretAccessKey, - const char *httpVerb, const char *md5, - const char *contentType, - const char *canonicalizedAmzHeaders, - const char *canonicalizedResource); - #endif /* PRIVATE_H */ |