Skip to content

Instantly share code, notes, and snippets.

@lestrrat
Created October 9, 2009 07:05
Show Gist options
  • Save lestrrat/205809 to your computer and use it in GitHub Desktop.
Save lestrrat/205809 to your computer and use it in GitHub Desktop.
/*
* 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