Removed graph, httpd and webserver

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@9757 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
ultramage 2007-02-01 01:33:37 +00:00
parent 287219ad0d
commit 7390d2d950
51 changed files with 14 additions and 1924 deletions

View File

@ -4,6 +4,7 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2007/01/31
* Removed graph, httpd and webserver
* Wiped out the old night code (use svn if you want it) [ultramage]
2007/01/30
* 'Long Range Attacked' mob skill conditions will no longer trigger on

View File

@ -109,7 +109,7 @@ MKDEF = CC="$(CC)" CFLAGS="$(CFLAGS)" LIB_S="$(LIBS)"
endif
.PHONY: txt sql common login login_sql char char_sql map map_sql ladmin converters \
addons plugins tools webserver clean zlib depend
addons plugins tools clean zlib depend
txt : Makefile.cache conf common login char map ladmin
@ -153,9 +153,6 @@ ladmin: src/ladmin/GNUmakefile common
plugins addons: src/plugins/GNUmakefile common
$(MAKE) -C src/plugins $(MKDEF)
webserver:
$(MAKE) -C src/$@ $(MKDEF)
tools:
$(MAKE) -C src/tool $(MKDEF)

View File

@ -25,8 +25,5 @@ plugin: upnp
// Process id logging
//plugin: pid
// Built-in webserver
//plugin: httpd
// Console parser
//plugin: console

View File

@ -3,12 +3,12 @@ all txt: char-server
COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o \
../common/obj/db.o ../common/obj/plugins.o ../common/obj/lock.o \
../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/utils.o \
../common/obj/strlib.o ../common/obj/graph.o ../common/obj/grfio.o \
../common/obj/strlib.o ../common/obj/grfio.o \
../common/obj/mapindex.o ../common/obj/ers.o ../zlib/unz.o
COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h \
../common/version.h ../common/db.h ../common/plugins.h ../common/lock.h \
../common/malloc.h ../common/showmsg.h ../common/utils.h ../common/strlib.h \
../common/graph.h ../common/grfio.h ../common/mapindex.h
../common/grfio.h ../common/mapindex.h
%.o: %.c
$(COMPILE.c) -DTXT_ONLY $(OUTPUT_OPTION) $<

View File

@ -3,12 +3,12 @@ all sql: char-server_sql
COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o \
../common/obj/db.o ../common/obj/plugins.o ../common/obj/lock.o \
../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/utils.o \
../common/obj/strlib.o ../common/obj/graph.o ../common/obj/grfio.o \
../common/obj/strlib.o ../common/obj/grfio.o \
../common/obj/mapindex.o ../common/obj/ers.o ../zlib/unz.o
COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h \
../common/version.h ../common/db.h ../common/plugins.h ../common/lock.h \
../common/malloc.h ../common/showmsg.h ../common/utils.h ../common/strlib.h \
../common/graph.h ../common/grfio.h ../common/mapindex.h
../common/grfio.h ../common/mapindex.h
char-server_sql: char.o inter.o int_party.o int_guild.o int_storage.o int_pet.o int_homun.o itemdb.o $(COMMON_OBJ)
$(CC) -o ../../$@ $^ $(LIB_S)

View File

@ -5,7 +5,7 @@ obj:
common: obj/core.o obj/socket.o obj/timer.o obj/db.o obj/plugins.o obj/lock.o \
obj/nullpo.o obj/malloc.o obj/showmsg.o obj/strlib.o obj/utils.o \
obj/graph.o obj/grfio.o obj/minicore.o obj/minisocket.o obj/minimalloc.o \
obj/grfio.o obj/minicore.o obj/minisocket.o obj/minimalloc.o \
obj/mapindex.o obj/unz.o obj/ers.o obj/md5calc.o
@ -48,7 +48,6 @@ obj/ers.o: ers.c ers.h cbasetypes.h
obj/db.o: db.c db.h showmsg.h ers.h
obj/lock.o: lock.c lock.h showmsg.h
obj/grfio.o: grfio.c grfio.h
obj/graph.o: graph.c graph.h
obj/nullpo.o: nullpo.c nullpo.h showmsg.h
obj/malloc.o: malloc.c malloc.h showmsg.h
obj/plugins.o: plugins.c plugins.h plugin.h

View File

@ -19,7 +19,6 @@
#include "../common/db.h"
#include "../common/socket.h"
#include "../common/timer.h"
#include "../common/graph.h"
#include "../common/plugins.h"
#endif
@ -258,7 +257,6 @@ int main (int argc, char **argv)
plugins_init();
do_init(argc,argv);
graph_init();
plugin_event_trigger(EVENT_ATHENA_INIT);
{// Main runtime cycle
@ -273,7 +271,6 @@ int main (int argc, char **argv)
}
plugin_event_trigger(EVENT_ATHENA_FINAL);
graph_final();
do_final();
timer_final();

View File

@ -1,318 +0,0 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
// graph creation is enabled
// #define ENABLE_GRAPH
#ifdef ENABLE_GRAPH
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef _WIN32
#include <unistd.h>
#endif
#ifdef MINGW
#include <io.h>
#endif
#include "../common/core.h"
#include "../common/timer.h"
#include "../common/grfio.h"
#include "../common/malloc.h"
#include "graph.h"
struct graph {
int width;
int height;
int pallet_count;
int png_len;
int png_dirty;
unsigned char* raw_data;
unsigned char* png_data;
int * graph_value;
int graph_max;
};
void graph_write_dword(unsigned char* p,unsigned int v) {
p[0] = (unsigned char)((v >> 24) & 0xFF);
p[1] = (unsigned char)((v >> 16) & 0xFF);
p[2] = (unsigned char)((v >> 8) & 0xFF);
p[3] = (unsigned char)(v & 0xFF);
}
struct graph* graph_create(unsigned int x,unsigned int y) {
struct graph *g = (struct graph*)aCalloc(sizeof(struct graph),1);
if(g == NULL) return NULL;
// 256 * 3 : パレットデータ
// x * y * 2 : イメージのバッファ
// 256 : チャンクデータなどの予備
g->png_data = (unsigned char *) aMalloc(4 * 256 + (x + 1) * y * 2);
g->raw_data = (unsigned char *) aCalloc( (x + 1) * y , 1);
memcpy(
g->png_data,
"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x08\x03\x00\x00\x00\xFF\xFF\xFF"
"\xFF\x00\x00\x00\x03\x50\x4C\x54\x45\xFF\xFF\xFF\xA7\xC4\x1B\xC8",0x30
);
graph_write_dword(g->png_data + 0x10,x);
graph_write_dword(g->png_data + 0x14,y);
graph_write_dword(g->png_data + 0x1D,grfio_crc32(g->png_data+0x0C,0x11));
g->pallet_count = 1;
g->width = x;
g->height = y;
g->png_dirty = 1;
g->graph_value = (int *) aCalloc(x,sizeof(int));
g->graph_max = 1;
return g;
}
void graph_pallet(struct graph* g, int index,unsigned long c) {
if(g == NULL || c >= 256) return;
if(g->pallet_count <= index) {
memset(g->png_data + 0x29 + 3 * g->pallet_count,0,(index - g->pallet_count) * 3);
g->pallet_count = index + 1;
}
g->png_data[0x29 + index * 3 ] = (unsigned char)((c >> 16) & 0xFF); // R
g->png_data[0x29 + index * 3 + 1] = (unsigned char)((c >> 8) & 0xFF); // G
g->png_data[0x29 + index * 3 + 2] = (unsigned char)( c & 0xFF); // B
graph_write_dword(g->png_data + 0x21,g->pallet_count * 3);
graph_write_dword(
g->png_data + 0x29 + g->pallet_count * 3,
grfio_crc32(g->png_data + 0x25,g->pallet_count * 3 + 4)
);
g->png_dirty = 1;
}
void graph_setpixel(struct graph* g,int x,int y,int color) {
if(g == NULL || color >= 256) { return; }
if(x < 0) x = 0;
if(y < 0) y = 0;
if(x >= g->width) { x = g->width - 1; }
if(y >= g->height) { y = g->height - 1; }
if(color >= g->pallet_count) { graph_pallet(g,color,graph_rgb(0,0,0)); }
g->raw_data[y * (g->width + 1) + x + 1] = (unsigned char)color;
g->png_dirty = 1;
}
int graph_getpixel(struct graph* g,int x,int y) {
if(x < 0) x = 0;
if(y < 0) y = 0;
if(x >= g->width) { x = g->width - 1; }
if(y >= g->height) { y = g->height - 1; }
return g->raw_data[y * (g->width + 1) + x + 1];
}
const unsigned char* graph_output(struct graph* g,int *len) {
unsigned long inflate_len;
unsigned char *p;
if(g == NULL) return NULL;
if(g->png_dirty == 0) {
*len = g->png_len;
return g->png_data;
}
p = g->png_data + 0x2D + 3 * g->pallet_count;
inflate_len = 2 * (g->width + 1) * g->height;
memcpy(p + 4,"IDAT",4);
encode_zip(p + 8,&inflate_len,g->raw_data,(g->width + 1) * g->height);
graph_write_dword(p,inflate_len);
graph_write_dword(p + 8 + inflate_len,grfio_crc32(p + 4, inflate_len + 4));
p += 0x0C + inflate_len;
memcpy(p,"\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60\x82",0x0C);
p += 0x0C;
g->png_len = p - g->png_data;
g->png_dirty = 0;
*len = g->png_len;
return g->png_data;
}
void graph_free(struct graph* g) {
if(g != NULL) {
aFree(g->png_data);
aFree(g->raw_data);
aFree(g->graph_value);
aFree(g);
}
}
// とりあえず不効率版。後ほど書き直し予定
void graph_square(struct graph* g,int x,int y,int xe,int ye,int color) {
int i,j;
if(g == NULL) return;
if(x < 0) { x = 0; }
if(y < 0) { y = 0; }
if(xe > g->width) { xe = g->width; }
if(ye > g->height) { ye = g->height; }
for(i = y;i < ye ; i++) {
for(j = x; j < xe ; j++) {
graph_setpixel(g,j,i,color);
}
}
}
// とりあえず不効率版。後ほど書き直し予定
void graph_scroll(struct graph* g,int n,int color) {
int x,y;
if(g == NULL) return;
for(y = 0; y < g->height; y++) {
for(x = 0; x < g->width - n; x++) {
graph_setpixel(g,x,y,graph_getpixel(g,x + n,y));
}
for( ; x < g->width; x++) {
graph_setpixel(g,x,y,color);
}
}
}
void graph_data(struct graph* g,int value) {
int i, j, start;
if(g == NULL) return;
memmove(&g->graph_value[0],&g->graph_value[1],sizeof(int) * (g->width - 1));
g->graph_value[g->width - 1] = value;
if(value > g->graph_max) {
// 最大値を超えたので再描画
g->graph_max = value;
graph_square(g,0,0,g->width,g->height,0);
start = 0;
} else {
// スクロールしてポイント打つ
graph_scroll(g,1,0);
start = g->width - 1;
}
for(i = start; i < g->width; i++) {
int h0 = (i == 0 ? 0 : g->graph_value[i - 1]) * g->height / g->graph_max;
int h1 = (g->graph_value[i] ) * g->height / g->graph_max;
int h2 = (h0 < h1 ? 1 : -1);
for(j = h0; j != h1; j += h2) {
graph_setpixel(g,i,g->height - 1 - j,1);
}
graph_setpixel(g,i,g->height - 1 - h1,1);
}
}
// 上の関数群を利用して、自動的にグラフを作成するタイマー群
#define GRP_WIDTH 300 // グラフの幅
#define GRP_HEIGHT 200 // グラフの高さ
#define GRP_COLOR graph_rgb(0,0,255) // グラフの色
#define GRP_INTERVEL 60*1000 // グラフの更新間隔
#define GRP_PATH "httpd/"
struct graph_sensor {
struct graph* graph;
char* str;
char hash[32];
int scanid;
int drawid;
int interval;
unsigned int (*func)(void);
};
static struct graph_sensor *sensor;
static int sensor_max;
static int graph_scan_timer(int tid,unsigned int tick,int id,int data)
{
if(id >= 0 && id < sensor_max)
graph_data(sensor[id].graph,sensor[id].func());
return 0;
}
// modified by Celest -- i'm trying to separate it from httpd if possible ^^;
static int graph_draw_timer(int tid,unsigned int tick,int id,int data)
{
char png_file[24];
FILE *fp;
// create/update the png file
do {
const char *png_data;
int len;
sprintf (png_file, GRP_PATH"%s.png", sensor[id].hash);
fp = fopen(png_file, "w");
// if another png of the same hash exists
// (i.e 2nd login server with the same sensors)
// this will fail = not good >.<
if (fp == NULL)
break;
png_data = graph_output(sensor[id].graph, &len);
fwrite(png_data,1,len,fp);
fclose(fp);
} while (0);
// create/update text snippet
do {
char buf[8192], *p;
p = buf;
sprintf (png_file, GRP_PATH"%s.graph", sensor[id].hash);
fp = fopen(png_file, "w");
if (fp == NULL)
break;
p += sprintf(p,"<h2>%s</h2>\n\n",
sensor[id].str);
p += sprintf(p,"<p><img src=\"%s.png\" width=\"%d\" height=\"%d\"></p>\n",
sensor[id].hash, GRP_WIDTH,GRP_HEIGHT);
p += sprintf(p,"<p>Max: %d, Interval: %d sec</p>\n\n",
sensor[id].graph->graph_max, sensor[id].interval / 1000);
fprintf(fp, buf);
fclose(fp);
} while (0);
return 0;
}
void graph_add_sensor(const unsigned char* string, int interval, unsigned int (*callback_func)(void))
{
int draw_interval = interval * 2;
struct graph *g = graph_create(GRP_WIDTH,GRP_HEIGHT);
graph_pallet(g,1,GRP_COLOR);
sensor = (struct graph_sensor *) aRealloc(sensor, sizeof(struct graph_sensor) * (sensor_max + 1));
sensor[sensor_max].graph = g;
sensor[sensor_max].str = aStrdup(string);
// create crc32 hash of the sensor's name
sprintf (sensor[sensor_max].hash, "%lu%c", grfio_crc32(string,strlen(string)), 'a' + SERVER_TYPE);
sensor[sensor_max].func = callback_func;
sensor[sensor_max].scanid = add_timer_interval(gettick() + 500, graph_scan_timer, sensor_max, 0, interval);
sensor[sensor_max].drawid = add_timer_interval(gettick() + 1000, graph_draw_timer, sensor_max, 0, draw_interval < 60000 ? 60000 : draw_interval);
sensor[sensor_max].interval = interval;
sensor_max++;
}
void graph_final (void)
{
int i;
for(i = 0; i < sensor_max; i++) {
char png_file[24];
// remove the png and snippet file
sprintf (png_file, GRP_PATH"%s.png", sensor[i].hash);
unlink (png_file);
sprintf (png_file, GRP_PATH"%s.graph", sensor[i].hash);
unlink (png_file);
graph_free(sensor[i].graph);
aFree(sensor[i].str);
//delete_timer(sensor[i].scanid,graph_scan_timer);
//delete_timer(sensor[i].drawid,graph_draw_timer);
}
aFree(sensor);
sensor_max = 0;
}
void graph_init (void)
{
graph_add_sensor ("Memory Usage", 1000, malloc_usage);
add_timer_func_list(graph_scan_timer, "graph_scan_timer");
add_timer_func_list(graph_draw_timer, "graph_draw_timer");
}
#else
void graph_init (void) {}
void graph_final (void) {}
#endif

View File

@ -1,27 +0,0 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
#ifndef _GRAPH_H_
#define _GRAPH_H_
void graph_init (void);
void graph_final (void);
struct graph* graph_create(unsigned int x,unsigned int y);
void graph_pallet(struct graph* g, int index,unsigned long c);
const unsigned char* graph_output(struct graph* g,int *len);
void graph_setpixel(struct graph* g,int x,int y,int color);
void graph_scroll(struct graph* g,int n,int color);
void graph_square(struct graph* g,int x,int y,int xe,int ye,int color);
// athenaの状態を調査するセンサーを追加する。
// string : センサーの名称(Login Users など)
// inetrval : センサーの値を所得する間隔(msec)
// callback_func : センサーの値を返す関数( unsigned int login_users(void); など)
void graph_add_sensor(const char* string, int interval, unsigned int (*callback_func)(void));
#define graph_rgb(r,g,b) (((r) << 16) | ((g) << 8) | (b))
#endif

View File

@ -3,13 +3,13 @@ all txt: login-server
COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o \
../common/obj/db.o ../common/obj/plugins.o ../common/obj/lock.o \
../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/utils.o \
../common/obj/strlib.o ../common/obj/graph.o ../common/obj/grfio.o \
../common/obj/strlib.o ../common/obj/grfio.o \
../common/obj/mapindex.o ../common/obj/ers.o ../common/obj/md5calc.o \
../zlib/unz.o
COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h \
../common/version.h ../common/db.h ../common/plugins.h ../common/lock.h \
../common/malloc.h ../common/showmsg.h ../common/utils.h ../common/strlib.h \
../common/graph.h ../common/grfio.h ../common/mapindex.h \
../common/grfio.h ../common/mapindex.h \
../common/md5calc.h
%.o: %.c

View File

@ -3,13 +3,13 @@ all sql: login-server_sql
COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o \
../common/obj/db.o ../common/obj/plugins.o ../common/obj/lock.o \
../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/utils.o \
../common/obj/strlib.o ../common/obj/graph.o ../common/obj/grfio.o \
../common/obj/strlib.o ../common/obj/grfio.o \
../common/obj/mapindex.o ../common/obj/ers.o ../common/obj/md5calc.o \
../zlib/unz.o
COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h \
../common/version.h ../common/db.h ../common/plugins.h ../common/lock.h \
../common/malloc.h ../common/showmsg.h ../common/utils.h ../common/strlib.h \
../common/graph.h ../common/grfio.h ../common/mapindex.h \
../common/grfio.h ../common/mapindex.h \
../common/md5calc.h
login-server_sql: login.o $(COMMON_OBJ)

View File

@ -12,13 +12,13 @@ COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o \
../common/obj/db.o ../common/obj/plugins.o ../common/obj/lock.o \
../common/obj/nullpo.o ../common/obj/malloc.o ../common/obj/showmsg.o \
../common/obj/utils.o ../common/obj/strlib.o ../common/obj/grfio.o \
../common/obj/graph.o ../common/obj/mapindex.o ../common/obj/ers.o \
../common/obj/mapindex.o ../common/obj/ers.o \
../zlib/unz.o
COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/db.h \
../common/plugins.h ../common/lock.h ../common/nullpo.h ../common/malloc.h \
../common/showmsg.h ../common/utils.h ../common/strlib.h ../common/grfio.h \
../common/graph.h ../common/mapindex.h
../common/mapindex.h
OBJECTS = obj/map.o obj/chrif.o obj/clif.o obj/pc.o obj/status.o obj/npc.o \
obj/npc_chat.o obj/chat.o obj/path.o obj/itemdb.o obj/mob.o obj/script.o \

View File

@ -1,5 +1,5 @@
OBJECTS = sample.dll sig.dll pid.dll gui.dll upnp.dll httpd.dll console.dll
OBJECTS = sample.dll sig.dll pid.dll gui.dll upnp.dll console.dll
ifdef CYGWIN
PLUGINEXT = dll
@ -16,12 +16,6 @@ txt sql all: $(PLUGINS)
$(CC) $(CFLAGS) -shared -o ../../plugins/$@ $<
@touch $@
httpd.$(PLUGINEXT): httpd.c
$(CC) $(CFLAGS) -shared -o ../../plugins/$@ $< \
../common/obj/minimalloc.o ../common/obj/db.o ../common/obj/showmsg.o \
../common/obj/utils.o ../common/obj/ers.o
@touch $@
sig.$(PLUGINEXT): sig.c
$(CC) $(CFLAGS) -shared -o ../../plugins/$@ $< \
../common/obj/showmsg.o ../common/obj/utils.o \
@ -29,14 +23,12 @@ sig.$(PLUGINEXT): sig.c
@touch $@
gui.$(PLUGINEXT): ../../plugins/gui.conf
httpd.$(PLUGINEXT): ../../plugins/httpd.conf
upnp.$(PLUGINEXT): ../../plugins/upnp.conf
../../plugins/%.conf: %.txt
cp -r $< $@
../../plugins/gui.conf: gui.txt
../../plugins/httpd.conf: httpd.txt
../../plugins/upnp.conf: upnp.txt
depend:

View File

@ -1,751 +0,0 @@
#ifdef __WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../common/db.h"
//mmo required for definition of stricmp
#include "../common/mmo.h"
#include "../common/utils.h"
#include "../common/malloc.h"
#include "../common/socket.h"
#include "../common/plugin.h"
//#include "httpd.h"
/** Created by End_of_Exam, ported to plugin and modified by Celest **/
PLUGIN_INFO = {
"HttpDaemon",
PLUGIN_CORE,
"0.1",
PLUGIN_VERSION,
"HTTP Daemon"
};
PLUGIN_EVENTS_TABLE = {
{ "do_init", "Plugin_Init" },
{ "do_final", "Plugin_Final" },
{ NULL, NULL }
};
enum HTTPD_STATUS {
HTTPD_REQUEST_WAIT = 0, // リクエスト待ち
HTTPD_REQUEST_WAIT_POST, // リクエスト待ち(post)
HTTPD_REQUEST_OK, // リクエスト解釈完了
HTTPD_SEND_HEADER, // ヘッダ送信完了
HTTPD_WAITING_SEND // データが送信し終わるまで待っている状態
};
enum {
HTTPD_METHOD_UNKNOWN = 0,
HTTPD_METHOD_GET,
HTTPD_METHOD_POST
};
struct httpd_session_data {
int fd;
int status;
int http_ver;
int header_len;
int data_len;
int method;
int persist;
int request_count;
unsigned int tick;
const unsigned char* url;
const unsigned char* query;
};
// undefine socket operations included from socket.h,
// since we are going to use 'sessiond' instead
#undef RFIFOP
#undef RFIFOREST
#undef WFIFOP
#define RFIFOP(fd,pos) (sessiond[fd]->rdata+sessiond[fd]->rdata_pos+(pos))
#define RFIFOREST(fd) (sessiond[fd]->rdata_size-sessiond[fd]->rdata_pos)
#define WFIFOP(fd,pos) (sessiond[fd]->wdata+sessiond[fd]->wdata_size+(pos))
struct socket_data **sessiond;
char *server_type;
unsigned int (*gettick)();
int (*add_timer_interval)(unsigned int,int (*)(int,unsigned int,int,int),int,int,int);
int *max_fd;
int (*delete_sessiond)(int);
int (*_WFIFOSET)(int,int);
int (*_RFIFOSKIP)(int,int);
static int max_persist_requests = 32; // 持続通信での最大リクエスト数
static int request_timeout[] = { 2500, 60*1000 }; // タイムアウト(最初、持続)
static char document_root[256] = "./httpd/"; // ドキュメントルート
// httpd に入っているページと、呼び出すコールバック関数の一覧
struct dbt *httpd_files;
void httpd_send(struct httpd_session_data*, int, const char *, int, const void *);
int httpd_check (struct socket_data *sd)
{
// httpd に回すどうかの判定がまだ行われてない
// 先頭2バイトが GE ならhttpd に回してみる
if (sd->rdata_size >= 2 &&
sd->rdata[0] == 'G' && sd->rdata[1] == 'E')
return 1;
return 0;
}
int httpd_strcasencmp(const char *s1, const char *s2,int len)
{
while(len-- && (*s1 || *s2) ) {
if((*s1 | 0x20) != (*s2 | 0x20)) {
return ((*s1 | 0x20) > (*s2 | 0x20) ? 1 : -1);
}
s1++; s2++;
}
return 0;
}
// httpd にページを追加する
// for などでページ名を合成できるように、key はstrdup()したものを使う
void httpd_pages (const char* url, void (*httpd_func)(struct httpd_session_data*, const char*))
{
if (strdb_get(httpd_files,(unsigned char*)(url+1)) == NULL) {
strdb_put(httpd_files, (unsigned char*)aStrdup(url+1), httpd_func);
} else {
strdb_put(httpd_files, (unsigned char*)(url+1), httpd_func);
}
}
static void (*httpd_default)(struct httpd_session_data* sd,const char* url);
const char *httpd_get_error( struct httpd_session_data* sd, int* status )
{
const char* msg;
// httpd のステータスを決める
switch(*status) {
case 200: msg = "OK"; break;
case 400: msg = "Bad Request"; break;
case 401: msg = "Unauthorized"; break; // 未使用
case 403: msg = "Forbidden"; break; // 未使用
case 404: msg = "Not Found"; break;
case 408: msg = "Request Timedout"; break;
case 411: msg = "Length Required"; break;
case 413: msg = "Request Entity Too Large"; break;
default:
*status = 500; msg = "Internal Server Error"; break;
}
return msg;
}
void httpd_send_error(struct httpd_session_data* sd,int status)
{
const char* msg = httpd_get_error( sd, &status );
httpd_send(sd, status, "text/plain",strlen(msg),msg);
}
void httpd_send_head (struct httpd_session_data* sd, int status, const char *content_type, int content_len)
{
char head[256];
int len;
const char* msg;
if (sd->status != HTTPD_REQUEST_OK)
return;
msg = httpd_get_error( sd, &status );
if(content_len == -1 || ++sd->request_count >= max_persist_requests ) {
// 長さが分からない or リクエスト限界を超えたので切断する
len = sprintf(
head,
"HTTP/1.%d %d %s\r\nContent-Type: %s\r\nConnection: close\r\n\r\n",
sd->http_ver,status,msg,content_type
);
sd->persist = 0;
len = sprintf(
head,
"HTTP/1.%d %d %s\r\nContent-Type: %s\r\n\r\n",
sd->http_ver,status,msg,content_type
);
sd->http_ver = 0; // 長さが分からないので、HTTP/1.0 扱い(自動切断)にする
} else {
len = sprintf(
head,
"HTTP/1.%d %d %s\r\nContent-Type: %s\r\nContent-Length: %d\r\n\r\n",
sd->http_ver,status,msg,content_type,content_len
);
}
memcpy(WFIFOP(sd->fd,0),head,len);
_WFIFOSET(sd->fd,len);
sd->status = HTTPD_SEND_HEADER;
sd->data_len = content_len;
}
void httpd_send_data (struct httpd_session_data* sd, int content_len, const void *data)
{
const char* msg = (const char*)data;
if (sd->status == HTTPD_REQUEST_OK) {
// ヘッダの送信忘れているので、適当に補う
httpd_send_head(sd,200,"application/octet-stream",-1);
} else if(sd->status != HTTPD_SEND_HEADER && sd->status != HTTPD_WAITING_SEND) {
return;
}
sd->data_len -= content_len;
// 巨大なサイズのファイルも送信出来るように分割して送る
while (content_len > 0) {
int send_byte = content_len;
if(send_byte > 12*1024) send_byte = 12*1024;
memcpy(WFIFOP(sd->fd,0),msg,send_byte);
_WFIFOSET(sd->fd,send_byte);
msg += send_byte; content_len -= send_byte;
}
sd->status = HTTPD_WAITING_SEND;
}
void httpd_send (struct httpd_session_data* sd, int status, const char *content_type, int content_len, const void *data)
{
httpd_send_head(sd,status,content_type,content_len);
httpd_send_data(sd,content_len,data);
}
void httpd_parse_header(struct httpd_session_data* sd);
void httpd_parse_request_ok(struct httpd_session_data *sd);
int httpd_parse (int fd)
{
struct httpd_session_data *sd = (struct httpd_session_data *)sessiond[fd]->session_data2;
if (sessiond[fd]->eof) {
delete_sessiond(fd);
return 0;
}
if (sd == NULL) {
sd = (struct httpd_session_data*) aMalloc (sizeof(struct httpd_session_data));
sd->fd = fd;
sessiond[fd]->session_data2 = sd;
sd->tick = gettick();
sd->persist = 0;
sd->request_count = 0;
}
printf ("status %d\n", sd->status);
switch(sd->status) {
case HTTPD_REQUEST_WAIT:
// リクエスト待ち
if(RFIFOREST(fd) > 1024) {
// リクエストが長すぎるので、エラー扱いする
sd->status = HTTPD_REQUEST_OK;
httpd_send_error(sd,400); // Bad Request
} else if( (int)( gettick() - sd->tick ) > request_timeout[sd->persist] ) {
// リクエストに時間がかかりすぎているので、エラー扱いする
sd->status = HTTPD_REQUEST_OK;
httpd_send_error(sd,408); // Request Timeout
} else if(sd->header_len == RFIFOREST(fd)) {
// 状態が以前と同じなので、リクエストを再解析する必要は無い
} else {
int limit = RFIFOREST(fd);
unsigned char *req = RFIFOP(fd,0);
sd->header_len = RFIFOREST(fd);
do {
if(*req == '\n' && limit > 0) {
limit--; req++;
if(*req == '\r' && limit > 0) { limit--; req++; }
if(*req == '\n') {
// HTTPヘッダの終点を見つけた
*req = 0;
sd->header_len = (req - RFIFOP(fd,0)) + 1;
httpd_parse_header(sd);
break;
}
}
} while(req++,--limit > 0);
}
break;
case HTTPD_REQUEST_WAIT_POST:
if(RFIFOREST(sd->fd) >= sd->header_len) {
unsigned char temp = RFIFOB(sd->fd,sd->header_len);
RFIFOB(sd->fd,sd->header_len) = 0;
httpd_parse_request_ok(sd);
RFIFOB(sd->fd,sd->header_len) = temp;
}
break;
case HTTPD_REQUEST_OK:
case HTTPD_SEND_HEADER:
// リクエストが終わったまま何も送信されていない状態なので、
// 強制切断
printf ("httpd: eof\n");
sessiond[fd]->eof = 1;
break;
case HTTPD_WAITING_SEND:
// データの送信が終わるまで待機
//if(sessiond[fd]->wdata_size == sessiond[fd]->wdata_pos) {
// i *hope* this is correct o.o;
if(sessiond[fd]->wdata_size == 0) {
// HTTP/1.0は手動切断
// if(sd->http_ver == 0) {
if(sd->persist == 0) {
printf ("httpd: eof\n");
sessiond[fd]->eof = 1;
}
// RFIFO からリクエストデータの消去と構造体の初期化
_RFIFOSKIP(fd,sd->header_len);
sd->status = HTTPD_REQUEST_WAIT;
sd->tick = gettick();
sd->header_len = 0;
sd->query = NULL;
// sd->http_ver = 0; // ver は保持
sd->method = HTTPD_METHOD_UNKNOWN;
printf("httpd_parse: [% 3d] request sended RFIFOREST:%d\n", fd, RFIFOREST(fd));
}
break;
}
return 0;
}
void httpd_parse_header_sub( struct httpd_session_data* sd, const char *p1, int* plen )
{
int len = 0;
// HTTPのバージョンを調査
if(!strncmp(p1 ,"HTTP/1.1",8)) {
sd->http_ver = 1;
sd->persist = 1;
} else {
sd->http_ver = 0;
sd->persist = 0;
}
p1 = strchr(p1,'\n');
while(p1) {
// Content-Length: の調査
if(!httpd_strcasencmp(p1+1,"Content-Length: ",16)) {
len = atoi(p1 + 17);
}
// Connection: の調査
if(!httpd_strcasencmp(p1+1,"Connection: ",12)) {
if( httpd_strcasencmp(p1+13,"close",5)==0 && sd->http_ver==1 )
sd->persist = 0;
if( httpd_strcasencmp(p1+13,"Keep-Alive",10)==0 && sd->http_ver==0 )
sd->persist = 1;
}
p1 = strchr(p1+1,'\n');
}
if(plen) *plen = len;
return;
}
void httpd_parse_header(struct httpd_session_data* sd)
{
int i;
int status = 400; // Bad Request
unsigned char* req = RFIFOP(sd->fd,0);
do {
if(!strncmp(req,"GET /",5)) {
// GET リクエスト
req += 5;
for(i = 0;req[i]; i++) {
if(req[i] == ' ' || req[i] == '?') break;
if(!isalnum(req[i]) && req[i] != '.' && req[i] != '_' && req[i] != '-') break;
}
if(req[i] == ' ') {
req[i] = 0;
sd->url = req;
sd->query = NULL;
sd->status = HTTPD_REQUEST_OK;
} else if(req[i] == '?') {
req[i] = 0;
sd->query = &req[++i];
for(;req[i];i++) {
if(
isalnum(req[i]) || req[i] == '+' || req[i] == '%' || req[i] == '&' ||
req[i] == '='
) {
continue;
} else {
break;
}
}
if(req[i] != ' ') {
break;
}
req[i] = 0;
sd->url = req;
} else {
break;
}
// ヘッダ解析
httpd_parse_header_sub( sd, &req[i+1], NULL );
printf("httpd: request %s %s\n", sd->url, sd->query);
sd->method = HTTPD_METHOD_GET;
httpd_parse_request_ok(sd);
} else if(!strncmp(req,"POST /",6)) {
int len;
req += 6; status = 404;
for(i = 0;req[i]; i++) {
if(req[i] == ' ') break;
if(!isalnum(req[i]) && req[i] != '.' && req[i] != '_' && req[i] != '-') break;
}
if(req[i] != ' ') {
break;
}
req[i] = 0;
sd->url = req;
// ヘッダ解析
httpd_parse_header_sub( sd, &req[i+1], &len );
if(len <= 0 || len >= 32*1024) {
// とりあえず32KB以上のリクエストは不正扱い
status = ( len==0 )? 411 : ( len>32*1024 )? 413 : 400;
break;
}
sd->query = RFIFOP(sd->fd,sd->header_len);
sd->method = HTTPD_METHOD_POST;
sd->header_len += len;
if(RFIFOREST(sd->fd) >= sd->header_len) {
unsigned char temp = RFIFOB(sd->fd,sd->header_len);
RFIFOB(sd->fd,sd->header_len) = 0;
httpd_parse_request_ok(sd);
RFIFOB(sd->fd,sd->header_len) = temp;
} else {
// POSTのデータが送られてくるのを待つ
sd->status = HTTPD_REQUEST_WAIT_POST;
}
} else {
break;
}
} while(0);
if(sd->status == HTTPD_REQUEST_WAIT) {
sd->status = HTTPD_REQUEST_OK;
httpd_send_error(sd,status);
}
}
void httpd_parse_request_ok (struct httpd_session_data *sd)
{
void (*httpd_parse_func)(struct httpd_session_data*,const char*);
sd->status = HTTPD_REQUEST_OK;
// ファイル名が求まったので、ページが無いか検索する
// printf("httpd_parse: [% 3d] request /%s\n", fd, req);
httpd_parse_func = strdb_get(httpd_files,(unsigned char*)sd->url);
if(httpd_parse_func == NULL) {
httpd_parse_func = httpd_default;
}
if(httpd_parse_func == NULL) {
httpd_send_error(sd,404); // Not Found
} else {
httpd_parse_func(sd,sd->url);
if(sd->status == HTTPD_REQUEST_OK) {
httpd_send_error(sd,404); // Not Found
}
}
if(sd->persist == 1 && sd->data_len) {
// 長さが変なデータ(こんなの送るなよ…)
printf("httpd_parse: send size mismatch when parsing /%s\n", sd->url);
sessiond[sd->fd]->eof = 1;
}
if(sd->status == HTTPD_REQUEST_OK) {
httpd_send_error(sd,404);
}
}
char* httpd_get_value(struct httpd_session_data* sd,const char* val)
{
int src_len = strlen(val);
const unsigned char* src_p = sd->query;
if(src_p == NULL) return aStrdup("");
do {
if(!memcmp(src_p,val,src_len) && src_p[src_len] == '=') {
break;
}
src_p = strchr(src_p + 1,'&');
if(src_p) src_p++;
} while(src_p);
if(src_p != NULL) {
// 目的の文字列を見つけた
const unsigned char* p2;
int dest_len;
char* dest_p;
src_p += src_len + 1;
p2 = strchr(src_p,'&');
if(p2 == NULL) {
src_len = strlen(src_p);
} else {
src_len = (p2 - src_p);
}
dest_p = aMalloc(src_len + 1);
dest_len = 0;
while(src_len > 0) {
if(*src_p == '%' && src_len > 2) {
int c1 = 0,c2 = 0;
if(src_p[1] >= '0' && src_p[1] <= '9') c1 = src_p[1] - '0';
if(src_p[1] >= 'A' && src_p[1] <= 'F') c1 = src_p[1] - 'A' + 10;
if(src_p[1] >= 'a' && src_p[1] <= 'f') c1 = src_p[1] - 'a' + 10;
if(src_p[2] >= '0' && src_p[2] <= '9') c2 = src_p[2] - '0';
if(src_p[2] >= 'A' && src_p[2] <= 'F') c2 = src_p[2] - 'A' + 10;
if(src_p[2] >= 'a' && src_p[2] <= 'f') c2 = src_p[2] - 'a' + 10;
dest_p[dest_len++] = (c1 << 4) | c2;
src_p += 3; src_len -= 3;
} else if(*src_p == '+') {
dest_p[dest_len++] = ' ';
src_p++; src_len--;
} else {
dest_p[dest_len++] = *(src_p++); src_len--;
}
}
dest_p[dest_len] = 0;
return dest_p;
}
return aStrdup("");
}
// MIMEタイプ判定。主要なものだけ判定して、残りはapplication/octet-stream
static const char* httpd_mimetype(const char* url)
{
char *ext = strrchr(url,'.');
if(ext) {
if(!strcmp(ext,".html")) return "text/html";
if(!strcmp(ext,".htm")) return "text/html";
if(!strcmp(ext,".css")) return "text/css";
if(!strcmp(ext,".js")) return "text/javascript";
if(!strcmp(ext,".txt")) return "text/plain";
if(!strcmp(ext,".gif")) return "image/gif";
if(!strcmp(ext,".jpg")) return "image/jpeg";
if(!strcmp(ext,".jpeg")) return "image/jpeg";
if(!strcmp(ext,".png")) return "image/png";
if(!strcmp(ext,".xbm")) return "image/xbm";
if(!strcmp(ext,".zip")) return "application/zip";
}
return "application/octet-stream";
}
void httpd_send_file(struct httpd_session_data* sd, const char* url)
{
FILE *fp;
int file_size;
char file_buf[8192];
if(sd->status != HTTPD_REQUEST_OK) return;
if(url[0] == '\0') url = "index.html";
// url の最大長は約1010バイトなので、バッファオーバーフローの心配は無し
sprintf(file_buf, "%s%s", document_root, url);
fp = fopen(file_buf,"rb");
if(fp == NULL) {
httpd_send_error(sd,404);
} else {
fseek(fp,0,SEEK_END);
file_size = ftell(fp);
fseek(fp,0,SEEK_SET);
httpd_send_head(sd,200,httpd_mimetype(url),file_size);
while(file_size > 0) {
int read_byte = file_size;
if(file_size > 8192) read_byte = 8192;
fread(file_buf,1,read_byte,fp);
httpd_send_data(sd,read_byte,file_buf);
file_size -= read_byte;
}
fclose(fp);
}
}
char* httpd_binary_encode(const char* val)
{
char *buf = aMalloc(strlen(val) * 3 + 1);
char *p = buf;
while(*val) {
if(isalnum((unsigned char)*val)) {
*(p++) = *(val++);
} else {
unsigned char c1 = *(val++);
unsigned char c2 = (c1 >> 4);
unsigned char c3 = (c1 & 0x0F);
*(p++) = '%';
*(p++) = c2 + (c2 >= 10 ? 'A'-10 : '0');
*(p++) = c3 + (c3 >= 10 ? 'A'-10 : '0');
}
}
*p = 0;
return buf;
}
char* httpd_quote_meta(const char* p1)
{
char *buf = aMalloc(strlen(p1) * 6 + 1);
char *p2 = buf;
while(*p1) {
switch(*p1) {
case '<': memcpy(p2,"&lt;",4); p2 += 4; p1++; break;
case '>': memcpy(p2,"&gt;",4); p2 += 4; p1++; break;
case '&': memcpy(p2,"&amp;",5); p2 += 5; p1++; break;
case '"': memcpy(p2,"&quot;",6); p2 += 6; p1++; break;
default: *(p2++) = *(p1++);
}
}
*p2 = 0;
return buf;
}
///////// Graph / HTML snippets functions /////////////////////////////
struct file_entry {
char *filename;
struct file_entry *next;
};
struct file_entry *fileentry_head = NULL;
static void httpd_graph_load (const char *filename)
{
struct file_entry *entry;
char type = *server_type + 'a';
int len = strlen(filename);
if (len <= 7 || filename[len - 7] != type)
return;
entry = fileentry_head;
while (entry) {
if (strcmpi(entry->filename, filename) == 0)
return;
entry = entry->next;
}
entry = (struct file_entry *) aMalloc (sizeof(struct file_entry));
entry->filename = aStrdup(filename);
entry->next = fileentry_head;
fileentry_head = entry;
}
// scan for available html snippets
static int httpd_graph_find (int tid, unsigned int tick, int id, int data)
{
findfile("httpd", ".graph", httpd_graph_load);
return 0;
}
static void httpd_graph_parse (struct httpd_session_data *sd,const char* url)
{
// output html
struct file_entry *entry = fileentry_head;
char buf[8192];
char *p = buf;
FILE *fp;
p += sprintf(p,"<html><head><title>Athena Sensors</title></head>\n\n<body>\n");
p += sprintf(p,"<h1>Athena Sensors</h1>\n\n");
while (entry) {
// insert snippets into html
char line[1024];
fp = fopen(entry->filename, "r");
if (fp == NULL) {
entry = entry->next;
continue;
}
while(fgets(line, sizeof(line) -1, fp))
p += sprintf(p, line);
fclose(fp);
entry = entry->next;
}
p += sprintf(p,"</body></html>\n");
httpd_send(sd,200,"text/html",p - buf,buf);
}
//////////////// Initialise / Finalise /////////////////////////////
void do_final (void)
{
int fd;
struct file_entry *entry = fileentry_head, *entry2;
// clear up graph entries
while (entry) {
entry2 = entry->next;
aFree(entry->filename);
aFree(entry);
entry = entry2;
}
// clear up existing http connections
for (fd = 0; fd < *max_fd; fd++)
if (sessiond[fd] && sessiond[fd]->type == SESSION_HTTP)
delete_sessiond(fd);
httpd_files->destroy(httpd_files,NULL);
// clear up the database
db_final();
// clear up allocated memory
// note: the memory manager, if enabled, would be
// separate from the parent program, which is also
// why we need to delete our http sessions
// separately above
malloc_final();
}
void do_init (void)
{
struct func_parse_table *parse_table;
int enable_httpd = 1;
do {
char line[1024], w1[1024], w2[1024];
FILE *fp = fopen("plugins/httpd.conf","r");
if (fp == NULL)
break;
while(fgets(line, sizeof(line) -1, fp)) {
if (line[0] == '/' && line[1] == '/')
continue;
if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2) {
if(strcmpi(w1,"enable_httpd")==0){
enable_httpd = atoi(w2);
} else if(strcmpi(w1,"document_root")==0){
strcpy(document_root, w2);
} else if(strcmpi(w1,"request_timeout_first")==0){
request_timeout[0] = atoi(w2);
} else if(strcmpi(w1,"request_timeout_persist")==0){
request_timeout[1] = atoi(w2);
} else if(strcmpi(w1,"max_persist_request")==0){
max_persist_requests = atoi(w2);
}
}
}
fclose(fp);
} while (0);
if (!enable_httpd)
return;
malloc_init();
db_init();
IMPORT_SYMBOL(server_type, 0);
IMPORT_SYMBOL(gettick, 5);
IMPORT_SYMBOL(add_timer_interval, 8);
IMPORT_SYMBOL(max_fd, 13);
IMPORT_SYMBOL(sessiond, 14);
IMPORT_SYMBOL(delete_sessiond, 15);
IMPORT_SYMBOL(_WFIFOSET, 16);
IMPORT_SYMBOL(_RFIFOSKIP, 17);
IMPORT_SYMBOL(parse_table, 18);
// register http parsing function
parse_table[SESSION_HTTP].check = httpd_check;
parse_table[SESSION_HTTP].func = httpd_parse;
httpd_files = db_alloc(__FILE__,__LINE__,DB_STRING,DB_OPT_RELEASE_KEY,50);
httpd_default = httpd_send_file;
httpd_pages ("/graph", httpd_graph_parse);
add_timer_interval(gettick()+10000,httpd_graph_find,0,0,10000);
return;
}

View File

@ -1,107 +0,0 @@
#ifndef _HTTPD_H_
#define _HTTPD_H_
struct httpd_session_data;
// NOTE by Celest: This file is not used by httpd.c, but included only as an API reference.
// 注意
// 1.athena内蔵のhttpd で大きなファイルを送信することはお勧めしません。
// 200KB を超えるようなファイルは、別のソフトを利用することを勧めます。
// 2.ファイル名に使える文字は、[A-Za-z0-9-_\.] です。他の文字を使うと、
// BAD REQUEST で弾かれます。
void httpd_pages(const char* url,void(*httpd_func)(struct httpd_session_data* sd,const char* url));
// 指定されたURL に対するコールバック関数を設定する。この関数は、以下のように
// 実装する必要がある。
//
// 1. URL は、先頭のスラッシュが省かれたファイル名です。例えば、"GET / HTTP/1.0"
// という風にリクエストされた時、URL には""(空文字)が入り、"GET /hoge HTTP/1.0"
// の時には、"hoge"が入ります。
// 2. リクエストされたページが見つかったら、httpd_send() または、httpd_send_head()
// とhttpd_send_data() の組を呼び出し、データを出力する。
// 3. httpd_send_file を指定すると、httpd/ 以下にあるファイルを出力する。ファイルに
// 空文字が指定された時は、index.htmlが指定されたものとみなされる。
char* httpd_get_value(struct httpd_session_data* sd,const char* val);
// リクエストされたアドレスに渡されたフォームデータのうち、該当する文字列を返す。
// 例えば、"GET /status/graph?image=users HTTP/1.0"というリクエストの場合、
// httpd_get_value(sd,"image"); は、 "users"を返す。この関数の戻り値は、呼び出し元が
// 解放しなければならない。また、該当する文字列が無い時は、空の文字列を返す。
unsigned int httpd_get_ip(struct httpd_session_data *sd);
// クライアントのIPを返す。
void httpd_default_page(void(*httpd_func)(struct httpd_session_data* sd,const char* url));
// 指定されたURL が登録されていない時に呼び出す関数を設定する。この関数を呼び出さないか、
// 関数の引数にNULLを指定すると、404 Not Found を返す。
void httpd_send(struct httpd_session_data* sd,int status,const char *content_type,int content_len,const void *data);
// HTTPヘッダ、データを組にして送信する。この関数を呼び出した後に、httpd_send_data を
// 呼び出してはならない。
//
// sd : httpd_set_parse_func() に渡されたものをそのまま渡すこと。
// status : HTTPヘッダに加えるstatus。通常は200。
// content_type : 送信するデータのタイプ。text/html , image/jpeg など。
// content_len : 送信するデータの長さ。
// data : 送信するデータへのポインタ
void httpd_send_head(struct httpd_session_data* sd,int status,const char *content_type,int content_len);
// HTTPヘッダを送信する。
//
// sd : 同上
// status : 同上
// content_type : 同上
// content_len : content_lenを-1に指定することで、この関数が呼ばれた時点で
// 長さが分からないデータを送信することができる。この場合は
// 強制的にHTTP/1.0 接続となり、オーバーヘッドが大きくなるので、
// あまりお勧めはしない。
void httpd_send_data(struct httpd_session_data* sd,int content_len,const void *data);
// データを送信する。この関数を、httpd_send_head() を呼び出す前に呼び出された場合、
// content_type = application/octet-stream, content_len = -1 としてヘッダが送信される。
// sd : 同上
// content_len : 送信するデータのdata長さを指定する。
// data : 送信するデータ
void httpd_send_file(struct httpd_session_data* sd,const char* url);
// ファイルを送信する。この関数は、httpd_send_head() を呼び出す前に呼び出さなければ
// ならない。ファイルに空文字が指定されたときは、index.htmlが指定されたと見なされる。
void httpd_send_error(struct httpd_session_data* sd,int status);
// HTTPエラーメッセージを送信する。status はHTTPのエラーコードと同じ。
// 400 Bad Request, 404 Not Found, 500 Internal Server Error など。
int httpd_parse(int fd);
// 初期化処理
void do_init_httpd(void);
void do_final_httpd(void);
#endif

View File

@ -1,20 +0,0 @@
//
// HTTP Daemon Plugin Configuration
//
// Enabled the http daemon?
enable_httpd: 1
// WWW Root path
//(The ending slash is required!)
document_root: httpd/
// Request timeout (first request)
// Both of the following are in milliseconds
request_timeout_first: 2500
// Request timeout (consequent requests)
request_timeout_persist: 60000
// Maximum persistent requests
max_persist_request: 32

View File

@ -1,20 +0,0 @@
all:
#Generate framework...
$(CC) -c parse.c
$(CC) -c generate.c
$(CC) -c htmlstyle.c
$(CC) -c logs.c
#Generate "pages"...
cd pages && $(CC) -c about.c && cd ..
cd pages && $(CC) -c sample.c && cd ..
cd pages && $(CC) -c notdone.c && cd ..
#Building the server...
$(CC) -o webserver main.c parse.o generate.o htmlstyle.o \
logs.o pages/about.o pages/sample.o pages/notdone.o
clean:
rm -f *.o
rm -f pages/*.o
rm -f webserver

View File

@ -1,50 +0,0 @@
Here's the webserver API, so you can work on the webserver.
My personal goal is to make this interface simple, so that coding it
will be like coding in some scripting language...
char *get_param(char in_string[500], char swhat[500]);
This function simply returns various data from the query string.
*Pass get_param NOTHING longer than 500 in length!
What do I pass where in_string is?
The query string.
What do I pass where swhat is?
One of two things...
Either 0 for the path of the 'page'
or you can pass it the param you wish to lookup.
char *get_query(char *inquery);
This function simply returns a query string from the raw server request.
This is used once in main, I doubt you'll need it.
void web_send(int sockin, char *in_data);
Super easy way of sending data to a webpage!
Simply put in the socket name and then the data.
Ex:
web_send(socket, "I like cheese!\n");
char *html_header(char* title);
Easy way to print the eAthena header for the server.
Ex:
web_send(sockethere, html_header("About"));

View File

@ -1,11 +0,0 @@
This readme is intended for the programmers of eAthena.
This webserver's apis are in API.txt.
To make this simple, generate.c should handle most of the work this sever does
in terms of what people see.
When a request is made the server shoots it off to generate.c.
You are welcome to create more functions used by generate.c to generate pages
though, so don't feel limited by that one file.

View File

@ -1,38 +0,0 @@
void generate_page(char password[25], int sock_in, char *query, char *ip)
{
char *page = get_param(query, 0);
char *ppass = get_param(query, "password");
if ( (ppass == 0) || (strcmp(password, ppass) != 0) )
{
web_send(sock_in, html_header("Enter your password"));
web_send(sock_in, "<H1>NOT LOGGED IN!</H1><form action=\"/\" method=\"GET\">\n");
web_send(sock_in, "Enter your password:<br>\n<input type=\"text\" name=\"password\">\n");
web_send(sock_in, "<input type=\"submit\" value=\"Login\">\n");
}
else
{
//To make this simple, we will have a bunch of if statements
//that then shoot out data off into functions.
//The 'index'
if ( strcmp(page, "/") == 0 )
generate_notdone(sock_in, query, ip);
//About page:
if ( strcmp(page, "/about.html") == 0 )
generate_about(sock_in, query, ip);
//Test page:
if ( strcmp(page, "/testing/") == 0 )
generate_sample(sock_in, query, ip);
}
}

View File

@ -1,51 +0,0 @@
char output[10000];
char *html_header(char *title)
{
memset(output, 0x0, 10000);
char *text = "<body text=\"#000000\" bgcolor=\"#939393\" link=\"#0033FF\">\n"
"<br><table width=\"92%\" cellspacing=\"1\" cellpadding=\"0\" border=\"0\"\n"
"align=\"center\" class=\"bordercolor\"><tbody><tr><td class=\"bordercolor\" width=\"100%\">\n"
"<table bgcolor=\"#ffffff\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\">\n"
"<tbody><tr><td><table border=\"0\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" bgcolor=\"#ffffff\">\n"
"<tbody><tr><img src=\"http://eathena.sourceforge.net/athena.jpg\" alt=\"Athena\">\n"
"<td bgcolor=\"#ffffff\"></td></tr></tbody></table></td></tr></tbody></table>\n"
"</td></tr><tr align=\"left\"><td class=\"bordercolor\"><table bgcolor=\"#c6c6c6\" width=\"100%\" cellspacing=\"0\"\n"
"cellpadding=\"0\" style=\"text-align: left; margin-right: auto; margin-left: 0px;\">\n";
"<tbody><tr><td width=\"100%\" align=\"center\"><table border=\"0\" width=\"100%\" cellpadding=\"3\"\n"
"cellspacing=\"0\" bgcolor=\"#c6c6c6\" align=\"center\"><tbody><tr>"
"<td valign=\"middle\" bgcolor=\"#c6c6c6\" align=\"center\"><a href=\"/cgi-bin/forum/YaBB.cgi\">"
"<span style=\"text-decoration: underline;\"><span style=\"font-weight: bold;\">\n"
"To the Forum</span></span></a><br></td></tr></tbody></table></td></tr></tbody>\n"
"</table></td></tr><tr><td class=\"bordercolor\" align=\"center\">\n"
"<table bgcolor=\"#ffffff\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n"
"<tbody><tr><td width=\"100%\" align=\"center\"><table border=\"0\" width=\"100%\" cellpadding=\"5\"\n"
"cellspacing=\"0\" bgcolor=\"#ffffff\" align=\"center\"><tbody><tr>\n"
"<td valign=\"middle\" bgcolor=\"#ffffff\" align=\"center\"><font size=\"2\" color=\"#6e94b7\">\n"
"<b>Athena</b> &laquo; Portal &raquo;</font></td></tr></tbody></table></td></tr></tbody>"
"</table></td></tr></tbody></table>\n";
sprintf(output, "<title>%s</title>\n%s\n", title, text);
return output;
}
char *html_start_form(char *location, char *action)
{
memset(output, 0x0, 10000);
sprintf(output, "<form action=\"%s\" method=\"%s\">", location, action);
return output;
}
char *html_end_forum(void)
{
return "</form>";
}

View File

@ -1,8 +0,0 @@
#include <time.h>
void log_visit(char *query, char *ip)
{
time_t timer;
timer=time(NULL);
printf("%s - \"%s\" - %s", ip, query, asctime(localtime(&timer)));
}

View File

@ -1,142 +0,0 @@
/***************************************************************************
description
-------------------
author : (C) 2004 by Michael J. Flickinger
email : mjflick@cpan.org
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#define BLOG 10
char *header = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n";
char recvin[500], password[25];
int s_port;
void sigchld_handler(int s)
{
while(wait(NULL) > 0);
}
int main(int argc, char **argv)
{
if (argc < 3)
{
printf("eAthena Web Server\n");
printf("usage: %s [password] [port]\n", argv[0]);
exit(0);
}
s_port = atoi(argv[2]);
if ((s_port < 1) || (s_port > 65534))
{
printf("Error: The port you choose is not valid port.\n");
exit(0);
}
if (strlen(argv[1]) > 25)
{
printf("Error: Your password is too long.\n");
printf("It must be shorter than 25 characters.\n");
exit(0);
}
memset(password, 0x0, 25);
memcpy(password, argv[1], strlen(argv[1]));
int sockfd, new_fd;
struct sockaddr_in my_addr;
struct sockaddr_in their_addr;
int sin_size;
struct sigaction sa;
int yes=1;
if ((sockfd = socket(AF_INET, SOCK_STREAM,0)) == -1)
{
perror("Darn, this is broken.");
exit(0);
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
{
perror("Error... :-(");
}
//Now we know we have a working socket. :-)
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(s_port);
my_addr.sin_addr.s_addr = INADDR_ANY;
memset(&(my_addr.sin_zero), '\0', 8);
if ( bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
{
perror("can not bind to this port");
exit(0);
}
if ( listen(sockfd, BLOG) == -1)
{
perror("can not listen on port");
exit(0);
}
sa.sa_handler = sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1)
{
perror("sigaction sucks");
exit(0);
}
printf("The eAthena webserver is up and listening on port %i.\n", s_port);
while(1)
{
sin_size = sizeof(struct sockaddr_in);
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (!fork())
{
close(sockfd);
memset(recvin, 0x0, 500);
recv(new_fd, recvin, 500, 0);
send(new_fd, header, strlen(header), 0);
generate_page(password, new_fd, get_query(recvin), inet_ntoa(their_addr.sin_addr));
log_visit(get_query(recvin), inet_ntoa(their_addr.sin_addr));
close(new_fd);
exit(0);
}
close(new_fd);
}
return 0;
}

View File

@ -1,6 +0,0 @@
void generate_about(int sock_in, char *query, char *ip)
{
//printf("%s", html_header("About"));
web_send(sock_in, html_header("About"));
web_send(sock_in, "<center>eAthena Web Server!</center>\n");
}

View File

@ -1,5 +0,0 @@
void generate_notdone(int sock_in, char *query, char *ip)
{
web_send(sock_in, "<title>Not here!</title>\n");
web_send(sock_in, "<h2><center>This page/feature is not done yet.</center>\n</h2>");
}

View File

@ -1,24 +0,0 @@
void generate_sample(int sock_in, char *query, char *ip)
{
char *name = get_param(query, "name");
web_send(sock_in, "<title>SAMPLE</title>\n");
//If a name was not entered...
if ( name == '\0' )
{
web_send(sock_in, "<form action=\"/testing/\" method=\"GET\">\n");
web_send(sock_in, "<input type=\"text\" name=\"name\">\n");
web_send(sock_in, "<input type=\"submit\">\n");
}
else
{
web_send(sock_in, "Your name is: ");
web_send(sock_in, get_param(query, "name"));
}
printf("OK!\n");
}

View File

@ -1,135 +0,0 @@
#include <stdlib.h>
char filtered_query[2000];
char rdata[500];
char param_n[500];
char param_d[500];
char *get_query(char *inquery)
{
memset(filtered_query, 0x0, 2000);
sscanf(inquery, "GET %s %[$]", filtered_query);
return(filtered_query);
}
void web_send(int sockin, char *in_data)
{
send(sockin, in_data, strlen(in_data), 0);
}
//THIS IS BAD CODE BE CAREFULL WITH IT!
//Watch out for buffer overflow...
//When using please make sure to check the string size.
//Also note:
//I take no pride in this code, it is a really bad way of doing this...
char *get_param(char in_string[500], char swhat[500])
{
int i = 0;
int marker, iswitch, pint, dint;
char flux[500];
memset(flux, 0x0, 500);
//Get the path of out "page"
if (swhat == 0)
{
//while i is not equal to array size
while (i != 500)
{
//if there is a question mark, halt!
if (in_string[i] == '?')
{
i = 499;
}
else
rdata[i] = in_string[i];
i++;
}
return rdata;
}
else //so, we want a param...
{
//calculate where param begins
while (i != 500)
{
if (in_string[i] == '?')
{
marker = i + 1;
i = 499;
}
i++;
}
i = 0;
//keep morons from trying to crash this
if ((marker > 500)||(marker < 1))
marker = 500;
while(marker != 500)
{
if ((in_string[marker] != '&') && (in_string[marker] != '\0'))
{
flux[i] = in_string[marker];
i++;
}
else
{
//we have a param, now we must dig through it
//clear temp vars
memset(param_n, 0x0, 500);
memset(param_d, 0x0, 500);
iswitch = 0;
pint = 0;
dint = 0;
i = 0;
//split result into param_n and param_d
while(i != 500)
{
if ( (flux[i] != '=') && (flux[i] != '\0') )
{
if (iswitch == 0)
{
param_n[pint] = flux[i];
pint++;
}
else
{
param_d[dint] = flux[i];
dint++;
}
}
else
{
iswitch = 1;
}
if (flux[i] == '\0')
i = 499;
i++;
}
if ( strcmp(param_n, swhat) == 0 )
{
return param_d;
}
i = 0;
}
if (in_string[marker] == '\0')
{
marker = 499;
}
marker++;
}
return 0;
}
}

View File

@ -82,14 +82,6 @@ SOURCE=..\..\src\common\ers.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.c
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\grfio.c
# End Source File
# Begin Source File

View File

@ -83,14 +83,6 @@ SOURCE=..\..\src\common\ers.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.c
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\grfio.c
# End Source File
# Begin Source File

View File

@ -83,14 +83,6 @@ SOURCE=..\..\src\common\ers.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.c
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\grfio.c
# End Source File
# Begin Source File

View File

@ -83,14 +83,6 @@ SOURCE=..\..\src\common\ers.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.c
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\grfio.c
# End Source File
# Begin Source File

View File

@ -83,14 +83,6 @@ SOURCE=..\..\src\common\ers.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.c
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\grfio.c
# End Source File
# Begin Source File

View File

@ -84,14 +84,6 @@ SOURCE=..\..\src\common\ers.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.c
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\grfio.c
# End Source File
# Begin Source File

View File

@ -83,14 +83,6 @@ SOURCE=..\..\src\common\ers.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.c
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\grfio.c
# End Source File
# Begin Source File

View File

@ -83,14 +83,6 @@ SOURCE=..\..\src\common\ers.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.c
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\grfio.c
# End Source File
# Begin Source File

View File

@ -82,14 +82,6 @@ SOURCE=..\..\src\common\ers.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.c
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\grfio.c
# End Source File
# Begin Source File

View File

@ -83,14 +83,6 @@ SOURCE=..\..\src\common\ers.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.c
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\grfio.c
# End Source File
# Begin Source File

View File

@ -82,14 +82,6 @@ SOURCE=..\..\src\common\ers.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.c
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\grfio.c
# End Source File
# Begin Source File

View File

@ -83,14 +83,6 @@ SOURCE=..\..\src\common\ers.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.c
# End Source File
# Begin Source File
SOURCE=..\..\src\common\graph.h
# End Source File
# Begin Source File
SOURCE=..\..\src\common\grfio.c
# End Source File
# Begin Source File

View File

@ -151,9 +151,6 @@
<File
RelativePath="..\src\common\ers.c">
</File>
<File
RelativePath="..\src\common\graph.c">
</File>
<File
RelativePath="..\src\common\grfio.c">
</File>
@ -236,9 +233,6 @@
<File
RelativePath="..\src\common\db.h">
</File>
<File
RelativePath="..\src\common\graph.h">
</File>
<File
RelativePath="..\src\common\grfio.h">
</File>

View File

@ -149,9 +149,6 @@
<File
RelativePath="..\src\common\ers.c">
</File>
<File
RelativePath="..\src\common\graph.c">
</File>
<File
RelativePath="..\src\common\grfio.c">
</File>
@ -228,9 +225,6 @@
<File
RelativePath="..\src\common\db.h">
</File>
<File
RelativePath="..\src\common\graph.h">
</File>
<File
RelativePath="..\src\common\grfio.h">
</File>

View File

@ -150,9 +150,6 @@
<File
RelativePath="..\src\common\ers.c">
</File>
<File
RelativePath="..\src\common\graph.c">
</File>
<File
RelativePath="..\src\common\grfio.c">
</File>
@ -208,9 +205,6 @@
<File
RelativePath="..\src\common\db.h">
</File>
<File
RelativePath="..\src\common\graph.h">
</File>
<File
RelativePath="..\src\common\grfio.h">
</File>

View File

@ -152,9 +152,6 @@
<File
RelativePath="..\src\common\ers.c">
</File>
<File
RelativePath="..\src\common\graph.c">
</File>
<File
RelativePath="..\src\common\grfio.c">
</File>
@ -210,9 +207,6 @@
<File
RelativePath="..\src\common\db.h">
</File>
<File
RelativePath="..\src\common\graph.h">
</File>
<File
RelativePath="..\src\common\grfio.h">
</File>

View File

@ -173,9 +173,6 @@
<File
RelativePath="..\src\common\ers.c">
</File>
<File
RelativePath="..\src\common\graph.c">
</File>
<File
RelativePath="..\src\common\grfio.c">
</File>
@ -324,9 +321,6 @@
<File
RelativePath="..\src\common\ers.h">
</File>
<File
RelativePath="..\src\common\graph.h">
</File>
<File
RelativePath="..\src\common\grfio.h">
</File>

View File

@ -174,9 +174,6 @@
<File
RelativePath="..\src\common\ers.c">
</File>
<File
RelativePath="..\src\common\graph.c">
</File>
<File
RelativePath="..\src\common\grfio.c">
</File>
@ -325,9 +322,6 @@
<File
RelativePath="..\src\common\ers.h">
</File>
<File
RelativePath="..\src\common\graph.h">
</File>
<File
RelativePath="..\src\common\grfio.h">
</File>

View File

@ -219,10 +219,6 @@
RelativePath="..\src\common\ers.c"
>
</File>
<File
RelativePath="..\src\common\graph.c"
>
</File>
<File
RelativePath="..\src\common\grfio.c"
>
@ -323,10 +319,6 @@
RelativePath="..\src\common\db.h"
>
</File>
<File
RelativePath="..\src\common\graph.h"
>
</File>
<File
RelativePath="..\src\common\grfio.h"
>

View File

@ -218,10 +218,6 @@
RelativePath="..\src\common\ers.c"
>
</File>
<File
RelativePath="..\src\common\graph.c"
>
</File>
<File
RelativePath="..\src\common\grfio.c"
>
@ -322,10 +318,6 @@
RelativePath="..\src\common\db.h"
>
</File>
<File
RelativePath="..\src\common\graph.h"
>
</File>
<File
RelativePath="..\src\common\grfio.h"
>

View File

@ -212,10 +212,6 @@
RelativePath="..\src\common\ers.c"
>
</File>
<File
RelativePath="..\src\common\graph.c"
>
</File>
<File
RelativePath="..\src\common\grfio.c"
>
@ -288,10 +284,6 @@
RelativePath="..\src\common\db.h"
>
</File>
<File
RelativePath="..\src\common\graph.h"
>
</File>
<File
RelativePath="..\src\common\grfio.h"
>

View File

@ -219,10 +219,6 @@
RelativePath="..\src\common\ers.c"
>
</File>
<File
RelativePath="..\src\common\graph.c"
>
</File>
<File
RelativePath="..\src\common\grfio.c"
>
@ -295,10 +291,6 @@
RelativePath="..\src\common\db.h"
>
</File>
<File
RelativePath="..\src\common\graph.h"
>
</File>
<File
RelativePath="..\src\common\grfio.h"
>

View File

@ -245,10 +245,6 @@
RelativePath="..\src\common\ers.c"
>
</File>
<File
RelativePath="..\src\common\graph.c"
>
</File>
<File
RelativePath="..\src\common\grfio.c"
>
@ -445,10 +441,6 @@
RelativePath="..\src\common\ers.h"
>
</File>
<File
RelativePath="..\src\common\graph.h"
>
</File>
<File
RelativePath="..\src\common\grfio.h"
>

View File

@ -247,10 +247,6 @@
RelativePath="..\src\common\ers.c"
>
</File>
<File
RelativePath="..\src\common\graph.c"
>
</File>
<File
RelativePath="..\src\common\grfio.c"
>
@ -447,10 +443,6 @@
RelativePath="..\src\common\ers.h"
>
</File>
<File
RelativePath="..\src\common\graph.h"
>
</File>
<File
RelativePath="..\src\common\grfio.h"
>