Created
October 9, 2009 07:05
-
-
Save lestrrat/205809 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* requires tokyodystopia, libapreq2 | |
* TODO: make it possible to configure from httpd.conf | |
* remove all the hardcoded gunk | |
* test properly | |
* Yes, I looked at tdserver.c. Thanks to Kawai-san | |
*/ | |
#include "httpd.h" | |
#include "http_config.h" | |
#include "http_log.h" | |
#include "http_protocol.h" | |
#include "ap_config.h" | |
#include <apr_tables.h> | |
#include <apreq2/apreq_param.h> | |
#include <dystopia.h> | |
#include <ttutil.h> | |
static int64_t tdserver_get_key_from_uri(request_rec *); | |
static int tdserver_handle_get(request_rec *, TCIDB *); | |
static int tdserver_handle_post(request_rec *, TCIDB *); | |
/* The sample content handler */ | |
static int tdserver_handler(request_rec *r) | |
{ | |
int rc; | |
if (strcmp(r->handler, "tdserver")) | |
return DECLINED; | |
if (r->header_only) | |
return DECLINED; | |
r->content_type = "text/plain"; | |
TCIDB *idb = tcidbnew(); | |
char *filename = "/tmp/tcidb.db"; | |
if ( ! tcidbopen(idb, filename, IDBOWRITER | IDBOCREAT | IDBOREADER) ) { | |
ap_log_error(APLOG_MARK, APLOG_ERR, HTTP_INTERNAL_SERVER_ERROR, r->server, "Could not open database"); | |
return DECLINED; | |
} | |
switch( r->method_number ) { | |
case M_GET: | |
rc = tdserver_handle_get(r, idb); | |
break; | |
case M_POST: | |
rc = tdserver_handle_post(r, idb); | |
break; | |
default: | |
rc = DECLINED; | |
} | |
tcidbclose(idb); | |
return rc; | |
} | |
static int tdserver_handle_get(request_rec *r, TCIDB *idb) | |
{ | |
ap_rputs("handle_get\n", r); | |
if (r->args) { | |
char *q; | |
apr_table_t *t = apr_table_make(r->pool, 0); | |
apreq_parse_query_string(r->pool, t, r->args); | |
if ( q = apr_table_get(t, "q") ) { | |
int i; | |
int rnum; | |
uint64_t *result; | |
ap_rputs( "searching...\n", r ); | |
result = tcidbsearch2(idb, q, &rnum); | |
for( i = 0; i < rnum; i++ ) { | |
if (i > 0) | |
ap_rputs( ",", r ); | |
ap_rprintf( r, "%d", result[i] ); | |
} | |
} | |
apr_table_clear(t); | |
} else { | |
ap_rputs( tcidbget(idb, tdserver_get_key_from_uri(r)), r); | |
} | |
return OK; | |
} | |
static int64_t tdserver_get_key_from_uri(request_rec *r) | |
{ | |
char *kbuf; | |
char *uri; | |
int ksiz; | |
int key; | |
/* use the URL as the key */ | |
uri = r->uri; | |
if (*uri == '/') | |
uri++; | |
kbuf = tcurldecode(uri, &ksiz); | |
key = tcatoi(kbuf); | |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uri (%s) maps to key(%d)", kbuf, key); | |
free(kbuf); | |
return key; | |
} | |
#define MAX_BUFSIZ 8192 | |
static int tdserver_handle_post(request_rec *r, TCIDB *idb) | |
{ | |
apr_status_t rv; | |
int seen_eos; | |
apr_bucket_brigade *bb; | |
apr_size_t dbpos = 0; | |
apr_size_t bufbytes = 1024; | |
char *dbuf; | |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "handle_post"); | |
ap_rputs("handle_post\n", r); | |
dbuf = apr_palloc(r->pool, bufbytes + 1); | |
bb = apr_brigade_create(r->pool, r->connection->bucket_alloc); | |
do { | |
ap_rputs("in do\n", r); | |
apr_bucket *bucket; rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES, APR_BLOCK_R | |
EAD, HUGE_STRING_LEN); | |
if (rv != APR_SUCCESS) { | |
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, | |
"Error reading request entity data"); | |
return HTTP_INTERNAL_SERVER_ERROR; | |
} | |
for (bucket = APR_BRIGADE_FIRST(bb); | |
bucket != APR_BRIGADE_SENTINEL(bb); | |
bucket = APR_BUCKET_NEXT(bucket)) | |
{ | |
const char *data; | |
apr_size_t len; | |
ap_rputs("in forloop\n", r); | |
if (APR_BUCKET_IS_EOS(bucket)) { | |
ap_rputs("seen_eos\n", r); | |
seen_eos = 1; | |
break; | |
} | |
/* We can't do much with this. */ | |
if (APR_BUCKET_IS_FLUSH(bucket)) { | |
ap_rputs("is flush\n", r); | |
continue; | |
} | |
ap_rputs("going to read\n", r); | |
/* read */ | |
apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ); | |
{ | |
int cursize; | |
if ((dbpos + len) > bufbytes) { | |
cursize = bufbytes - dbpos; | |
} | |
else { | |
cursize = len; | |
} | |
memcpy(dbuf + dbpos, data, cursize); | |
dbpos += cursize; | |
} | |
} | |
apr_brigade_cleanup(bb); | |
} | |
while (!seen_eos); | |
apr_brigade_cleanup(bb); | |
dbuf[dbpos] = '\0'; | |
tcidbput(idb, tdserver_get_key_from_uri(r), dbuf); | |
return OK; | |
} | |
static void tdserver_register_hooks(apr_pool_t *p) | |
{ | |
ap_hook_handler(tdserver_handler, NULL, NULL, APR_HOOK_MIDDLE); | |
} | |
/* Dispatch list for API hooks */ | |
module AP_MODULE_DECLARE_DATA tdserver_module = { | |
STANDARD20_MODULE_STUFF, | |
NULL, /* create per-dir config structures */ | |
NULL, /* merge per-dir config structures */ | |
NULL, /* create per-server config structures */ | |
NULL, /* merge per-server config structures */ | |
NULL, /* table of config file commands */ | |
tdserver_register_hooks /* register hooks */ | |
}; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment