Just committed the following to tabled.git on my local laptop, on a side branch. This won't be pushed onto the main tabled branch until Friday, to give people time to convert as zaitcev suggested in the 'new hail repository' thread. As a side note, this requires a couple hail.git commits that will be pushed to upstream hail.git from my local laptop in a couple hours (movement of uri_parse from tabled's libhttpstor into libhail), so you'll need to update hail.git before being able to use the patch below. commit d4cfbcac3f00088cf38df2834a880f7e75ca6f0b Author: Jeff Garzik <jgarzik@xxxxxxxxx> Date: Wed Jul 7 18:29:26 2010 -0400 Link with libhail, eliminating much local code. Signed-off-by: Jeff Garzik <jgarzik@xxxxxxxxx> .gitignore | 9 autogen.sh | 6 configure.ac | 32 - include/Makefile.am | 2 include/httpstor.h | 100 ---- include/httputil.h | 84 --- lib/.gitignore | 10 lib/Makefile.am | 23 lib/httpstor.c | 944 -------------------------------------- lib/httputil.c | 366 -------------- lib/libhttpstor-uninstalled.pc.in | 12 lib/libhttpstor.pc.in | 13 lib/uri.c | 289 ----------- server/.gitignore | 4 server/Makefile.am | 2 server/bucket.c | 18 server/object.c | 34 - server/server.c | 30 - server/status.c | 6 server/tabled.h | 2 test/Makefile.am | 9 test/basic-bucket.c | 29 - test/basic-object.c | 19 test/hdr-content-type.c | 23 test/hdr-meta.c | 23 test/it-works.c | 17 test/large-object.c | 27 - test/libtest.c | 36 + test/test.h | 3 test/wait-for-listen.c | 1 30 files changed, 165 insertions(+), 2008 deletions(-) diff --git a/.gitignore b/.gitignore index f9d8404..704329c 100644 --- a/.gitignore +++ b/.gitignore @@ -19,15 +19,6 @@ install-sh missing push stamp-h1 -libtool -ltmain.sh - -# app-specific -tabled -tdbadm - -libtabled.a -libtdb.a tabled*.tar.gz tabled-config.h* diff --git a/autogen.sh b/autogen.sh index 949dbd3..989604a 100755 --- a/autogen.sh +++ b/autogen.sh @@ -5,12 +5,8 @@ set -e -# libtoolize needs to be run twice, for some reason -# to avoid errors relating to ltmain.sh installation - -libtoolize --force aclocal autoheader automake --gnu --add-missing --copy autoconf -libtoolize --force + diff --git a/configure.ac b/configure.ac index 6112a6b..dbd438d 100644 --- a/configure.ac +++ b/configure.ac @@ -17,21 +17,6 @@ dnl You should have received a copy of the GNU General Public License dnl along with this program; if not, write to the Free Software dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -m4_define([libhttpstor_major_version], [1]) -m4_define([libhttpstor_minor_version], [1]) -m4_define([libhttpstor_micro_version], [1]) -m4_define([libhttpstor_interface_age], [1]) -# If you need a modifier for the version number. -# Normally empty, but can be used to make "fixup" releases. -m4_define([libhttpstor_extraversion], []) - -dnl libtool versioning from libhttpstor -m4_define([libhttpstor_current], [m4_eval(100 * libhttpstor_minor_version + libhttpstor_micro_version - libhttpstor_interface_age)]) -m4_define([libhttpstor_binary_age], [m4_eval(100 * libhttpstor_minor_version + libhttpstor_micro_version)]) -m4_define([libhttpstor_revision], [libhttpstor_interface_age]) -m4_define([libhttpstor_age], [m4_eval(libhttpstor_binary_age - libhttpstor_interface_age)]) -m4_define([libhttpstor_version], [libhttpstor_major_version().libhttpstor_minor_version().libhttpstor_micro_version()libhttpstor_extraversion()]) - AC_INIT([tabled], [0.5], [http://hail.wiki.kernel.org/]) @@ -40,26 +25,13 @@ AC_CONFIG_SRCDIR([server/server.c]) AM_INIT_AUTOMAKE([gnu]) AC_CONFIG_HEADERS([tabled-config.h]) -LIBHTTPSTOR_MAJOR_VERSION=libhttpstor_major_version -LIBHTTPSTOR_MINOR_VERSION=libhttpstor_minor_version -LIBHTTPSTOR_MICRO_VERSION=libhttpstor_micro_version -LIBHTTPSTOR_INTERFACE_AGE=libhttpstor_interface_age - -LIBHTTPSTOR_CURRENT=libhttpstor_current -LIBHTTPSTOR_REVISION=libhttpstor_revision -LIBHTTPSTOR_AGE=libhttpstor_age - -AC_SUBST(LIBHTTPSTOR_CURRENT) -AC_SUBST(LIBHTTPSTOR_REVISION) -AC_SUBST(LIBHTTPSTOR_AGE) - dnl Make sure anyone changing configure.ac/Makefile.am has a clue AM_MAINTAINER_MODE dnl Checks for programs AC_PROG_CC AC_PROG_GCC_TRADITIONAL -AM_PROG_LIBTOOL +AC_PROG_RANLIB PKG_PROG_PKG_CONFIG dnl Checks for header files. @@ -119,8 +91,6 @@ dnl AC_SUBST(CHUNKDC_LIBS) AC_CONFIG_FILES([doc/Makefile lib/Makefile - lib/libhttpstor.pc - lib/libhttpstor-uninstalled.pc include/Makefile server/Makefile test/Makefile diff --git a/include/Makefile.am b/include/Makefile.am index 163f7f8..4613c6f 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,5 +1,3 @@ -include_HEADERS = httpstor.h - EXTRA_DIST = elist.h httputil.h tdb.h diff --git a/include/httpstor.h b/include/httpstor.h deleted file mode 100644 index 07a0111..0000000 --- a/include/httpstor.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef __HTTPSTOR_H__ -#define __HTTPSTOR_H__ - -/* - * Copyright 2008-2009 Red Hat, Inc. - * - * 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. - * - * 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; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - -#include <stdbool.h> -#include <stdint.h> -#include <curl/curl.h> -#include <glib.h> - -struct httpstor_client { - CURL *curl; - char *acc; - char *host; - char *user; - char *key; - bool verbose; -}; - -struct httpstor_bucket { - char *name; - char *time_create; -}; - -struct httpstor_blist { - char *own_id; /* ID */ - char *own_name; /* DisplayName */ - GList *list; /* list of httpstor_bucket */ -}; - -struct httpstor_object { - char *key; - char *time_mod; - char *etag; - uint64_t size; - char *storage; - char *own_id; - char *own_name; -}; - -struct httpstor_keylist { - char *name; - char *prefix; - char *marker; - char *delim; - unsigned int max_keys; - bool trunc; - GList *contents; - GList *common_pfx; -}; - -extern void httpstor_free(struct httpstor_client *httpstor); -extern void httpstor_free_blist(struct httpstor_blist *blist); -extern void httpstor_free_bucket(struct httpstor_bucket *buck); -extern void httpstor_free_object(struct httpstor_object *obj); -extern void httpstor_free_keylist(struct httpstor_keylist *keylist); - -extern struct httpstor_client *httpstor_new(const char *service_acc, - const char *service_host, const char *user, const char *secret_key); - -extern bool httpstor_add_bucket(struct httpstor_client *httpstor, const char *name); -extern bool httpstor_del_bucket(struct httpstor_client *httpstor, const char *name); - -extern struct httpstor_blist *httpstor_list_buckets(struct httpstor_client *httpstor); - -extern bool httpstor_get(struct httpstor_client *httpstor, const char *bucket, const char *key, - size_t (*write_cb)(void *, size_t, size_t, void *), - void *user_data, bool want_headers); -extern void *httpstor_get_inline(struct httpstor_client *httpstor, const char *bucket, - const char *key, bool want_headers, size_t *len); -extern bool httpstor_put(struct httpstor_client *httpstor, const char *bucket, const char *key, - size_t (*read_cb)(void *, size_t, size_t, void *), - uint64_t len, void *user_data, char **user_hdrs); -extern bool httpstor_put_inline(struct httpstor_client *httpstor, const char *bucket, - const char *key, void *data, uint64_t len, - char **user_hdrs); -extern bool httpstor_del(struct httpstor_client *httpstor, const char *bucket, const char *key); - -extern struct httpstor_keylist *httpstor_keys(struct httpstor_client *httpstor, const char *bucket, - const char *prefix, const char *marker, - const char *delim, unsigned int max_keys); - -#endif /* __HTTPSTOR_H__ */ diff --git a/include/httputil.h b/include/httputil.h index b2e8f30..dfbdd4b 100644 --- a/include/httputil.h +++ b/include/httputil.h @@ -26,91 +26,7 @@ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #endif -#define PATH_ESCAPE_MASK 0x02 -#define QUERY_ESCAPE_MASK 0x04 - -enum { - REQ_MAX_HDR = 128, /* max hdrs per req */ -}; - -struct uri { - char *scheme; - unsigned int scheme_len; - char *userinfo; - unsigned int userinfo_len; - char *hostname; - unsigned int hostname_len; - - unsigned int port; - - char *path; - unsigned int path_len; - char *query; - unsigned int query_len; - char *fragment; - unsigned int fragment_len; /* see FIXME in uri.c */ -}; - -struct http_hdr { - char *key; - char *val; -}; - -struct http_req { - char *method; /* GET, POST, etc. */ - struct uri uri; /* URI */ - int major; /* HTTP version */ - int minor; - - char *orig_path; - - unsigned int n_hdr; /* list of headers */ - struct http_hdr hdr[REQ_MAX_HDR]; -}; - -enum ReqQ { - URIQ_ACL, - URIQ_LOCATION, - URIQ_LOGGING, - URIQ_TORRENT, - URIQNUM -}; - -enum ReqACLC { - ACLC_PRIV, - ACLC_PUB_R, - ACLC_PUB_RW, - ACLC_AUTH_R, - ACLCNUM -}; - -/* httputil.c */ -extern char *time2str(char *buf, int len, time_t time); -extern time_t str2time(const char *timestr); -extern int req_hdr_push(struct http_req *req, char *key, char *val); -extern char *req_hdr(struct http_req *req, const char *key); -extern void req_sign(struct http_req *req, const char *bucket, const char *key, - char *b64hmac_out); -extern GHashTable *req_query(struct http_req *req); -extern int req_is_query(struct http_req *req); -extern void req_free(struct http_req *req); -extern int req_acl_canned(struct http_req *req); - -/* uri.c */ -extern struct uri *uri_parse(struct uri *uri_dest, char *uri_src_text); -extern int field_unescape(char *s, int s_len); -extern char* field_escape (char *signed_str, unsigned char mask); - /* readport.c */ extern int tb_readport(const char *fname, char *buf, size_t len); -static inline bool http11(struct http_req *req) -{ - if (req->major > 1) - return true; - if (req->major == 1 && req->minor > 0) - return true; - return false; -} - #endif /* __HTTPUTIL_H__ */ diff --git a/lib/.gitignore b/lib/.gitignore index 43107ca..aa396d7 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -1,7 +1,3 @@ -*.lo -*.la -.libs -libhttputil.a -libhttpstor.a -libhttpstor-uninstalled.pc -libhttpstor.pc + +libtdb.a + diff --git a/lib/Makefile.am b/lib/Makefile.am index e22a490..12ee6c1 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,27 +1,8 @@ INCLUDES = -I$(top_srcdir)/include \ - @LIBCURL_CPPFLAGS@ @GLIB_CFLAGS@ @XML_CPPFLAGS@ + @GLIB_CFLAGS@ -noinst_LIBRARIES = libhttputil.a libtdb.a - -libhttputil_a_SOURCES = httputil.c uri.c readport.c +noinst_LIBRARIES = libtdb.a libtdb_a_SOURCES = tdb.c -EXTRA_DIST = - libhttpstor.pc.in libhttpstor-uninstalled.pc.in - -LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@ - -lib_LTLIBRARIES = libhttpstor.la - -libhttpstor_la_SOURCES = httpstor.c - -libhttpstor_la_LDFLAGS = \ - -version-info $(LIBHTTPSTOR_CURRENT):$(LIBHTTPSTOR_REVISION):$(LIBHTTPSTOR_AGE) \ - -no-undefined \ - -export-symbols-regex "^[^_].*" - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libhttpstor.pc - diff --git a/lib/httpstor.c b/lib/httpstor.c deleted file mode 100644 index b024cad..0000000 --- a/lib/httpstor.c +++ /dev/null @@ -1,944 +0,0 @@ - -/* - * Copyright 2008-2009 Red Hat, Inc. - * - * 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. - * - * 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; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#define _GNU_SOURCE -#include "tabled-config.h" - -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <curl/curl.h> -#include <openssl/hmac.h> -#include <libxml/tree.h> -#include <glib.h> -#include <httpstor.h> -#include <httputil.h> - -static int _strcasecmp(const unsigned char *a, const char *b) -{ - return xmlStrcasecmp(a, (const unsigned char *) b); -} - -static int _strcmp(const unsigned char *a, const char *b) -{ - return xmlStrcmp(a, (const unsigned char *) b); -} - -void httpstor_free(struct httpstor_client *httpstor) -{ - if (httpstor->curl) - curl_easy_cleanup(httpstor->curl); - free(httpstor->acc); - free(httpstor->host); - free(httpstor->user); - free(httpstor->key); - free(httpstor); -} - -/* - * The service accessor is a "host:port" string that gets resolved to IP - * address and then create a TCP connection to the server. The service host, - * however, is used to form the "Host: host" HTTP header. The host of the - * accessor should be the same on the sane installations, but whatever. - */ -struct httpstor_client *httpstor_new(const char *service_acc, - const char *service_host, const char *user, const char *secret_key) -{ - struct httpstor_client *httpstor; - - httpstor = calloc(1, sizeof(struct httpstor_client)); - if (!httpstor) - return NULL; - - httpstor->acc = strdup(service_acc); - httpstor->host = strdup(service_host); - httpstor->user = strdup(user); - httpstor->key = strdup(secret_key); - if (!httpstor->acc || !httpstor->host || !httpstor->user || !httpstor->key) - goto err_out; - - if (curl_global_init(CURL_GLOBAL_ALL)) - goto err_out; - - httpstor->curl = curl_easy_init(); - if (!httpstor->curl) - goto err_out; - - return httpstor; - -err_out: - httpstor_free(httpstor); - return NULL; -} - -static size_t all_data_cb(void *ptr, size_t size, size_t nmemb, void *user_data) -{ - GByteArray *all_data = user_data; - int len = size * nmemb; - - g_byte_array_append(all_data, ptr, len); - - return len; -} - -void httpstor_free_bucket(struct httpstor_bucket *buck) -{ - if (!buck) - return; - - free(buck->name); - free(buck->time_create); - free(buck); -} - -void httpstor_free_blist(struct httpstor_blist *blist) -{ - GList *tmp; - - if (!blist) - return; - - free(blist->own_id); - free(blist->own_name); - - tmp = blist->list; - while (tmp) { - struct httpstor_bucket *buck; - - buck = tmp->data; - httpstor_free_bucket(buck); - - tmp = tmp->next; - } - - g_list_free(blist->list); - - free(blist); -} - -static void httpstor_parse_buckets(xmlDocPtr doc, xmlNode *node, - struct httpstor_blist *blist) -{ - struct httpstor_bucket *buck; - xmlNode *tmp; - - while (node) { - if (node->type != XML_ELEMENT_NODE) - goto next; - - if (_strcmp(node->name, "Bucket")) - goto next; - - buck = calloc(1, sizeof(*buck)); - if (!buck) - goto next; - - tmp = node->children; - while (tmp) { - if (tmp->type != XML_ELEMENT_NODE) - goto next_tmp; - - if (!_strcmp(tmp->name, "Name")) - buck->name = (char *) xmlNodeListGetString(doc, - tmp->children, 1); - - else if (!_strcmp(tmp->name, "CreationDate")) - buck->time_create = (char *) - xmlNodeListGetString(doc, - tmp->children, 1); - -next_tmp: - tmp = tmp->next; - } - - if (!buck->name) - httpstor_free_bucket(buck); - else - blist->list = g_list_append(blist->list, buck); - -next: - node = node->next; - } -} - -struct httpstor_blist *httpstor_list_buckets(struct httpstor_client *httpstor) -{ - struct http_req req; - char datestr[80], timestr[64], hmac[64], auth[128], host[80], url[80]; - struct curl_slist *headers = NULL; - struct httpstor_blist *blist; - xmlDocPtr doc; - xmlNode *node; - xmlChar *xs; - GByteArray *all_data; - int rc; - - all_data = g_byte_array_new(); - if (!all_data) - return NULL; - - memset(&req, 0, sizeof(req)); - req.method = "GET"; - req.orig_path = "/"; - - sprintf(datestr, "Date: %s", - time2str(timestr, sizeof(timestr), time(NULL))); - - req_hdr_push(&req, "Date", timestr); - - req_sign(&req, NULL, httpstor->key, hmac); - - sprintf(auth, "Authorization: AWS %s:%s", httpstor->user, hmac); - sprintf(host, "Host: %s", httpstor->host); - - headers = curl_slist_append(headers, host); - headers = curl_slist_append(headers, datestr); - headers = curl_slist_append(headers, auth); - - snprintf(url, sizeof(url), "http://%s/", httpstor->acc); - - curl_easy_reset(httpstor->curl); - if (httpstor->verbose) - curl_easy_setopt(httpstor->curl, CURLOPT_VERBOSE, 1); - curl_easy_setopt(httpstor->curl, CURLOPT_URL, url); - curl_easy_setopt(httpstor->curl, CURLOPT_HTTPHEADER, headers); - curl_easy_setopt(httpstor->curl, CURLOPT_ENCODING, ""); - curl_easy_setopt(httpstor->curl, CURLOPT_FAILONERROR, 1); - curl_easy_setopt(httpstor->curl, CURLOPT_WRITEFUNCTION, all_data_cb); - curl_easy_setopt(httpstor->curl, CURLOPT_WRITEDATA, all_data); - curl_easy_setopt(httpstor->curl, CURLOPT_TCP_NODELAY, 1); - - rc = curl_easy_perform(httpstor->curl); - - curl_slist_free_all(headers); - - if (rc) - goto err_out; - - doc = xmlReadMemory((char *) all_data->data, all_data->len, - "foo.xml", NULL, 0); - if (!doc) - goto err_out; - - node = xmlDocGetRootElement(doc); - if (!node) - goto err_out_doc; - - if (_strcmp(node->name, "ListAllMyBucketsResult")) - goto err_out_doc; - - blist = calloc(1, sizeof(*blist)); - if (!blist) - goto err_out_doc; - - node = node->children; - while (node) { - if (node->type != XML_ELEMENT_NODE) { - node = node->next; - continue; - } - - if (!_strcmp(node->name, "Owner")) { - xmlNode *tmp; - - tmp = node->children; - while (tmp) { - if (tmp->type != XML_ELEMENT_NODE) { - tmp = tmp->next; - continue; - } - - if (!_strcmp(tmp->name, "ID")) { - xs = xmlNodeListGetString(doc, - tmp->children, 1); - blist->own_id = strdup((char *)xs); - xmlFree(xs); - } - - else if (!_strcmp(tmp->name, "DisplayName")) { - xs = xmlNodeListGetString(doc, - tmp->children, 1); - blist->own_name = strdup((char *)xs); - xmlFree(xs); - } - - tmp = tmp->next; - } - } - - else if (!_strcmp(node->name, "Buckets")) - httpstor_parse_buckets(doc, node->children, blist); - - node = node->next; - } - - xmlFreeDoc(doc); - g_byte_array_free(all_data, TRUE); - all_data = NULL; - - return blist; - -err_out_doc: - xmlFreeDoc(doc); -err_out: - g_byte_array_free(all_data, TRUE); - all_data = NULL; - return NULL; -} - -static bool __httpstor_ad_bucket(struct httpstor_client *httpstor, const char *name, - bool delete) -{ - struct http_req req; - char datestr[80], timestr[64], hmac[64], auth[128], host[80], - url[80], orig_path[80]; - struct curl_slist *headers = NULL; - int rc; - - sprintf(orig_path, "/%s/", name); - - memset(&req, 0, sizeof(req)); - req.method = delete ? "DELETE" : "PUT"; - req.orig_path = orig_path; - - sprintf(datestr, "Date: %s", - time2str(timestr, sizeof(timestr), time(NULL))); - - req_hdr_push(&req, "Date", timestr); - - req_sign(&req, NULL, httpstor->key, hmac); - - sprintf(auth, "Authorization: AWS %s:%s", httpstor->user, hmac); - sprintf(host, "Host: %s", httpstor->host); - snprintf(url, sizeof(url), "http://%s/%s/", httpstor->acc, name); - - headers = curl_slist_append(headers, host); - headers = curl_slist_append(headers, datestr); - headers = curl_slist_append(headers, auth); - - curl_easy_reset(httpstor->curl); - if (httpstor->verbose) - curl_easy_setopt(httpstor->curl, CURLOPT_VERBOSE, 1); - curl_easy_setopt(httpstor->curl, CURLOPT_URL, url); - curl_easy_setopt(httpstor->curl, CURLOPT_HTTPHEADER, headers); - curl_easy_setopt(httpstor->curl, CURLOPT_FAILONERROR, 1); - curl_easy_setopt(httpstor->curl, CURLOPT_CUSTOMREQUEST, req.method); - curl_easy_setopt(httpstor->curl, CURLOPT_TCP_NODELAY, 1); - - rc = curl_easy_perform(httpstor->curl); - - curl_slist_free_all(headers); - - return (rc == 0); -} - -bool httpstor_add_bucket(struct httpstor_client *httpstor, const char *name) -{ - return __httpstor_ad_bucket(httpstor, name, false); -} - -bool httpstor_del_bucket(struct httpstor_client *httpstor, const char *name) -{ - return __httpstor_ad_bucket(httpstor, name, true); -} - -bool httpstor_get(struct httpstor_client *httpstor, const char *bucket, const char *key, - size_t (*write_cb)(void *, size_t, size_t, void *), - void *user_data, bool want_headers) -{ - struct http_req req; - char datestr[80], timestr[64], hmac[64], auth[128], host[80], - url[80], *orig_path, *stmp; - struct curl_slist *headers = NULL; - int rc; - - if (asprintf(&stmp, "/%s/%s", bucket, key) < 0) - return false; - - orig_path = field_escape(stmp, PATH_ESCAPE_MASK); - - memset(&req, 0, sizeof(req)); - req.method = "GET"; - req.orig_path = orig_path; - - sprintf(datestr, "Date: %s", - time2str(timestr, sizeof(timestr), time(NULL))); - - req_hdr_push(&req, "Date", timestr); - - req_sign(&req, NULL, httpstor->key, hmac); - - sprintf(auth, "Authorization: AWS %s:%s", httpstor->user, hmac); - sprintf(host, "Host: %s", httpstor->host); - snprintf(url, sizeof(url), "http://%s%s", httpstor->acc, orig_path); - - headers = curl_slist_append(headers, host); - headers = curl_slist_append(headers, datestr); - headers = curl_slist_append(headers, auth); - - curl_easy_reset(httpstor->curl); - if (httpstor->verbose) - curl_easy_setopt(httpstor->curl, CURLOPT_VERBOSE, 1); - curl_easy_setopt(httpstor->curl, CURLOPT_URL, url); - curl_easy_setopt(httpstor->curl, CURLOPT_HEADER, want_headers ? 1 : 0); - curl_easy_setopt(httpstor->curl, CURLOPT_HTTPHEADER, headers); - curl_easy_setopt(httpstor->curl, CURLOPT_ENCODING, ""); - curl_easy_setopt(httpstor->curl, CURLOPT_FAILONERROR, 1); - curl_easy_setopt(httpstor->curl, CURLOPT_WRITEFUNCTION, write_cb); - curl_easy_setopt(httpstor->curl, CURLOPT_WRITEDATA, user_data); - curl_easy_setopt(httpstor->curl, CURLOPT_TCP_NODELAY, 1); - - rc = curl_easy_perform(httpstor->curl); - - curl_slist_free_all(headers); - free(orig_path); - - return (rc == 0); -} - -void *httpstor_get_inline(struct httpstor_client *httpstor, const char *bucket, const char *key, - bool want_headers, size_t *len) -{ - bool rcb; - void *mem; - GByteArray *all_data; - - all_data = g_byte_array_new(); - if (!all_data) - return NULL; - - rcb = httpstor_get(httpstor, bucket, key, all_data_cb, all_data, want_headers); - if (!rcb) { - g_byte_array_free(all_data, TRUE); - return NULL; - } - - if (len) - *len = all_data->len; - - mem = all_data->data; - - g_byte_array_free(all_data, FALSE); - return mem; -} - -bool httpstor_put(struct httpstor_client *httpstor, const char *bucket, const char *key, - size_t (*read_cb)(void *, size_t, size_t, void *), - uint64_t len, void *user_data, char **user_hdrs) -{ - struct http_req req; - char datestr[80], timestr[64], hmac[64], auth[128], host[80], - url[80], *orig_path, *stmp, *uhdr_buf = NULL; - struct curl_slist *headers = NULL; - int rc = -1; - - if (asprintf(&stmp, "/%s/%s", bucket, key) < 0) - return false; - - orig_path = field_escape(stmp, PATH_ESCAPE_MASK); - - memset(&req, 0, sizeof(req)); - req.method = "PUT"; - req.orig_path = orig_path; - - sprintf(datestr, "Date: %s", - time2str(timestr, sizeof(timestr), time(NULL))); - - req_hdr_push(&req, "Date", timestr); - - if (user_hdrs) { - int idx = 0; - size_t uhdr_len = 0, ukey_len; - void *p; - char *colon, *ukey, *uval; - - /* 1. add to curl hdr list. 2. count hdr byte size */ - while (user_hdrs[idx]) { - headers = curl_slist_append(headers, user_hdrs[idx]); - uhdr_len += strlen(user_hdrs[idx]) + 2; - idx++; - } - - /* alloc buf to hold all hdr strings */ - uhdr_buf = calloc(1, uhdr_len); - if (!uhdr_buf) - goto out; - - /* copy and nul-terminate hdr keys and values for signing */ - idx = 0; - p = uhdr_buf; - while (user_hdrs[idx]) { - ukey = p; - colon = strchr(user_hdrs[idx], ':'); - if (colon) { - ukey_len = colon - user_hdrs[idx]; - memcpy(ukey, user_hdrs[idx], ukey_len); - ukey[ukey_len] = 0; - - p += ukey_len + 1; - - colon++; - while (*colon && isspace(*colon)) - colon++; - - uval = p; - strcpy(uval, colon); - p += strlen(uval) + 1; - - req_hdr_push(&req, ukey, uval); - } - idx++; - } - } - - req_sign(&req, NULL, httpstor->key, hmac); - - sprintf(auth, "Authorization: AWS %s:%s", httpstor->user, hmac); - sprintf(host, "Host: %s", httpstor->host); - snprintf(url, sizeof(url), "http://%s%s", httpstor->acc, orig_path); - - headers = curl_slist_append(headers, host); - headers = curl_slist_append(headers, datestr); - headers = curl_slist_append(headers, auth); - - curl_easy_reset(httpstor->curl); - if (httpstor->verbose) - curl_easy_setopt(httpstor->curl, CURLOPT_VERBOSE, 1); - curl_easy_setopt(httpstor->curl, CURLOPT_URL, url); - curl_easy_setopt(httpstor->curl, CURLOPT_HTTPHEADER, headers); - curl_easy_setopt(httpstor->curl, CURLOPT_FAILONERROR, 1); - curl_easy_setopt(httpstor->curl, CURLOPT_READFUNCTION, read_cb); - curl_easy_setopt(httpstor->curl, CURLOPT_READDATA, user_data); - curl_easy_setopt(httpstor->curl, CURLOPT_CUSTOMREQUEST, req.method); - curl_easy_setopt(httpstor->curl, CURLOPT_UPLOAD, 1); - curl_easy_setopt(httpstor->curl, CURLOPT_INFILESIZE_LARGE, - (curl_off_t)len); - curl_easy_setopt(httpstor->curl, CURLOPT_TCP_NODELAY, 1); - - rc = curl_easy_perform(httpstor->curl); - - curl_slist_free_all(headers); - free(orig_path); - -out: - free(uhdr_buf); - return (rc == 0); -} - -struct httpstor_put_info { - void *data; - uint64_t len; -}; - -static size_t read_inline_cb(void *ptr, size_t size, size_t nmemb, - void *user_data) -{ - struct httpstor_put_info *spi = user_data; - int len = size * nmemb; - - len = MIN(len, spi->len); - if (len) { - memcpy(ptr, spi->data, len); - spi->data += len; - spi->len -= len; - } - - return len; -} - -bool httpstor_put_inline(struct httpstor_client *httpstor, const char *bucket, const char *key, - void *data, uint64_t len, char **user_hdrs) -{ - struct httpstor_put_info spi = { data, len }; - - return httpstor_put(httpstor, bucket, key, read_inline_cb, len, &spi, user_hdrs); -} - -bool httpstor_del(struct httpstor_client *httpstor, const char *bucket, const char *key) -{ - struct http_req req; - char datestr[80], timestr[64], hmac[64], auth[128], host[80], - url[80], *orig_path, *stmp; - struct curl_slist *headers = NULL; - int rc; - - if (asprintf(&stmp, "/%s/%s", bucket, key) < 0) - return false; - - orig_path = field_escape(stmp, PATH_ESCAPE_MASK); - - memset(&req, 0, sizeof(req)); - req.method = "DELETE"; - req.orig_path = orig_path; - - sprintf(datestr, "Date: %s", - time2str(timestr, sizeof(timestr), time(NULL))); - - req_hdr_push(&req, "Date", timestr); - - req_sign(&req, NULL, httpstor->key, hmac); - - sprintf(auth, "Authorization: AWS %s:%s", httpstor->user, hmac); - sprintf(host, "Host: %s", httpstor->host); - snprintf(url, sizeof(url), "http://%s%s", httpstor->acc, orig_path); - - headers = curl_slist_append(headers, host); - headers = curl_slist_append(headers, datestr); - headers = curl_slist_append(headers, auth); - - curl_easy_reset(httpstor->curl); - if (httpstor->verbose) - curl_easy_setopt(httpstor->curl, CURLOPT_VERBOSE, 1); - curl_easy_setopt(httpstor->curl, CURLOPT_URL, url); - curl_easy_setopt(httpstor->curl, CURLOPT_HTTPHEADER, headers); - curl_easy_setopt(httpstor->curl, CURLOPT_FAILONERROR, 1); - curl_easy_setopt(httpstor->curl, CURLOPT_CUSTOMREQUEST, req.method); - curl_easy_setopt(httpstor->curl, CURLOPT_TCP_NODELAY, 1); - - rc = curl_easy_perform(httpstor->curl); - - curl_slist_free_all(headers); - free(orig_path); - - return (rc == 0); -} - -GString *append_qparam(GString *str, const char *key, const char *val, - char *arg_char) -{ - char *stmp, s[32]; - - str = g_string_append(str, arg_char); - arg_char[0] = '&'; - - sprintf(s, "%s=", key); - str = g_string_append(str, key); - - stmp = field_escape(strdup(val), QUERY_ESCAPE_MASK); - str = g_string_append(str, stmp); - free(stmp); - - return str; -} - -void httpstor_free_object(struct httpstor_object *obj) -{ - if (!obj) - return; - - free(obj->key); - free(obj->time_mod); - free(obj->etag); - free(obj->storage); - free(obj->own_id); - free(obj->own_name); - free(obj); -} - -void httpstor_free_keylist(struct httpstor_keylist *keylist) -{ - GList *tmp; - - if (!keylist) - return; - - free(keylist->name); - free(keylist->prefix); - free(keylist->marker); - free(keylist->delim); - - tmp = keylist->common_pfx; - while (tmp) { - free(tmp->data); - tmp = tmp->next; - } - - tmp = keylist->contents; - while (tmp) { - httpstor_free_object(tmp->data); - tmp = tmp->next; - } - g_list_free(keylist->contents); - - free(keylist); -} - -static void httpstor_parse_key(xmlDocPtr doc, xmlNode *node, - struct httpstor_keylist *keylist) -{ - struct httpstor_object *obj = calloc(1, sizeof(*obj)); - xmlChar *xs; - - obj = calloc(1, sizeof(*obj)); - if (!obj) - return; - - while (node) { - if (node->type != XML_ELEMENT_NODE) { - node = node->next; - continue; - } - - if (!_strcmp(node->name, "Key")) { - xs = xmlNodeListGetString(doc, node->children, 1); - obj->key = strdup((char *)xs); - xmlFree(xs); - } - else if (!_strcmp(node->name, "LastModified")) { - xs = xmlNodeListGetString(doc, node->children, 1); - obj->time_mod = strdup((char *)xs); - xmlFree(xs); - } - else if (!_strcmp(node->name, "ETag")) { - xs = xmlNodeListGetString(doc, node->children, 1); - obj->etag = strdup((char *)xs); - xmlFree(xs); - } - else if (!_strcmp(node->name, "Size")) { - xs = xmlNodeListGetString(doc, node->children, 1); - obj->size = atoll((char *) xs); - xmlFree(xs); - } - else if (!_strcmp(node->name, "StorageClass")) { - xs = xmlNodeListGetString(doc, node->children, 1); - obj->storage = strdup((char *)xs); - xmlFree(xs); - } - else if (!_strcmp(node->name, "Owner")) { - xmlNode *tmp; - - tmp = node->children; - while (tmp) { - if (tmp->type != XML_ELEMENT_NODE) { - tmp = tmp->next; - continue; - } - - if (!_strcmp(tmp->name, "ID")) { - xs = xmlNodeListGetString(doc, - tmp->children, 1); - obj->own_id = strdup((char *)xs); - xmlFree(xs); - } - - else if (!_strcmp(tmp->name, "DisplayName")) { - xs = xmlNodeListGetString(doc, - tmp->children, 1); - obj->own_name = strdup((char *)xs); - xmlFree(xs); - } - - tmp = tmp->next; - } - } - - node = node->next; - } - - if (obj->key) - keylist->contents = g_list_append(keylist->contents, obj); - else - httpstor_free_object(obj); -} - -struct httpstor_keylist *httpstor_keys(struct httpstor_client *httpstor, const char *bucket, - const char *prefix, const char *marker, - const char *delim, unsigned int max_keys) -{ - struct http_req req; - char datestr[80], timestr[64], hmac[64], auth[128], host[80]; - char orig_path[strlen(bucket) + 8]; - struct curl_slist *headers = NULL; - struct httpstor_keylist *keylist; - xmlDocPtr doc; - xmlNode *node; - xmlChar *xs; - GByteArray *all_data; - GString *url; - int rc; - char arg_char[2] = "?"; - - all_data = g_byte_array_new(); - if (!all_data) - return NULL; - - sprintf(orig_path, "/%s/", bucket); - - memset(&req, 0, sizeof(req)); - req.method = "GET"; - req.orig_path = orig_path; - - sprintf(datestr, "Date: %s", - time2str(timestr, sizeof(timestr), time(NULL))); - - req_hdr_push(&req, "Date", timestr); - - req_sign(&req, NULL, httpstor->key, hmac); - - sprintf(auth, "Authorization: AWS %s:%s", httpstor->user, hmac); - sprintf(host, "Host: %s", httpstor->host); - - headers = curl_slist_append(headers, host); - headers = curl_slist_append(headers, datestr); - headers = curl_slist_append(headers, auth); - - url = g_string_sized_new(256); - if (!url) { - curl_slist_free_all(headers); - goto err_out; - } - - url = g_string_append(url, "http://"); - url = g_string_append(url, httpstor->acc); - url = g_string_append(url, orig_path); - - if (prefix) - url = append_qparam(url, "prefix", prefix, arg_char); - if (marker) - url = append_qparam(url, "marker", marker, arg_char); - if (delim) - url = append_qparam(url, "delimiter", delim, arg_char); - if (max_keys) { - char mk[32]; - sprintf(mk, "%smax-keys=%u", arg_char, max_keys); - url = g_string_append(url, mk); - } - - curl_easy_reset(httpstor->curl); - if (httpstor->verbose) - curl_easy_setopt(httpstor->curl, CURLOPT_VERBOSE, 1); - curl_easy_setopt(httpstor->curl, CURLOPT_URL, url->str); - curl_easy_setopt(httpstor->curl, CURLOPT_HTTPHEADER, headers); - curl_easy_setopt(httpstor->curl, CURLOPT_ENCODING, ""); - curl_easy_setopt(httpstor->curl, CURLOPT_FAILONERROR, 1); - curl_easy_setopt(httpstor->curl, CURLOPT_WRITEFUNCTION, all_data_cb); - curl_easy_setopt(httpstor->curl, CURLOPT_WRITEDATA, all_data); - curl_easy_setopt(httpstor->curl, CURLOPT_TCP_NODELAY, 1); - - rc = curl_easy_perform(httpstor->curl); - - g_string_free(url, TRUE); - curl_slist_free_all(headers); - - if (rc) - goto err_out; - - doc = xmlReadMemory((char *) all_data->data, all_data->len, - "foo.xml", NULL, 0); - if (!doc) - goto err_out; - - node = xmlDocGetRootElement(doc); - if (!node) - goto err_out_doc; - - if (_strcmp(node->name, "ListBucketResult")) - goto err_out_doc; - - keylist = calloc(1, sizeof(*keylist)); - if (!keylist) - goto err_out_doc; - - node = node->children; - while (node) { - if (node->type != XML_ELEMENT_NODE) { - node = node->next; - continue; - } - - if (!_strcmp(node->name, "Name")) { - xs = xmlNodeListGetString(doc, node->children, 1); - keylist->name = strdup((char *)xs); - xmlFree(xs); - } - else if (!_strcmp(node->name, "Prefix")) { - xs = xmlNodeListGetString(doc, node->children, 1); - keylist->prefix = strdup((char *)xs); - xmlFree(xs); - } - else if (!_strcmp(node->name, "Marker")) { - xs = xmlNodeListGetString(doc, node->children, 1); - keylist->marker = strdup((char *)xs); - xmlFree(xs); - } - else if (!_strcmp(node->name, "Delimiter")) { - xs = xmlNodeListGetString(doc, node->children, 1); - keylist->delim = strdup((char *)xs); - xmlFree(xs); - } - else if (!_strcmp(node->name, "MaxKeys")) { - xs = xmlNodeListGetString(doc, node->children, 1); - keylist->max_keys = (unsigned int) atoi((char *)xs); - xmlFree(xs); - } - else if (!_strcmp(node->name, "IsTruncated")) { - xs = xmlNodeListGetString(doc, node->children, 1); - - if (!_strcasecmp(xs, "true")) - keylist->trunc = true; - else if (!_strcasecmp(xs, "1")) - keylist->trunc = true; - else - keylist->trunc = false; - - xmlFree(xs); - } - else if (!_strcmp(node->name, "CommonPrefixes")) { - xmlNode *tmp; - - tmp = node->children; - while (tmp) { - if (tmp->type != XML_ELEMENT_NODE) { - tmp = tmp->next; - continue; - } - - if (!_strcmp(tmp->name, "Prefix")) { - xs = xmlNodeListGetString(doc, - tmp->children, 1); - keylist->common_pfx = - g_list_append( - keylist->common_pfx, - strdup((char *)xs)); - xmlFree(xs); - } - - tmp = tmp->next; - } - } - else if (!_strcmp(node->name, "Contents")) - httpstor_parse_key(doc, node->children, keylist); - - node = node->next; - } - - xmlFreeDoc(doc); - g_byte_array_free(all_data, TRUE); - all_data = NULL; - - return keylist; - -err_out_doc: - xmlFreeDoc(doc); -err_out: - g_byte_array_free(all_data, TRUE); - all_data = NULL; - return NULL; -} - diff --git a/lib/httputil.c b/lib/httputil.c deleted file mode 100644 index 1c56be9..0000000 --- a/lib/httputil.c +++ /dev/null @@ -1,366 +0,0 @@ - -/* - * Copyright 2008-2009 Red Hat, Inc. - * - * 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. - * - * 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; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#define _GNU_SOURCE -#include "tabled-config.h" - -#include <string.h> -#include <ctype.h> -#include <errno.h> -#include <time.h> -#include <glib.h> -#include <openssl/hmac.h> -#include <httputil.h> - -time_t str2time(const char *timestr) -{ - struct tm tm; - - memset(&tm, 0, sizeof(tm)); - - if (!strptime(timestr, "%a, %d %b %Y %H:%M:%S %z", &tm)) - return 0; - - return mktime(&tm); -} - -char *time2str(char *strbuf, int buflen, time_t src_time) -{ - struct tm tm; - size_t rc; - - if (buflen <= 0) - return NULL; /* too wrong, better crash right away. */ - gmtime_r(&src_time, &tm); - rc = strftime(strbuf, buflen, "%a, %d %b %Y %H:%M:%S %z", &tm); - if (rc >= buflen) - strbuf[buflen-1] = 0; - else if (rc == 0) - strbuf[0] = 0; - return strbuf; -} - -/* - * Temporary list of headers. - */ -struct custom_hdr { - char *key; /* by malloc */ - char *val; /* by ref */ -}; - -struct custom_hdr_vec { - int num; - struct custom_hdr vec[REQ_MAX_HDR]; -}; - -static const char amzpfx[] = "x-amz-"; -#define AMZPFX amzpfx -#define AMZPFXLEN (sizeof("x-amz-")-1) - -static int cust_cmp(const void *p1, const void *p2) -{ - struct custom_hdr *h1 = (struct custom_hdr *)p1; - struct custom_hdr *h2 = (struct custom_hdr *)p2; - return strcmp(h1->key, h2->key); -} - -/* - * Create a list of headers for us to iterate. - * Preconvert keys to lowercase, sort, but leave duplicates as is. - */ -static int cust_init(struct custom_hdr_vec *cv, struct http_req *req) -{ - int cnt; - int i, j; - const char *key; - char *ckey; - int klen; - - cnt = 0; - for (i = 0; i < req->n_hdr; i++) { - key = req->hdr[i].key; - if (!strncasecmp(AMZPFX, key, AMZPFXLEN)) { - klen = strlen(key) - AMZPFXLEN; - if ((ckey = malloc(klen+1)) == NULL) { - while (cnt-- != 0) - free(cv->vec[cnt].key); - goto enocore; - } - for (j = 0; j < klen; j++) - ckey[j] = tolower(key[AMZPFXLEN + j]); - ckey[j] = 0; - - cv->vec[cnt].key = ckey; - cv->vec[cnt].val = req->hdr[i].val; - cnt++; - } - } - cv->num = cnt; - - qsort(cv->vec, cv->num, sizeof(struct custom_hdr), cust_cmp); - return 0; - - enocore: - return -1; -} - -static void cust_fin(struct custom_hdr_vec *cv) -{ - int i; - - for (i = 0; i < cv->num; i++) { - free(cv->vec[i].key); - } -} - -/* - */ -int req_hdr_push(struct http_req *req, char *key, char *val) -{ - struct http_hdr *hdr; - - if (req->n_hdr == REQ_MAX_HDR) - return -ENOSPC; - - while (isspace(*val)) - val++; - - hdr = &req->hdr[req->n_hdr++]; - hdr->key = key; - hdr->val = val; - - return 0; -} - -char *req_hdr(struct http_req *req, const char *key) -{ - int i; - - for (i = 0; i < req->n_hdr; i++) - if (!strcasecmp(key, req->hdr[i].key)) - return req->hdr[i].val; - - return NULL; -} - -static inline void _HMAC_Update(HMAC_CTX *ctx, const void *data, int len) -{ - HMAC_Update(ctx, data, len); -} - -static void req_sign_hdr(struct http_req *req, HMAC_CTX *ctx, const char *_hdr) -{ - char *hdr = req_hdr(req, _hdr); - if (hdr) - _HMAC_Update(ctx, hdr, strlen(hdr)); - _HMAC_Update(ctx, "\n", 1); -} - -static void req_sign_amz(HMAC_CTX *ctx, struct http_req *req) -{ - struct custom_hdr_vec cust; - struct custom_hdr *p; - struct custom_hdr *prev; - int i; - - if (cust_init(&cust, req)) - return; - - prev = NULL; - p = &cust.vec[0]; - for (i = 0; i < cust.num; i++) { - if (prev) { - if (!strcmp(prev->key, p->key)) { - _HMAC_Update(ctx, ",", 1); - } else { - _HMAC_Update(ctx, "\n", 1); - - _HMAC_Update(ctx, AMZPFX, AMZPFXLEN); - _HMAC_Update(ctx, p->key, strlen(p->key)); - _HMAC_Update(ctx, ":", 1); - prev = p; - } - } else { - _HMAC_Update(ctx, AMZPFX, AMZPFXLEN); - _HMAC_Update(ctx, p->key, strlen(p->key)); - _HMAC_Update(ctx, ":", 1); - prev = p; - } - _HMAC_Update(ctx, p->val, strlen(p->val)); - p++; - } - if (prev) - _HMAC_Update(ctx, "\n", 1); - - cust_fin(&cust); -} - -static const char *req_query_sign[URIQNUM] = { - "acl", - "location", - "logging", - "torrent", -}; - -void req_sign(struct http_req *req, const char *bucket, const char *key, - char *b64hmac_out) -{ - HMAC_CTX ctx; - unsigned int len = 0; - unsigned char md[EVP_MAX_MD_SIZE]; - int save = 0, state = 0, b64_len; - - HMAC_CTX_init(&ctx); - HMAC_Init(&ctx, key, strlen(key), EVP_sha1()); - - _HMAC_Update(&ctx, req->method, strlen(req->method)); - _HMAC_Update(&ctx, "\n", 1); - - req_sign_hdr(req, &ctx, "content-md5"); - req_sign_hdr(req, &ctx, "content-type"); - if (req_hdr(req, "x-amz-date")) - _HMAC_Update(&ctx, "\n", 1); - else - req_sign_hdr(req, &ctx, "date"); - - req_sign_amz(&ctx, req); - - if (bucket) { - _HMAC_Update(&ctx, "/", 1); - _HMAC_Update(&ctx, bucket, strlen(bucket)); - } - - _HMAC_Update(&ctx, req->orig_path, strlen(req->orig_path)); - - if (req_is_query(req) != -1) { - _HMAC_Update(&ctx, "?", 1); - _HMAC_Update(&ctx, req->uri.query, req->uri.query_len); - } - - HMAC_Final(&ctx, md, &len); - HMAC_CTX_cleanup(&ctx); - - b64_len = g_base64_encode_step(md, len, FALSE, b64hmac_out, - &state, &save); - b64_len += g_base64_encode_close(FALSE, b64hmac_out + b64_len, - &state, &save); - b64hmac_out[b64_len] = 0; -} - -void req_free(struct http_req *req) -{ - free(req->orig_path); - req->orig_path = NULL; -} - -GHashTable *req_query(struct http_req *req) -{ - char *qtmp, *q, *tmp, *end; - int qlen, qtmplen; - GHashTable *ht; - - ht = g_hash_table_new_full(g_str_hash, g_str_equal, free, free); - if (!ht) - return NULL; - - qtmp = alloca(req->uri.query_len + 1); - - q = req->uri.query; - qlen = req->uri.query_len; - - while (qlen > 0) { - char *key, *val; - int keylen, vallen, valskip; - - tmp = memchr(q, '=', qlen); - if (!tmp || (tmp == q)) - break; - - keylen = tmp - q; - end = memchr(tmp, '&', qlen - keylen); - - memcpy(qtmp, q, keylen); - qtmp[keylen] = 0; - qtmplen = field_unescape(qtmp, strlen(qtmp)); - - key = g_ascii_strdown(qtmp, qtmplen); - - qlen -= (keylen + 1); - q += (keylen + 1); - tmp++; - - if (end) - vallen = end - tmp; - else - vallen = qlen; - - memcpy(qtmp, tmp, vallen); - qtmplen = field_unescape(qtmp, vallen); - - val = g_strndup(qtmp, qtmplen); - - valskip = vallen; - if (end) - valskip++; - - qlen -= valskip; - q += valskip; - - g_hash_table_insert(ht, key, val); - } - - return ht; -} - -int req_is_query(struct http_req *req) -{ - int i; - - if (req->uri.query_len) - for (i = 0; i < URIQNUM; i++) - if (!strcasecmp(req->uri.query, req_query_sign[i])) - return i; - return -1; -} - -static const char *req_acl_cans[ACLCNUM] = { - "private", - "public-read", - "public-read-write", - "authenticated-read" -}; - -/* - * Return -1 if no header is present, which is ok. - * Return ACLCNUM if header is present, but the policy is invalid. - */ -int req_acl_canned(struct http_req *req) -{ - const char *aclhdr; - int i; - - aclhdr = req_hdr(req, "x-amz-acl"); - if (!aclhdr) - return -1; - - for (i = 0; i < ACLCNUM; i++) - if (!strcasecmp(aclhdr, req_acl_cans[i])) - return i; - return ACLCNUM; -} diff --git a/lib/libhttpstor-uninstalled.pc.in b/lib/libhttpstor-uninstalled.pc.in deleted file mode 100644 index ac2753a..0000000 --- a/lib/libhttpstor-uninstalled.pc.in +++ /dev/null @@ -1,12 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ -libhttpstor_serverdir=@libexecdir@ - -Name: libhttpstor -Description: libhttpstor -Requires: glib-2.0 -Version: @VERSION@ -Libs: ${pc_top_builddir}/${pcfiledir}/libhttpstor.la -#Cflags: -I${pc_top_builddir}/${pcfiledir}/.. diff --git a/lib/libhttpstor.pc.in b/lib/libhttpstor.pc.in deleted file mode 100644 index 44fd82d..0000000 --- a/lib/libhttpstor.pc.in +++ /dev/null @@ -1,13 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ -libhttpstor_serverdir=@libexecdir@ -localstatedir=@localstatedir@ - -Name: libhttpstor -Description: libhttpstor -Requires: glib-2.0 -Version: @VERSION@ -Libs: -L${libdir} -lhttpstor -#Cflags: -I${includedir}/libhttpstor-2.0 diff --git a/lib/uri.c b/lib/uri.c deleted file mode 100644 index a2cf2f5..0000000 --- a/lib/uri.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Taken from GNet and modified for tabled - */ - -/* GNet - Networking library - * Copyright (C) 2000-2003 David Helder, David Bolcsfoldi, Eric Williams - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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. - */ - -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <stdbool.h> -#include <httputil.h> - -/* our own ISSPACE. ANSI isspace is locale dependent */ -#define ISSPACE(C) (((C) >= 9 && (C) <= 13) || (C) == ' ') - -#define ASSIGN(token, ptr, len) \ - do { \ - uri->token = (ptr); \ - uri->token##_len = (len); \ - } while (0) - -struct uri *uri_parse(struct uri *uri, char *uri_text) -{ - char *p, *temp; - - memset(uri, 0, sizeof(*uri)); - - /* Skip initial whitespace */ - p = uri_text; - while (*p && ISSPACE((int)*p)) - ++p; - if (!*p) /* Error if it's just a string of space */ - return NULL; - - /* Scheme */ - temp = p; - while (*p && *p != ':' && *p != '/' && *p != '?' && *p != '#') - ++p; - if (*p == ':') { - ASSIGN(scheme, temp, p - temp); - ++p; - } else /* This char is NUL, /, ?, or # */ - p = temp; - - /* Authority */ - if (*p == '/' && p[1] == '/') { - p += 2; - - /* Userinfo */ - temp = p; - while (*p && *p != '@' && *p != '/') /* Look for @ or / */ - ++p; - if (*p == '@') { /* Found userinfo */ - ASSIGN(userinfo, temp, p - temp); - ++p; - } else - p = temp; - - /* Hostname */ - - /* Check for no hostname at all (e.g. file:// URIs) */ - if (*p == '/') - goto path; - - /* Check for IPv6 canonical hostname in brackets */ - if (*p == '[') { - p++; /* Skip [ */ - temp = p; - while (*p && *p != ']') - ++p; - if ((p - temp) == 0) - goto error; - ASSIGN(hostname, temp, p - temp); - if (*p) - p++; /* Skip ] (if there) */ - } else { - temp = p; - while (*p && *p != '/' && *p != '?' && *p != '#' - && *p != ':') - ++p; - if ((p - temp) == 0) - goto error; - ASSIGN(hostname, temp, p - temp); - } - - /* Port */ - if (*p == ':') { - for (++p; isdigit((int)*p); ++p) - uri->port = uri->port * 10 + (*p - '0'); - } - - } - - /* Path (we are liberal and won't check if it starts with /) */ - -path: - temp = p; - while (*p && *p != '?' && *p != '#') - ++p; - if (p != temp) - ASSIGN(path, temp, p - temp); - - /* Query */ - if (*p == '?') { - temp = p + 1; - while (*p && *p != '#') - ++p; - ASSIGN(query, temp, p - temp); - } - - /* Fragment */ - if (*p == '#') { - ++p; - uri->fragment = p; - /* FIXME: assign uri->fragment_len! */ - } - - return uri; - -error: - return NULL; -} - -int field_unescape(char *s, int s_len) -{ - int dst_len = 0; - char *src; - char *dst; - - for (src = dst = s; s_len; ++src, ++dst, ++dst_len, --s_len) { - if (src[0] == '%' && (s_len > 2)) { - int high, low; - - if ('a' <= src[1] && src[1] <= 'f') - high = src[1] - 'a' + 10; - else if ('A' <= src[1] && src[1] <= 'F') - high = src[1] - 'A' + 10; - else if ('0' <= src[1] && src[1] <= '9') - high = src[1] - '0'; - else /* malformed */ - goto regular_copy; - - if ('a' <= src[2] && src[2] <= 'f') - low = src[2] - 'a' + 10; - else if ('A' <= src[2] && src[2] <= 'F') - low = src[2] - 'A' + 10; - else if ('0' <= src[2] && src[2] <= '9') - low = src[2] - '0'; - else /* malformed */ - goto regular_copy; - - *dst = (char)((high << 4) + low); - src += 2; - s_len -= 2; - } else { -regular_copy: - /* micro-opt: a lot of URIs do not include escape - * sequences. by testing the pointer addresses - * we can avoid a lot of reading+writing of the - * same data - */ - if (dst != src) - *dst = *src; - } - } - - return dst_len; -} - -static const guchar neednt_escape_table[] = -{ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x00, 0x0c, - 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x00, 0x00, 0x0f, - 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -char* field_escape (char *signed_str, unsigned char mask) -{ - int len; - int i; - bool must_escape = false; - unsigned char *str; - char *dst; - gint j; - - str = (unsigned char *) signed_str; - - if (str == NULL) - return NULL; - - /* Roughly calculate buffer size */ - len = 0; - for (i = 0; str[i]; i++) - { - if (neednt_escape_table[str[i]] & mask) - len++; - else - { - len += 3; - must_escape = TRUE; - } - } - - /* Don't escape if unnecessary */ - if (must_escape == FALSE) - return signed_str; - - /* Allocate buffer */ - dst = (gchar*) g_malloc(len + 1); - - /* Copy */ - for (i = j = 0; str[i]; i++, j++) - { - /* Unescaped character */ - if (neednt_escape_table[str[i]] & mask) - { - dst[j] = str[i]; - } - - /* Escaped character */ - else - { - dst[j] = '%'; - - if (((str[i] & 0xf0) >> 4) < 10) - dst[j+1] = ((str[i] & 0xf0) >> 4) + '0'; - else - dst[j+1] = ((str[i] & 0xf0) >> 4) + 'a' - 10; - - if ((str[i] & 0x0f) < 10) - dst[j+2] = (str[i] & 0x0f) + '0'; - else - dst[j+2] = (str[i] & 0x0f) + 'a' - 10; - - j += 2; /* and j is incremented in loop too */ - } - } - dst[j] = '\0'; - - g_free (signed_str); - return dst; -} - diff --git a/server/.gitignore b/server/.gitignore new file mode 100644 index 0000000..fafb1ca --- /dev/null +++ b/server/.gitignore @@ -0,0 +1,4 @@ + +tabled +tdbadm + diff --git a/server/Makefile.am b/server/Makefile.am index 6ebfd05..6397245 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -6,7 +6,7 @@ sbin_PROGRAMS = tabled tdbadm tabled_SOURCES = tabled.h \ bucket.c cldu.c config.c object.c replica.c \ server.c status.c storage.c storparse.c util.c -tabled_LDADD = ../lib/libhttputil.a ../lib/libtdb.a \ +tabled_LDADD = ../lib/libtdb.a \ @HAIL_LIBS@ @PCRE_LIBS@ @GLIB_LIBS@ \ @CRYPTO_LIBS@ @DB4_LIBS@ @EVENT_LIBS@ @SSL_LIBS@ diff --git a/server/bucket.c b/server/bucket.c index 0acf987..a95d23e 100644 --- a/server/bucket.c +++ b/server/bucket.c @@ -265,7 +265,7 @@ bool service_list(struct client *cli, const char *user) " </Bucket>\r\n", ent->name, - time2str(timestr, sizeof(timestr), + hutil_time2str(timestr, sizeof(timestr), GUINT64_FROM_LE(ent->time_create))); if (!s) goto err_out_content; @@ -467,7 +467,7 @@ bool bucket_add(struct client *cli, const char *user, const char *bucket) /* prepare parameters */ setacl = false; if (cli->req.uri.query_len) { - switch (req_is_query(&cli->req)) { + switch (hreq_is_query(&cli->req)) { case URIQ_ACL: setacl = true; break; @@ -477,7 +477,7 @@ bool bucket_add(struct client *cli, const char *user, const char *bucket) } } - if ((rc = req_acl_canned(&cli->req)) == ACLCNUM) { + if ((rc = hreq_acl_canned(&cli->req)) == ACLCNUM) { err = InvalidArgument; goto err_par; } @@ -562,7 +562,7 @@ bool bucket_add(struct client *cli, const char *user, const char *bucket) "\r\n", cli->req.major, cli->req.minor, - time2str(timestr, sizeof(timestr), time(NULL)), + hutil_time2str(timestr, sizeof(timestr), time(NULL)), bucket) < 0) return cli_err(cli, InternalError); @@ -715,7 +715,7 @@ bool bucket_del(struct client *cli, const char *user, const char *bucket) "\r\n", cli->req.major, cli->req.minor, - time2str(timestr, sizeof(timestr), time(NULL))) < 0) + hutil_time2str(timestr, sizeof(timestr), time(NULL))) < 0) return cli_err(cli, InternalError); rc = cli_writeq(cli, hdr, strlen(hdr), cli_cb_free, hdr); @@ -939,7 +939,7 @@ static bool bucket_list_keys(struct client *cli, const char *user, } /* parse URI query string */ - param = req_query(&cli->req); + param = hreq_query(&cli->req); if (!param) goto err_out; @@ -1110,7 +1110,7 @@ static bool bucket_list_keys(struct client *cli, const char *user, " </Contents>\r\n", vp->key, - time2str(timestr, sizeof(timestr), vp->mtime / 1000000), + hutil_time2str(timestr, sizeof(timestr), vp->mtime / 1000000), vp->md5, (unsigned long long) vp->size, vp->owner, @@ -1185,7 +1185,7 @@ bool access_list(struct client *cli, const char *bucket, const char *key, } /* parse URI query string */ - param = req_query(&cli->req); + param = hreq_query(&cli->req); if (!param) goto err_out; @@ -1360,7 +1360,7 @@ bool bucket_list(struct client *cli, const char *user, const char *bucket) getacl = false; if (cli->req.uri.query_len) { - switch (req_is_query(&cli->req)) { + switch (hreq_is_query(&cli->req)) { case URIQ_ACL: getacl = true; break; diff --git a/server/object.c b/server/object.c index 6d7fe92..207bb3e 100644 --- a/server/object.c +++ b/server/object.c @@ -224,7 +224,7 @@ bool object_del(struct client *cli, const char *user, "\r\n", cli->req.major, cli->req.minor, - time2str(timestr, sizeof(timestr), time(NULL))) < 0) + hutil_time2str(timestr, sizeof(timestr), time(NULL))) < 0) return cli_err(cli, InternalError); rc = cli_writeq(cli, hdr, strlen(hdr), cli_cb_free, hdr); @@ -337,7 +337,7 @@ static bool object_put_end(struct client *cli) uint64_t tmp_time; void *mem; - if (http11(&cli->req)) + if (hreq_http11(&cli->req)) cli->state = evt_recycle; else cli->state = evt_dispose; @@ -376,7 +376,7 @@ static bool object_put_end(struct client *cli) md5str(md, md5); - type = req_hdr(&cli->req, "content-type"); + type = hreq_hdr(&cli->req, "content-type"); if (!type) type = "binary/octet-stream"; else @@ -515,7 +515,7 @@ static bool object_put_end(struct client *cli) cli->req.major, cli->req.minor, md5, - time2str(timestr, sizeof(timestr), time(NULL))) < 0) { + hutil_time2str(timestr, sizeof(timestr), time(NULL))) < 0) { /* FIXME: cleanup failure */ applog(LOG_ERR, "OOM in object_put_end"); return cli_err(cli, InternalError); @@ -878,13 +878,13 @@ static bool object_put_acls(struct client *cli, const char *user, if (!user || !has_access(user, bucket, key, "WRITE_ACP")) return cli_err(cli, AccessDenied); - if ((rc = req_acl_canned(&cli->req)) == ACLCNUM) { + if ((rc = hreq_acl_canned(&cli->req)) == ACLCNUM) { err = InvalidArgument; goto err_out_parm; } canacl = (rc == -1)? ACLC_PRIV: rc; - if (http11(&cli->req)) + if (hreq_http11(&cli->req)) cli->state = evt_recycle; else cli->state = evt_dispose; @@ -929,7 +929,7 @@ static bool object_put_acls(struct client *cli, const char *user, "\r\n", cli->req.major, cli->req.minor, - time2str(timestr, sizeof(timestr), time(NULL))) < 0) { + hutil_time2str(timestr, sizeof(timestr), time(NULL))) < 0) { /* FIXME: cleanup failure */ applog(LOG_ERR, "OOM in object_put_end"); return cli_err(cli, InternalError); @@ -959,7 +959,7 @@ bool object_put(struct client *cli, const char *user, const char *bucket, setacl = false; if (cli->req.uri.query_len) { - switch (req_is_query(&cli->req)) { + switch (hreq_is_query(&cli->req)) { case URIQ_ACL: setacl = true; break; @@ -1162,7 +1162,7 @@ static bool object_get_body(struct client *cli, const char *user, md5 = obj->md5; - hdr = req_hdr(&cli->req, "if-match"); + hdr = hreq_hdr(&cli->req, "if-match"); if (hdr && strcmp(md5, hdr)) { err = PreconditionFailed; goto err_out_reset; @@ -1250,11 +1250,11 @@ static bool object_get_body(struct client *cli, const char *user, stor_node_put(stnode); - hdr = req_hdr(&cli->req, "if-unmodified-since"); + hdr = hreq_hdr(&cli->req, "if-unmodified-since"); if (hdr) { time_t t; - t = str2time(hdr); + t = hutil_str2time(hdr); if (!t) { err = InvalidArgument; goto err_out_in_end; @@ -1266,11 +1266,11 @@ static bool object_get_body(struct client *cli, const char *user, } } - hdr = req_hdr(&cli->req, "if-modified-since"); + hdr = hreq_hdr(&cli->req, "if-modified-since"); if (hdr) { time_t t; - t = str2time(hdr); + t = hutil_str2time(hdr); if (!t) { err = InvalidArgument; goto err_out_in_end; @@ -1282,7 +1282,7 @@ static bool object_get_body(struct client *cli, const char *user, } } - hdr = req_hdr(&cli->req, "if-none-match"); + hdr = hreq_hdr(&cli->req, "if-none-match"); if (hdr && (!strcmp(md5, hdr))) { modified = false; want_body = false; @@ -1302,8 +1302,8 @@ static bool object_get_body(struct client *cli, const char *user, modified ? 200 : 304, (unsigned long long) GUINT64_FROM_LE(obj->size), md5, - time2str(timestr, sizeof(timestr), time(NULL)), - time2str(modstr, sizeof(modstr), + hutil_time2str(timestr, sizeof(timestr), time(NULL)), + hutil_time2str(modstr, sizeof(modstr), GUINT64_FROM_LE(obj->mtime) / 1000000), extra_hdr->str) < 0) goto err_out_in_end; @@ -1396,7 +1396,7 @@ bool object_get(struct client *cli, const char *user, const char *bucket, getacl = false; if (cli->req.uri.query_len) { - switch (req_is_query(&cli->req)) { + switch (hreq_is_query(&cli->req)) { case URIQ_ACL: getacl = true; break; diff --git a/server/server.c b/server/server.c index 4e8dba3..7950693 100644 --- a/server/server.c +++ b/server/server.c @@ -356,7 +356,7 @@ static int authcheck(struct http_req *req, char *extra_bucket, pass = val.data; } - req_sign(req, extra_bucket, pass, b64sig); + hreq_sign(req, extra_bucket, pass, b64sig); free(pass); if (strncmp(b64sig, auth + captured[4], usiglen) != 0) { @@ -493,7 +493,7 @@ static void cli_free(struct client *cli) close(cli->fd); } - req_free(&cli->req); + hreq_free(&cli->req); if (cli->write_cnt_max > tabled_srv.stats.max_write_buf) tabled_srv.stats.max_write_buf = cli->write_cnt_max; @@ -519,7 +519,7 @@ static bool cli_evt_recycle(struct client *cli, unsigned int events) { unsigned int slop; - req_free(&cli->req); + hreq_free(&cli->req); cli->hdr_start = NULL; cli->hdr_end = NULL; @@ -769,7 +769,7 @@ bool cli_err(struct client *cli, enum errcode code) cli->req.minor, err_info[code].status, strlen(content), - time2str(timestr, sizeof(timestr), time(NULL)), + hutil_time2str(timestr, sizeof(timestr), time(NULL)), "*"); if (rc < 0) { free(content); @@ -788,7 +788,7 @@ bool cli_err(struct client *cli, enum errcode code) cli->req.minor, err_info[code].status, strlen(content), - time2str(timestr, sizeof(timestr), time(NULL))); + hutil_time2str(timestr, sizeof(timestr), time(NULL))); if (rc < 0) { free(content); return false; @@ -819,7 +819,7 @@ static bool cli_resp(struct client *cli, int http_status, { int rc; char *hdr, timestr[50]; - bool rcb, cxn_close = !http11(&cli->req); + bool rcb, cxn_close = !hreq_http11(&cli->req); if (asprintf(&hdr, "HTTP/%d.%d %d x\r\n" @@ -834,7 +834,7 @@ static bool cli_resp(struct client *cli, int http_status, http_status, content_type, strlist_len(content), - time2str(timestr, sizeof(timestr), time(NULL)), + hutil_time2str(timestr, sizeof(timestr), time(NULL)), cxn_close ? "Connection: close\r\n" : "") < 0) { __strlist_free(content); return false; @@ -901,11 +901,11 @@ static bool cli_evt_http_req(struct client *cli, unsigned int events) } /* grab useful headers */ - host = req_hdr(req, "host"); - content_len_str = req_hdr(req, "content-length"); - auth = req_hdr(req, "authorization"); + host = hreq_hdr(req, "host"); + content_len_str = hreq_hdr(req, "content-length"); + auth = hreq_hdr(req, "authorization"); if (req->major > 1 || req->minor > 0) { - char *expect = req_hdr(req, "expect"); + char *expect = hreq_hdr(req, "expect"); if (expect && strcasestr(expect, "100-continue")) expect_cont = true; } @@ -947,7 +947,7 @@ static bool cli_evt_http_req(struct client *cli, unsigned int events) * the operations below may override this next-state setting, * however. */ - if (http11(req)) + if (hreq_http11(req)) cli->state = evt_recycle; else cli->state = evt_dispose; @@ -1113,7 +1113,7 @@ static bool cli_hdr_flush(struct client *cli, bool *loop_state) *tmp = 0; /* add to list of headers */ - if (req_hdr_push(&cli->req, cli->hdr_start, tmp + 1)) { + if (hreq_hdr_push(&cli->req, cli->hdr_start, tmp + 1)) { err_resp = InvalidArgument; goto err_out; } @@ -1246,14 +1246,14 @@ static bool cli_evt_parse_req(struct client *cli, unsigned int events) strup(cli->req.method); /* URI is the second token, immediately following the first space */ - if (!uri_parse(&cli->req.uri, sp1 + 1)) { + if (!huri_parse(&cli->req.uri, sp1 + 1)) { err_resp = InvalidURI; goto err_out; } cli->req.orig_path = g_strndup(cli->req.uri.path, cli->req.uri.path_len); - cli->req.uri.path_len = field_unescape(cli->req.uri.path, + cli->req.uri.path_len = huri_field_unescape(cli->req.uri.path, cli->req.uri.path_len); /* HTTP version is the final token, following second space */ diff --git a/server/status.c b/server/status.c index 8fb142b..e9fbb38 100644 --- a/server/status.c +++ b/server/status.c @@ -102,7 +102,7 @@ static bool stat_err(struct client *cli, enum errcode code) "\r\n", cli->req.major, cli->req.minor, err_status, strlen(content), - time2str(timestr, sizeof(timestr), time(NULL))); + hutil_time2str(timestr, sizeof(timestr), time(NULL))); if (rc < 0) goto out_hdr; @@ -160,7 +160,7 @@ bool stat_evt_http_req(struct client *cli, unsigned int events) bool rcb; /* grab useful headers */ - // content_len_str = req_hdr(req, "content-length"); + // content_len_str = hreq_hdr(req, "content-length"); path = strdup(req->uri.path); if (!path) @@ -178,7 +178,7 @@ bool stat_evt_http_req(struct client *cli, unsigned int events) * the operations below may override this next-state setting, * however. */ - if (http11(req)) + if (hreq_http11(req)) cli->state = evt_recycle; else cli->state = evt_dispose; diff --git a/server/tabled.h b/server/tabled.h index b6e4cbb..ae67838 100644 --- a/server/tabled.h +++ b/server/tabled.h @@ -27,7 +27,7 @@ #include <glib.h> #include <pcre.h> #include <event.h> -#include <httputil.h> +#include <hstor.h> #include <elist.h> #include <tdb.h> #include <hail_log.h> diff --git a/test/Makefile.am b/test/Makefile.am index 3d751bc..9264cba 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -34,10 +34,9 @@ check_PROGRAMS = basic-bucket basic-object it-works large-object \ noinst_LIBRARIES = libtest.a -TESTLDADD = ../lib/libhttpstor.la \ - ../lib/libhttputil.a \ - libtest.a \ - @LIBCURL@ @GLIB_LIBS@ @CRYPTO_LIBS@ @XML_LIBS@ +TESTLDADD = libtest.a \ + @HAIL_LIBS@ @GLIB_LIBS@ \ + @LIBCURL@ @CRYPTO_LIBS@ @XML_LIBS@ basic_bucket_LDADD = $(TESTLDADD) basic_object_LDADD = $(TESTLDADD) large_object_LDADD = $(TESTLDADD) @@ -45,6 +44,6 @@ hdr_content_type_LDADD = $(TESTLDADD) hdr_meta_LDADD = $(TESTLDADD) it_works_LDADD = $(TESTLDADD) -wait_for_listen_LDADD = ../lib/libhttputil.a +wait_for_listen_LDADD = libtest.a TESTS_ENVIRONMENT=top_srcdir=$(top_srcdir) diff --git a/test/basic-bucket.c b/test/basic-bucket.c index da54547..a1c705d 100644 --- a/test/basic-bucket.c +++ b/test/basic-bucket.c @@ -22,15 +22,14 @@ #include <string.h> #include <locale.h> -#include <httpstor.h> -#include <httputil.h> +#include <hstor.h> #include "test.h" int main(int argc, char *argv[]) { - struct httpstor_client *httpstor; - struct httpstor_blist *blist; - struct httpstor_bucket *buck; + struct hstor_client *hstor; + struct hstor_blist *blist; + struct hstor_bucket *buck; bool rcb; char accbuf[80]; int rc; @@ -40,22 +39,22 @@ int main(int argc, char *argv[]) rc = tb_readport(TEST_FILE_TB, accbuf, sizeof(accbuf)); OK(rc > 0); - httpstor = httpstor_new(accbuf, TEST_HOST, TEST_USER, TEST_USER_KEY); - OK(httpstor); + hstor = hstor_new(accbuf, TEST_HOST, TEST_USER, TEST_USER_KEY); + OK(hstor); /* make sure bucket list is empty */ - blist = httpstor_list_buckets(httpstor); + blist = hstor_list_buckets(hstor); OK(blist); OK(!blist->list); - httpstor_free_blist(blist); + hstor_free_blist(blist); /* add bucket */ - rcb = httpstor_add_bucket(httpstor, "test1"); + rcb = hstor_add_bucket(hstor, "test1"); OK(rcb); /* make sure bucket list contains one item */ - blist = httpstor_list_buckets(httpstor); + blist = hstor_list_buckets(hstor); OK(blist); OK(blist->list); OK(blist->list->next == NULL); @@ -63,18 +62,18 @@ int main(int argc, char *argv[]) buck = blist->list->data; OK(!strcmp(buck->name, "test1")); - httpstor_free_blist(blist); + hstor_free_blist(blist); /* delete bucket */ - rcb = httpstor_del_bucket(httpstor, "test1"); + rcb = hstor_del_bucket(hstor, "test1"); OK(rcb); /* make sure bucket list is empty */ - blist = httpstor_list_buckets(httpstor); + blist = hstor_list_buckets(hstor); OK(blist); OK(!blist->list); - httpstor_free_blist(blist); + hstor_free_blist(blist); return 0; } diff --git a/test/basic-object.c b/test/basic-object.c index 0761e31..85adc79 100644 --- a/test/basic-object.c +++ b/test/basic-object.c @@ -22,15 +22,14 @@ #include <string.h> #include <locale.h> -#include <httpstor.h> -#include <httputil.h> +#include <hstor.h> #include "test.h" int main(int argc, char *argv[]) { static char bucket[] = "test1"; static char key[] = "my first key"; - struct httpstor_client *httpstor; + struct hstor_client *hstor; char accbuf[80]; int rc; bool rcb; @@ -43,29 +42,29 @@ int main(int argc, char *argv[]) rc = tb_readport(TEST_FILE_TB, accbuf, sizeof(accbuf)); OK(rc > 0); - httpstor = httpstor_new(accbuf, TEST_HOST, TEST_USER, TEST_USER_KEY); - OK(httpstor); + hstor = hstor_new(accbuf, TEST_HOST, TEST_USER, TEST_USER_KEY); + OK(hstor); /* add bucket */ - rcb = httpstor_add_bucket(httpstor, bucket); + rcb = hstor_add_bucket(hstor, bucket); OK(rcb); /* store object */ - rcb = httpstor_put_inline(httpstor, bucket, key, val, strlen(val), NULL); + rcb = hstor_put_inline(hstor, bucket, key, val, strlen(val), NULL); OK(rcb); /* get object */ - mem = httpstor_get_inline(httpstor, bucket, key, false, &len); + mem = hstor_get_inline(hstor, bucket, key, false, &len); OK(mem); OK(len == strlen(val)); OK(!memcmp(val, mem, strlen(val))); /* delete object */ - rcb = httpstor_del(httpstor, bucket, key); + rcb = hstor_del(hstor, bucket, key); OK(rcb); /* delete bucket */ - rcb = httpstor_del_bucket(httpstor, bucket); + rcb = hstor_del_bucket(hstor, bucket); OK(rcb); return 0; diff --git a/test/hdr-content-type.c b/test/hdr-content-type.c index f798638..6987372 100644 --- a/test/hdr-content-type.c +++ b/test/hdr-content-type.c @@ -25,8 +25,7 @@ #include <stdlib.h> #include <ctype.h> #include <locale.h> -#include <httpstor.h> -#include <httputil.h> +#include <hstor.h> #include "test.h" static char bucket[] = "test-hdr-ctt"; @@ -38,17 +37,17 @@ static char *user_hdrs[] = { NULL }; -static void runtest(struct httpstor_client *httpstor) +static void runtest(struct hstor_client *hstor) { bool rcb; void *data = NULL; size_t data_len = 0; - rcb = httpstor_put_inline(httpstor, bucket, key, + rcb = hstor_put_inline(hstor, bucket, key, value, strlen(value) + 1, user_hdrs); OK(rcb); - data = httpstor_get_inline(httpstor, bucket, key, true, &data_len); + data = hstor_get_inline(hstor, bucket, key, true, &data_len); OK(data); OK(data_len > 0); @@ -60,7 +59,7 @@ static void runtest(struct httpstor_client *httpstor) int main(int argc, char *argv[]) { - struct httpstor_client *httpstor; + struct hstor_client *hstor; char accbuf[80]; int rc; bool rcb; @@ -70,19 +69,19 @@ int main(int argc, char *argv[]) rc = tb_readport(TEST_FILE_TB, accbuf, sizeof(accbuf)); OK(rc > 0); - httpstor = httpstor_new(accbuf, TEST_HOST, TEST_USER, TEST_USER_KEY); - OK(httpstor); + hstor = hstor_new(accbuf, TEST_HOST, TEST_USER, TEST_USER_KEY); + OK(hstor); /* add bucket - since tests are independent, we do not rely on others */ - rcb = httpstor_add_bucket(httpstor, bucket); + rcb = hstor_add_bucket(hstor, bucket); OK(rcb); - runtest(httpstor); + runtest(hstor); - rcb = httpstor_del(httpstor, bucket, key); + rcb = hstor_del(hstor, bucket, key); OK(rcb); - rcb = httpstor_del_bucket(httpstor, bucket); + rcb = hstor_del_bucket(hstor, bucket); OK(rcb); return 0; diff --git a/test/hdr-meta.c b/test/hdr-meta.c index 424006c..d7f7414 100644 --- a/test/hdr-meta.c +++ b/test/hdr-meta.c @@ -25,8 +25,7 @@ #include <stdlib.h> #include <ctype.h> #include <locale.h> -#include <httpstor.h> -#include <httputil.h> +#include <hstor.h> #include "test.h" static char bucket[] = "test-hdr-meta"; @@ -39,18 +38,18 @@ static char *user_hdrs[] = { NULL }; -static void runtest(struct httpstor_client *httpstor) +static void runtest(struct hstor_client *hstor) { bool rcb; void *data = NULL; size_t data_len = 0; int idx; - rcb = httpstor_put_inline(httpstor, bucket, key, + rcb = hstor_put_inline(hstor, bucket, key, value, strlen(value) + 1, user_hdrs); OK(rcb); - data = httpstor_get_inline(httpstor, bucket, key, true, &data_len); + data = hstor_get_inline(hstor, bucket, key, true, &data_len); OK(data); OK(data_len > 0); @@ -67,7 +66,7 @@ static void runtest(struct httpstor_client *httpstor) int main(int argc, char *argv[]) { - struct httpstor_client *httpstor; + struct hstor_client *hstor; char accbuf[80]; int rc; bool rcb; @@ -77,19 +76,19 @@ int main(int argc, char *argv[]) rc = tb_readport(TEST_FILE_TB, accbuf, sizeof(accbuf)); OK(rc > 0); - httpstor = httpstor_new(accbuf, TEST_HOST, TEST_USER, TEST_USER_KEY); - OK(httpstor); + hstor = hstor_new(accbuf, TEST_HOST, TEST_USER, TEST_USER_KEY); + OK(hstor); /* add bucket - since tests are independent, we do not rely on others */ - rcb = httpstor_add_bucket(httpstor, bucket); + rcb = hstor_add_bucket(hstor, bucket); OK(rcb); - runtest(httpstor); + runtest(hstor); - rcb = httpstor_del(httpstor, bucket, key); + rcb = hstor_del(hstor, bucket, key); OK(rcb); - rcb = httpstor_del_bucket(httpstor, bucket); + rcb = hstor_del_bucket(hstor, bucket); OK(rcb); return 0; diff --git a/test/it-works.c b/test/it-works.c index c1fddd3..534f6cd 100644 --- a/test/it-works.c +++ b/test/it-works.c @@ -22,14 +22,13 @@ #include <string.h> #include <locale.h> -#include <httpstor.h> -#include <httputil.h> +#include <hstor.h> #include "test.h" int main(int argc, char *argv[]) { - struct httpstor_client *httpstor; - struct httpstor_blist *blist; + struct hstor_client *hstor; + struct hstor_blist *blist; char accbuf[80]; int rc; @@ -38,14 +37,14 @@ int main(int argc, char *argv[]) rc = tb_readport(TEST_FILE_TB, accbuf, sizeof(accbuf)); OK(rc > 0); - httpstor = httpstor_new(accbuf, TEST_HOST, TEST_USER, TEST_USER_KEY); - OK(httpstor); + hstor = hstor_new(accbuf, TEST_HOST, TEST_USER, TEST_USER_KEY); + OK(hstor); - blist = httpstor_list_buckets(httpstor); + blist = hstor_list_buckets(hstor); OK(blist); - OK(!strcmp(blist->own_id, httpstor->user)); - OK(!strcmp(blist->own_name, httpstor->user)); + OK(!strcmp(blist->own_id, hstor->user)); + OK(!strcmp(blist->own_name, hstor->user)); OK(!blist->list); return 0; diff --git a/test/large-object.c b/test/large-object.c index 919bbc4..dbe2027 100644 --- a/test/large-object.c +++ b/test/large-object.c @@ -30,8 +30,7 @@ #include <string.h> #include <stdlib.h> #include <locale.h> -#include <httpstor.h> -#include <httputil.h> +#include <hstor.h> #include "test.h" #define BLKSZ0 1024 @@ -162,7 +161,7 @@ static size_t get_cb(void *ptr, size_t membsize, size_t nmemb, void *user_data) return nmemb; } -static void runtest(struct httpstor_client *httpstor, +static void runtest(struct hstor_client *hstor, size_t blklen, int nblks) { off_t total = blklen * nblks; @@ -176,7 +175,7 @@ static void runtest(struct httpstor_client *httpstor, putctx.blksize = blklen; putctx.total = total; - rcb = httpstor_put(httpstor, bucket, key, put_cb, total, &putctx, NULL); + rcb = hstor_put(hstor, bucket, key, put_cb, total, &putctx, NULL); OK(rcb); OK(putctx.off == total); @@ -186,7 +185,7 @@ static void runtest(struct httpstor_client *httpstor, getctx.csum = CSUM_INIT; getctx.blksize = blklen; - rcb = httpstor_get(httpstor, bucket, key, get_cb, &getctx, false); + rcb = hstor_get(hstor, bucket, key, get_cb, &getctx, false); OK(rcb); OK(getctx.off == total); @@ -195,7 +194,7 @@ static void runtest(struct httpstor_client *httpstor, int main(int argc, char *argv[]) { - struct httpstor_client *httpstor; + struct hstor_client *hstor; char accbuf[80]; int rc; bool rcb; @@ -205,21 +204,21 @@ int main(int argc, char *argv[]) rc = tb_readport(TEST_FILE_TB, accbuf, sizeof(accbuf)); OK(rc > 0); - httpstor = httpstor_new(accbuf, TEST_HOST, TEST_USER, TEST_USER_KEY); - OK(httpstor); + hstor = hstor_new(accbuf, TEST_HOST, TEST_USER, TEST_USER_KEY); + OK(hstor); /* add bucket - since tests are independent, we do not rely on others */ - rcb = httpstor_add_bucket(httpstor, bucket); + rcb = hstor_add_bucket(hstor, bucket); OK(rcb); - runtest(httpstor, BLKSZ0, NBLKS0); - runtest(httpstor, BLKSZ1, NBLKS1); - runtest(httpstor, BLKSZ2, NBLKS2); + runtest(hstor, BLKSZ0, NBLKS0); + runtest(hstor, BLKSZ1, NBLKS1); + runtest(hstor, BLKSZ2, NBLKS2); - rcb = httpstor_del(httpstor, bucket, key); + rcb = hstor_del(hstor, bucket, key); OK(rcb); - rcb = httpstor_del_bucket(httpstor, bucket); + rcb = hstor_del_bucket(hstor, bucket); OK(rcb); return 0; diff --git a/test/libtest.c b/test/libtest.c index bdfe912..1e15172 100644 --- a/test/libtest.c +++ b/test/libtest.c @@ -17,9 +17,14 @@ * */ +#include <sys/types.h> +#include <sys/stat.h> #include <string.h> #include <stdbool.h> +#include <unistd.h> #include <ctype.h> +#include <errno.h> +#include <fcntl.h> #include "test.h" bool find_our_hdr(const char *hdr, const void *data, size_t data_len) @@ -61,3 +66,34 @@ bool find_our_hdr(const char *hdr, const void *data, size_t data_len) return false; } +/* + * Read a port number from a port file, fill buffer. + * Unlike cld_readport, host is included as well, and we use strings. + */ +int tb_readport(const char *fname, char *buf, size_t len) +{ + int fd; + char *s; + int rc; + + if (len < 3) + return -EDOM; + if ((fd = open(fname, O_RDONLY)) == -1) + return -errno; + rc = read(fd, buf, len-1); + close(fd); + if (rc < 0) + return -errno; + if (rc == 0) + return -EPIPE; + buf[rc] = 0; + + s = strchr(buf, '\n'); + if (s) { + *s = 0; + rc = s - buf; + } + + return rc; +} + diff --git a/test/test.h b/test/test.h index 50b7e36..ae7b68b 100644 --- a/test/test.h +++ b/test/test.h @@ -19,7 +19,7 @@ * */ - +#include <stdbool.h> #include <stdlib.h> #include <stdio.h> @@ -39,5 +39,6 @@ } while (0) extern bool find_our_hdr(const char *hdr, const void *data, size_t data_len); +extern int tb_readport(const char *fname, char *buf, size_t len); #endif /* __TABLED_TEST_H__ */ diff --git a/test/wait-for-listen.c b/test/wait-for-listen.c index d52690e..fef5028 100644 --- a/test/wait-for-listen.c +++ b/test/wait-for-listen.c @@ -34,7 +34,6 @@ #include <time.h> #include <unistd.h> #include <netdb.h> -#include <httputil.h> #include "test.h" #define ADDRSIZE 24 /* Enough for IPv6, including port. */ -- To unsubscribe from this list: send the line "unsubscribe hail-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html