enhanced proxying to handle protocol upgrade.
enhanced qse_mbsword() and its family to accept an extra delimiter
This commit is contained in:
parent
8a32cbc4f1
commit
1df4e0bc9f
@ -1584,40 +1584,52 @@ QSE_EXPORT qse_wchar_t* qse_wcsxnrcasestr (
|
||||
|
||||
const qse_mchar_t* qse_mbsword (
|
||||
const qse_mchar_t* str,
|
||||
const qse_mchar_t* word
|
||||
const qse_mchar_t* word,
|
||||
qse_mchar_t extra_delim
|
||||
);
|
||||
|
||||
const qse_wchar_t* qse_wcsword (
|
||||
const qse_wchar_t* str,
|
||||
const qse_wchar_t* word
|
||||
const qse_wchar_t* word,
|
||||
qse_wchar_t extra_delim
|
||||
);
|
||||
|
||||
/**
|
||||
* The qse_mbsxword() function finds a whole word in a string.
|
||||
* The word can be delimited by white spaces or an extra delimiter
|
||||
* \a extra_delim. Pass QSE_MT('\0') if no extra delimiter is
|
||||
* needed.
|
||||
*/
|
||||
const qse_mchar_t* qse_mbsxword (
|
||||
const qse_mchar_t* str,
|
||||
qse_size_t len,
|
||||
const qse_mchar_t* word
|
||||
const qse_mchar_t* word,
|
||||
qse_mchar_t extra_delim
|
||||
);
|
||||
|
||||
/**
|
||||
* The qse_wcsxword() function finds a whole word in a string.
|
||||
* The word can be delimited by white spaces or an extra delimiter
|
||||
* \a extra_delim. Pass QSE_WT('\0') if no extra delimiter is
|
||||
* needed.
|
||||
*/
|
||||
const qse_wchar_t* qse_wcsxword (
|
||||
const qse_wchar_t* str,
|
||||
qse_size_t len,
|
||||
const qse_wchar_t* word
|
||||
const qse_wchar_t* word,
|
||||
qse_wchar_t extra_delim
|
||||
);
|
||||
|
||||
const qse_mchar_t* qse_mbscaseword (
|
||||
const qse_mchar_t* str,
|
||||
const qse_mchar_t* word
|
||||
const qse_mchar_t* word,
|
||||
qse_mchar_t extra_delim
|
||||
);
|
||||
|
||||
const qse_wchar_t* qse_wcscaseword (
|
||||
const qse_wchar_t* str,
|
||||
const qse_wchar_t* word
|
||||
const qse_wchar_t* word,
|
||||
qse_wchar_t extra_delim
|
||||
);
|
||||
|
||||
/**
|
||||
@ -1627,7 +1639,8 @@ const qse_wchar_t* qse_wcscaseword (
|
||||
const qse_mchar_t* qse_mbsxcaseword (
|
||||
const qse_mchar_t* str,
|
||||
qse_size_t len,
|
||||
const qse_mchar_t* word
|
||||
const qse_mchar_t* word,
|
||||
qse_mchar_t extra_delim
|
||||
);
|
||||
|
||||
/**
|
||||
@ -1637,19 +1650,20 @@ const qse_mchar_t* qse_mbsxcaseword (
|
||||
const qse_wchar_t* qse_wcsxcaseword (
|
||||
const qse_wchar_t* str,
|
||||
qse_size_t len,
|
||||
const qse_wchar_t* word
|
||||
const qse_wchar_t* word,
|
||||
qse_wchar_t extra_delim
|
||||
);
|
||||
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
# define qse_strword(str,word) qse_mbsword(str,word)
|
||||
# define qse_strxword(str,len,word) qse_mbsxword(str,len,word)
|
||||
# define qse_strcaseword(str,word) qse_mbscaseword(str,word)
|
||||
# define qse_strxcaseword(str,len,word) qse_mbsxcaseword(str,len,word)
|
||||
# define qse_strword(str,word,edelim) qse_mbsword(str,word,edelim)
|
||||
# define qse_strxword(str,len,word,edelim) qse_mbsxword(str,len,word,edelim)
|
||||
# define qse_strcaseword(str,word,edelim) qse_mbscaseword(str,word,edelim)
|
||||
# define qse_strxcaseword(str,len,word,edelim) qse_mbsxcaseword(str,len,word,edelim)
|
||||
#else
|
||||
# define qse_strword(str,word) qse_wcsword(str,word)
|
||||
# define qse_strxword(str,len,word) qse_wcsxword(str,len,word)
|
||||
# define qse_strcaseword(str,word) qse_wcscaseword(str,word)
|
||||
# define qse_strxcaseword(str,len,word) qse_wcsxcaseword(str,len,word)
|
||||
# define qse_strword(str,word,edelim) qse_wcsword(str,word,edelim)
|
||||
# define qse_strxword(str,len,word,edelim) qse_wcsxword(str,len,word,edelim)
|
||||
# define qse_strcaseword(str,word,edelim) qse_wcscaseword(str,word,edelim)
|
||||
# define qse_strxcaseword(str,len,word,edelim) qse_wcsxcaseword(str,len,word,edelim)
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -38,7 +38,8 @@ enum qse_htrd_errnum_t
|
||||
QSE_HTRD_EBADRE,
|
||||
QSE_HTRD_EBADHDR,
|
||||
QSE_HTRD_ERECBS,
|
||||
QSE_HTRD_ECONCB
|
||||
QSE_HTRD_ECONCB,
|
||||
QSE_HTRD_ESUSPENDED
|
||||
};
|
||||
|
||||
typedef enum qse_htrd_errnum_t qse_htrd_errnum_t;
|
||||
@ -56,8 +57,7 @@ enum qse_htrd_option_t
|
||||
QSE_HTRD_REQUEST = (1 << 4), /**< parse input as a request */
|
||||
QSE_HTRD_RESPONSE = (1 << 5), /**< parse input as a response */
|
||||
QSE_HTRD_TRAILERS = (1 << 6), /**< store trailers in a separate table */
|
||||
QSE_HTRD_STRICT = (1 << 7), /**< be more picky */
|
||||
QSE_HTRD_DUMMY = (1 << 8) /**< be dummy */
|
||||
QSE_HTRD_STRICT = (1 << 7) /**< be more picky */
|
||||
};
|
||||
|
||||
typedef enum qse_htrd_option_t qse_htrd_option_t;
|
||||
@ -75,6 +75,7 @@ struct qse_htrd_t
|
||||
qse_mmgr_t* mmgr;
|
||||
qse_htrd_errnum_t errnum;
|
||||
int option;
|
||||
int flags;
|
||||
|
||||
const qse_htrd_recbs_t* recbs;
|
||||
|
||||
@ -149,7 +150,7 @@ QSE_EXPORT void qse_htrd_clear (
|
||||
);
|
||||
|
||||
QSE_EXPORT int qse_htrd_getoption (
|
||||
qse_htrd_t* htrd
|
||||
qse_htrd_t* htrd
|
||||
);
|
||||
|
||||
QSE_EXPORT void qse_htrd_setoption (
|
||||
@ -185,6 +186,22 @@ QSE_EXPORT int qse_htrd_halt (
|
||||
qse_htrd_t* htrd
|
||||
);
|
||||
|
||||
QSE_EXPORT void qse_htrd_suspend (
|
||||
qse_htrd_t* htrd
|
||||
);
|
||||
|
||||
QSE_EXPORT void qse_htrd_resume (
|
||||
qse_htrd_t* htrd
|
||||
);
|
||||
|
||||
QSE_EXPORT void qse_htrd_dummify (
|
||||
qse_htrd_t* htrd
|
||||
);
|
||||
|
||||
QSE_EXPORT void qse_htrd_undummify (
|
||||
qse_htrd_t* htrd
|
||||
);
|
||||
|
||||
QSE_EXPORT int qse_htrd_scanqparam (
|
||||
qse_htrd_t* http,
|
||||
const qse_mcstr_t* cstr
|
||||
|
@ -21,32 +21,34 @@
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/chr.h>
|
||||
|
||||
const qse_mchar_t* qse_mbsword (
|
||||
const qse_mchar_t* str, const qse_mchar_t* word)
|
||||
#define IS_MDELIM(x,delim) (QSE_ISMSPACE(x) || (x) == delim)
|
||||
#define IS_WDELIM(x,delim) (QSE_ISWSPACE(x) || (x) == delim)
|
||||
|
||||
const qse_mchar_t* qse_mbsword (const qse_mchar_t* str, const qse_mchar_t* word, qse_mchar_t extra_delim)
|
||||
{
|
||||
/* find a full word in a string */
|
||||
|
||||
const qse_mchar_t* ptr = str;
|
||||
|
||||
if (extra_delim == QSE_MT('\0')) extra_delim = QSE_MT(' ');
|
||||
do
|
||||
{
|
||||
const qse_mchar_t* s;
|
||||
|
||||
while (QSE_ISMSPACE(*ptr)) ptr++;
|
||||
while (IS_MDELIM(*ptr,extra_delim)) ptr++;
|
||||
if (*ptr == QSE_MT('\0')) return QSE_NULL;
|
||||
|
||||
s = ptr;
|
||||
while (*ptr != QSE_MT('\0') && !QSE_ISMSPACE(*ptr)) ptr++;
|
||||
while (*ptr != QSE_MT('\0') && !IS_MDELIM(*ptr,extra_delim)) ptr++;
|
||||
|
||||
if (qse_mbsxcmp (s, ptr-s, word) == 0) return s;
|
||||
if (qse_mbsxcmp (s, ptr - s, word) == 0) return s;
|
||||
}
|
||||
while (*ptr != QSE_MT('\0'));
|
||||
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
const qse_mchar_t* qse_mbsxword (
|
||||
const qse_mchar_t* str, qse_size_t len, const qse_mchar_t* word)
|
||||
const qse_mchar_t* qse_mbsxword (const qse_mchar_t* str, qse_size_t len, const qse_mchar_t* word, qse_mchar_t extra_delim)
|
||||
{
|
||||
/* find a full word in a string */
|
||||
|
||||
@ -54,93 +56,93 @@ const qse_mchar_t* qse_mbsxword (
|
||||
const qse_mchar_t* end = str + len;
|
||||
const qse_mchar_t* s;
|
||||
|
||||
if (extra_delim == QSE_MT('\0')) extra_delim = QSE_MT(' ');
|
||||
do
|
||||
{
|
||||
while (ptr < end && QSE_ISMSPACE(*ptr)) ptr++;
|
||||
while (ptr < end && IS_MDELIM(*ptr,extra_delim)) ptr++;
|
||||
if (ptr >= end) return QSE_NULL;
|
||||
|
||||
s = ptr;
|
||||
while (ptr < end && !QSE_ISMSPACE(*ptr)) ptr++;
|
||||
while (ptr < end && !IS_MDELIM(*ptr,extra_delim)) ptr++;
|
||||
|
||||
if (qse_mbsxcmp (s, ptr-s, word) == 0) return s;
|
||||
if (qse_mbsxcmp (s, ptr - s, word) == 0) return s;
|
||||
}
|
||||
while (ptr < end);
|
||||
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
const qse_mchar_t* qse_mbscaseword (
|
||||
const qse_mchar_t* str, const qse_mchar_t* word)
|
||||
const qse_mchar_t* qse_mbscaseword (const qse_mchar_t* str, const qse_mchar_t* word, qse_mchar_t extra_delim)
|
||||
{
|
||||
/* find a full word in a string */
|
||||
|
||||
const qse_mchar_t* ptr = str;
|
||||
|
||||
if (extra_delim == QSE_MT('\0')) extra_delim = QSE_MT(' ');
|
||||
do
|
||||
{
|
||||
const qse_mchar_t* s;
|
||||
|
||||
while (QSE_ISMSPACE(*ptr)) ptr++;
|
||||
while (IS_MDELIM(*ptr,extra_delim)) ptr++;
|
||||
if (*ptr == QSE_MT('\0')) return QSE_NULL;
|
||||
|
||||
s = ptr;
|
||||
while (*ptr != QSE_MT('\0') && !QSE_ISMSPACE(*ptr)) ptr++;
|
||||
while (*ptr != QSE_MT('\0') && !IS_MDELIM(*ptr,extra_delim)) ptr++;
|
||||
|
||||
if (qse_mbsxcasecmp (s, ptr-s, word) == 0) return s;
|
||||
if (qse_mbsxcasecmp (s, ptr - s, word) == 0) return s;
|
||||
}
|
||||
while (*ptr != QSE_MT('\0'));
|
||||
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
const qse_mchar_t* qse_mbsxcaseword (
|
||||
const qse_mchar_t* str, qse_size_t len, const qse_mchar_t* word)
|
||||
const qse_mchar_t* qse_mbsxcaseword (const qse_mchar_t* str, qse_size_t len, const qse_mchar_t* word, qse_mchar_t extra_delim)
|
||||
{
|
||||
const qse_mchar_t* ptr = str;
|
||||
const qse_mchar_t* end = str + len;
|
||||
const qse_mchar_t* s;
|
||||
|
||||
if (extra_delim == QSE_MT('\0')) extra_delim = QSE_MT(' ');
|
||||
do
|
||||
{
|
||||
while (ptr < end && QSE_ISMSPACE(*ptr)) ptr++;
|
||||
while (ptr < end && IS_MDELIM(*ptr,extra_delim)) ptr++;
|
||||
if (ptr >= end) return QSE_NULL;
|
||||
|
||||
s = ptr;
|
||||
while (ptr < end && !QSE_ISMSPACE(*ptr)) ptr++;
|
||||
while (ptr < end && !IS_MDELIM(*ptr,extra_delim)) ptr++;
|
||||
|
||||
if (qse_mbsxcasecmp (s, ptr-s, word) == 0) return s;
|
||||
if (qse_mbsxcasecmp (s, ptr - s, word) == 0) return s;
|
||||
}
|
||||
while (ptr < end);
|
||||
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
const qse_wchar_t* qse_wcsword (
|
||||
const qse_wchar_t* str, const qse_wchar_t* word)
|
||||
const qse_wchar_t* qse_wcsword (const qse_wchar_t* str, const qse_wchar_t* word, qse_wchar_t extra_delim)
|
||||
{
|
||||
/* find a full word in a string */
|
||||
|
||||
const qse_wchar_t* ptr = str;
|
||||
|
||||
if (extra_delim == QSE_WT('\0')) extra_delim = QSE_WT(' ');
|
||||
do
|
||||
{
|
||||
const qse_wchar_t* s;
|
||||
|
||||
while (QSE_ISWSPACE(*ptr)) ptr++;
|
||||
while (IS_WDELIM(*ptr,extra_delim)) ptr++;
|
||||
if (*ptr == QSE_WT('\0')) return QSE_NULL;
|
||||
|
||||
s = ptr;
|
||||
while (*ptr != QSE_WT('\0') && !QSE_ISWSPACE(*ptr)) ptr++;
|
||||
while (*ptr != QSE_WT('\0') && !IS_WDELIM(*ptr,extra_delim)) ptr++;
|
||||
|
||||
if (qse_wcsxcmp (s, ptr-s, word) == 0) return s;
|
||||
if (qse_wcsxcmp (s, ptr - s, word) == 0) return s;
|
||||
}
|
||||
while (*ptr != QSE_WT('\0'));
|
||||
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
const qse_wchar_t* qse_wcsxword (
|
||||
const qse_wchar_t* str, qse_size_t len, const qse_wchar_t* word)
|
||||
const qse_wchar_t* qse_wcsxword (const qse_wchar_t* str, qse_size_t len, const qse_wchar_t* word, qse_wchar_t extra_delim)
|
||||
{
|
||||
/* find a full word in a string */
|
||||
|
||||
@ -148,61 +150,62 @@ const qse_wchar_t* qse_wcsxword (
|
||||
const qse_wchar_t* end = str + len;
|
||||
const qse_wchar_t* s;
|
||||
|
||||
if (extra_delim == QSE_WT('\0')) extra_delim = QSE_WT(' ');
|
||||
do
|
||||
{
|
||||
while (ptr < end && QSE_ISWSPACE(*ptr)) ptr++;
|
||||
while (ptr < end && IS_WDELIM(*ptr,extra_delim)) ptr++;
|
||||
if (ptr >= end) return QSE_NULL;
|
||||
|
||||
s = ptr;
|
||||
while (ptr < end && !QSE_ISWSPACE(*ptr)) ptr++;
|
||||
while (ptr < end && !IS_WDELIM(*ptr,extra_delim)) ptr++;
|
||||
|
||||
if (qse_wcsxcmp (s, ptr-s, word) == 0) return s;
|
||||
if (qse_wcsxcmp (s, ptr - s, word) == 0) return s;
|
||||
}
|
||||
while (ptr < end);
|
||||
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
const qse_wchar_t* qse_wcscaseword (
|
||||
const qse_wchar_t* str, const qse_wchar_t* word)
|
||||
const qse_wchar_t* qse_wcscaseword (const qse_wchar_t* str, const qse_wchar_t* word, qse_wchar_t extra_delim)
|
||||
{
|
||||
/* find a full word in a string */
|
||||
|
||||
const qse_wchar_t* ptr = str;
|
||||
|
||||
if (extra_delim == QSE_WT('\0')) extra_delim = QSE_WT(' ');
|
||||
do
|
||||
{
|
||||
const qse_wchar_t* s;
|
||||
|
||||
while (QSE_ISWSPACE(*ptr)) ptr++;
|
||||
while (IS_WDELIM(*ptr,extra_delim)) ptr++;
|
||||
if (*ptr == QSE_WT('\0')) return QSE_NULL;
|
||||
|
||||
s = ptr;
|
||||
while (*ptr != QSE_WT('\0') && !QSE_ISWSPACE(*ptr)) ptr++;
|
||||
while (*ptr != QSE_WT('\0') && !IS_WDELIM(*ptr,extra_delim)) ptr++;
|
||||
|
||||
if (qse_wcsxcasecmp (s, ptr-s, word) == 0) return s;
|
||||
if (qse_wcsxcasecmp (s, ptr - s, word) == 0) return s;
|
||||
}
|
||||
while (*ptr != QSE_WT('\0'));
|
||||
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
const qse_wchar_t* qse_wcsxcaseword (
|
||||
const qse_wchar_t* str, qse_size_t len, const qse_wchar_t* word)
|
||||
const qse_wchar_t* qse_wcsxcaseword (const qse_wchar_t* str, qse_size_t len, const qse_wchar_t* word, qse_wchar_t extra_delim)
|
||||
{
|
||||
const qse_wchar_t* ptr = str;
|
||||
const qse_wchar_t* end = str + len;
|
||||
const qse_wchar_t* s;
|
||||
|
||||
if (extra_delim == QSE_WT('\0')) extra_delim = QSE_WT(' ');
|
||||
do
|
||||
{
|
||||
while (ptr < end && QSE_ISWSPACE(*ptr)) ptr++;
|
||||
while (ptr < end && IS_WDELIM(*ptr,extra_delim)) ptr++;
|
||||
if (ptr >= end) return QSE_NULL;
|
||||
|
||||
s = ptr;
|
||||
while (ptr < end && !QSE_ISWSPACE(*ptr)) ptr++;
|
||||
while (ptr < end && !IS_WDELIM(*ptr,extra_delim)) ptr++;
|
||||
|
||||
if (qse_wcsxcasecmp (s, ptr-s, word) == 0) return s;
|
||||
if (qse_wcsxcasecmp (s, ptr - s, word) == 0) return s;
|
||||
}
|
||||
while (ptr < end);
|
||||
|
||||
|
@ -25,8 +25,13 @@
|
||||
|
||||
static const qse_mchar_t NUL = QSE_MT('\0');
|
||||
|
||||
/* for htrd->fed.s.flags */
|
||||
#define CONSUME_UNTIL_CLOSE (1 << 0)
|
||||
|
||||
/* for htrd->flags */
|
||||
#define FEEDING_SUSPENDED (1 << 0)
|
||||
#define FEEDING_DUMMIFIED (1 << 1)
|
||||
|
||||
static QSE_INLINE int is_whspace_octet (qse_mchar_t c)
|
||||
{
|
||||
return c == QSE_MT(' ') || c == QSE_MT('\t') || c == QSE_MT('\r') || c == QSE_MT('\n');
|
||||
@ -457,6 +462,7 @@ badre:
|
||||
void qse_htrd_clear (qse_htrd_t* htrd)
|
||||
{
|
||||
clear_feed (htrd);
|
||||
htrd->flags = 0;
|
||||
}
|
||||
|
||||
qse_mmgr_t* qse_htrd_getmmgr (qse_htrd_t* htrd)
|
||||
@ -491,21 +497,21 @@ void qse_htrd_setrecbs (qse_htrd_t* htrd, const qse_htrd_recbs_t* recbs)
|
||||
|
||||
static int capture_connection (qse_htrd_t* htrd, qse_htb_pair_t* pair)
|
||||
{
|
||||
int n;
|
||||
qse_htre_hdrval_t* val;
|
||||
|
||||
val = QSE_HTB_VPTR(pair);
|
||||
while (val->next) val = val->next;
|
||||
|
||||
n = qse_mbscmp (val->ptr, QSE_MT("close"));
|
||||
if (n == 0)
|
||||
/* The value for Connection: may get comma-separated.
|
||||
* so use qse_mbscaseword() instead of qse_mbscmp(). */
|
||||
|
||||
if (qse_mbscaseword (val->ptr, QSE_MT("close"), QSE_MT(',')))
|
||||
{
|
||||
htrd->re.flags &= ~QSE_HTRE_ATTR_KEEPALIVE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = qse_mbscmp (val->ptr, QSE_MT("keep-alive"));
|
||||
if (n == 0)
|
||||
if (qse_mbscaseword (val->ptr, QSE_MT("keep-alive"), QSE_MT(',')))
|
||||
{
|
||||
htrd->re.flags |= QSE_HTRE_ATTR_KEEPALIVE;
|
||||
return 0;
|
||||
@ -758,7 +764,7 @@ static qse_htb_pair_t* hdr_cbserter (
|
||||
* character is used by Set-Cookie in a way that conflicts with
|
||||
* such folding.
|
||||
*
|
||||
* So i just maintain the list of valuea for a key instead of
|
||||
* So i just maintain the list of values for a key instead of
|
||||
* folding them.
|
||||
*/
|
||||
|
||||
@ -826,7 +832,7 @@ qse_mchar_t* parse_header_field (
|
||||
{
|
||||
/* ignore a line without a colon */
|
||||
p++;
|
||||
return p;
|
||||
return p;
|
||||
}
|
||||
}
|
||||
goto badhdr;
|
||||
@ -945,7 +951,6 @@ static QSE_INLINE int parse_initial_line_and_headers (
|
||||
}
|
||||
while (1);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1061,10 +1066,10 @@ static const qse_mchar_t* get_trailing_headers (
|
||||
{
|
||||
while (is_whspace_octet(*p)) p++;
|
||||
if (*p == '\0') break;
|
||||
|
||||
|
||||
/* TODO: return error if protocol is 0.9.
|
||||
* HTTP/0.9 must not get headers... */
|
||||
|
||||
|
||||
p = parse_header_field (
|
||||
htrd, p,
|
||||
((htrd->option & QSE_HTRD_TRAILERS)? &htrd->re.trailers: &htrd->re.hdrtab)
|
||||
@ -1107,7 +1112,14 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
|
||||
|
||||
QSE_ASSERT (len > 0);
|
||||
|
||||
if (htrd->option & QSE_HTRD_DUMMY)
|
||||
if (htrd->flags & FEEDING_SUSPENDED)
|
||||
{
|
||||
htrd->errnum = QSE_HTRD_ESUSPENDED;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*if (htrd->option & QSE_HTRD_DUMMY)*/
|
||||
if (htrd->flags & FEEDING_DUMMIFIED)
|
||||
{
|
||||
/* treat everything as contents.
|
||||
* i don't care about headers or whatsoever. */
|
||||
@ -1159,13 +1171,13 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
|
||||
|
||||
switch (b)
|
||||
{
|
||||
case '\0':
|
||||
case QSE_MT('\0'):
|
||||
/* guarantee that the request does not contain
|
||||
* a null character */
|
||||
htrd->errnum = QSE_HTRD_EBADRE;
|
||||
return -1;
|
||||
|
||||
case '\n':
|
||||
case QSE_MT('\n'):
|
||||
{
|
||||
if (htrd->fed.s.crlf <= 1)
|
||||
{
|
||||
@ -1302,7 +1314,6 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
|
||||
{
|
||||
htrd->fed.s.need = htrd->re.attr.content_length;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (htrd->fed.s.need > 0)
|
||||
@ -1348,7 +1359,7 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
|
||||
htrd->fed.s.need = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (htrd->fed.s.chunk.phase == GET_CHUNK_DATA)
|
||||
{
|
||||
QSE_ASSERT (htrd->fed.s.need == 0);
|
||||
@ -1358,7 +1369,7 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
|
||||
while (ptr < end && is_space_octet(*ptr)) ptr++;
|
||||
if (ptr < end)
|
||||
{
|
||||
if (*ptr == '\n')
|
||||
if (*ptr == QSE_MT('\n'))
|
||||
{
|
||||
/* end of chunk data. */
|
||||
ptr++;
|
||||
@ -1442,10 +1453,17 @@ qse_printf (QSE_T("CONTENT_LENGTH %d, RAW HEADER LENGTH %d\n"),
|
||||
clear_feed (htrd);
|
||||
if (ptr >= end) return 0; /* no more feeds to handle */
|
||||
|
||||
if (htrd->option & QSE_HTRD_DUMMY)
|
||||
if (htrd->flags & FEEDING_SUSPENDED)
|
||||
{
|
||||
htrd->errnum = QSE_HTRD_ESUSPENDED;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*if (htrd->option & QSE_HTRD_DUMMY)*/
|
||||
if (htrd->flags & FEEDING_DUMMIFIED)
|
||||
{
|
||||
/* once the mode changes to RAW in a callback,
|
||||
* left-over is pused as contents */
|
||||
* left-over is pushed as contents */
|
||||
if (ptr < end)
|
||||
return push_content (htrd, ptr, end - ptr);
|
||||
else
|
||||
@ -1466,7 +1484,7 @@ qse_printf (QSE_T("CONTENT_LENGTH %d, RAW HEADER LENGTH %d\n"),
|
||||
break;
|
||||
}
|
||||
|
||||
case '\r':
|
||||
case QSE_MT('\r'):
|
||||
if (htrd->fed.s.crlf == 0 || htrd->fed.s.crlf == 2)
|
||||
htrd->fed.s.crlf++;
|
||||
else htrd->fed.s.crlf = 1;
|
||||
@ -1533,6 +1551,26 @@ int qse_htrd_halt (qse_htrd_t* htrd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qse_htrd_suspend (qse_htrd_t* htrd)
|
||||
{
|
||||
htrd->flags |= FEEDING_SUSPENDED;
|
||||
}
|
||||
|
||||
void qse_htrd_resume (qse_htrd_t* htrd)
|
||||
{
|
||||
htrd->flags &= ~FEEDING_SUSPENDED;
|
||||
}
|
||||
|
||||
void qse_htrd_dummify (qse_htrd_t* htrd)
|
||||
{
|
||||
htrd->flags |= FEEDING_DUMMIFIED;
|
||||
}
|
||||
|
||||
void qse_htrd_undummify (qse_htrd_t* htrd)
|
||||
{
|
||||
htrd->flags &= ~FEEDING_DUMMIFIED;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int qse_htrd_scanqparam (qse_htrd_t* htrd, const qse_mcstr_t* cstr)
|
||||
{
|
||||
|
@ -504,4 +504,3 @@ qse_mchar_t* qse_perenchttpstrdup (int opt, const qse_mchar_t* str, qse_mmgr_t*
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
@ -53,9 +53,12 @@ struct task_proxy_t
|
||||
#define PROXY_URL_PREREWRITTEN (1 << 12) /* URL has been prerewritten in prerewrite(). */
|
||||
#define PROXY_URL_REWRITTEN (1 << 13)
|
||||
#define PROXY_URL_REDIRECTED (1 << 14)
|
||||
#define PROXY_X_FORWARDED_FOR (1 << 15) /* X-Forwarded-For added */
|
||||
#define PROXY_VIA (1 << 16) /* Via added to the request */
|
||||
#define PROXY_VIA_RETURNING (1 << 17) /* Via added to the response */
|
||||
#define PROXY_X_FORWARDED_FOR (1 << 15) /* X-Forwarded-For: added */
|
||||
#define PROXY_VIA (1 << 16) /* Via: added to the request */
|
||||
#define PROXY_VIA_RETURNING (1 << 17) /* Via: added to the response */
|
||||
#define PROXY_UPGRADE_REQUESTED (1 << 18)
|
||||
#define PROXY_PROTOCOL_SWITCHED (1 << 19)
|
||||
#define PROXY_GOT_BAD_REQUEST (1 << 20)
|
||||
int flags;
|
||||
qse_httpd_t* httpd;
|
||||
qse_httpd_client_t* client;
|
||||
@ -340,8 +343,8 @@ static int proxy_snatch_client_input_raw (
|
||||
/* this function is never called with ptr of QSE_NULL
|
||||
* because this callback is set manually after the request
|
||||
* has been discarded or completed in task_init_proxy() and
|
||||
* qse_htre_completecontent or qse-htre_discardcontent() is
|
||||
* not called again. Unlinkw proxy_snatch_client_input(),
|
||||
* qse_htre_completecontent() or qse_htre_discardcontent() is
|
||||
* not called again. Unlike proxy_snatch_client_input(),
|
||||
* it doesn't care about EOF indicated by ptr of QSE_NULL. */
|
||||
if (ptr && !(proxy->reqflags & PROXY_REQ_FWDERR))
|
||||
{
|
||||
@ -660,7 +663,6 @@ static int proxy_htrd_peek_peer_output (qse_htrd_t* htrd, qse_htre_t* res)
|
||||
}
|
||||
/* end initial line */
|
||||
|
||||
|
||||
if (proxy->resflags & PROXY_RES_PEER_LENGTH_FAKE)
|
||||
{
|
||||
/* length should be added by force.
|
||||
@ -778,6 +780,37 @@ static int proxy_htrd_peek_peer_output (qse_htrd_t* htrd, qse_htre_t* res)
|
||||
}
|
||||
}
|
||||
|
||||
if (proxy->flags & PROXY_UPGRADE_REQUESTED)
|
||||
{
|
||||
QSE_ASSERT (proxy->req != QSE_NULL);
|
||||
|
||||
if (qse_htre_getscodeval(res) == 101)
|
||||
{
|
||||
/* Unlike raw proxying entasked for CONNECT for which disconnection
|
||||
* is supposed to be scheduled by the caller, protocol upgrade
|
||||
* can be requested over a normal http stream. A stream whose
|
||||
* protocol has been switched must not be sustained after the
|
||||
* task is over. */
|
||||
if (qse_httpd_entaskdisconnect (httpd, proxy->client, xtn->task) == QSE_NULL) return -1;
|
||||
proxy->flags |= PROXY_PROTOCOL_SWITCHED;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* the update request is not granted. restore the reader
|
||||
* to the original state so that HTTP packets can be handled
|
||||
* later on. */
|
||||
qse_htrd_undummify (proxy->client->htrd);
|
||||
qse_htre_unsetconcb (proxy->req);
|
||||
proxy->req = QSE_NULL;
|
||||
}
|
||||
|
||||
/* let the reader accept data to be fed */
|
||||
qse_htrd_resume (proxy->client->htrd);
|
||||
|
||||
/*task->trigger.v[0].mask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;*/ /* peer */
|
||||
proxy->task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_READ; /* client-side */
|
||||
}
|
||||
|
||||
proxy->res_pending = QSE_MBS_LEN(proxy->res) - proxy->res_consumed;
|
||||
return 0;
|
||||
}
|
||||
@ -815,11 +848,6 @@ static void proxy_forward_client_input_to_peer (qse_httpd_t* httpd, qse_httpd_ta
|
||||
/* normal forwarding */
|
||||
qse_ssize_t n;
|
||||
|
||||
#if 0
|
||||
qse_printf (QSE_T("PROXY FORWARD: @@@@@@@@@@WRITING[%.*hs]\n"),
|
||||
(int)QSE_MBS_LEN(proxy->reqfwdbuf),
|
||||
QSE_MBS_PTR(proxy->reqfwdbuf));
|
||||
#endif
|
||||
httpd->errnum = QSE_HTTPD_ENOERR;
|
||||
n = httpd->opt.scb.peer.send (
|
||||
httpd, &proxy->peer,
|
||||
@ -854,13 +882,15 @@ to the head all the time.. grow the buffer to a certain limit. */
|
||||
qse_mbs_del (proxy->reqfwdbuf, 0, n);
|
||||
if (QSE_MBS_LEN(proxy->reqfwdbuf) <= 0)
|
||||
{
|
||||
if (proxy->req == QSE_NULL) goto done;
|
||||
else task->trigger.v[0].mask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||
/* the forwarding buffer is emptied after sending. */
|
||||
if (!proxy->req) goto done;
|
||||
task->trigger.v[0].mask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (proxy->req == QSE_NULL)
|
||||
else if (!proxy->req)
|
||||
{
|
||||
done:
|
||||
/* there is nothing to read from the client side and
|
||||
@ -1011,7 +1041,7 @@ static int task_init_proxy (
|
||||
/* the caller must make sure that the actual content is discarded or completed
|
||||
* and the following data is treated as contents */
|
||||
QSE_ASSERT (arg->req->state & (QSE_HTRE_DISCARDED | QSE_HTRE_COMPLETED));
|
||||
QSE_ASSERT (qse_htrd_getoption(client->htrd) & QSE_HTRD_DUMMY);
|
||||
/*QSE_ASSERT (qse_htrd_getoption(client->htrd) & QSE_HTRD_DUMMY);*/
|
||||
|
||||
proxy->req = arg->req;
|
||||
qse_htre_setconcb (proxy->req, proxy_snatch_client_input_raw, task);
|
||||
@ -1228,13 +1258,55 @@ qse_mbs_ncat (proxy->reqfwdbuf, spc, QSE_COUNTOF(spc));
|
||||
snatch_needed = 1;
|
||||
}
|
||||
|
||||
if (snatch_needed)
|
||||
if (qse_htre_getheaderval(arg->req, QSE_MT("Upgrade")))
|
||||
{
|
||||
/* set up a callback to be called when the request content
|
||||
* is fed to the htrd reader. qse_htre_addcontent() that
|
||||
* htrd calls invokes this callback. */
|
||||
/* Upgrade: is found in the request header */
|
||||
const qse_htre_hdrval_t* hv;
|
||||
hv = qse_htre_getheaderval(arg->req, QSE_MT("Connection"));
|
||||
while (hv)
|
||||
{
|
||||
if (qse_mbscaseword (hv->ptr, QSE_MT("Upgrade"), QSE_MT(','))) break;
|
||||
hv = hv->next;
|
||||
}
|
||||
|
||||
if (!hv) goto no_upgrade;
|
||||
|
||||
if (snatch_needed)
|
||||
{
|
||||
/* The upgrade request can't have contents.
|
||||
* Not allowing contents makes implementation easier. */
|
||||
httpd->errnum = QSE_HTTPD_EBADREQ;
|
||||
proxy->flags |= PROXY_GOT_BAD_REQUEST;
|
||||
goto oops;
|
||||
}
|
||||
|
||||
/* cause feeding of client data to fail. i do this because
|
||||
* it's unknown if upgrade will get granted or not.
|
||||
* if it's granted, the client input should be treated
|
||||
* as an octet string. If not, it should still be handled
|
||||
* as HTTP. */
|
||||
qse_htrd_suspend (client->htrd);
|
||||
|
||||
/* prearrange to not parse client input when feeding is resumed */
|
||||
qse_htrd_dummify (client->htrd);
|
||||
|
||||
proxy->flags |= PROXY_UPGRADE_REQUESTED;
|
||||
proxy->req = arg->req;
|
||||
qse_htre_setconcb (proxy->req, proxy_snatch_client_input, task);
|
||||
|
||||
/* prearrange to capature client input when feeding is resumed */
|
||||
qse_htre_setconcb (proxy->req, proxy_snatch_client_input_raw, proxy->task);
|
||||
}
|
||||
else
|
||||
{
|
||||
no_upgrade:
|
||||
if (snatch_needed)
|
||||
{
|
||||
/* set up a callback to be called when the request content
|
||||
* is fed to the htrd reader. qse_htre_addcontent() that
|
||||
* htrd calls invokes this callback. */
|
||||
proxy->req = arg->req;
|
||||
qse_htre_setconcb (proxy->req, proxy_snatch_client_input, task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1253,9 +1325,6 @@ nomem_oops:
|
||||
/* goto oops */
|
||||
|
||||
oops:
|
||||
|
||||
printf ("init_proxy failed...........................................\n");
|
||||
|
||||
/* since a new task can't be added in the initializer,
|
||||
* i mark that initialization failed and let task_main_proxy()
|
||||
* add an error task */
|
||||
@ -1276,7 +1345,6 @@ printf ("init_proxy failed...........................................\n");
|
||||
proxy->flags |= PROXY_INIT_FAILED;
|
||||
task->ctx = proxy;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1290,6 +1358,16 @@ static void task_fini_proxy (
|
||||
if (proxy->peer_status & PROXY_PEER_OPEN)
|
||||
httpd->opt.scb.peer.close (httpd, &proxy->peer);
|
||||
|
||||
if ((proxy->flags & (PROXY_UPGRADE_REQUESTED | PROXY_PROTOCOL_SWITCHED)) == PROXY_UPGRADE_REQUESTED)
|
||||
{
|
||||
/* upgrade requested but protocol switching not completed yet.
|
||||
* this can happen because dummification is performed before
|
||||
* the 101 response is received. */
|
||||
|
||||
/* no harm to call this multiple times */
|
||||
qse_htrd_undummify (proxy->client->htrd);
|
||||
}
|
||||
|
||||
if (proxy->res) qse_mbs_close (proxy->res);
|
||||
if (proxy->peer_htrd) qse_htrd_close (proxy->peer_htrd);
|
||||
if (proxy->reqfwdbuf) qse_mbs_close (proxy->reqfwdbuf);
|
||||
@ -1311,24 +1389,12 @@ printf ("task_main_proxy_5 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask
|
||||
task->trigger.v[0].mask, task->trigger.v[1].mask, task->trigger.cmask);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
if (task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_READABLE)
|
||||
{
|
||||
/* if the client side is readable */
|
||||
proxy_forward_client_input_to_peer (httpd, task, 0);
|
||||
}
|
||||
else if (task->trigger.v[0].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE)
|
||||
{
|
||||
/* if the peer side is writable while the client side is not readable*/
|
||||
proxy_forward_client_input_to_peer (httpd, task, 1);
|
||||
}
|
||||
#endif
|
||||
proxy_forward_client_input_to_peer (httpd, task);
|
||||
|
||||
if (/*(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITABLE) && */ proxy->buflen > 0)
|
||||
{
|
||||
/* wrote to the client socket as long as there's something to
|
||||
* write. it's safe to do so as the socket is non-blocking.
|
||||
/* write to the client socket as long as there's something.
|
||||
* it's safe to do so as the socket is non-blocking.
|
||||
* i commented out the check in the 'if' condition above */
|
||||
|
||||
/* TODO: check if proxy outputs more than content-length if it is set... */
|
||||
@ -1352,7 +1418,7 @@ printf ("task_main_proxy_5 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask
|
||||
}
|
||||
|
||||
/* if forwarding didn't finish, something is not really right...
|
||||
* so long as the output from CGI is finished, no more forwarding
|
||||
* so long as the output from peer is finished, no more forwarding
|
||||
* is performed */
|
||||
return (proxy->buflen > 0 || proxy->req ||
|
||||
(proxy->reqfwdbuf && QSE_MBS_LEN(proxy->reqfwdbuf) > 0))? 1: 0;
|
||||
@ -1362,23 +1428,13 @@ static int task_main_proxy_4 (
|
||||
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
||||
{
|
||||
task_proxy_t* proxy = (task_proxy_t*)task->ctx;
|
||||
|
||||
|
||||
#if 0
|
||||
printf ("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask=%d\n",
|
||||
printf ("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger.cmask=%d\n",
|
||||
task->trigger.v[0].mask, task->trigger.v[1].mask, task->trigger.cmask);
|
||||
#endif
|
||||
|
||||
proxy_forward_client_input_to_peer (httpd, task);
|
||||
/*
|
||||
if (task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_READABLE)
|
||||
{
|
||||
proxy_forward_client_input_to_peer (httpd, task, 0);
|
||||
}
|
||||
else if (task->trigger.v[0].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE)
|
||||
{
|
||||
proxy_forward_client_input_to_peer (httpd, task, 1);
|
||||
}
|
||||
*/
|
||||
|
||||
if ((task->trigger.v[0].mask & QSE_HTTPD_TASK_TRIGGER_READABLE) &&
|
||||
proxy->buflen < QSE_SIZEOF(proxy->buf))
|
||||
@ -1436,6 +1492,12 @@ printf ("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask
|
||||
qse_htre_unsetconcb (proxy->req);
|
||||
proxy->req = QSE_NULL;
|
||||
}
|
||||
else if (proxy->flags & PROXY_PROTOCOL_SWITCHED)
|
||||
{
|
||||
qse_htrd_undummify (proxy->client->htrd);
|
||||
qse_htre_unsetconcb (proxy->req);
|
||||
proxy->req = QSE_NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1443,7 +1505,7 @@ printf ("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask
|
||||
{
|
||||
proxy->buflen += n;
|
||||
proxy->peer_output_received += n;
|
||||
|
||||
|
||||
if (proxy->resflags & PROXY_RES_PEER_LENGTH)
|
||||
{
|
||||
QSE_ASSERT (!(proxy->flags & PROXY_RAW));
|
||||
@ -1507,22 +1569,12 @@ static int task_main_proxy_3 (
|
||||
|
||||
task_proxy_t* proxy = (task_proxy_t*)task->ctx;
|
||||
|
||||
#if 0
|
||||
qse_printf (QSE_T("task_main_proxy_3 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask=%d\n"),
|
||||
#if 0
|
||||
printf ("task_main_proxy_3 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask=%d\n",
|
||||
task->trigger.v[0].mask, task->trigger.v[1].mask, task->trigger.cmask);
|
||||
#endif
|
||||
|
||||
proxy_forward_client_input_to_peer (httpd, task);
|
||||
/*
|
||||
if (task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_READABLE)
|
||||
{
|
||||
proxy_forward_client_input_to_peer (httpd, task, 0);
|
||||
}
|
||||
else if (task->trigger.v[0].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE)
|
||||
{
|
||||
proxy_forward_client_input_to_peer (httpd, task, 1);
|
||||
}
|
||||
*/
|
||||
|
||||
if (/*(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITABLE) &&*/ proxy->res_pending > 0)
|
||||
{
|
||||
@ -1566,6 +1618,12 @@ qse_printf (QSE_T("task_main_proxy_3 trigger[0].mask=%d trigger[1].mask=%d trigg
|
||||
qse_mbs_clear (proxy->res);
|
||||
proxy->res_consumed = 0;
|
||||
|
||||
if (proxy->flags & PROXY_PROTOCOL_SWITCHED)
|
||||
{
|
||||
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_READ;
|
||||
goto read_more;
|
||||
}
|
||||
|
||||
if ((proxy->resflags & PROXY_RES_CLIENT_CHUNK) ||
|
||||
((proxy->resflags & PROXY_RES_PEER_LENGTH) && proxy->peer_output_received >= proxy->peer_output_length))
|
||||
{
|
||||
@ -1575,6 +1633,7 @@ qse_printf (QSE_T("task_main_proxy_3 trigger[0].mask=%d trigger[1].mask=%d trigg
|
||||
}
|
||||
else
|
||||
{
|
||||
read_more:
|
||||
/* there are still more to read from the peer.
|
||||
* arrange to read the remaining contents from the peer */
|
||||
task->main = task_main_proxy_4;
|
||||
@ -1596,24 +1655,7 @@ static int task_main_proxy_2 (
|
||||
task_proxy_t* proxy = (task_proxy_t*)task->ctx;
|
||||
int http_errnum = 500;
|
||||
|
||||
#if 0
|
||||
printf ("task_main_proxy_2 trigger[0].mask=%d trigger[1].mask=%d cmask=%d\n",
|
||||
task->trigger.v[0].mask, task->trigger.v[1].mask, task->trigger.cmask);
|
||||
#endif
|
||||
|
||||
proxy_forward_client_input_to_peer (httpd, task);
|
||||
#if 0
|
||||
if (task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_READABLE)
|
||||
{
|
||||
/* client is readable */
|
||||
proxy_forward_client_input_to_peer (httpd, task, 0);
|
||||
}
|
||||
else if (task->trigger.v[0].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE)
|
||||
{
|
||||
/* client is not readable but peer is writable */
|
||||
proxy_forward_client_input_to_peer (httpd, task, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (/*(task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITABLE) && */ proxy->res_pending > 0)
|
||||
{
|
||||
@ -1624,8 +1666,8 @@ printf ("task_main_proxy_2 trigger[0].mask=%d trigger[1].mask=%d cmask=%d\n",
|
||||
* '100 Continue' to the client.
|
||||
*
|
||||
* attempt to write to the client regardless of writability of
|
||||
* the cleint socket as it is non-blocking. see the check commented
|
||||
* in the 'if' condition above. */
|
||||
* the cleint socket as it is non-blocking. see the check commented
|
||||
* out in the 'if' condition above. */
|
||||
|
||||
qse_ssize_t n;
|
||||
qse_size_t count;
|
||||
@ -1729,14 +1771,6 @@ printf ("task_main_proxy_2 trigger[0].mask=%d trigger[1].mask=%d cmask=%d\n",
|
||||
proxy->buflen += n;
|
||||
}
|
||||
|
||||
#if 0
|
||||
qse_printf (QSE_T("#####PROXY FEEDING %d [\n"), (int)proxy->buflen);
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < proxy->buflen; i++) qse_printf (QSE_T("%hc"), proxy->buf[i]);
|
||||
}
|
||||
qse_printf (QSE_T("]\n"));
|
||||
#endif
|
||||
if (proxy->buflen > 0)
|
||||
{
|
||||
if (qse_htrd_feed (proxy->peer_htrd, proxy->buf, proxy->buflen) <= -1)
|
||||
@ -1749,7 +1783,13 @@ qse_printf (QSE_T("]\n"));
|
||||
proxy->buflen = 0;
|
||||
}
|
||||
|
||||
if (QSE_MBS_LEN(proxy->res) > 0)
|
||||
if (proxy->flags & PROXY_PROTOCOL_SWITCHED)
|
||||
{
|
||||
task->trigger.cmask = QSE_HTTPD_TASK_TRIGGER_READ;
|
||||
if (QSE_MBS_LEN(proxy->res) > 0) task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||
task->main = task_main_proxy_3;
|
||||
}
|
||||
else if (QSE_MBS_LEN(proxy->res) > 0)
|
||||
{
|
||||
if (proxy->resflags & PROXY_RES_RECEIVED_RESCON)
|
||||
{
|
||||
@ -1842,10 +1882,17 @@ static int task_main_proxy_1 (
|
||||
{
|
||||
/* connected to the peer now */
|
||||
proxy->peer_status |= PROXY_PEER_CONNECTED;
|
||||
if (proxy->req)
|
||||
if (!(proxy->flags & PROXY_UPGRADE_REQUESTED) && proxy->req)
|
||||
{
|
||||
/* need to read from the client-side as
|
||||
* the content has not been received in full. */
|
||||
* the content has not been received in full.
|
||||
*
|
||||
* proxy->req is set to the original request when snatching is
|
||||
* required. it's also set to the original request when protocol
|
||||
* upgrade is requested. however, a upgrade request containing
|
||||
* contents is treated as a bad request. so i don't arrange
|
||||
* to read from the client side when PROXY_UPGRADE_REQUESTED
|
||||
* is on. */
|
||||
task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_READ;
|
||||
}
|
||||
|
||||
@ -2124,7 +2171,12 @@ static int task_main_proxy (
|
||||
|
||||
if (proxy->flags & PROXY_INIT_FAILED)
|
||||
{
|
||||
if (proxy->flags & PROXY_PEER_NAME_UNRESOLVED) http_errnum = 404; /* 404 Not Found */
|
||||
if (proxy->flags & PROXY_GOT_BAD_REQUEST)
|
||||
{
|
||||
http_errnum = 400; /* 400 Bad Request */
|
||||
proxy->keepalive = 0; /* force Connect: close in the response */
|
||||
}
|
||||
else if (proxy->flags & PROXY_PEER_NAME_UNRESOLVED) http_errnum = 404; /* 404 Not Found */
|
||||
goto oops;
|
||||
}
|
||||
|
||||
@ -2194,7 +2246,7 @@ static int task_main_proxy (
|
||||
* for a socket descriptor into 1 event.
|
||||
*
|
||||
* if this happens, qse_http_resolvename() can be called
|
||||
* multiple times.
|
||||
* multiple times. set this flag to prevent double resolution.
|
||||
*/
|
||||
proxy->flags |= PROXY_PEER_NAME_RESOLVING;
|
||||
|
||||
@ -2268,10 +2320,18 @@ static int task_main_proxy (
|
||||
{
|
||||
/* peer connected already */
|
||||
proxy->peer_status |= PROXY_PEER_CONNECTED;
|
||||
if (proxy->req)
|
||||
if (!(proxy->flags & PROXY_UPGRADE_REQUESTED) && proxy->req)
|
||||
{
|
||||
/* need to read from the client-side as
|
||||
* the content has not been received in full. */
|
||||
* the content has not been received in full.
|
||||
*
|
||||
* proxy->req is set to the original request when snatching is
|
||||
* required. it's also set to the original request when protocol
|
||||
* upgrade is requested. however, a upgrade request containing
|
||||
* contents is treated as a bad request. so i don't arrange
|
||||
* to read from the client side when PROXY_UPGRADE_REQUESTED
|
||||
* is on.
|
||||
*/
|
||||
task->trigger.cmask = QSE_HTTPD_TASK_TRIGGER_READ;
|
||||
}
|
||||
|
||||
|
@ -792,9 +792,6 @@ resolved:
|
||||
static void tmr_dns_tmout_update (qse_tmr_t* tmr, qse_tmr_index_t old_index, qse_tmr_index_t new_index, void* ctx)
|
||||
{
|
||||
dns_req_t* req = (dns_req_t*)ctx;
|
||||
|
||||
printf (">>tmr_dns_tmout_updated req->>%p\n", req);
|
||||
printf (">>tmr_dns_tmout_updated existing->%d, old->%d new->%d\n", (int)req->tmr_tmout, (int)old_index, (int)new_index);
|
||||
QSE_ASSERT (req->tmr_tmout == old_index);
|
||||
req->tmr_tmout = new_index;
|
||||
}
|
||||
|
@ -347,7 +347,6 @@ static void tmr_urs_tmout_update (qse_tmr_t* tmr, qse_tmr_index_t old_index, qse
|
||||
{
|
||||
urs_req_t* req = (urs_req_t*)ctx;
|
||||
|
||||
printf (">>tmr_urs_tmout_updated existing=%d old=%d new=%d\n", (int)req->tmr_tmout, (int)old_index, (int)new_index);
|
||||
QSE_ASSERT (req->tmr_tmout == old_index);
|
||||
req->tmr_tmout = new_index;
|
||||
}
|
||||
|
@ -2242,7 +2242,7 @@ printf ("SWITCHING HTRD TO DUMMY.... %s\n", qse_htre_getqpath(req));
|
||||
/* Switch the http read to a dummy mode so that the subsqeuent
|
||||
* input(request) is just treated as data to the request just
|
||||
* completed */
|
||||
qse_htrd_setoption (client->htrd, qse_htrd_getoption(client->htrd) | QSE_HTRD_DUMMY);
|
||||
qse_htrd_dummify (client->htrd);
|
||||
|
||||
if (server_xtn->makersrc (httpd, client, req, &rsrc) <= -1)
|
||||
{
|
||||
|
@ -711,7 +711,6 @@ qse_printf (QSE_T("failed to accept from server [%s] [%d]\n"), tmp, server->hand
|
||||
static void tmr_idle_update (qse_tmr_t* tmr, qse_tmr_index_t old_index, qse_tmr_index_t new_index, void* ctx)
|
||||
{
|
||||
qse_httpd_client_t* client = (qse_httpd_client_t*)ctx;
|
||||
printf ("tmr_idle updated old_index %d new_index %d tmr_idle %d\n", (int)old_index, (int)new_index, (int)client->tmr_idle);
|
||||
QSE_ASSERT (client->tmr_idle == old_index);
|
||||
client->tmr_idle = new_index;
|
||||
}
|
||||
@ -720,7 +719,6 @@ static void tmr_idle_handle (qse_tmr_t* tmr, const qse_ntime_t* now, void* ctx)
|
||||
{
|
||||
qse_httpd_client_t* client = (qse_httpd_client_t*)ctx;
|
||||
|
||||
printf ("check if client is idle...\n");
|
||||
if (qse_cmptime(now, &client->last_active) >= 0)
|
||||
{
|
||||
qse_ntime_t diff;
|
||||
@ -728,14 +726,12 @@ printf ("check if client is idle...\n");
|
||||
if (qse_cmptime(&diff, &client->server->httpd->opt.idle_limit) >= 0)
|
||||
{
|
||||
/* this client is idle */
|
||||
printf ("client is idle purging....\n");
|
||||
purge_client (client->server->httpd, client);
|
||||
}
|
||||
else
|
||||
{
|
||||
qse_tmr_event_t idle_event;
|
||||
|
||||
printf ("client is NOT idle....\n");
|
||||
QSE_ASSERT (client->server->httpd->tmr == tmr);
|
||||
|
||||
/*qse_gettime (&idle_event.when);*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user