implemented proxy peer connection caching experimentally
This commit is contained in:
parent
f0fe04fef2
commit
643f84a8dd
@ -167,8 +167,13 @@ enum qse_httpd_peer_flag_t
|
|||||||
/* internal use only */
|
/* internal use only */
|
||||||
QSE_HTTPD_PEER_PENDING = (1 << 21),
|
QSE_HTTPD_PEER_PENDING = (1 << 21),
|
||||||
|
|
||||||
|
/* internal use only */
|
||||||
|
QSE_HTTPD_PEER_CACHED = (1 << 23),
|
||||||
|
|
||||||
/* all internal enumerators */
|
/* all internal enumerators */
|
||||||
QSE_HTTPD_PEER_ALL_INTERNALS = (QSE_HTTPD_PEER_CONNECTED | QSE_HTTPD_PEER_PENDING)
|
QSE_HTTPD_PEER_ALL_INTERNALS = (QSE_HTTPD_PEER_CONNECTED |
|
||||||
|
QSE_HTTPD_PEER_PENDING |
|
||||||
|
QSE_HTTPD_PEER_CACHED)
|
||||||
};
|
};
|
||||||
typedef enum qse_httpd_peer_flag_t qse_httpd_peer_flag_t;
|
typedef enum qse_httpd_peer_flag_t qse_httpd_peer_flag_t;
|
||||||
|
|
||||||
@ -176,10 +181,20 @@ typedef struct qse_httpd_peer_t qse_httpd_peer_t;
|
|||||||
struct qse_httpd_peer_t
|
struct qse_httpd_peer_t
|
||||||
{
|
{
|
||||||
int flags; /* 0 or bitwised-OR'ed of qse_httpd_peer_flag_t enumerators */
|
int flags; /* 0 or bitwised-OR'ed of qse_httpd_peer_flag_t enumerators */
|
||||||
|
|
||||||
qse_nwad_t nwad;
|
qse_nwad_t nwad;
|
||||||
qse_nwad_t local; /* local side address facing the peer */
|
qse_nwad_t local; /* local side address facing the peer */
|
||||||
|
|
||||||
|
/* peer.open can set these handles */
|
||||||
qse_httpd_hnd_t handle;
|
qse_httpd_hnd_t handle;
|
||||||
qse_httpd_hnd_t handle2;
|
qse_httpd_hnd_t handle2;
|
||||||
|
|
||||||
|
/* peer links for the proxy peer cache list in client.
|
||||||
|
* internal use only. don't mess with these */
|
||||||
|
qse_httpd_peer_t* next;
|
||||||
|
qse_httpd_peer_t* prev;
|
||||||
|
|
||||||
|
qse_ntime_t timestamp; /* internal use only */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum qse_httpd_mux_mask_t
|
enum qse_httpd_mux_mask_t
|
||||||
@ -332,6 +347,42 @@ struct qse_httpd_scb_t
|
|||||||
int (*accept) (qse_httpd_t* httpd, qse_httpd_server_t* server, qse_httpd_client_t* client);
|
int (*accept) (qse_httpd_t* httpd, qse_httpd_server_t* server, qse_httpd_client_t* client);
|
||||||
} server;
|
} server;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
void (*close) (
|
||||||
|
qse_httpd_t* httpd,
|
||||||
|
qse_httpd_client_t* client);
|
||||||
|
|
||||||
|
void (*shutdown) (
|
||||||
|
qse_httpd_t* httpd,
|
||||||
|
qse_httpd_client_t* client);
|
||||||
|
|
||||||
|
/* action */
|
||||||
|
qse_ssize_t (*recv) (
|
||||||
|
qse_httpd_t* httpd,
|
||||||
|
qse_httpd_client_t* client,
|
||||||
|
qse_mchar_t* buf, qse_size_t bufsize);
|
||||||
|
|
||||||
|
qse_ssize_t (*send) (
|
||||||
|
qse_httpd_t* httpd,
|
||||||
|
qse_httpd_client_t* client,
|
||||||
|
const qse_mchar_t* buf, qse_size_t bufsize);
|
||||||
|
|
||||||
|
qse_ssize_t (*sendfile) (
|
||||||
|
qse_httpd_t* httpd,
|
||||||
|
qse_httpd_client_t* client,
|
||||||
|
qse_httpd_hnd_t handle, qse_foff_t* offset, qse_size_t count);
|
||||||
|
|
||||||
|
/* event notification */
|
||||||
|
int (*accepted) (
|
||||||
|
qse_httpd_t* httpd,
|
||||||
|
qse_httpd_client_t* client); /* optional */
|
||||||
|
void (*closed) (
|
||||||
|
qse_httpd_t* httpd,
|
||||||
|
qse_httpd_client_t* client); /* optional */
|
||||||
|
} client;
|
||||||
|
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
int (*open) (qse_httpd_t* httpd, qse_httpd_peer_t* peer);
|
int (*open) (qse_httpd_t* httpd, qse_httpd_peer_t* peer);
|
||||||
@ -399,40 +450,6 @@ struct qse_httpd_scb_t
|
|||||||
qse_httpd_dirent_t* ent);
|
qse_httpd_dirent_t* ent);
|
||||||
} dir;
|
} dir;
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
void (*close) (
|
|
||||||
qse_httpd_t* httpd,
|
|
||||||
qse_httpd_client_t* client);
|
|
||||||
|
|
||||||
void (*shutdown) (
|
|
||||||
qse_httpd_t* httpd,
|
|
||||||
qse_httpd_client_t* client);
|
|
||||||
|
|
||||||
/* action */
|
|
||||||
qse_ssize_t (*recv) (
|
|
||||||
qse_httpd_t* httpd,
|
|
||||||
qse_httpd_client_t* client,
|
|
||||||
qse_mchar_t* buf, qse_size_t bufsize);
|
|
||||||
|
|
||||||
qse_ssize_t (*send) (
|
|
||||||
qse_httpd_t* httpd,
|
|
||||||
qse_httpd_client_t* client,
|
|
||||||
const qse_mchar_t* buf, qse_size_t bufsize);
|
|
||||||
|
|
||||||
qse_ssize_t (*sendfile) (
|
|
||||||
qse_httpd_t* httpd,
|
|
||||||
qse_httpd_client_t* client,
|
|
||||||
qse_httpd_hnd_t handle, qse_foff_t* offset, qse_size_t count);
|
|
||||||
|
|
||||||
/* event notification */
|
|
||||||
int (*accepted) (
|
|
||||||
qse_httpd_t* httpd,
|
|
||||||
qse_httpd_client_t* client); /* optional */
|
|
||||||
void (*closed) (
|
|
||||||
qse_httpd_t* httpd,
|
|
||||||
qse_httpd_client_t* client); /* optional */
|
|
||||||
} client;
|
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
@ -663,6 +680,12 @@ struct qse_httpd_client_t
|
|||||||
int initial_ifindex;
|
int initial_ifindex;
|
||||||
|
|
||||||
/* == PRIVATE == */
|
/* == PRIVATE == */
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
qse_httpd_peer_t* first;
|
||||||
|
qse_httpd_peer_t* last;
|
||||||
|
} peer; /* list of proxy peers for this client */
|
||||||
|
|
||||||
qse_htrd_t* htrd;
|
qse_htrd_t* htrd;
|
||||||
int status;
|
int status;
|
||||||
qse_httpd_task_trigger_t trigger;
|
qse_httpd_task_trigger_t trigger;
|
||||||
@ -1404,9 +1427,9 @@ QSE_EXPORT qse_httpd_mod_t* qse_httpd_findmod (
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
QSE_EXPORT int qse_httpd_inserttimerevent (
|
QSE_EXPORT int qse_httpd_inserttimerevent (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
const qse_httpd_timer_event_t* event,
|
const qse_httpd_timer_event_t* event,
|
||||||
qse_httpd_timer_index_t* index
|
qse_httpd_timer_index_t* index
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@ -1415,6 +1438,7 @@ QSE_EXPORT void qse_httpd_removetimerevent (
|
|||||||
qse_httpd_timer_index_t index
|
qse_httpd_timer_index_t index
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,8 @@ struct task_proxy_t
|
|||||||
qse_mchar_t* peer_name;
|
qse_mchar_t* peer_name;
|
||||||
qse_uint16_t peer_port;
|
qse_uint16_t peer_port;
|
||||||
|
|
||||||
qse_httpd_peer_t peer;
|
qse_httpd_peer_t* peer; /* it points to static_peer initially. it can get changed to something else */
|
||||||
|
qse_httpd_peer_t static_peer;
|
||||||
#define PROXY_PEER_OPEN (1 << 0)
|
#define PROXY_PEER_OPEN (1 << 0)
|
||||||
#define PROXY_PEER_CONNECTED (1 << 1)
|
#define PROXY_PEER_CONNECTED (1 << 1)
|
||||||
int peer_status;
|
int peer_status;
|
||||||
@ -132,17 +133,19 @@ struct proxy_peer_htrd_xtn_t
|
|||||||
qse_httpd_task_t* task;
|
qse_httpd_task_t* task;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void log_proxy_error (task_proxy_t* proxy, const qse_mchar_t* shortmsg)
|
/* ----------------------------------------------------------------- */
|
||||||
{
|
|
||||||
/* TODO: change this to HTTPD_DBGOUTXXXX */
|
|
||||||
qse_httpd_act_t msg;
|
|
||||||
qse_size_t pos = 0;
|
|
||||||
|
|
||||||
msg.code = QSE_HTTPD_CATCH_MERRMSG;
|
#if defined(QSE_HTTPD_DEBUG)
|
||||||
pos += qse_mbsxcpy (&msg.u.merrmsg[pos], QSE_COUNTOF(msg.u.merrmsg) - pos, shortmsg);
|
#define DBGOUT_PROXY_ERROR(proxy, msg) \
|
||||||
pos += qse_nwadtombs (&proxy->peer.nwad, &msg.u.merrmsg[pos], QSE_COUNTOF(msg.u.merrmsg) - pos, QSE_NWADTOMBS_ALL);
|
do { \
|
||||||
proxy->httpd->opt.rcb.logact (proxy->httpd, &msg);
|
qse_mchar_t tmp1[128], tmp2[128]; \
|
||||||
}
|
qse_nwadtombs (&(proxy)->peer->nwad, tmp1, QSE_COUNTOF(tmp1), QSE_NWADTOMBS_ALL); \
|
||||||
|
qse_nwadtombs (&(proxy)->client->remote_addr, tmp2, QSE_COUNTOF(tmp2), QSE_NWADTOMBS_ALL); \
|
||||||
|
HTTPD_DBGOUT3 ("Proxy error with peer [%hs] client [%hs] - %hs\n", tmp1, tmp2, msg); \
|
||||||
|
} while(0)
|
||||||
|
#else
|
||||||
|
#define DBGOUT_PROXY_ERROR(proxy, msg)
|
||||||
|
#endif
|
||||||
|
|
||||||
static int proxy_add_header_to_buffer (
|
static int proxy_add_header_to_buffer (
|
||||||
task_proxy_t* proxy, qse_mbs_t* buf, const qse_mchar_t* key, const qse_htre_hdrval_t* val)
|
task_proxy_t* proxy, qse_mbs_t* buf, const qse_mchar_t* key, const qse_htre_hdrval_t* val)
|
||||||
@ -705,9 +708,7 @@ static int proxy_htrd_peek_peer_output (qse_htrd_t* htrd, qse_htre_t* res)
|
|||||||
if ((proxy->resflags & PROXY_RES_PEER_LENGTH) &&
|
if ((proxy->resflags & PROXY_RES_PEER_LENGTH) &&
|
||||||
proxy->peer_output_received > proxy->peer_output_length)
|
proxy->peer_output_received > proxy->peer_output_length)
|
||||||
{
|
{
|
||||||
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
DBGOUT_PROXY_ERROR (proxy, "Redundant output from peer");
|
||||||
log_proxy_error (proxy, "proxy redundant output - ");
|
|
||||||
|
|
||||||
httpd->errnum = QSE_HTTPD_EINVAL; /* TODO: change it to a better error code */
|
httpd->errnum = QSE_HTTPD_EINVAL; /* TODO: change it to a better error code */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -831,7 +832,7 @@ static void proxy_forward_client_input_to_peer (qse_httpd_t* httpd, qse_httpd_ta
|
|||||||
|
|
||||||
httpd->errnum = QSE_HTTPD_ENOERR;
|
httpd->errnum = QSE_HTTPD_ENOERR;
|
||||||
n = httpd->opt.scb.peer.send (
|
n = httpd->opt.scb.peer.send (
|
||||||
httpd, &proxy->peer,
|
httpd, proxy->peer,
|
||||||
QSE_MBS_PTR(proxy->reqfwdbuf),
|
QSE_MBS_PTR(proxy->reqfwdbuf),
|
||||||
QSE_MBS_LEN(proxy->reqfwdbuf)
|
QSE_MBS_LEN(proxy->reqfwdbuf)
|
||||||
);
|
);
|
||||||
@ -840,8 +841,7 @@ static void proxy_forward_client_input_to_peer (qse_httpd_t* httpd, qse_httpd_ta
|
|||||||
{
|
{
|
||||||
if (httpd->errnum != QSE_HTTPD_EAGAIN)
|
if (httpd->errnum != QSE_HTTPD_EAGAIN)
|
||||||
{
|
{
|
||||||
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
DBGOUT_PROXY_ERROR (proxy, "Cannot send to peer");
|
||||||
log_proxy_error (proxy, "proxy send-to-peer error - ");
|
|
||||||
|
|
||||||
proxy->reqflags |= PROXY_REQ_FWDERR;
|
proxy->reqflags |= PROXY_REQ_FWDERR;
|
||||||
qse_mbs_clear (proxy->reqfwdbuf);
|
qse_mbs_clear (proxy->reqfwdbuf);
|
||||||
@ -902,7 +902,7 @@ static void adjust_peer_name_and_port (task_proxy_t* proxy)
|
|||||||
if (proxy->flags & PROXY_RAW) proxy->peer_port = QSE_HTTPD_DEFAULT_SECURE_PORT;
|
if (proxy->flags & PROXY_RAW) proxy->peer_port = QSE_HTTPD_DEFAULT_SECURE_PORT;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (proxy->peer.flags & QSE_HTTPD_PEER_SECURE)
|
if (proxy->peer->flags & QSE_HTTPD_PEER_SECURE)
|
||||||
proxy->peer_port = QSE_HTTPD_DEFAULT_SECURE_PORT;
|
proxy->peer_port = QSE_HTTPD_DEFAULT_SECURE_PORT;
|
||||||
else
|
else
|
||||||
proxy->peer_port = QSE_HTTPD_DEFAULT_PORT;
|
proxy->peer_port = QSE_HTTPD_DEFAULT_PORT;
|
||||||
@ -947,9 +947,10 @@ static int task_init_proxy (
|
|||||||
if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_X_FORWARDED) proxy->flags |= PROXY_X_FORWARDED;
|
if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_X_FORWARDED) proxy->flags |= PROXY_X_FORWARDED;
|
||||||
if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_ALLOW_UPGRADE) proxy->flags |= PROXY_ALLOW_UPGRADE;
|
if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_ALLOW_UPGRADE) proxy->flags |= PROXY_ALLOW_UPGRADE;
|
||||||
|
|
||||||
if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_DST_SECURE) proxy->peer.flags |= QSE_HTTPD_PEER_SECURE;
|
proxy->peer = &proxy->static_peer;
|
||||||
|
if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_DST_SECURE) proxy->peer->flags |= QSE_HTTPD_PEER_SECURE;
|
||||||
|
|
||||||
proxy->peer.local = arg->rsrc->src.nwad;
|
proxy->peer->local = arg->rsrc->src.nwad;
|
||||||
if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_DST_STR)
|
if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_DST_STR)
|
||||||
{
|
{
|
||||||
/* the destination given is a string.
|
/* the destination given is a string.
|
||||||
@ -982,7 +983,7 @@ static int task_init_proxy (
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
proxy->peer.nwad = arg->rsrc->dst.nwad;
|
proxy->peer->nwad = arg->rsrc->dst.nwad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_ENABLE_URS)
|
if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_ENABLE_URS)
|
||||||
@ -1352,14 +1353,48 @@ static void task_fini_proxy (
|
|||||||
|
|
||||||
if (proxy->peer_status & PROXY_PEER_OPEN)
|
if (proxy->peer_status & PROXY_PEER_OPEN)
|
||||||
{
|
{
|
||||||
#if defined(QSE_HTTPD_DEBUG)
|
int reuse = 0;
|
||||||
|
|
||||||
|
/* check if the peer connection can be reused */
|
||||||
|
if (!(proxy->flags & (PROXY_RAW | PROXY_UPGRADE_REQUESTED | PROXY_PROTOCOL_SWITCHED)) &&
|
||||||
|
!(proxy->resflags & PROXY_RES_PEER_CLOSE))
|
||||||
{
|
{
|
||||||
qse_mchar_t tmp[128];
|
qse_mchar_t tmpch;
|
||||||
qse_nwadtombs (&proxy->peer.nwad, tmp, QSE_COUNTOF(tmp), QSE_NWADTOMBS_ALL);
|
|
||||||
HTTPD_DBGOUT2 ("Closing peer [%hs] - %zd\n", tmp, (qse_size_t)proxy->peer.handle);
|
/* check if the peer connection dropped connection or
|
||||||
|
* sending excessive data. don't reuse such a connection */
|
||||||
|
if (httpd->opt.scb.peer.recv (httpd, proxy->peer, &tmpch, 1) <= -1 &&
|
||||||
|
httpd->errnum == QSE_HTTPD_EAGAIN) reuse = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reuse && qse_httpd_cacheproxypeer (httpd, client, proxy->peer))
|
||||||
|
{
|
||||||
|
/* cache a reusable peer connection */
|
||||||
|
|
||||||
|
#if defined(QSE_HTTPD_DEBUG)
|
||||||
|
qse_mchar_t tmp[128];
|
||||||
|
|
||||||
|
qse_nwadtombs (&proxy->peer->nwad, tmp, QSE_COUNTOF(tmp), QSE_NWADTOMBS_ALL);
|
||||||
|
HTTPD_DBGOUT2 ("Cached peer [%hs] - %zd\n", tmp, (qse_size_t)proxy->peer->handle);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if defined(QSE_HTTPD_DEBUG)
|
||||||
|
qse_mchar_t tmp[128];
|
||||||
|
|
||||||
|
qse_nwadtombs (&proxy->peer->nwad, tmp, QSE_COUNTOF(tmp), QSE_NWADTOMBS_ALL);
|
||||||
|
HTTPD_DBGOUT2 ("Closing peer [%hs] - %zd\n", tmp, (qse_size_t)proxy->peer->handle);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
httpd->opt.scb.peer.close (httpd, proxy->peer);
|
||||||
|
|
||||||
|
if (proxy->peer->flags & QSE_HTTPD_PEER_CACHED)
|
||||||
|
{
|
||||||
|
QSE_ASSERT (proxy->peer != &proxy->static_peer);
|
||||||
|
qse_httpd_freemem (httpd, proxy->peer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
httpd->opt.scb.peer.close (httpd, &proxy->peer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((proxy->flags & (PROXY_UPGRADE_REQUESTED | PROXY_PROTOCOL_SWITCHED)) == PROXY_UPGRADE_REQUESTED)
|
if ((proxy->flags & (PROXY_UPGRADE_REQUESTED | PROXY_PROTOCOL_SWITCHED)) == PROXY_UPGRADE_REQUESTED)
|
||||||
@ -1409,8 +1444,7 @@ printf ("task_main_proxy_5 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask
|
|||||||
if (httpd->errnum != QSE_HTTPD_EAGAIN)
|
if (httpd->errnum != QSE_HTTPD_EAGAIN)
|
||||||
{
|
{
|
||||||
/* can't return internal server error any more... */
|
/* can't return internal server error any more... */
|
||||||
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
DBGOUT_PROXY_ERROR (proxy, "Cannot send to client");
|
||||||
log_proxy_error (proxy, "proxy send-to-client error - ");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1448,7 +1482,7 @@ printf ("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger.cmask=%
|
|||||||
/* reading from the peer */
|
/* reading from the peer */
|
||||||
httpd->errnum = QSE_HTTPD_ENOERR;
|
httpd->errnum = QSE_HTTPD_ENOERR;
|
||||||
n = httpd->opt.scb.peer.recv (
|
n = httpd->opt.scb.peer.recv (
|
||||||
httpd, &proxy->peer,
|
httpd, proxy->peer,
|
||||||
&proxy->buf[proxy->buflen],
|
&proxy->buf[proxy->buflen],
|
||||||
QSE_SIZEOF(proxy->buf) - proxy->buflen
|
QSE_SIZEOF(proxy->buf) - proxy->buflen
|
||||||
);
|
);
|
||||||
@ -1457,8 +1491,7 @@ printf ("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger.cmask=%
|
|||||||
/* can't return internal server error any more... */
|
/* can't return internal server error any more... */
|
||||||
if (httpd->errnum != QSE_HTTPD_EAGAIN)
|
if (httpd->errnum != QSE_HTTPD_EAGAIN)
|
||||||
{
|
{
|
||||||
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
DBGOUT_PROXY_ERROR (proxy, "Cannot receive from peer");
|
||||||
log_proxy_error (proxy, "proxy recv-from-peer error - ");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1473,8 +1506,7 @@ printf ("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger.cmask=%
|
|||||||
|
|
||||||
if (proxy->peer_output_received < proxy->peer_output_length)
|
if (proxy->peer_output_received < proxy->peer_output_length)
|
||||||
{
|
{
|
||||||
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
DBGOUT_PROXY_ERROR (proxy, "Premature content end");
|
||||||
log_proxy_error (proxy, "proxy premature eof(content) - ");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1517,8 +1549,7 @@ printf ("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger.cmask=%
|
|||||||
if (proxy->peer_output_received > proxy->peer_output_length)
|
if (proxy->peer_output_received > proxy->peer_output_length)
|
||||||
{
|
{
|
||||||
/* proxy returning too much data... something is wrong in PROXY */
|
/* proxy returning too much data... something is wrong in PROXY */
|
||||||
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
DBGOUT_PROXY_ERROR (proxy, "Redundant output from peer");
|
||||||
log_proxy_error (proxy, "proxy redundant output - ");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else if (proxy->peer_output_received == proxy->peer_output_length)
|
else if (proxy->peer_output_received == proxy->peer_output_length)
|
||||||
@ -1547,8 +1578,7 @@ printf ("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger.cmask=%
|
|||||||
if (httpd->errnum != QSE_HTTPD_EAGAIN)
|
if (httpd->errnum != QSE_HTTPD_EAGAIN)
|
||||||
{
|
{
|
||||||
/* can't return internal server error any more... */
|
/* can't return internal server error any more... */
|
||||||
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
DBGOUT_PROXY_ERROR (proxy, "Cannot send to client");
|
||||||
log_proxy_error (proxy, "proxy send-to-client error - ");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1559,7 +1589,7 @@ printf ("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger.cmask=%
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proxy->peer.flags & QSE_HTTPD_PEER_PENDING)
|
if (proxy->peer->flags & QSE_HTTPD_PEER_PENDING)
|
||||||
{
|
{
|
||||||
/* this QSE_HTTPD_CLIENT_PENDING thing is a dirty hack for SSL.
|
/* this QSE_HTTPD_CLIENT_PENDING thing is a dirty hack for SSL.
|
||||||
* In SSL, data is transmitted in a record. a record can be
|
* In SSL, data is transmitted in a record. a record can be
|
||||||
@ -1620,8 +1650,7 @@ printf ("task_main_proxy_3 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask
|
|||||||
{
|
{
|
||||||
if (httpd->errnum != QSE_HTTPD_EAGAIN)
|
if (httpd->errnum != QSE_HTTPD_EAGAIN)
|
||||||
{
|
{
|
||||||
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
DBGOUT_PROXY_ERROR (proxy, "Cannot send to client");
|
||||||
log_proxy_error (proxy, "proxy send-to-client error - ");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1709,8 +1738,7 @@ static int task_main_proxy_2 (
|
|||||||
{
|
{
|
||||||
if (httpd->errnum != QSE_HTTPD_EAGAIN)
|
if (httpd->errnum != QSE_HTTPD_EAGAIN)
|
||||||
{
|
{
|
||||||
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
DBGOUT_PROXY_ERROR (proxy, "Cannot send to client");
|
||||||
log_proxy_error (proxy, "proxy send-to-client error - ");
|
|
||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1741,7 +1769,7 @@ static int task_main_proxy_2 (
|
|||||||
/* there is something to read from peer */
|
/* there is something to read from peer */
|
||||||
httpd->errnum = QSE_HTTPD_ENOERR;
|
httpd->errnum = QSE_HTTPD_ENOERR;
|
||||||
n = httpd->opt.scb.peer.recv (
|
n = httpd->opt.scb.peer.recv (
|
||||||
httpd, &proxy->peer,
|
httpd, proxy->peer,
|
||||||
&proxy->buf[proxy->buflen],
|
&proxy->buf[proxy->buflen],
|
||||||
QSE_SIZEOF(proxy->buf) - proxy->buflen
|
QSE_SIZEOF(proxy->buf) - proxy->buflen
|
||||||
);
|
);
|
||||||
@ -1749,8 +1777,7 @@ static int task_main_proxy_2 (
|
|||||||
{
|
{
|
||||||
if (httpd->errnum != QSE_HTTPD_EAGAIN)
|
if (httpd->errnum != QSE_HTTPD_EAGAIN)
|
||||||
{
|
{
|
||||||
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
DBGOUT_PROXY_ERROR (proxy, "Cannot receive from peer");
|
||||||
log_proxy_error (proxy, "proxy recv-from-peer error - ");
|
|
||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1760,9 +1787,7 @@ static int task_main_proxy_2 (
|
|||||||
{
|
{
|
||||||
/* end of output from peer before it has seen a header.
|
/* end of output from peer before it has seen a header.
|
||||||
* the proxy peer must be bad. */
|
* the proxy peer must be bad. */
|
||||||
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
DBGOUT_PROXY_ERROR (proxy, "Premature header end from peer");
|
||||||
log_proxy_error (proxy, "proxy premature eof(header) - ");
|
|
||||||
|
|
||||||
if (!(proxy->resflags & PROXY_RES_RECEIVED_100)) http_errnum = 502;
|
if (!(proxy->resflags & PROXY_RES_RECEIVED_100)) http_errnum = 502;
|
||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
@ -1782,8 +1807,7 @@ static int task_main_proxy_2 (
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* premature eof from the peer */
|
/* premature eof from the peer */
|
||||||
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
DBGOUT_PROXY_ERROR (proxy, "No chunked content from peer");
|
||||||
log_proxy_error (proxy, "proxy no content(chunked) - ");
|
|
||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1886,7 +1910,7 @@ static int task_main_proxy_1 (
|
|||||||
int n;
|
int n;
|
||||||
|
|
||||||
httpd->errnum = QSE_HTTPD_ENOERR;
|
httpd->errnum = QSE_HTTPD_ENOERR;
|
||||||
n = httpd->opt.scb.peer.connected (httpd, &proxy->peer);
|
n = httpd->opt.scb.peer.connected (httpd, proxy->peer);
|
||||||
if (n <= -1)
|
if (n <= -1)
|
||||||
{
|
{
|
||||||
/* TODO: translate more error codes to http error codes... */
|
/* TODO: translate more error codes to http error codes... */
|
||||||
@ -1898,7 +1922,7 @@ static int task_main_proxy_1 (
|
|||||||
#if defined(QSE_HTTPD_DEBUG)
|
#if defined(QSE_HTTPD_DEBUG)
|
||||||
{
|
{
|
||||||
qse_mchar_t tmp[128];
|
qse_mchar_t tmp[128];
|
||||||
qse_nwadtombs (&proxy->peer.nwad, tmp, QSE_COUNTOF(tmp), QSE_NWADTOMBS_ALL);
|
qse_nwadtombs (&proxy->peer->nwad, tmp, QSE_COUNTOF(tmp), QSE_NWADTOMBS_ALL);
|
||||||
HTTPD_DBGOUT1 ("Cannnot connect to peer [%hs]\n", tmp);
|
HTTPD_DBGOUT1 ("Cannnot connect to peer [%hs]\n", tmp);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1982,11 +2006,11 @@ static void on_peer_name_resolved (qse_httpd_t* httpd, const qse_mchar_t* name,
|
|||||||
{
|
{
|
||||||
/* resolved successfully */
|
/* resolved successfully */
|
||||||
|
|
||||||
proxy->peer.nwad = *nwad;
|
proxy->peer->nwad = *nwad;
|
||||||
qse_setnwadport (&proxy->peer.nwad, qse_hton16(proxy->peer_port));
|
qse_setnwadport (&proxy->peer->nwad, qse_hton16(proxy->peer_port));
|
||||||
|
|
||||||
if (proxy->peer.local.type == QSE_NWAD_NX)
|
if (proxy->peer->local.type == QSE_NWAD_NX)
|
||||||
proxy->peer.local.type = proxy->peer.nwad.type;
|
proxy->peer->local.type = proxy->peer->nwad.type;
|
||||||
|
|
||||||
proxy->flags |= PROXY_PEER_NAME_RESOLVED;
|
proxy->flags |= PROXY_PEER_NAME_RESOLVED;
|
||||||
}
|
}
|
||||||
@ -2006,7 +2030,7 @@ static void on_peer_name_resolved (qse_httpd_t* httpd, const qse_mchar_t* name,
|
|||||||
if (proxy->flags & PROXY_PEER_NAME_RESOLVED)
|
if (proxy->flags & PROXY_PEER_NAME_RESOLVED)
|
||||||
{
|
{
|
||||||
qse_mchar_t tmp[128];
|
qse_mchar_t tmp[128];
|
||||||
qse_nwadtombs (&proxy->peer.nwad, tmp, 128, QSE_NWADTOMBS_ALL);
|
qse_nwadtombs (&proxy->peer->nwad, tmp, 128, QSE_NWADTOMBS_ALL);
|
||||||
HTTPD_DBGOUT2 ("Peer name [%hs] resolved to [%hs]\n", name, tmp);
|
HTTPD_DBGOUT2 ("Peer name [%hs] resolved to [%hs]\n", name, tmp);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -2039,7 +2063,7 @@ static void on_url_rewritten (qse_httpd_t* httpd, const qse_mchar_t* url, const
|
|||||||
qse_setnwadport (&nwad, qse_hton16(QSE_HTTPD_DEFAULT_PORT));
|
qse_setnwadport (&nwad, qse_hton16(QSE_HTTPD_DEFAULT_PORT));
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy->peer.nwad = nwad;
|
proxy->peer->nwad = nwad;
|
||||||
proxy->flags |= PROXY_URL_REWRITTEN;
|
proxy->flags |= PROXY_URL_REWRITTEN;
|
||||||
proxy->flags &= ~PROXY_RESOLVE_PEER_NAME; /* skip dns */
|
proxy->flags &= ~PROXY_RESOLVE_PEER_NAME; /* skip dns */
|
||||||
}
|
}
|
||||||
@ -2139,9 +2163,9 @@ static void on_url_rewritten (qse_httpd_t* httpd, const qse_mchar_t* url, const
|
|||||||
|
|
||||||
/* TODO: antything todo when http is rewritten to HTTPS or vice versa */
|
/* TODO: antything todo when http is rewritten to HTTPS or vice versa */
|
||||||
if (proto_len == 8)
|
if (proto_len == 8)
|
||||||
proxy->peer.flags |= QSE_HTTPD_PEER_SECURE;
|
proxy->peer->flags |= QSE_HTTPD_PEER_SECURE;
|
||||||
else
|
else
|
||||||
proxy->peer.flags &= ~QSE_HTTPD_PEER_SECURE;
|
proxy->peer->flags &= ~QSE_HTTPD_PEER_SECURE;
|
||||||
|
|
||||||
if (qse_mbstonwad (tmp, &nwad) <= -1)
|
if (qse_mbstonwad (tmp, &nwad) <= -1)
|
||||||
{
|
{
|
||||||
@ -2157,14 +2181,14 @@ static void on_url_rewritten (qse_httpd_t* httpd, const qse_mchar_t* url, const
|
|||||||
qse_setnwadport (&nwad, qse_hton16(proto_len == 8? QSE_HTTPD_DEFAULT_SECURE_PORT: QSE_HTTPD_DEFAULT_PORT));
|
qse_setnwadport (&nwad, qse_hton16(proto_len == 8? QSE_HTTPD_DEFAULT_SECURE_PORT: QSE_HTTPD_DEFAULT_PORT));
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy->peer.nwad = nwad;
|
proxy->peer->nwad = nwad;
|
||||||
proxy->flags |= PROXY_URL_REWRITTEN;
|
proxy->flags |= PROXY_URL_REWRITTEN;
|
||||||
proxy->flags &= ~PROXY_RESOLVE_PEER_NAME; /* skip dns */
|
proxy->flags &= ~PROXY_RESOLVE_PEER_NAME; /* skip dns */
|
||||||
|
|
||||||
#if defined(QSE_HTTPD_DEBUG)
|
#if defined(QSE_HTTPD_DEBUG)
|
||||||
{
|
{
|
||||||
qse_mchar_t tmp[128];
|
qse_mchar_t tmp[128];
|
||||||
qse_nwadtombs (&proxy->peer.nwad, tmp, 128, QSE_NWADTOMBS_ALL);
|
qse_nwadtombs (&proxy->peer->nwad, tmp, 128, QSE_NWADTOMBS_ALL);
|
||||||
HTTPD_DBGOUT4 ("Peer name resolved to [%hs] in url rewriting. new_url [%hs] %d %d\n",
|
HTTPD_DBGOUT4 ("Peer name resolved to [%hs] in url rewriting. new_url [%hs] %d %d\n",
|
||||||
tmp, new_url,
|
tmp, new_url,
|
||||||
(int)proxy->qpath_pos_in_reqfwdbuf,
|
(int)proxy->qpath_pos_in_reqfwdbuf,
|
||||||
@ -2209,6 +2233,7 @@ static int task_main_proxy (
|
|||||||
proxy_peer_htrd_xtn_t* xtn;
|
proxy_peer_htrd_xtn_t* xtn;
|
||||||
int http_errnum = 500;
|
int http_errnum = 500;
|
||||||
int n;
|
int n;
|
||||||
|
qse_httpd_peer_t* peer_from_cache;
|
||||||
|
|
||||||
if (proxy->flags & PROXY_INIT_FAILED)
|
if (proxy->flags & PROXY_INIT_FAILED)
|
||||||
{
|
{
|
||||||
@ -2265,18 +2290,18 @@ static int task_main_proxy (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (proxy->dns_preresolve_mod && proxy->dns_preresolve_mod->dns_preresolve)
|
if (proxy->dns_preresolve_mod && proxy->dns_preresolve_mod->dns_preresolve)
|
||||||
x = proxy->dns_preresolve_mod->dns_preresolve (proxy->dns_preresolve_mod, client, proxy->peer_name, &proxy->peer.nwad);
|
x = proxy->dns_preresolve_mod->dns_preresolve (proxy->dns_preresolve_mod, client, proxy->peer_name, &proxy->peer->nwad);
|
||||||
else
|
else
|
||||||
x = httpd->opt.scb.dns.preresolve (httpd, client, proxy->peer_name, &proxy->peer.nwad);
|
x = httpd->opt.scb.dns.preresolve (httpd, client, proxy->peer_name, &proxy->peer->nwad);
|
||||||
if (x <= -1) goto oops;
|
if (x <= -1) goto oops;
|
||||||
|
|
||||||
if (x == 0)
|
if (x == 0)
|
||||||
{
|
{
|
||||||
/* preresolve() indicates that proxy->peer.nwad contains the
|
/* preresolve() indicates that proxy->peer->nwad contains the
|
||||||
* final address. no actual dns resolution is required */
|
* final address. no actual dns resolution is required */
|
||||||
proxy->flags |= PROXY_PEER_NAME_RESOLVED;
|
proxy->flags |= PROXY_PEER_NAME_RESOLVED;
|
||||||
proxy->flags &= ~PROXY_RESOLVE_PEER_NAME;
|
proxy->flags &= ~PROXY_RESOLVE_PEER_NAME;
|
||||||
qse_setnwadport (&proxy->peer.nwad, qse_hton16(proxy->peer_port));
|
qse_setnwadport (&proxy->peer->nwad, qse_hton16(proxy->peer_port));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2330,37 +2355,84 @@ static int task_main_proxy (
|
|||||||
proxy->res_consumed = 0;
|
proxy->res_consumed = 0;
|
||||||
proxy->res_pending = 0;
|
proxy->res_pending = 0;
|
||||||
|
|
||||||
httpd->errnum = QSE_HTTPD_ENOERR;
|
/* get a cached peer connection */
|
||||||
n = httpd->opt.scb.peer.open (httpd, &proxy->peer);
|
peer_from_cache = qse_httpd_decacheproxypeer (httpd, client, &proxy->peer->nwad, &proxy->peer->local, (proxy->peer->flags & QSE_HTTPD_PEER_SECURE));
|
||||||
if (n <= -1)
|
if (peer_from_cache)
|
||||||
{
|
{
|
||||||
/* TODO: translate more error codes to http error codes... */
|
qse_mchar_t tmpch;
|
||||||
if (httpd->errnum == QSE_HTTPD_ENOENT) http_errnum = 404;
|
|
||||||
else if (httpd->errnum == QSE_HTTPD_EACCES ||
|
QSE_ASSERT (peer_from_cache->flags & QSE_HTTPD_PEER_CACHED);
|
||||||
httpd->errnum == QSE_HTTPD_ECONN) http_errnum = 403;
|
|
||||||
|
/* test if the cached connection is still ok */
|
||||||
|
if (httpd->opt.scb.peer.recv (httpd, peer_from_cache, &tmpch, 1) <= -1 &&
|
||||||
|
httpd->errnum == QSE_HTTPD_EAGAIN)
|
||||||
|
{
|
||||||
|
/* this connection seems to be ok. it didn't return EOF nor any data.
|
||||||
|
* A valid connection can't return data yes as no request has been sent.*/
|
||||||
|
#if defined(QSE_HTTPD_DEBUG)
|
||||||
|
{
|
||||||
|
qse_mchar_t tmp[128];
|
||||||
|
qse_nwadtombs (&peer_from_cache->nwad, tmp, QSE_COUNTOF(tmp), QSE_NWADTOMBS_ALL);
|
||||||
|
HTTPD_DBGOUT2 ("Decached peer [%hs] - %zd\n", tmp, (qse_size_t)peer_from_cache->handle);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* the cached connection seems to be stale or invalid */
|
||||||
|
#if defined(QSE_HTTPD_DEBUG)
|
||||||
|
{
|
||||||
|
qse_mchar_t tmp[128];
|
||||||
|
qse_nwadtombs (&peer_from_cache->nwad, tmp, QSE_COUNTOF(tmp), QSE_NWADTOMBS_ALL);
|
||||||
|
HTTPD_DBGOUT2 ("Decached and closed stale peer [%hs] - %zd\n", tmp, (qse_size_t)peer_from_cache->handle);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
httpd->opt.scb.peer.close (httpd, peer_from_cache);
|
||||||
|
qse_httpd_freemem (httpd, peer_from_cache);
|
||||||
|
|
||||||
|
peer_from_cache = QSE_NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (peer_from_cache)
|
||||||
|
{
|
||||||
|
proxy->peer = peer_from_cache; /* switch the peer pointer to the one acquired from the cache */
|
||||||
|
n = 1; /* act as if it just got connected */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
httpd->errnum = QSE_HTTPD_ENOERR;
|
||||||
|
n = httpd->opt.scb.peer.open (httpd, proxy->peer);
|
||||||
|
if (n <= -1)
|
||||||
|
{
|
||||||
|
/* TODO: translate more error codes to http error codes... */
|
||||||
|
if (httpd->errnum == QSE_HTTPD_ENOENT) http_errnum = 404;
|
||||||
|
else if (httpd->errnum == QSE_HTTPD_EACCES ||
|
||||||
|
httpd->errnum == QSE_HTTPD_ECONN) http_errnum = 403;
|
||||||
|
|
||||||
|
#if defined(QSE_HTTPD_DEBUG)
|
||||||
|
{
|
||||||
|
qse_mchar_t tmp[128];
|
||||||
|
qse_nwadtombs (&proxy->peer->nwad, tmp, QSE_COUNTOF(tmp), QSE_NWADTOMBS_ALL);
|
||||||
|
HTTPD_DBGOUT1 ("Cannnot open peer [%hs]\n", tmp);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(QSE_HTTPD_DEBUG)
|
#if defined(QSE_HTTPD_DEBUG)
|
||||||
{
|
{
|
||||||
qse_mchar_t tmp[128];
|
qse_mchar_t tmp[128];
|
||||||
qse_nwadtombs (&proxy->peer.nwad, tmp, QSE_COUNTOF(tmp), QSE_NWADTOMBS_ALL);
|
qse_nwadtombs (&proxy->peer->nwad, tmp, QSE_COUNTOF(tmp), QSE_NWADTOMBS_ALL);
|
||||||
HTTPD_DBGOUT1 ("Cannnot open peer [%hs]\n", tmp);
|
HTTPD_DBGOUT2 ("Opened peer [%hs] - %zd\n", tmp, (qse_size_t)proxy->peer->handle);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
goto oops;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(QSE_HTTPD_DEBUG)
|
|
||||||
{
|
|
||||||
qse_mchar_t tmp[128];
|
|
||||||
qse_nwadtombs (&proxy->peer.nwad, tmp, QSE_COUNTOF(tmp), QSE_NWADTOMBS_ALL);
|
|
||||||
HTTPD_DBGOUT2 ("Opened peer [%hs] - %zd\n", tmp, (qse_size_t)proxy->peer.handle);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
proxy->peer_status |= PROXY_PEER_OPEN;
|
proxy->peer_status |= PROXY_PEER_OPEN;
|
||||||
task->trigger.v[0].mask = QSE_HTTPD_TASK_TRIGGER_READ;
|
task->trigger.v[0].mask = QSE_HTTPD_TASK_TRIGGER_READ;
|
||||||
task->trigger.v[0].handle = proxy->peer.handle;
|
task->trigger.v[0].handle = proxy->peer->handle;
|
||||||
/*task->trigger.cmask = QSE_HTTPD_TASK_TRIGGER_READ;*/
|
/*task->trigger.cmask = QSE_HTTPD_TASK_TRIGGER_READ;*/
|
||||||
task->trigger.cmask = 0;
|
task->trigger.cmask = 0;
|
||||||
|
|
||||||
|
@ -814,10 +814,10 @@ static void tmr_dns_tmout_handle (qse_tmr_t* tmr, const qse_ntime_t* now, qse_tm
|
|||||||
*---------------------------------------------------------------- */
|
*---------------------------------------------------------------- */
|
||||||
if (req->dns_retries > 0)
|
if (req->dns_retries > 0)
|
||||||
{
|
{
|
||||||
httpd_xtn_t* httpd_xtn;
|
/*httpd_xtn_t* httpd_xtn;*/
|
||||||
qse_tmr_event_t tmout_event;
|
qse_tmr_event_t tmout_event;
|
||||||
|
|
||||||
httpd_xtn = qse_httpd_getxtn (dc->httpd);
|
/*httpd_xtn = qse_httpd_getxtn (dc->httpd);*/
|
||||||
|
|
||||||
QSE_MEMSET (&tmout_event, 0, QSE_SIZEOF(tmout_event));
|
QSE_MEMSET (&tmout_event, 0, QSE_SIZEOF(tmout_event));
|
||||||
qse_gettime (&tmout_event.when);
|
qse_gettime (&tmout_event.when);
|
||||||
|
@ -274,7 +274,7 @@ static void urs_close (qse_httpd_t* httpd, qse_httpd_urs_t* urs)
|
|||||||
static int urs_recv (qse_httpd_t* httpd, qse_httpd_urs_t* urs, qse_httpd_hnd_t handle)
|
static int urs_recv (qse_httpd_t* httpd, qse_httpd_urs_t* urs, qse_httpd_hnd_t handle)
|
||||||
{
|
{
|
||||||
urs_ctx_t* dc = (urs_ctx_t*)urs->ctx;
|
urs_ctx_t* dc = (urs_ctx_t*)urs->ctx;
|
||||||
httpd_xtn_t* httpd_xtn;
|
/*httpd_xtn_t* httpd_xtn;*/
|
||||||
|
|
||||||
qse_skad_t fromaddr;
|
qse_skad_t fromaddr;
|
||||||
qse_sck_len_t fromlen;
|
qse_sck_len_t fromlen;
|
||||||
@ -285,9 +285,7 @@ static int urs_recv (qse_httpd_t* httpd, qse_httpd_urs_t* urs, qse_httpd_hnd_t h
|
|||||||
urs_req_t* req;
|
urs_req_t* req;
|
||||||
qse_mchar_t* spc;
|
qse_mchar_t* spc;
|
||||||
|
|
||||||
printf ("URS_RECV............................................\n");
|
/*httpd_xtn = qse_httpd_getxtn (httpd);*/
|
||||||
|
|
||||||
httpd_xtn = qse_httpd_getxtn (httpd);
|
|
||||||
|
|
||||||
/* TODO: use recvmsg with MSG_ERRQUEUE... set socket option IP_RECVERR... */
|
/* TODO: use recvmsg with MSG_ERRQUEUE... set socket option IP_RECVERR... */
|
||||||
fromlen = QSE_SIZEOF(fromaddr);
|
fromlen = QSE_SIZEOF(fromaddr);
|
||||||
@ -359,10 +357,10 @@ static void tmr_urs_tmout_handle (qse_tmr_t* tmr, const qse_ntime_t* now, qse_tm
|
|||||||
*---------------------------------------------------------------- */
|
*---------------------------------------------------------------- */
|
||||||
if (req->urs_retries > 0)
|
if (req->urs_retries > 0)
|
||||||
{
|
{
|
||||||
httpd_xtn_t* httpd_xtn;
|
/*httpd_xtn_t* httpd_xtn;*/
|
||||||
qse_tmr_event_t tmout_event;
|
qse_tmr_event_t tmout_event;
|
||||||
|
|
||||||
httpd_xtn = qse_httpd_getxtn (dc->httpd);
|
/*httpd_xtn = qse_httpd_getxtn (dc->httpd);*/
|
||||||
|
|
||||||
QSE_MEMSET (&tmout_event, 0, QSE_SIZEOF(tmout_event));
|
QSE_MEMSET (&tmout_event, 0, QSE_SIZEOF(tmout_event));
|
||||||
qse_gettime (&tmout_event.when);
|
qse_gettime (&tmout_event.when);
|
||||||
|
@ -1134,6 +1134,192 @@ oops:
|
|||||||
|
|
||||||
/* ------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static void client_close (qse_httpd_t* httpd, qse_httpd_client_t* client)
|
||||||
|
{
|
||||||
|
qse_shutsckhnd (client->handle, QSE_SHUTSCKHND_RW);
|
||||||
|
qse_closesckhnd (client->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void client_shutdown (qse_httpd_t* httpd, qse_httpd_client_t* client)
|
||||||
|
{
|
||||||
|
qse_shutsckhnd (client->handle, QSE_SHUTSCKHND_RW);
|
||||||
|
}
|
||||||
|
|
||||||
|
static qse_ssize_t client_recv (
|
||||||
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
||||||
|
qse_mchar_t* buf, qse_size_t bufsize)
|
||||||
|
{
|
||||||
|
if (client->status & QSE_HTTPD_CLIENT_SECURE)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_SSL)
|
||||||
|
int ret = SSL_read (HANDLE_TO_SSL(client->handle2), buf, bufsize);
|
||||||
|
if (ret <= -1)
|
||||||
|
{
|
||||||
|
int err = SSL_get_error(HANDLE_TO_SSL(client->handle2),ret);
|
||||||
|
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
|
||||||
|
qse_httpd_seterrnum (httpd, QSE_HTTPD_EAGAIN);
|
||||||
|
else
|
||||||
|
qse_httpd_seterrnum (httpd, QSE_HTTPD_ESYSERR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SSL_pending (HANDLE_TO_SSL(client->handle2)) > 0)
|
||||||
|
client->status |= QSE_HTTPD_CLIENT_PENDING;
|
||||||
|
else
|
||||||
|
client->status &= ~QSE_HTTPD_CLIENT_PENDING;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
|
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qse_ssize_t ret;
|
||||||
|
ret = recv (client->handle, buf, bufsize, 0);
|
||||||
|
if (ret <= -1) qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static qse_ssize_t client_send (
|
||||||
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
||||||
|
const qse_mchar_t* buf, qse_size_t bufsize)
|
||||||
|
{
|
||||||
|
if (client->status & QSE_HTTPD_CLIENT_SECURE)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_SSL)
|
||||||
|
int ret = SSL_write (HANDLE_TO_SSL(client->handle2), buf, bufsize);
|
||||||
|
if (ret <= -1)
|
||||||
|
{
|
||||||
|
int err = SSL_get_error(HANDLE_TO_SSL(client->handle2),ret);
|
||||||
|
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
|
||||||
|
qse_httpd_seterrnum (httpd, QSE_HTTPD_EAGAIN);
|
||||||
|
else
|
||||||
|
qse_httpd_seterrnum (httpd, QSE_HTTPD_ESYSERR);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
|
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qse_ssize_t ret = send (client->handle, buf, bufsize, 0);
|
||||||
|
if (ret <= -1) qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static qse_ssize_t client_sendfile (
|
||||||
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
||||||
|
qse_httpd_hnd_t handle, qse_foff_t* offset, qse_size_t count)
|
||||||
|
{
|
||||||
|
if (client->status & QSE_HTTPD_CLIENT_SECURE)
|
||||||
|
{
|
||||||
|
return __send_file_ssl (httpd, (void*)client->handle2, handle, offset, count);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return __send_file (httpd, client->handle, handle, offset, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int client_accepted (qse_httpd_t* httpd, qse_httpd_client_t* client)
|
||||||
|
{
|
||||||
|
if (client->status & QSE_HTTPD_CLIENT_SECURE)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_SSL)
|
||||||
|
int ret;
|
||||||
|
SSL* ssl;
|
||||||
|
server_xtn_t* server_xtn;
|
||||||
|
|
||||||
|
server_xtn = (server_xtn_t*)qse_httpd_getserverxtn (httpd, client->server);
|
||||||
|
|
||||||
|
|
||||||
|
if (!server_xtn->ssl_ctx)
|
||||||
|
{
|
||||||
|
/* performed the delayed ssl initialization */
|
||||||
|
if (init_server_ssl (httpd, client->server) <= -1) return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSE_ASSERT (server_xtn->ssl_ctx != QSE_NULL);
|
||||||
|
QSE_ASSERT (QSE_SIZEOF(client->handle2) >= QSE_SIZEOF(ssl));
|
||||||
|
|
||||||
|
if (HANDLE_TO_SSL(client->handle2))
|
||||||
|
{
|
||||||
|
ssl = HANDLE_TO_SSL(client->handle2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ssl = SSL_new (server_xtn->ssl_ctx);
|
||||||
|
if (ssl == QSE_NULL)
|
||||||
|
{
|
||||||
|
httpd->errnum = QSE_HTTPD_ESYSERR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
client->handle2 = SSL_TO_HANDLE(ssl);
|
||||||
|
if (SSL_set_fd (ssl, client->handle) == 0)
|
||||||
|
{
|
||||||
|
/* don't free ssl here since client_closed()
|
||||||
|
* will free it */
|
||||||
|
httpd->errnum = QSE_HTTPD_ESYSERR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSL_set_read_ahead (ssl, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = SSL_accept (ssl);
|
||||||
|
if (ret <= 0)
|
||||||
|
{
|
||||||
|
int err = SSL_get_error(ssl, ret);
|
||||||
|
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
|
||||||
|
{
|
||||||
|
/* handshaking isn't complete. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
||||||
|
{
|
||||||
|
qse_httpd_act_t msg;
|
||||||
|
msg.code = QSE_HTTPD_CATCH_MERRMSG;
|
||||||
|
ERR_error_string_n (err, msg.u.merrmsg, QSE_COUNTOF(msg.u.merrmsg));
|
||||||
|
httpd->opt.rcb.logact (httpd, &msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* client_closed() free this. no SSL_free() here.
|
||||||
|
SSL_free (ssl); */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; /* accept completed */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void client_closed (qse_httpd_t* httpd, qse_httpd_client_t* client)
|
||||||
|
{
|
||||||
|
if (client->status & QSE_HTTPD_CLIENT_SECURE)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_SSL)
|
||||||
|
if ((SSL*)client->handle2)
|
||||||
|
{
|
||||||
|
SSL_shutdown ((SSL*)client->handle2); /* is this needed? */
|
||||||
|
SSL_free ((SSL*)client->handle2);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
static int peer_open (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
|
static int peer_open (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
|
||||||
{
|
{
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
@ -2130,193 +2316,6 @@ static int dir_read (qse_httpd_t* httpd, qse_httpd_hnd_t handle, qse_httpd_diren
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
static void client_close (qse_httpd_t* httpd, qse_httpd_client_t* client)
|
|
||||||
{
|
|
||||||
qse_shutsckhnd (client->handle, QSE_SHUTSCKHND_RW);
|
|
||||||
qse_closesckhnd (client->handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void client_shutdown (qse_httpd_t* httpd, qse_httpd_client_t* client)
|
|
||||||
{
|
|
||||||
qse_shutsckhnd (client->handle, QSE_SHUTSCKHND_RW);
|
|
||||||
}
|
|
||||||
|
|
||||||
static qse_ssize_t client_recv (
|
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
|
||||||
qse_mchar_t* buf, qse_size_t bufsize)
|
|
||||||
{
|
|
||||||
if (client->status & QSE_HTTPD_CLIENT_SECURE)
|
|
||||||
{
|
|
||||||
#if defined(HAVE_SSL)
|
|
||||||
int ret = SSL_read (HANDLE_TO_SSL(client->handle2), buf, bufsize);
|
|
||||||
if (ret <= -1)
|
|
||||||
{
|
|
||||||
int err = SSL_get_error(HANDLE_TO_SSL(client->handle2),ret);
|
|
||||||
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
|
|
||||||
qse_httpd_seterrnum (httpd, QSE_HTTPD_EAGAIN);
|
|
||||||
else
|
|
||||||
qse_httpd_seterrnum (httpd, QSE_HTTPD_ESYSERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SSL_pending (HANDLE_TO_SSL(client->handle2)) > 0)
|
|
||||||
client->status |= QSE_HTTPD_CLIENT_PENDING;
|
|
||||||
else
|
|
||||||
client->status &= ~QSE_HTTPD_CLIENT_PENDING;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
#else
|
|
||||||
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
|
|
||||||
return -1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
qse_ssize_t ret;
|
|
||||||
ret = recv (client->handle, buf, bufsize, 0);
|
|
||||||
if (ret <= -1) qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static qse_ssize_t client_send (
|
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
|
||||||
const qse_mchar_t* buf, qse_size_t bufsize)
|
|
||||||
{
|
|
||||||
if (client->status & QSE_HTTPD_CLIENT_SECURE)
|
|
||||||
{
|
|
||||||
#if defined(HAVE_SSL)
|
|
||||||
int ret = SSL_write (HANDLE_TO_SSL(client->handle2), buf, bufsize);
|
|
||||||
if (ret <= -1)
|
|
||||||
{
|
|
||||||
int err = SSL_get_error(HANDLE_TO_SSL(client->handle2),ret);
|
|
||||||
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
|
|
||||||
qse_httpd_seterrnum (httpd, QSE_HTTPD_EAGAIN);
|
|
||||||
else
|
|
||||||
qse_httpd_seterrnum (httpd, QSE_HTTPD_ESYSERR);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
#else
|
|
||||||
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
|
|
||||||
return -1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
qse_ssize_t ret = send (client->handle, buf, bufsize, 0);
|
|
||||||
if (ret <= -1) qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static qse_ssize_t client_sendfile (
|
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
|
||||||
qse_httpd_hnd_t handle, qse_foff_t* offset, qse_size_t count)
|
|
||||||
{
|
|
||||||
if (client->status & QSE_HTTPD_CLIENT_SECURE)
|
|
||||||
{
|
|
||||||
return __send_file_ssl (httpd, (void*)client->handle2, handle, offset, count);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return __send_file (httpd, client->handle, handle, offset, count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int client_accepted (qse_httpd_t* httpd, qse_httpd_client_t* client)
|
|
||||||
{
|
|
||||||
if (client->status & QSE_HTTPD_CLIENT_SECURE)
|
|
||||||
{
|
|
||||||
#if defined(HAVE_SSL)
|
|
||||||
int ret;
|
|
||||||
SSL* ssl;
|
|
||||||
server_xtn_t* server_xtn;
|
|
||||||
|
|
||||||
server_xtn = (server_xtn_t*)qse_httpd_getserverxtn (httpd, client->server);
|
|
||||||
|
|
||||||
|
|
||||||
if (!server_xtn->ssl_ctx)
|
|
||||||
{
|
|
||||||
/* performed the delayed ssl initialization */
|
|
||||||
if (init_server_ssl (httpd, client->server) <= -1) return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSE_ASSERT (server_xtn->ssl_ctx != QSE_NULL);
|
|
||||||
QSE_ASSERT (QSE_SIZEOF(client->handle2) >= QSE_SIZEOF(ssl));
|
|
||||||
|
|
||||||
if (HANDLE_TO_SSL(client->handle2))
|
|
||||||
{
|
|
||||||
ssl = HANDLE_TO_SSL(client->handle2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ssl = SSL_new (server_xtn->ssl_ctx);
|
|
||||||
if (ssl == QSE_NULL)
|
|
||||||
{
|
|
||||||
httpd->errnum = QSE_HTTPD_ESYSERR;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
client->handle2 = SSL_TO_HANDLE(ssl);
|
|
||||||
if (SSL_set_fd (ssl, client->handle) == 0)
|
|
||||||
{
|
|
||||||
/* don't free ssl here since client_closed()
|
|
||||||
* will free it */
|
|
||||||
httpd->errnum = QSE_HTTPD_ESYSERR;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
SSL_set_read_ahead (ssl, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = SSL_accept (ssl);
|
|
||||||
if (ret <= 0)
|
|
||||||
{
|
|
||||||
int err = SSL_get_error(ssl, ret);
|
|
||||||
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
|
|
||||||
{
|
|
||||||
/* handshaking isn't complete. */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
|
||||||
{
|
|
||||||
qse_httpd_act_t msg;
|
|
||||||
msg.code = QSE_HTTPD_CATCH_MERRMSG;
|
|
||||||
ERR_error_string_n (err, msg.u.merrmsg, QSE_COUNTOF(msg.u.merrmsg));
|
|
||||||
httpd->opt.rcb.logact (httpd, &msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* client_closed() free this. no SSL_free() here.
|
|
||||||
SSL_free (ssl); */
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
|
|
||||||
return -1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1; /* accept completed */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void client_closed (qse_httpd_t* httpd, qse_httpd_client_t* client)
|
|
||||||
{
|
|
||||||
if (client->status & QSE_HTTPD_CLIENT_SECURE)
|
|
||||||
{
|
|
||||||
#if defined(HAVE_SSL)
|
|
||||||
if ((SSL*)client->handle2)
|
|
||||||
{
|
|
||||||
SSL_shutdown ((SSL*)client->handle2); /* is this needed? */
|
|
||||||
SSL_free ((SSL*)client->handle2);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------- */
|
||||||
#if 0
|
#if 0
|
||||||
static qse_htb_walk_t walk (qse_htb_t* htb, qse_htb_pair_t* pair, void* ctx)
|
static qse_htb_walk_t walk (qse_htb_t* htb, qse_htb_pair_t* pair, void* ctx)
|
||||||
@ -2606,6 +2605,18 @@ static qse_httpd_scb_t httpd_system_callbacks =
|
|||||||
server_accept
|
server_accept
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/* client connection */
|
||||||
|
{
|
||||||
|
client_close,
|
||||||
|
client_shutdown,
|
||||||
|
client_recv,
|
||||||
|
client_send,
|
||||||
|
client_sendfile,
|
||||||
|
client_accepted,
|
||||||
|
client_closed
|
||||||
|
},
|
||||||
|
|
||||||
|
/* proxy peer */
|
||||||
{
|
{
|
||||||
peer_open,
|
peer_open,
|
||||||
peer_close,
|
peer_close,
|
||||||
@ -2647,17 +2658,6 @@ static qse_httpd_scb_t httpd_system_callbacks =
|
|||||||
dir_read
|
dir_read
|
||||||
},
|
},
|
||||||
|
|
||||||
/* client connection */
|
|
||||||
{
|
|
||||||
client_close,
|
|
||||||
client_shutdown,
|
|
||||||
client_recv,
|
|
||||||
client_send,
|
|
||||||
client_sendfile,
|
|
||||||
client_accepted,
|
|
||||||
client_closed
|
|
||||||
},
|
|
||||||
|
|
||||||
/* dns */
|
/* dns */
|
||||||
{
|
{
|
||||||
dns_open,
|
dns_open,
|
||||||
|
@ -406,8 +406,7 @@ static qse_httpd_real_task_t* enqueue_task (
|
|||||||
return new_task;
|
return new_task;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QSE_INLINE int dequeue_task (
|
static QSE_INLINE int dequeue_task (qse_httpd_t* httpd, qse_httpd_client_t* client)
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client)
|
|
||||||
{
|
{
|
||||||
qse_httpd_real_task_t* task;
|
qse_httpd_real_task_t* task;
|
||||||
qse_size_t i;
|
qse_size_t i;
|
||||||
@ -447,14 +446,134 @@ static QSE_INLINE int dequeue_task (
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QSE_INLINE void purge_tasks (
|
static QSE_INLINE void purge_tasks (qse_httpd_t* httpd, qse_httpd_client_t* client)
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client)
|
|
||||||
{
|
{
|
||||||
while (dequeue_task (httpd, client) == 0);
|
while (dequeue_task (httpd, client) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
/* ----------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static QSE_INLINE void unchain_cached_proxy_peer (qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_peer_t* peer)
|
||||||
|
{
|
||||||
|
QSE_ASSERT (peer->flags & QSE_HTTPD_PEER_CACHED);
|
||||||
|
|
||||||
|
if (peer->next) peer->next->prev = peer->prev;
|
||||||
|
else client->peer.last = peer->prev;
|
||||||
|
|
||||||
|
if (peer->prev) peer->prev->next = peer->next;
|
||||||
|
else client->peer.first = peer->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void purge_cached_proxy_peer (qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_peer_t* peer)
|
||||||
|
{
|
||||||
|
unchain_cached_proxy_peer (httpd, client, peer);
|
||||||
|
|
||||||
|
#if defined(QSE_HTTPD_DEBUG)
|
||||||
|
{
|
||||||
|
qse_mchar_t tmp[128];
|
||||||
|
|
||||||
|
qse_nwadtombs (&peer->nwad, tmp, QSE_COUNTOF(tmp), QSE_NWADTOMBS_ALL);
|
||||||
|
HTTPD_DBGOUT2 ("Closing cached peer [%hs] - %zd\n", tmp, (qse_size_t)peer->handle);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
httpd->opt.scb.peer.close (httpd, peer);
|
||||||
|
qse_httpd_freemem (httpd, peer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void purge_cached_proxy_peers (qse_httpd_t* httpd, qse_httpd_client_t* client)
|
||||||
|
{
|
||||||
|
while (client->peer.first)
|
||||||
|
{
|
||||||
|
purge_cached_proxy_peer (httpd, client, client->peer.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_httpd_peer_t* qse_httpd_cacheproxypeer (qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_peer_t* tmpl)
|
||||||
|
{
|
||||||
|
qse_httpd_peer_t* peer;
|
||||||
|
|
||||||
|
if (tmpl->flags & QSE_HTTPD_PEER_CACHED)
|
||||||
|
{
|
||||||
|
/* If QSE_HTTPD_PEER_CACHED is set, tmpl points to a block allocated
|
||||||
|
* here previously. Link such a block to the cache list */
|
||||||
|
peer = tmpl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Clone the peer object if it's not previsouly allocated here */
|
||||||
|
peer = qse_httpd_allocmem (httpd, QSE_SIZEOF(*peer));
|
||||||
|
if (peer == QSE_NULL) goto oops;
|
||||||
|
|
||||||
|
QSE_MEMCPY (peer, tmpl, QSE_SIZEOF(*peer));
|
||||||
|
peer->flags |= QSE_HTTPD_PEER_CACHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* place the peer at the back of the peer list of a client */
|
||||||
|
if (client->peer.last)
|
||||||
|
{
|
||||||
|
peer->next = QSE_NULL;
|
||||||
|
peer->prev = client->peer.last;
|
||||||
|
client->peer.last->next = peer;
|
||||||
|
client->peer.last = peer;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
peer->next = QSE_NULL;
|
||||||
|
peer->prev = QSE_NULL;
|
||||||
|
client->peer.first = peer;
|
||||||
|
client->peer.last = peer;
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_gettime (&peer->timestamp);
|
||||||
|
return peer;
|
||||||
|
|
||||||
|
oops:
|
||||||
|
if (peer) qse_httpd_freemem (httpd, peer);
|
||||||
|
return QSE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_httpd_peer_t* qse_httpd_decacheproxypeer (
|
||||||
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
||||||
|
const qse_nwad_t* nwad, const qse_nwad_t* local, int secure)
|
||||||
|
{
|
||||||
|
qse_httpd_peer_t* peer, * next;
|
||||||
|
qse_ntime_t now, diff;
|
||||||
|
static qse_ntime_t diff_limit = { 5, 0 }; /* TODO: make this configurable */
|
||||||
|
|
||||||
|
qse_gettime (&now);
|
||||||
|
|
||||||
|
peer = client->peer.first;
|
||||||
|
while (peer)
|
||||||
|
{
|
||||||
|
next = peer->next;
|
||||||
|
|
||||||
|
qse_subtime (&now, &peer->timestamp, &diff);
|
||||||
|
if (qse_cmptime(&diff, &diff_limit) >= 0)
|
||||||
|
{
|
||||||
|
/* the entry is too old */
|
||||||
|
purge_cached_proxy_peer (httpd, client, peer);
|
||||||
|
}
|
||||||
|
else if (qse_nwadequal (nwad, &peer->nwad) && qse_nwadequal (local, &peer->local))
|
||||||
|
{
|
||||||
|
if ((secure && (peer->flags & QSE_HTTPD_PEER_SECURE)) ||
|
||||||
|
(!secure && !(peer->flags & QSE_HTTPD_PEER_SECURE)))
|
||||||
|
{
|
||||||
|
unchain_cached_proxy_peer (httpd, client, peer);
|
||||||
|
peer->next = QSE_NULL;
|
||||||
|
peer->prev = QSE_NULL;
|
||||||
|
return peer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
peer = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QSE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------- */
|
||||||
static int htrd_peek_request (qse_htrd_t* htrd, qse_htre_t* req)
|
static int htrd_peek_request (qse_htrd_t* htrd, qse_htre_t* req)
|
||||||
{
|
{
|
||||||
htrd_xtn_t* xtn = (htrd_xtn_t*) qse_htrd_getxtn (htrd);
|
htrd_xtn_t* xtn = (htrd_xtn_t*) qse_htrd_getxtn (htrd);
|
||||||
@ -560,12 +679,12 @@ oops:
|
|||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_client (
|
static void free_client (qse_httpd_t* httpd, qse_httpd_client_t* client)
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client)
|
|
||||||
{
|
{
|
||||||
QSE_ASSERT (client->htrd != QSE_NULL);
|
QSE_ASSERT (client->htrd != QSE_NULL);
|
||||||
|
|
||||||
purge_tasks (httpd, client);
|
purge_tasks (httpd, client);
|
||||||
|
purge_cached_proxy_peers (httpd, client);
|
||||||
|
|
||||||
qse_htrd_close (client->htrd);
|
qse_htrd_close (client->htrd);
|
||||||
|
|
||||||
@ -611,7 +730,7 @@ static void purge_client (qse_httpd_t* httpd, qse_httpd_client_t* client)
|
|||||||
{
|
{
|
||||||
qse_mchar_t tmp[128];
|
qse_mchar_t tmp[128];
|
||||||
qse_nwadtombs (&client->remote_addr, tmp, QSE_COUNTOF(tmp), QSE_NWADTOMBS_ALL);
|
qse_nwadtombs (&client->remote_addr, tmp, QSE_COUNTOF(tmp), QSE_NWADTOMBS_ALL);
|
||||||
HTTPD_DBGOUT2 ("Purged client [%hs] - %zd\n", tmp, (qse_size_t)client->handle);
|
HTTPD_DBGOUT2 ("Purging client [%hs] - %zd\n", tmp, (qse_size_t)client->handle);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -192,6 +192,20 @@ void qse_httpd_remove_timer_event (
|
|||||||
qse_tmr_index_t index
|
qse_tmr_index_t index
|
||||||
);
|
);
|
||||||
|
|
||||||
|
qse_httpd_peer_t* qse_httpd_cacheproxypeer (
|
||||||
|
qse_httpd_t* httpd,
|
||||||
|
qse_httpd_client_t* client,
|
||||||
|
qse_httpd_peer_t* tmpl
|
||||||
|
);
|
||||||
|
|
||||||
|
qse_httpd_peer_t* qse_httpd_decacheproxypeer (
|
||||||
|
qse_httpd_t* httpd,
|
||||||
|
qse_httpd_client_t* client,
|
||||||
|
const qse_nwad_t* nwad,
|
||||||
|
const qse_nwad_t* local,
|
||||||
|
int secure
|
||||||
|
);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user