Browse Source

moved external functions to *-glue.c

this simplifies the linkage on windows and macosx
which can't reference the binary for symbols


git-svn-id: svn://svn.lighttpd.net/lighttpd/trunk@49 152afb58-edef-0310-8abb-c4023f1b3aa9
svn/tags/release-1.3.12
Jan Kneschke 17 years ago
parent
commit
d26f6893d9
  1. 5
      src/.cvsignore
  2. 17
      src/Makefile.am
  3. 197
      src/config.c
  4. 216
      src/configfile-glue.c
  5. 44
      src/connections-glue.c
  6. 42
      src/connections.c
  7. 136
      src/http-header-glue.c
  8. 128
      src/response.c

5
src/.cvsignore

@ -1,9 +1,10 @@
lemon
lighttpd
Makefile.in
Makefile
spawn-fcgi
chunk
lemon
lighttpd
*.exe
.deps
.libs
array

17
src/Makefile.am

@ -28,21 +28,26 @@ config.c: configparser.h
mod_ssi_expr.c: mod_ssi_exprparser.h
common_src=buffer.c log.c \
keyvalue.c response.c request.c chunk.c \
http_chunk.c stream.c fdevent.c connections.c \
keyvalue.c chunk.c \
http_chunk.c stream.c fdevent.c \
file_cache.c plugin.c joblist.c etag.c array.c \
data_string.c data_count.c data_array.c \
data_integer.c md5.c data_fastcgi.c \
fdevent_select.c fdevent_linux_rtsig.c \
fdevent_poll.c fdevent_linux_sysepoll.c \
fdevent_solaris_devpoll.c fdevent_freebsd_kqueue.c \
data_config.c bitset.c configparser.c \
inet_ntop_cache.c \
connections-glue.c \
configfile-glue.c \
http-header-glue.c
src = server.c response.c connections.c network.c \
network_write.c network_linux_sendfile.c \
network_freebsd_sendfile.c network_writev.c \
network_solaris_sendfilev.c network_openssl.c \
data_config.c bitset.c configparser.c config.c \
inet_ntop_cache.c network.c
src = server.c
config.c request.c
spawn_fcgi_SOURCES=spawn-fcgi.c

197
src/config.c

@ -20,136 +20,6 @@
#include "configparser.h"
#include "configfile.h"
/* handle global options */
int config_insert_values_global(server *srv, array *ca, const config_values_t cv[]) {
size_t i;
data_unset *du;
for (i = 0; cv[i].key; i++) {
data_string *touched;
if (NULL == (du = array_get_element(ca, cv[i].key))) {
/* no found */
continue;
}
/* touched */
touched = data_string_init();
buffer_copy_string(touched->value, "");
buffer_copy_string_buffer(touched->key, du->key);
array_insert_unique(srv->config_touched, (data_unset *)touched);
}
return config_insert_values_internal(srv, ca, cv);
}
/* parse config array */
int config_insert_values_internal(server *srv, array *ca, const config_values_t cv[]) {
size_t i;
data_unset *du;
for (i = 0; cv[i].key; i++) {
if (NULL == (du = array_get_element(ca, cv[i].key))) {
/* no found */
continue;
}
switch (cv[i].type) {
case T_CONFIG_ARRAY:
if (du->type == TYPE_ARRAY) {
size_t j;
data_array *da = (data_array *)du;
for (j = 0; j < da->value->used; j++) {
if (da->value->data[j]->type == TYPE_STRING) {
data_string *ds = data_string_init();
buffer_copy_string_buffer(ds->value, ((data_string *)(da->value->data[j]))->value);
buffer_copy_string_buffer(ds->key, ((data_string *)(da->value->data[j]))->key);
array_insert_unique(cv[i].destination, (data_unset *)ds);
} else {
log_error_write(srv, __FILE__, __LINE__, "sssbs", "unexpected type for key: ", cv[i].key, "[", da->value->data[i]->key, "](string)");
return -1;
}
}
} else {
log_error_write(srv, __FILE__, __LINE__, "sss", "unexpected type for key: ", cv[i].key, "array of strings");
return -1;
}
break;
case T_CONFIG_STRING:
if (du->type == TYPE_STRING) {
data_string *ds = (data_string *)du;
buffer_copy_string_buffer(cv[i].destination, ds->value);
} else {
log_error_write(srv, __FILE__, __LINE__, "ssss", "unexpected type for key: ", cv[i].key, "(string)", "\"...\"");
return -1;
}
break;
case T_CONFIG_SHORT:
switch(du->type) {
case TYPE_INTEGER: {
data_integer *di = (data_integer *)du;
*((unsigned short *)(cv[i].destination)) = di->value;
break;
}
case TYPE_STRING: {
data_string *ds = (data_string *)du;
log_error_write(srv, __FILE__, __LINE__, "ssbss", "unexpected type for key: ", cv[i].key, ds->value, "(short)", "0 ... 65535");
return -1;
}
default:
log_error_write(srv, __FILE__, __LINE__, "ssdss", "unexpected type for key: ", cv[i].key, du->type, "(short)", "0 ... 65535");
return -1;
}
break;
case T_CONFIG_BOOLEAN:
if (du->type == TYPE_STRING) {
data_string *ds = (data_string *)du;
if (0 == strcmp(ds->value->ptr, "enable")) {
*((unsigned short *)(cv[i].destination)) = 1;
} else if (0 == strcmp(ds->value->ptr, "disable")) {
*((unsigned short *)(cv[i].destination)) = 0;
} else {
log_error_write(srv, __FILE__, __LINE__, "ssbs", "ERROR: unexpected value for key:", cv[i].key, ds->value, "(enable|disable)");
return -1;
}
} else {
log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: unexpected type for key:", cv[i].key, "(string)", "\"(enable|disable)\"");
return -1;
}
break;
case T_CONFIG_LOCAL:
case T_CONFIG_UNSET:
break;
case T_CONFIG_DEPRECATED:
log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: found deprecated key:", cv[i].key, "-", (char *)(cv[i].destination));
srv->config_deprecated = 1;
break;
}
}
return 0;
}
static int config_insert(server *srv) {
size_t i;
@ -309,73 +179,6 @@ static int config_insert(server *srv) {
}
int config_check_cond(server *srv, connection *con, data_config *dc) {
buffer *l;
server_socket *srv_sock = con->srv_socket;
/* pass the rules */
l = srv->empty_string;
if (0 == strcmp(dc->comp_key->ptr, "HTTPhost")) {
l = con->uri.authority;
} else if (0 == strcmp(dc->comp_key->ptr, "HTTPurl")) {
l = con->uri.path;
} else if (0 == strcmp(dc->comp_key->ptr, "SERVERsocket")) {
l = srv_sock->srv_token;
} else if (0 == strcmp(dc->comp_key->ptr, "HTTPreferer")) {
data_string *ds;
if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Referer"))) {
l = ds->value;
}
} else if (0 == strcmp(dc->comp_key->ptr, "HTTPcookie")) {
data_string *ds;
if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Cookie"))) {
l = ds->value;
}
} else if (0 == strcmp(dc->comp_key->ptr, "HTTPuseragent")) {
data_string *ds;
if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "User-Agent"))) {
l = ds->value;
}
} else {
return 0;
}
switch(dc->cond) {
case CONFIG_COND_NE:
case CONFIG_COND_EQ:
if (buffer_is_equal(l, dc->match.string)) {
return (dc->cond == CONFIG_COND_EQ) ? 1 : 0;
} else {
return (dc->cond == CONFIG_COND_EQ) ? 0 : 1;
}
break;
#ifdef HAVE_PCRE_H
case CONFIG_COND_NOMATCH:
case CONFIG_COND_MATCH: {
#define N 10
int ovec[N * 3];
int n;
n = pcre_exec(dc->match.regex, NULL, l->ptr, l->used - 1, 0, 0, ovec, N * 3);
if (n > 0) {
return (dc->cond == CONFIG_COND_MATCH) ? 1 : 0;
} else {
return (dc->cond == CONFIG_COND_MATCH) ? 0 : 1;
}
break;
}
#endif
default:
/* no way */
break;
}
return 0;
}
#define PATCH(x) con->conf.x = s->x
int config_setup_connection(server *srv, connection *con) {

216
src/configfile-glue.c

@ -0,0 +1,216 @@
#include "base.h"
#include "buffer.h"
#include "array.h"
#include "log.h"
/**
* like all glue code this file contains functions which
* are the external interface of lighttpd. The functions
* are used by the server itself and the plugins.
*
* The main-goal is to have a small library in the end
* which is linked against both and which will define
* the interface itself in the end.
*
*/
/* handle global options */
/* parse config array */
int config_insert_values_internal(server *srv, array *ca, const config_values_t cv[]) {
size_t i;
data_unset *du;
for (i = 0; cv[i].key; i++) {
if (NULL == (du = array_get_element(ca, cv[i].key))) {
/* no found */
continue;
}
switch (cv[i].type) {
case T_CONFIG_ARRAY:
if (du->type == TYPE_ARRAY) {
size_t j;
data_array *da = (data_array *)du;
for (j = 0; j < da->value->used; j++) {
if (da->value->data[j]->type == TYPE_STRING) {
data_string *ds = data_string_init();
buffer_copy_string_buffer(ds->value, ((data_string *)(da->value->data[j]))->value);
buffer_copy_string_buffer(ds->key, ((data_string *)(da->value->data[j]))->key);
array_insert_unique(cv[i].destination, (data_unset *)ds);
} else {
log_error_write(srv, __FILE__, __LINE__, "sssbs", "unexpected type for key: ", cv[i].key, "[", da->value->data[i]->key, "](string)");
return -1;
}
}
} else {
log_error_write(srv, __FILE__, __LINE__, "sss", "unexpected type for key: ", cv[i].key, "array of strings");
return -1;
}
break;
case T_CONFIG_STRING:
if (du->type == TYPE_STRING) {
data_string *ds = (data_string *)du;
buffer_copy_string_buffer(cv[i].destination, ds->value);
} else {
log_error_write(srv, __FILE__, __LINE__, "ssss", "unexpected type for key: ", cv[i].key, "(string)", "\"...\"");
return -1;
}
break;
case T_CONFIG_SHORT:
switch(du->type) {
case TYPE_INTEGER: {
data_integer *di = (data_integer *)du;
*((unsigned short *)(cv[i].destination)) = di->value;
break;
}
case TYPE_STRING: {
data_string *ds = (data_string *)du;
log_error_write(srv, __FILE__, __LINE__, "ssbss", "unexpected type for key: ", cv[i].key, ds->value, "(short)", "0 ... 65535");
return -1;
}
default:
log_error_write(srv, __FILE__, __LINE__, "ssdss", "unexpected type for key: ", cv[i].key, du->type, "(short)", "0 ... 65535");
return -1;
}
break;
case T_CONFIG_BOOLEAN:
if (du->type == TYPE_STRING) {
data_string *ds = (data_string *)du;
if (buffer_is_equal_string(ds->value, CONST_STR_LEN("enable"))) {
*((unsigned short *)(cv[i].destination)) = 1;
} else if (buffer_is_equal_string(ds->value, CONST_STR_LEN("disable"))) {
*((unsigned short *)(cv[i].destination)) = 0;
} else {
log_error_write(srv, __FILE__, __LINE__, "ssbs", "ERROR: unexpected value for key:", cv[i].key, ds->value, "(enable|disable)");
return -1;
}
} else {
log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: unexpected type for key:", cv[i].key, "(string)", "\"(enable|disable)\"");
return -1;
}
break;
case T_CONFIG_LOCAL:
case T_CONFIG_UNSET:
break;
case T_CONFIG_DEPRECATED:
log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: found deprecated key:", cv[i].key, "-", (char *)(cv[i].destination));
srv->config_deprecated = 1;
break;
}
}
return 0;
}
int config_insert_values_global(server *srv, array *ca, const config_values_t cv[]) {
size_t i;
data_unset *du;
for (i = 0; cv[i].key; i++) {
data_string *touched;
if (NULL == (du = array_get_element(ca, cv[i].key))) {
/* no found */
continue;
}
/* touched */
touched = data_string_init();
buffer_copy_string(touched->value, "");
buffer_copy_string_buffer(touched->key, du->key);
array_insert_unique(srv->config_touched, (data_unset *)touched);
}
return config_insert_values_internal(srv, ca, cv);
}
int config_check_cond(server *srv, connection *con, data_config *dc) {
buffer *l;
server_socket *srv_sock = con->srv_socket;
/* pass the rules */
l = srv->empty_string;
if (buffer_is_equal_string(dc->comp_key, CONST_STR_LEN("HTTPhost"))) {
l = con->uri.authority;
} else if (buffer_is_equal_string(dc->comp_key, CONST_STR_LEN("HTTPurl"))) {
l = con->uri.path;
} else if (buffer_is_equal_string(dc->comp_key, CONST_STR_LEN("SERVERsocket"))) {
l = srv_sock->srv_token;
} else if (buffer_is_equal_string(dc->comp_key, CONST_STR_LEN("HTTPreferer"))) {
data_string *ds;
if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Referer"))) {
l = ds->value;
}
} else if (buffer_is_equal_string(dc->comp_key, CONST_STR_LEN("HTTPcookie"))) {
data_string *ds;
if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Cookie"))) {
l = ds->value;
}
} else if (buffer_is_equal_string(dc->comp_key, CONST_STR_LEN("HTTPuseragent"))) {
data_string *ds;
if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "User-Agent"))) {
l = ds->value;
}
} else {
return 0;
}
switch(dc->cond) {
case CONFIG_COND_NE:
case CONFIG_COND_EQ:
if (buffer_is_equal(l, dc->match.string)) {
return (dc->cond == CONFIG_COND_EQ) ? 1 : 0;
} else {
return (dc->cond == CONFIG_COND_EQ) ? 0 : 1;
}
break;
#ifdef HAVE_PCRE_H
case CONFIG_COND_NOMATCH:
case CONFIG_COND_MATCH: {
#define N 10
int ovec[N * 3];
int n;
n = pcre_exec(dc->match.regex, NULL, l->ptr, l->used - 1, 0, 0, ovec, N * 3);
if (n > 0) {
return (dc->cond == CONFIG_COND_MATCH) ? 1 : 0;
} else {
return (dc->cond == CONFIG_COND_MATCH) ? 0 : 1;
}
break;
}
#endif
default:
/* no way */
break;
}
return 0;
}

44
src/connections-glue.c

@ -0,0 +1,44 @@
#include "base.h"
const char *connection_get_state(connection_state_t state) {
switch (state) {
case CON_STATE_CONNECT: return "connect";
case CON_STATE_READ: return "read";
case CON_STATE_READ_POST: return "readpost";
case CON_STATE_WRITE: return "write";
case CON_STATE_CLOSE: return "close";
case CON_STATE_ERROR: return "error";
case CON_STATE_HANDLE_REQUEST: return "handle-req";
case CON_STATE_REQUEST_START: return "req-start";
case CON_STATE_REQUEST_END: return "req-end";
case CON_STATE_RESPONSE_START: return "resp-start";
case CON_STATE_RESPONSE_END: return "resp-end";
default: return "(unknown)";
}
}
const char *connection_get_short_state(connection_state_t state) {
switch (state) {
case CON_STATE_CONNECT: return ".";
case CON_STATE_READ: return "r";
case CON_STATE_READ_POST: return "R";
case CON_STATE_WRITE: return "W";
case CON_STATE_CLOSE: return "C";
case CON_STATE_ERROR: return "E";
case CON_STATE_HANDLE_REQUEST: return "h";
case CON_STATE_REQUEST_START: return "q";
case CON_STATE_REQUEST_END: return "Q";
case CON_STATE_RESPONSE_START: return "s";
case CON_STATE_RESPONSE_END: return "S";
default: return "x";
}
}
int connection_set_state(server *srv, connection *con, connection_state_t state) {
UNUSED(srv);
con->state = state;
return 0;
}

42
src/connections.c

@ -34,40 +34,6 @@
#include "sys-socket.h"
const char *connection_get_state(connection_state_t state) {
switch (state) {
case CON_STATE_CONNECT: return "connect";
case CON_STATE_READ: return "read";
case CON_STATE_READ_POST: return "readpost";
case CON_STATE_WRITE: return "write";
case CON_STATE_CLOSE: return "close";
case CON_STATE_ERROR: return "error";
case CON_STATE_HANDLE_REQUEST: return "handle-req";
case CON_STATE_REQUEST_START: return "req-start";
case CON_STATE_REQUEST_END: return "req-end";
case CON_STATE_RESPONSE_START: return "resp-start";
case CON_STATE_RESPONSE_END: return "resp-end";
default: return "(unknown)";
}
}
const char *connection_get_short_state(connection_state_t state) {
switch (state) {
case CON_STATE_CONNECT: return ".";
case CON_STATE_READ: return "r";
case CON_STATE_READ_POST: return "R";
case CON_STATE_WRITE: return "W";
case CON_STATE_CLOSE: return "C";
case CON_STATE_ERROR: return "E";
case CON_STATE_HANDLE_REQUEST: return "h";
case CON_STATE_REQUEST_START: return "q";
case CON_STATE_REQUEST_END: return "Q";
case CON_STATE_RESPONSE_START: return "s";
case CON_STATE_RESPONSE_END: return "S";
default: return "x";
}
}
static connection *connections_get_new_connection(server *srv) {
connections *conns = srv->conns;
size_t i;
@ -1168,14 +1134,6 @@ connection *connection_accept(server *srv, server_socket *srv_socket) {
}
}
int connection_set_state(server *srv, connection *con, connection_state_t state) {
UNUSED(srv);
con->state = state;
return 0;
}
int connection_state_machine(server *srv, connection *con) {
int done = 0, r;

136
src/http-header-glue.c

@ -0,0 +1,136 @@
#include <string.h>
#include <errno.h>
#include "base.h"
#include "array.h"
#include "buffer.h"
#include "log.h"
int response_header_insert(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
data_string *ds;
UNUSED(srv);
if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
ds = data_response_init();
}
buffer_copy_string_len(ds->key, key, keylen);
buffer_copy_string_len(ds->value, value, vallen);
array_insert_unique(con->response.headers, (data_unset *)ds);
return 0;
}
int response_header_overwrite(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
data_string *ds;
UNUSED(srv);
/* if there already is a key by this name overwrite the value */
if (NULL != (ds = (data_string *)array_get_element(con->response.headers, key))) {
buffer_copy_string(ds->value, value);
return 0;
}
return response_header_insert(srv, con, key, keylen, value, vallen);
}
int http_response_redirect_to_directory(server *srv, connection *con) {
buffer *o;
o = buffer_init();
if (con->conf.is_ssl) {
buffer_copy_string(o, "https://");
} else {
buffer_copy_string(o, "http://");
}
if (con->uri.authority->used) {
buffer_append_string_buffer(o, con->uri.authority);
} else {
/* get the name of the currently connected socket */
struct hostent *he;
#ifdef HAVE_IPV6
char hbuf[256];
#endif
sock_addr our_addr;
socklen_t our_addr_len;
our_addr_len = sizeof(our_addr);
if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
con->http_status = 500;
log_error_write(srv, __FILE__, __LINE__, "ss",
"can't get sockname", strerror(errno));
buffer_free(o);
return 0;
}
/* Lookup name: secondly try to get hostname for bind address */
switch(our_addr.plain.sa_family) {
#ifdef HAVE_IPV6
case AF_INET6:
if (0 != getnameinfo((const struct sockaddr *)(&our_addr.ipv6),
SA_LEN((const struct sockaddr *)&our_addr.ipv6),
hbuf, sizeof(hbuf), NULL, 0, 0)) {
char dst[INET6_ADDRSTRLEN];
log_error_write(srv, __FILE__, __LINE__,
"SSSS", "NOTICE: getnameinfo failed: ",
strerror(errno), ", using ip-address instead");
buffer_append_string(o,
inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr,
dst, sizeof(dst)));
} else {
buffer_append_string(o, hbuf);
}
break;
#endif
case AF_INET:
if (NULL == (he = gethostbyaddr((char *)&our_addr.ipv4.sin_addr, sizeof(struct in_addr), AF_INET))) {
log_error_write(srv, __FILE__, __LINE__,
"SSSS", "NOTICE: gethostbyaddr failed: ",
hstrerror(h_errno), ", using ip-address instead");
buffer_append_string(o, inet_ntoa(our_addr.ipv4.sin_addr));
} else {
buffer_append_string(o, he->h_name);
}
break;
default:
log_error_write(srv, __FILE__, __LINE__,
"S", "ERROR: unsupported address-type");
buffer_free(o);
return -1;
}
if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) ||
(con->conf.is_ssl == 1 && srv->srvconf.port == 443))) {
buffer_append_string(o, ":");
buffer_append_long(o, srv->srvconf.port);
}
}
buffer_append_string_buffer(o, con->uri.path);
buffer_append_string(o, "/");
if (!buffer_is_empty(con->uri.query)) {
buffer_append_string(o, "?");
buffer_append_string_buffer(o, con->uri.query);
}
response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(o));
con->http_status = 301;
buffer_free(o);
return 0;
}

128
src/response.c

@ -91,38 +91,6 @@ static size_t get_sa_len(const struct sockaddr *addr) {
int response_header_insert(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
data_string *ds;
UNUSED(srv);
if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
ds = data_response_init();
}
buffer_copy_string_len(ds->key, key, keylen);
buffer_copy_string_len(ds->value, value, vallen);
array_insert_unique(con->response.headers, (data_unset *)ds);
return 0;
}
int response_header_overwrite(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
data_string *ds;
UNUSED(srv);
/* if there already is a key by this name overwrite the value */
if (NULL != (ds = (data_string *)array_get_element(con->response.headers, key))) {
buffer_copy_string(ds->value, value);
return 0;
}
return response_header_insert(srv, con, key, keylen, value, vallen);
}
int http_response_write_basic_header(server *srv, connection *con) {
size_t i;
buffer *b;
@ -754,102 +722,6 @@ static int http_list_directory(server *srv, connection *con, buffer *dir) {
return 0;
}
int http_response_redirect_to_directory(server *srv, connection *con) {
buffer *o;
o = buffer_init();
if (con->conf.is_ssl) {
buffer_copy_string(o, "https://");
} else {
buffer_copy_string(o, "http://");
}
if (con->uri.authority->used) {
buffer_append_string_buffer(o, con->uri.authority);
} else {
/* get the name of the currently connected socket */
struct hostent *he;
#ifdef HAVE_IPV6
char hbuf[256];
#endif
sock_addr our_addr;
socklen_t our_addr_len;
our_addr_len = sizeof(our_addr);
if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
con->http_status = 500;
log_error_write(srv, __FILE__, __LINE__, "ss",
"can't get sockname", strerror(errno));
buffer_free(o);
return 0;
}
/* Lookup name: secondly try to get hostname for bind address */
switch(our_addr.plain.sa_family) {
#ifdef HAVE_IPV6
case AF_INET6:
if (0 != getnameinfo((const struct sockaddr *)(&our_addr.ipv6),
SA_LEN((const struct sockaddr *)&our_addr.ipv6),
hbuf, sizeof(hbuf), NULL, 0, 0)) {
char dst[INET6_ADDRSTRLEN];
log_error_write(srv, __FILE__, __LINE__,
"SSSS", "NOTICE: getnameinfo failed: ",
strerror(errno), ", using ip-address instead");
buffer_append_string(o,
inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr,
dst, sizeof(dst)));
} else {
buffer_append_string(o, hbuf);
}
break;
#endif
case AF_INET:
if (NULL == (he = gethostbyaddr((char *)&our_addr.ipv4.sin_addr, sizeof(struct in_addr), AF_INET))) {
log_error_write(srv, __FILE__, __LINE__,
"SSSS", "NOTICE: gethostbyaddr failed: ",
hstrerror(h_errno), ", using ip-address instead");
buffer_append_string(o, inet_ntoa(our_addr.ipv4.sin_addr));
} else {
buffer_append_string(o, he->h_name);
}
break;
default:
log_error_write(srv, __FILE__, __LINE__,
"S", "ERROR: unsupported address-type");
buffer_free(o);
return -1;
}
if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) ||
(con->conf.is_ssl == 1 && srv->srvconf.port == 443))) {
buffer_append_string(o, ":");
buffer_append_long(o, srv->srvconf.port);
}
}
buffer_append_string_buffer(o, con->uri.path);
buffer_append_string(o, "/");
if (!buffer_is_empty(con->uri.query)) {
buffer_append_string(o, "?");
buffer_append_string_buffer(o, con->uri.query);
}
response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(o));
con->http_status = 301;
buffer_free(o);
return 0;
}
handler_t http_response_prepare(server *srv, connection *con) {

Loading…
Cancel
Save