added https proxying without certificate check. this is different from CONNECT. when this feature is used, the proxy establishes a https connection to the origin server
This commit is contained in:
parent
ca272bb55e
commit
c9d23a0d8b
@ -199,6 +199,7 @@ struct loccfg_t
|
|||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned int allow_http: 1;
|
unsigned int allow_http: 1;
|
||||||
|
unsigned int allow_https: 1;
|
||||||
unsigned int allow_connect: 1;
|
unsigned int allow_connect: 1;
|
||||||
unsigned int allow_intercept: 2; /* 0: no, 1: proxy, 2: local */
|
unsigned int allow_intercept: 2; /* 0: no, 1: proxy, 2: local */
|
||||||
unsigned int allow_upgrade: 1;
|
unsigned int allow_upgrade: 1;
|
||||||
@ -468,6 +469,7 @@ static int get_server_root (
|
|||||||
{
|
{
|
||||||
qse_http_method_t mth;
|
qse_http_method_t mth;
|
||||||
qse_mchar_t* qpath;
|
qse_mchar_t* qpath;
|
||||||
|
int proto_len;
|
||||||
|
|
||||||
qse_memset (root, 0, QSE_SIZEOF(*root));
|
qse_memset (root, 0, QSE_SIZEOF(*root));
|
||||||
mth = qse_htre_getqmethodtype (qinfo->req);
|
mth = qse_htre_getqmethodtype (qinfo->req);
|
||||||
@ -534,13 +536,12 @@ static int get_server_root (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: handle https:// .... */
|
if ((loccfg->proxy.allow_http && qse_mbszcasecmp (qpath, QSE_MT("http://"), (proto_len = 7)) == 0) ||
|
||||||
if (loccfg->proxy.allow_http &&
|
(loccfg->proxy.allow_https && qse_mbszcasecmp (qpath, QSE_MT("https://"), (proto_len = 8)) == 0))
|
||||||
qse_mbszcasecmp (qpath, QSE_MT("http://"), 7) == 0)
|
|
||||||
{
|
{
|
||||||
qse_mchar_t* host, * slash;
|
qse_mchar_t* host, * slash;
|
||||||
|
|
||||||
host = qpath + 7;
|
host = qpath + proto_len;
|
||||||
slash = qse_mbschr (host, QSE_MT('/'));
|
slash = qse_mbschr (host, QSE_MT('/'));
|
||||||
|
|
||||||
if (slash && slash - host > 0)
|
if (slash && slash - host > 0)
|
||||||
@ -561,6 +562,7 @@ static int get_server_root (
|
|||||||
host = host - 1;
|
host = host - 1;
|
||||||
root->u.proxy.host = host;
|
root->u.proxy.host = host;
|
||||||
|
|
||||||
|
if (proto_len == 8) root->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_DST_SECURE;
|
||||||
if (qse_mbstonwad (host, &root->u.proxy.dst.nwad) <= -1)
|
if (qse_mbstonwad (host, &root->u.proxy.dst.nwad) <= -1)
|
||||||
{
|
{
|
||||||
root->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_DST_STR;
|
root->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_DST_STR;
|
||||||
@ -576,7 +578,6 @@ static int get_server_root (
|
|||||||
|
|
||||||
/* TODO: refrain from manipulating the request like this */
|
/* TODO: refrain from manipulating the request like this */
|
||||||
qinfo->req->u.q.path = slash; /* TODO: use setqpath or something... */
|
qinfo->req->u.q.path = slash; /* TODO: use setqpath or something... */
|
||||||
|
|
||||||
goto proxy_ok;
|
goto proxy_ok;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1513,6 +1514,11 @@ static int load_loccfg_proxy (qse_httpd_t* httpd, qse_xli_t* xli, qse_xli_list_t
|
|||||||
if (!pair && default_proxy) pair = qse_xli_findpair (xli, default_proxy, QSE_T("http")); /* server-default.proxy.http */
|
if (!pair && default_proxy) pair = qse_xli_findpair (xli, default_proxy, QSE_T("http")); /* server-default.proxy.http */
|
||||||
if (pair) cfg->proxy.allow_http = get_boolean ((qse_xli_str_t*)pair->val);
|
if (pair) cfg->proxy.allow_http = get_boolean ((qse_xli_str_t*)pair->val);
|
||||||
|
|
||||||
|
pair = QSE_NULL;
|
||||||
|
if (proxy) pair = qse_xli_findpair (xli, proxy, QSE_T("https")); /* server.host[].location[].proxy.https */
|
||||||
|
if (!pair && default_proxy) pair = qse_xli_findpair (xli, default_proxy, QSE_T("https")); /* server-default.proxy.https */
|
||||||
|
if (pair) cfg->proxy.allow_https = get_boolean ((qse_xli_str_t*)pair->val);
|
||||||
|
|
||||||
pair = QSE_NULL;
|
pair = QSE_NULL;
|
||||||
if (proxy) pair = qse_xli_findpair (xli, proxy, QSE_T("connect"));
|
if (proxy) pair = qse_xli_findpair (xli, proxy, QSE_T("connect"));
|
||||||
if (!pair && default_proxy) pair = qse_xli_findpair (xli, default_proxy, QSE_T("connect"));
|
if (!pair && default_proxy) pair = qse_xli_findpair (xli, default_proxy, QSE_T("connect"));
|
||||||
@ -2067,6 +2073,7 @@ static int open_config_file (qse_httpd_t* httpd)
|
|||||||
{ QSE_T("server-default.error-foot"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
|
{ QSE_T("server-default.error-foot"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
|
||||||
{ QSE_T("server-default.proxy"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } },
|
{ QSE_T("server-default.proxy"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } },
|
||||||
{ QSE_T("server-default.proxy.http"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
|
{ QSE_T("server-default.proxy.http"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
|
||||||
|
{ QSE_T("server-default.proxy.https"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
|
||||||
{ QSE_T("server-default.proxy.connect"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
|
{ QSE_T("server-default.proxy.connect"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
|
||||||
{ QSE_T("server-default.proxy.intercept"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
|
{ QSE_T("server-default.proxy.intercept"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
|
||||||
{ QSE_T("server-default.proxy.upgrade"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
|
{ QSE_T("server-default.proxy.upgrade"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
|
||||||
@ -2125,6 +2132,7 @@ static int open_config_file (qse_httpd_t* httpd)
|
|||||||
{ QSE_T("server.host.location.error-foot"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
|
{ QSE_T("server.host.location.error-foot"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
|
||||||
{ QSE_T("server.host.location.proxy"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } },
|
{ QSE_T("server.host.location.proxy"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } },
|
||||||
{ QSE_T("server.host.location.proxy.http"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
|
{ QSE_T("server.host.location.proxy.http"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
|
||||||
|
{ QSE_T("server.host.location.proxy.https"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
|
||||||
{ QSE_T("server.host.location.proxy.connect"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
|
{ QSE_T("server.host.location.proxy.connect"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
|
||||||
{ QSE_T("server.host.location.proxy.intercept"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
|
{ QSE_T("server.host.location.proxy.intercept"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
|
||||||
{ QSE_T("server.host.location.proxy.upgrade"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
|
{ QSE_T("server.host.location.proxy.upgrade"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
|
||||||
|
@ -58,7 +58,8 @@ enum qse_httpd_errnum_t
|
|||||||
QSE_HTTPD_EAGAIN,
|
QSE_HTTPD_EAGAIN,
|
||||||
|
|
||||||
QSE_HTTPD_ENOSVR, /* no active servers */
|
QSE_HTTPD_ENOSVR, /* no active servers */
|
||||||
QSE_HTTPD_ECONN,
|
QSE_HTTPD_ECONN, /* connection failure */
|
||||||
|
QSE_HTTPD_ESCONN, /* secure connection failure */
|
||||||
QSE_HTTPD_ENOBUF, /* no buffer available */
|
QSE_HTTPD_ENOBUF, /* no buffer available */
|
||||||
QSE_HTTPD_EDISCON, /* client disconnnected */
|
QSE_HTTPD_EDISCON, /* client disconnnected */
|
||||||
QSE_HTTPD_EBADREQ, /* bad request */
|
QSE_HTTPD_EBADREQ, /* bad request */
|
||||||
@ -146,12 +147,31 @@ struct qse_httpd_stat_t
|
|||||||
qse_ntime_t mtime;
|
qse_ntime_t mtime;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum qse_httpd_peer_flag_t
|
||||||
|
{
|
||||||
|
QSE_HTTPD_PEER_SECURE = (1 << 0),
|
||||||
|
|
||||||
|
/* ---------------------------------- */
|
||||||
|
|
||||||
|
/* indicate the underlying socket is connected. internal use only. don't set it */
|
||||||
|
QSE_HTTPD_PEER_CONNECTED = (1 << 20),
|
||||||
|
|
||||||
|
/* internal use only */
|
||||||
|
QSE_HTTPD_PEER_PENDING = (1 << 21),
|
||||||
|
|
||||||
|
/* all internal enumerators */
|
||||||
|
QSE_HTTPD_PEER_ALL_INTERNALS = (QSE_HTTPD_PEER_CONNECTED | QSE_HTTPD_PEER_PENDING)
|
||||||
|
};
|
||||||
|
typedef enum qse_httpd_peer_flag_t qse_httpd_peer_flag_t;
|
||||||
|
|
||||||
typedef struct qse_httpd_peer_t qse_httpd_peer_t;
|
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 */
|
||||||
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 */
|
||||||
qse_httpd_hnd_t handle;
|
qse_httpd_hnd_t handle;
|
||||||
|
qse_httpd_hnd_t handle2;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum qse_httpd_mux_mask_t
|
enum qse_httpd_mux_mask_t
|
||||||
@ -529,7 +549,7 @@ typedef struct qse_httpd_task_trigger_t qse_httpd_task_trigger_t;
|
|||||||
struct qse_httpd_task_trigger_t
|
struct qse_httpd_task_trigger_t
|
||||||
{
|
{
|
||||||
int flags; /**< [IN] bitwise-ORed of #qse_httpd_task_trigger_flag_t enumerators*/
|
int flags; /**< [IN] bitwise-ORed of #qse_httpd_task_trigger_flag_t enumerators*/
|
||||||
int cmask; /* client mask - QSE_HTTPD_TASK_TRIGGER_READ | QSE_HTTPD_TASK_TRIGGER_WRITE */
|
unsigned int cmask; /* client mask - QSE_HTTPD_TASK_TRIGGER_READ | QSE_HTTPD_TASK_TRIGGER_WRITE */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
int mask; /* QSE_HTTPD_TASK_TRIGGER_READ | QSE_HTTPD_TASK_TRIGGER_WRITE */
|
int mask; /* QSE_HTTPD_TASK_TRIGGER_READ | QSE_HTTPD_TASK_TRIGGER_WRITE */
|
||||||
@ -772,10 +792,11 @@ enum qse_httpd_rsrc_proxy_flag_t
|
|||||||
QSE_HTTPD_RSRC_PROXY_ALLOW_UPGRADE = (1 << 2), /* allow protocol upgrade */
|
QSE_HTTPD_RSRC_PROXY_ALLOW_UPGRADE = (1 << 2), /* allow protocol upgrade */
|
||||||
QSE_HTTPD_RSRC_PROXY_X_FORWARDED = (1 << 3), /* add x-forwarded-for and x-forwarded-proto */
|
QSE_HTTPD_RSRC_PROXY_X_FORWARDED = (1 << 3), /* add x-forwarded-for and x-forwarded-proto */
|
||||||
QSE_HTTPD_RSRC_PROXY_DST_STR = (1 << 4), /* destination is an unresovled string pointed to by dst.str */
|
QSE_HTTPD_RSRC_PROXY_DST_STR = (1 << 4), /* destination is an unresovled string pointed to by dst.str */
|
||||||
QSE_HTTPD_RSRC_PROXY_ENABLE_DNS = (1 << 5), /* dns service enabled (udp) */
|
QSE_HTTPD_RSRC_PROXY_DST_SECURE = (1 << 5), /* use secure connection to destination */
|
||||||
QSE_HTTPD_RSRC_PROXY_ENABLE_URS = (1 << 6), /* url rewriting enabled (udp) */
|
QSE_HTTPD_RSRC_PROXY_ENABLE_DNS = (1 << 6), /* dns service enabled (udp) */
|
||||||
QSE_HTTPD_RSRC_PROXY_DNS_SERVER = (1 << 7), /* dns address specified */
|
QSE_HTTPD_RSRC_PROXY_ENABLE_URS = (1 << 7), /* url rewriting enabled (udp) */
|
||||||
QSE_HTTPD_RSRC_PROXY_URS_SERVER = (1 << 8), /* urs address specified */
|
QSE_HTTPD_RSRC_PROXY_DNS_SERVER = (1 << 8), /* dns address specified */
|
||||||
|
QSE_HTTPD_RSRC_PROXY_URS_SERVER = (1 << 9), /* urs address specified */
|
||||||
};
|
};
|
||||||
typedef enum qse_httpd_rsrc_proxy_flag_t qse_httpd_rsrc_proxy_flag_t;
|
typedef enum qse_httpd_rsrc_proxy_flag_t qse_httpd_rsrc_proxy_flag_t;
|
||||||
|
|
||||||
|
@ -35,31 +35,31 @@ struct task_proxy_arg_t
|
|||||||
typedef struct task_proxy_t task_proxy_t;
|
typedef struct task_proxy_t task_proxy_t;
|
||||||
struct task_proxy_t
|
struct task_proxy_t
|
||||||
{
|
{
|
||||||
#define PROXY_INIT_FAILED (1 << 0)
|
#define PROXY_INIT_FAILED (1u << 0)
|
||||||
#define PROXY_RAW (1 << 1)
|
#define PROXY_RAW (1u << 1)
|
||||||
#define PROXY_TRANSPARENT (1 << 2)
|
#define PROXY_TRANSPARENT (1u << 2)
|
||||||
#define PROXY_DNS_SERVER (1 << 3) /* dns server address specified */
|
#define PROXY_DNS_SERVER (1u << 3) /* dns server address specified */
|
||||||
#define PROXY_URS_SERVER (1 << 4) /* urs server address specified */
|
#define PROXY_URS_SERVER (1u << 4) /* urs server address specified */
|
||||||
#define PROXY_OUTBAND_PEER_NAME (1 << 5) /* the peer_name pointer points to
|
#define PROXY_OUTBAND_PEER_NAME (1u << 5) /* the peer_name pointer points to
|
||||||
a separate memory chunk outside
|
a separate memory chunk outside
|
||||||
the task_proxy_t chunk. explicit
|
the task_proxy_t chunk. explicit
|
||||||
deallocatin is required */
|
deallocatin is required */
|
||||||
#define PROXY_RESOLVE_PEER_NAME (1 << 6)
|
#define PROXY_RESOLVE_PEER_NAME (1u << 6)
|
||||||
#define PROXY_PEER_NAME_RESOLVING (1 << 7)
|
#define PROXY_PEER_NAME_RESOLVING (1u << 7)
|
||||||
#define PROXY_PEER_NAME_RESOLVED (1 << 8)
|
#define PROXY_PEER_NAME_RESOLVED (1u << 8)
|
||||||
#define PROXY_PEER_NAME_UNRESOLVED (1 << 9)
|
#define PROXY_PEER_NAME_UNRESOLVED (1u << 9)
|
||||||
#define PROXY_REWRITE_URL (1 << 10)
|
#define PROXY_REWRITE_URL (1u << 10)
|
||||||
#define PROXY_URL_REWRITING (1 << 11)
|
#define PROXY_URL_REWRITING (1u << 11)
|
||||||
#define PROXY_URL_PREREWRITTEN (1 << 12) /* URL has been prerewritten in prerewrite(). */
|
#define PROXY_URL_PREREWRITTEN (1u << 12) /* URL has been prerewritten in prerewrite(). */
|
||||||
#define PROXY_URL_REWRITTEN (1 << 13)
|
#define PROXY_URL_REWRITTEN (1u << 13)
|
||||||
#define PROXY_URL_REDIRECTED (1 << 14)
|
#define PROXY_URL_REDIRECTED (1u << 14)
|
||||||
#define PROXY_X_FORWARDED (1 << 15) /* Add X-Forwarded-For and X-Forwarded-Proto */
|
#define PROXY_X_FORWARDED (1u << 15) /* Add X-Forwarded-For and X-Forwarded-Proto */
|
||||||
#define PROXY_VIA (1 << 16) /* Via: added to the request */
|
#define PROXY_VIA (1u << 16) /* Via: added to the request */
|
||||||
#define PROXY_VIA_RETURNING (1 << 17) /* Via: added to the response */
|
#define PROXY_VIA_RETURNING (1u << 17) /* Via: added to the response */
|
||||||
#define PROXY_ALLOW_UPGRADE (1 << 18)
|
#define PROXY_ALLOW_UPGRADE (1u << 18)
|
||||||
#define PROXY_UPGRADE_REQUESTED (1 << 19)
|
#define PROXY_UPGRADE_REQUESTED (1u << 19)
|
||||||
#define PROXY_PROTOCOL_SWITCHED (1 << 20)
|
#define PROXY_PROTOCOL_SWITCHED (1u << 20)
|
||||||
#define PROXY_GOT_BAD_REQUEST (1 << 21)
|
#define PROXY_GOT_BAD_REQUEST (1u << 21)
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
qse_httpd_t* httpd;
|
qse_httpd_t* httpd;
|
||||||
qse_httpd_client_t* client;
|
qse_httpd_client_t* client;
|
||||||
@ -899,7 +899,13 @@ static void adjust_peer_name_and_port (task_proxy_t* proxy)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
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 proxy->peer_port = QSE_HTTPD_DEFAULT_PORT;
|
else
|
||||||
|
{
|
||||||
|
if (proxy->peer.flags & QSE_HTTPD_PEER_SECURE)
|
||||||
|
proxy->peer_port = QSE_HTTPD_DEFAULT_SECURE_PORT;
|
||||||
|
else
|
||||||
|
proxy->peer_port = QSE_HTTPD_DEFAULT_PORT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -940,6 +946,8 @@ 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.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)
|
||||||
{
|
{
|
||||||
@ -1414,6 +1422,7 @@ static int task_main_proxy_4 (
|
|||||||
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
||||||
{
|
{
|
||||||
task_proxy_t* proxy = (task_proxy_t*)task->ctx;
|
task_proxy_t* proxy = (task_proxy_t*)task->ctx;
|
||||||
|
qse_ssize_t n;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
printf ("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger.cmask=%d\n",
|
printf ("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger.cmask=%d\n",
|
||||||
@ -1425,8 +1434,7 @@ printf ("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger.cmask=%
|
|||||||
if ((task->trigger.v[0].mask & QSE_HTTPD_TASK_TRIGGER_READABLE) &&
|
if ((task->trigger.v[0].mask & QSE_HTTPD_TASK_TRIGGER_READABLE) &&
|
||||||
proxy->buflen < QSE_SIZEOF(proxy->buf))
|
proxy->buflen < QSE_SIZEOF(proxy->buf))
|
||||||
{
|
{
|
||||||
qse_ssize_t n;
|
reread:
|
||||||
|
|
||||||
/* 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 (
|
||||||
@ -1521,7 +1529,6 @@ printf ("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger.cmask=%
|
|||||||
* side is writable. it should be safe to write whenever
|
* side is writable. it should be safe to write whenever
|
||||||
* this task function is called. even if it's not writable,
|
* this task function is called. even if it's not writable,
|
||||||
* it should still be ok as the client socket is non-blocking. */
|
* it should still be ok as the client socket is non-blocking. */
|
||||||
qse_ssize_t n;
|
|
||||||
|
|
||||||
httpd->errnum = QSE_HTTPD_ENOERR;
|
httpd->errnum = QSE_HTTPD_ENOERR;
|
||||||
n = httpd->opt.scb.client.send (httpd, client, proxy->buf, proxy->buflen);
|
n = httpd->opt.scb.client.send (httpd, client, proxy->buf, proxy->buflen);
|
||||||
@ -1542,6 +1549,24 @@ printf ("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger.cmask=%
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (proxy->peer.flags & QSE_HTTPD_PEER_PENDING)
|
||||||
|
{
|
||||||
|
/* this QSE_HTTPD_CLIENT_PENDING thing is a dirty hack for SSL.
|
||||||
|
* In SSL, data is transmitted in a record. a record can be
|
||||||
|
* as large as 16K bytes since its length field is 2 bytes.
|
||||||
|
* If SSL_read() has a record but it's given a smaller buffer
|
||||||
|
* than the actual record, the next call to select() won't return.
|
||||||
|
* there is no data to read at the socket layer. SSL_pending() can
|
||||||
|
* tell you the amount of data in the SSL buffer. I try to consume
|
||||||
|
* the pending data if the client.recv handler has set QSE_HTTPD_CLIENT_PENDING. */
|
||||||
|
|
||||||
|
/* BUG BUG BUG.
|
||||||
|
* it jumps back to read more. If the client-side is not writable,
|
||||||
|
* unnecessary loop is made between this 'goto' and the target label.
|
||||||
|
* HOW SHOULD I SOLVE THIS? USE A BIG BUFFER AS LARGE AS 16K? */
|
||||||
|
/*if (proxy->buflen < QSE_SIZEOF(proxy->buf))*/ goto reread;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2059,17 +2084,20 @@ printf ("XXXXXXXXXXXXXXXXXXXXXXXXXX URL REWRITTEN TO [%s].....\n", new_url);
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
int proto_len;
|
||||||
|
|
||||||
QSE_ASSERT (QSE_STR_LEN(proxy->reqfwdbuf) > 0);
|
QSE_ASSERT (QSE_STR_LEN(proxy->reqfwdbuf) > 0);
|
||||||
|
|
||||||
/* TODO: Host rewriting?? */
|
/* TODO: Host rewriting?? */
|
||||||
/* TODO: Host rewriting - to support it, headers must be made available thru request cloning.
|
/* TODO: Host rewriting - to support it, headers must be made available thru request cloning.
|
||||||
* the request may not be valid after task_init_proxy */
|
* the request may not be valid after task_init_proxy */
|
||||||
|
|
||||||
if (qse_mbszcasecmp (new_url, QSE_MT("http://"), 7) == 0)
|
if (qse_mbszcasecmp (new_url, QSE_MT("http://"), (proto_len = 7)) == 0 ||
|
||||||
|
qse_mbszcasecmp (new_url, QSE_MT("https://"), (proto_len = 8)) == 0)
|
||||||
{
|
{
|
||||||
const qse_mchar_t* host;
|
const qse_mchar_t* host;
|
||||||
|
|
||||||
host = new_url + 7;
|
host = new_url + proto_len;
|
||||||
if (host[0] != QSE_MT('/') && host[0] != QSE_MT('\0'))
|
if (host[0] != QSE_MT('/') && host[0] != QSE_MT('\0'))
|
||||||
{
|
{
|
||||||
const qse_mchar_t* slash;
|
const qse_mchar_t* slash;
|
||||||
@ -2093,6 +2121,12 @@ printf ("XXXXXXXXXXXXXXXXXXXXXXXXXX URL REWRITTEN TO [%s].....\n", new_url);
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: antything todo when http is rewritten to HTTPS or vice versa */
|
||||||
|
if (proto_len == 8)
|
||||||
|
proxy->peer.flags |= QSE_HTTPD_PEER_SECURE;
|
||||||
|
else
|
||||||
|
proxy->peer.flags &= ~QSE_HTTPD_PEER_SECURE;
|
||||||
|
|
||||||
if (qse_mbstonwad (tmp, &nwad) <= -1)
|
if (qse_mbstonwad (tmp, &nwad) <= -1)
|
||||||
{
|
{
|
||||||
proxy->flags |= PROXY_RESOLVE_PEER_NAME | PROXY_OUTBAND_PEER_NAME;
|
proxy->flags |= PROXY_RESOLVE_PEER_NAME | PROXY_OUTBAND_PEER_NAME;
|
||||||
@ -2104,7 +2138,7 @@ printf ("XXXXXXXXXXXXXXXXXXXXXXXXXX URL REWRITTEN TO [%s].....\n", new_url);
|
|||||||
if (qse_getnwadport(&nwad) == 0)
|
if (qse_getnwadport(&nwad) == 0)
|
||||||
{
|
{
|
||||||
/* i don't care if tmp is X.X.X.X:0 or just X.X.X.X */
|
/* i don't care if tmp is X.X.X.X:0 or just X.X.X.X */
|
||||||
qse_setnwadport (&nwad, qse_hton16(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;
|
||||||
|
@ -577,7 +577,8 @@ typedef struct httpd_xtn_t httpd_xtn_t;
|
|||||||
struct httpd_xtn_t
|
struct httpd_xtn_t
|
||||||
{
|
{
|
||||||
#if defined(HAVE_SSL)
|
#if defined(HAVE_SSL)
|
||||||
SSL_CTX* ssl_ctx;
|
SSL_CTX* ssl_client_ctx;
|
||||||
|
SSL_CTX* ssl_peer_ctx;
|
||||||
#endif
|
#endif
|
||||||
qse_httpd_ecb_t ecb;
|
qse_httpd_ecb_t ecb;
|
||||||
qse_httpd_dnsstd_t dns;
|
qse_httpd_dnsstd_t dns;
|
||||||
@ -587,7 +588,8 @@ struct httpd_xtn_t
|
|||||||
#if defined(HAVE_SSL)
|
#if defined(HAVE_SSL)
|
||||||
static int init_xtn_ssl (qse_httpd_t* httpd, qse_httpd_server_t* server)
|
static int init_xtn_ssl (qse_httpd_t* httpd, qse_httpd_server_t* server)
|
||||||
{
|
{
|
||||||
SSL_CTX* ctx;
|
/* BUG BUG BUG. SSL context for client must exist inside the seerver, i guess */
|
||||||
|
SSL_CTX* client_ctx = QSE_NULL;
|
||||||
httpd_xtn_t* xtn;
|
httpd_xtn_t* xtn;
|
||||||
server_xtn_t* server_xtn;
|
server_xtn_t* server_xtn;
|
||||||
qse_httpd_serverstd_ssl_t ssl;
|
qse_httpd_serverstd_ssl_t ssl;
|
||||||
@ -597,24 +599,28 @@ static int init_xtn_ssl (qse_httpd_t* httpd, qse_httpd_server_t* server)
|
|||||||
|
|
||||||
if (server_xtn->query (httpd, server, QSE_HTTPD_SERVERSTD_SSL, QSE_NULL, &ssl) <= -1)
|
if (server_xtn->query (httpd, server, QSE_HTTPD_SERVERSTD_SSL, QSE_NULL, &ssl) <= -1)
|
||||||
{
|
{
|
||||||
return -1;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ssl.certfile == QSE_NULL || ssl.keyfile == QSE_NULL)
|
if (ssl.certfile == QSE_NULL || ssl.keyfile == QSE_NULL)
|
||||||
{
|
{
|
||||||
qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL);
|
qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL);
|
||||||
return -1;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = SSL_CTX_new (SSLv23_server_method());
|
client_ctx = SSL_CTX_new (SSLv23_server_method());
|
||||||
if (ctx == QSE_NULL) return -1;
|
if (!client_ctx)
|
||||||
|
{
|
||||||
|
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOMEM);
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
/*SSL_CTX_set_info_callback(ctx,ssl_info_callback);*/
|
/*SSL_CTX_set_info_callback(ctx,ssl_info_callback);*/
|
||||||
|
|
||||||
if (SSL_CTX_use_certificate_file (ctx, ssl.certfile, SSL_FILETYPE_PEM) == 0 ||
|
if (SSL_CTX_use_certificate_file (client_ctx, ssl.certfile, SSL_FILETYPE_PEM) == 0 ||
|
||||||
SSL_CTX_use_PrivateKey_file (ctx, ssl.keyfile, SSL_FILETYPE_PEM) == 0 ||
|
SSL_CTX_use_PrivateKey_file (client_ctx, ssl.keyfile, SSL_FILETYPE_PEM) == 0 ||
|
||||||
SSL_CTX_check_private_key (ctx) == 0 /*||
|
SSL_CTX_check_private_key (client_ctx) == 0 /*||
|
||||||
SSL_CTX_use_certificate_chain_file (ctx, chainfile) == 0*/)
|
SSL_CTX_use_certificate_chain_file (client_ctx, chainfile) == 0*/)
|
||||||
{
|
{
|
||||||
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
||||||
{
|
{
|
||||||
@ -626,25 +632,60 @@ static int init_xtn_ssl (qse_httpd_t* httpd, qse_httpd_server_t* server)
|
|||||||
httpd->opt.rcb.logact (httpd, &msg);
|
httpd->opt.rcb.logact (httpd, &msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
SSL_CTX_free (ctx);
|
qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL); /* TODO: define a better error code */
|
||||||
return -1;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* TODO: SSL_CTX_set_verify(); SSL_CTX_set_verify_depth() */
|
/* TODO: SSL_CTX_set_verify(); SSL_CTX_set_verify_depth() */
|
||||||
/* TODO: CRYPTO_set_id_callback (); */
|
/* TODO: CRYPTO_set_id_callback (); */
|
||||||
/* TODO: CRYPTO_set_locking_callback (); */
|
/* TODO: CRYPTO_set_locking_callback (); */
|
||||||
|
SSL_CTX_set_read_ahead (client_ctx, 0);
|
||||||
|
|
||||||
|
xtn->ssl_client_ctx = client_ctx;
|
||||||
|
|
||||||
SSL_CTX_set_read_ahead (ctx, 0);
|
|
||||||
xtn->ssl_ctx = ctx;
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
oops:
|
||||||
|
if (client_ctx) SSL_CTX_free (client_ctx);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fini_xtn_ssl (httpd_xtn_t* xtn)
|
static void fini_xtn_ssl (httpd_xtn_t* xtn)
|
||||||
{
|
{
|
||||||
/* TODO: CRYPTO_set_id_callback (QSE_NULL); */
|
/* TODO: CRYPTO_set_id_callback (QSE_NULL); */
|
||||||
/* TODO: CRYPTO_set_locking_callback (QSE_NULL); */
|
/* TODO: CRYPTO_set_locking_callback (QSE_NULL); */
|
||||||
SSL_CTX_free (xtn->ssl_ctx);
|
SSL_CTX_free (xtn->ssl_client_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int init_xtn_peer_ssl (qse_httpd_t* httpd)
|
||||||
|
{
|
||||||
|
SSL_CTX* peer_ctx = QSE_NULL;
|
||||||
|
httpd_xtn_t* xtn;
|
||||||
|
|
||||||
|
xtn = (httpd_xtn_t*)qse_httpd_getxtn (httpd);
|
||||||
|
|
||||||
|
peer_ctx = SSL_CTX_new (SSLv23_client_method());
|
||||||
|
if (!peer_ctx)
|
||||||
|
{
|
||||||
|
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOMEM);
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
xtn->ssl_peer_ctx = peer_ctx;
|
||||||
|
|
||||||
|
printf ("SSL PEER CTX ============>%p\n", xtn->ssl_peer_ctx);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
oops:
|
||||||
|
if (peer_ctx) SSL_CTX_free (peer_ctx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fini_xtn_peer_ssl (httpd_xtn_t* xtn)
|
||||||
|
{
|
||||||
|
/* TODO: CRYPTO_set_id_callback (QSE_NULL); */
|
||||||
|
/* TODO: CRYPTO_set_locking_callback (QSE_NULL); */
|
||||||
|
SSL_CTX_free (xtn->ssl_peer_ctx);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -656,7 +697,8 @@ static void cleanup_standard_httpd (qse_httpd_t* httpd)
|
|||||||
xtn = (httpd_xtn_t*)qse_httpd_getxtn (httpd);
|
xtn = (httpd_xtn_t*)qse_httpd_getxtn (httpd);
|
||||||
|
|
||||||
#if defined(HAVE_SSL)
|
#if defined(HAVE_SSL)
|
||||||
if (xtn->ssl_ctx) fini_xtn_ssl (xtn);
|
if (xtn->ssl_peer_ctx) fini_xtn_peer_ssl (xtn);
|
||||||
|
if (xtn->ssl_client_ctx) fini_xtn_ssl (xtn);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_LTDL)
|
#if defined(USE_LTDL)
|
||||||
@ -1069,6 +1111,10 @@ static int peer_open (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
|
|||||||
int connaddrsize, bindaddrsize;
|
int connaddrsize, bindaddrsize;
|
||||||
int connected = 1;
|
int connected = 1;
|
||||||
qse_sck_hnd_t fd = QSE_INVALID_SCKHND;
|
qse_sck_hnd_t fd = QSE_INVALID_SCKHND;
|
||||||
|
SSL* ssl = QSE_NULL;
|
||||||
|
httpd_xtn_t* xtn;
|
||||||
|
|
||||||
|
xtn = (httpd_xtn_t*) qse_httpd_getxtn (httpd);
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
unsigned long cmd;
|
unsigned long cmd;
|
||||||
@ -1080,6 +1126,9 @@ static int peer_open (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
|
|||||||
int flag;
|
int flag;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* turn off internally used bits */
|
||||||
|
peer->flags &= ~QSE_HTTPD_PEER_ALL_INTERNALS;
|
||||||
|
|
||||||
connaddrsize = qse_nwadtoskad (&peer->nwad, &connaddr);
|
connaddrsize = qse_nwadtoskad (&peer->nwad, &connaddr);
|
||||||
if (connaddrsize <= -1)
|
if (connaddrsize <= -1)
|
||||||
{
|
{
|
||||||
@ -1117,6 +1166,33 @@ static int peer_open (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
|
|||||||
|
|
||||||
if (set_socket_nonblock (httpd, fd, 1) <= -1) goto oops;
|
if (set_socket_nonblock (httpd, fd, 1) <= -1) goto oops;
|
||||||
|
|
||||||
|
if (peer->flags & QSE_HTTPD_PEER_SECURE)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_SSL)
|
||||||
|
if (!xtn->ssl_peer_ctx)
|
||||||
|
{
|
||||||
|
/* TODO: peer ssl initialization doesn't have to be delayed... */
|
||||||
|
if (init_xtn_peer_ssl (httpd) <= -1) goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssl = SSL_new (xtn->ssl_peer_ctx);
|
||||||
|
if (ssl == QSE_NULL)
|
||||||
|
{
|
||||||
|
qse_httpd_seterrnum (httpd, QSE_HTTPD_ESYSERR); /* TODO: better error code */
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SSL_set_fd (ssl, fd) == 0)
|
||||||
|
{
|
||||||
|
qse_httpd_seterrnum (httpd, QSE_HTTPD_ESYSERR); /* TODO: better error code */
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
|
||||||
|
goto oops;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
if (connect (fd, (struct sockaddr*)&connaddr, connaddrsize) <= -1)
|
if (connect (fd, (struct sockaddr*)&connaddr, connaddrsize) <= -1)
|
||||||
{
|
{
|
||||||
@ -1154,13 +1230,48 @@ static int peer_open (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*if (set_socket_nonblock (httpd, fd, 0) <= -1) goto oops;*/
|
if ((peer->flags & QSE_HTTPD_PEER_SECURE) && connected)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_SSL)
|
||||||
|
int ret = SSL_connect (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. */
|
||||||
|
peer->flags |= QSE_HTTPD_PEER_CONNECTED;
|
||||||
|
connected = 0; /* not fully connected yet */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qse_httpd_seterrnum (httpd, QSE_HTTPD_ESCONN);
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
peer->flags |= QSE_HTTPD_PEER_CONNECTED;
|
||||||
|
/* socket connected + ssl connected */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* take note the socket handle is in the non-blocking mode here */
|
||||||
peer->handle = fd;
|
peer->handle = fd;
|
||||||
|
if (peer->flags & QSE_HTTPD_PEER_SECURE)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_SSL)
|
||||||
|
peer->handle2 = SSL_TO_HANDLE(ssl);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
return connected;
|
return connected;
|
||||||
|
|
||||||
oops:
|
oops:
|
||||||
qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
|
qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
|
||||||
|
#if defined(HAVE_SSL)
|
||||||
|
if (ssl) SSL_free (ssl);
|
||||||
|
#endif
|
||||||
if (qse_isvalidsckhnd(fd)) qse_closesckhnd (fd);
|
if (qse_isvalidsckhnd(fd)) qse_closesckhnd (fd);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -1170,10 +1281,16 @@ oops:
|
|||||||
|
|
||||||
static void peer_close (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
|
static void peer_close (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
|
||||||
{
|
{
|
||||||
|
if (peer->flags & QSE_HTTPD_PEER_SECURE)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_SSL)
|
||||||
|
SSL_free (HANDLE_TO_SSL(peer->handle2));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
qse_closesckhnd (peer->handle);
|
qse_closesckhnd (peer->handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int peer_connected (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
|
static int is_peer_socket_connected (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
int len;
|
int len;
|
||||||
@ -1245,32 +1362,122 @@ static int peer_connected (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int is_peer_connected_securely (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
|
||||||
|
{
|
||||||
|
int ret = SSL_connect (HANDLE_TO_SSL(peer->handle2));
|
||||||
|
if (ret <= 0)
|
||||||
|
{
|
||||||
|
int err = SSL_get_error(HANDLE_TO_SSL(peer->handle2), ret);
|
||||||
|
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
|
||||||
|
{
|
||||||
|
/* handshaking isn't complete. */
|
||||||
|
return 0; /* not connected */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qse_httpd_seterrnum (httpd, QSE_HTTPD_ESCONN);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int peer_connected (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
|
||||||
|
{
|
||||||
|
if (peer->flags & QSE_HTTPD_PEER_SECURE)
|
||||||
|
{
|
||||||
|
if (peer->flags & QSE_HTTPD_PEER_CONNECTED)
|
||||||
|
{
|
||||||
|
return is_peer_connected_securely (httpd, peer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int ret = is_peer_socket_connected (httpd, peer);
|
||||||
|
if (ret <= 0) return ret;
|
||||||
|
peer->flags |= QSE_HTTPD_PEER_CONNECTED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return is_peer_socket_connected (httpd, peer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static qse_ssize_t peer_recv (
|
static qse_ssize_t peer_recv (
|
||||||
qse_httpd_t* httpd, qse_httpd_peer_t* peer,
|
qse_httpd_t* httpd, qse_httpd_peer_t* peer,
|
||||||
qse_mchar_t* buf, qse_size_t bufsize)
|
qse_mchar_t* buf, qse_size_t bufsize)
|
||||||
{
|
{
|
||||||
#if defined(__DOS__)
|
if (peer->flags & QSE_HTTPD_PEER_SECURE)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_SSL)
|
||||||
|
int ret = SSL_read (HANDLE_TO_SSL(peer->handle2), buf, bufsize);
|
||||||
|
if (ret <= -1)
|
||||||
|
{
|
||||||
|
int err = SSL_get_error(HANDLE_TO_SSL(peer->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(peer->handle2)) > 0)
|
||||||
|
peer->flags |= QSE_HTTPD_PEER_PENDING;
|
||||||
|
else
|
||||||
|
peer->flags &= ~QSE_HTTPD_PEER_PENDING;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
|
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
|
||||||
return -1;
|
return -1;
|
||||||
#else
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if defined(__DOS__)
|
||||||
|
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
|
||||||
|
return -1;
|
||||||
|
#else
|
||||||
qse_ssize_t ret = recv (peer->handle, buf, bufsize, 0);
|
qse_ssize_t ret = recv (peer->handle, buf, bufsize, 0);
|
||||||
if (ret <= -1) qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
|
if (ret <= -1) qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
|
||||||
return ret;
|
return ret;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static qse_ssize_t peer_send (
|
static qse_ssize_t peer_send (
|
||||||
qse_httpd_t* httpd, qse_httpd_peer_t* peer,
|
qse_httpd_t* httpd, qse_httpd_peer_t* peer,
|
||||||
const qse_mchar_t* buf, qse_size_t bufsize)
|
const qse_mchar_t* buf, qse_size_t bufsize)
|
||||||
{
|
{
|
||||||
#if defined(__DOS__)
|
if (peer->flags & QSE_HTTPD_PEER_SECURE)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_SSL)
|
||||||
|
int ret = SSL_write (HANDLE_TO_SSL(peer->handle2), buf, bufsize);
|
||||||
|
if (ret <= -1)
|
||||||
|
{
|
||||||
|
int err = SSL_get_error(HANDLE_TO_SSL(peer->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);
|
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
|
||||||
return -1;
|
return -1;
|
||||||
#else
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if defined(__DOS__)
|
||||||
|
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
|
||||||
|
return -1;
|
||||||
|
#else
|
||||||
qse_ssize_t ret = send (peer->handle, buf, bufsize, 0);
|
qse_ssize_t ret = send (peer->handle, buf, bufsize, 0);
|
||||||
if (ret <= -1) qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
|
if (ret <= -1) qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
|
||||||
return ret;
|
return ret;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------- */
|
||||||
@ -2008,7 +2215,7 @@ static int client_accepted (qse_httpd_t* httpd, qse_httpd_client_t* client)
|
|||||||
httpd_xtn_t* xtn;
|
httpd_xtn_t* xtn;
|
||||||
|
|
||||||
xtn = (httpd_xtn_t*) qse_httpd_getxtn (httpd);
|
xtn = (httpd_xtn_t*) qse_httpd_getxtn (httpd);
|
||||||
if (!xtn->ssl_ctx)
|
if (!xtn->ssl_client_ctx)
|
||||||
{
|
{
|
||||||
/* delayed initialization of ssl */
|
/* delayed initialization of ssl */
|
||||||
if (init_xtn_ssl (httpd, client->server) <= -1)
|
if (init_xtn_ssl (httpd, client->server) <= -1)
|
||||||
@ -2017,7 +2224,7 @@ static int client_accepted (qse_httpd_t* httpd, qse_httpd_client_t* client)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QSE_ASSERT (xtn->ssl_ctx != QSE_NULL);
|
QSE_ASSERT (xtn->ssl_client_ctx != QSE_NULL);
|
||||||
QSE_ASSERT (QSE_SIZEOF(client->handle2) >= QSE_SIZEOF(ssl));
|
QSE_ASSERT (QSE_SIZEOF(client->handle2) >= QSE_SIZEOF(ssl));
|
||||||
|
|
||||||
if (HANDLE_TO_SSL(client->handle2))
|
if (HANDLE_TO_SSL(client->handle2))
|
||||||
@ -2026,7 +2233,7 @@ static int client_accepted (qse_httpd_t* httpd, qse_httpd_client_t* client)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ssl = SSL_new (xtn->ssl_ctx);
|
ssl = SSL_new (xtn->ssl_client_ctx);
|
||||||
if (ssl == QSE_NULL) return -1;
|
if (ssl == QSE_NULL) return -1;
|
||||||
|
|
||||||
client->handle2 = SSL_TO_HANDLE(ssl);
|
client->handle2 = SSL_TO_HANDLE(ssl);
|
||||||
@ -2058,7 +2265,8 @@ static int client_accepted (qse_httpd_t* httpd, qse_httpd_client_t* client)
|
|||||||
httpd->opt.rcb.logact (httpd, &msg);
|
httpd->opt.rcb.logact (httpd, &msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SSL_free (ssl); */
|
/* client_closed() free this. no SSL_free() here.
|
||||||
|
SSL_free (ssl); */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1103,12 +1103,11 @@ qse_printf (QSE_T("!!!!!FEEDING OK OK OK OK %d from %d\n"), (int)m, (int)client-
|
|||||||
/* 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
|
||||||
* as large as 16K bytes since its length field is 2 bytes.
|
* as large as 16K bytes since its length field is 2 bytes.
|
||||||
* If SSL_read() has record a record but it's given a
|
* If SSL_read() has a record but it's given a smaller buffer
|
||||||
* smaller buffer than the actuaal record, the next call
|
* than the actual record, the next call to select() won't return.
|
||||||
* to select() won't return. there is no data to read
|
* there is no data to read at the socket layer. SSL_pending() can
|
||||||
* at the socket layer. SSL_pending() can tell you the
|
* tell you the amount of data in the SSL buffer. I try to consume
|
||||||
* amount of data in the SSL buffer. I try to consume
|
* the pending data if the client.recv handler has set QSE_HTTPD_CLIENT_PENDING.
|
||||||
* the pending data if the client.recv handler set QSE_HTTPD_CLIENT_PENDING.
|
|
||||||
*
|
*
|
||||||
* TODO: Investigate if there is any starvation issues.
|
* TODO: Investigate if there is any starvation issues.
|
||||||
* What if a single client never stops sending?
|
* What if a single client never stops sending?
|
||||||
|
@ -100,8 +100,8 @@ struct qse_httpd_real_task_t
|
|||||||
qse_httpd_real_task_t* next;
|
qse_httpd_real_task_t* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_SEND_SIZE 4096
|
#define MAX_SEND_SIZE (4096 * 4)
|
||||||
#define MAX_RECV_SIZE 4096
|
#define MAX_RECV_SIZE (4096 * 2)
|
||||||
|
|
||||||
#define MAX_NWAD_TEXT_SIZE 96
|
#define MAX_NWAD_TEXT_SIZE 96
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user