added qse_htre_t and changed data type names
This commit is contained in:
parent
325a9d8b2b
commit
6fcd875403
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: str.h 497 2011-06-20 14:56:40Z hyunghwan.chung $
|
||||
* $Id: str.h 500 2011-06-29 15:12:36Z hyunghwan.chung $
|
||||
*
|
||||
Copyright 2006-2011 Chung, Hyung-Hwan.
|
||||
This file is part of QSE.
|
||||
@ -2144,10 +2144,11 @@ void qse_mbs_close (
|
||||
/**
|
||||
* The qse_mbs_init() function initializes a dynamically resizable string
|
||||
* If the parameter capa is 0, it doesn't allocate the internal buffer
|
||||
* in advance.
|
||||
* in advance and always succeeds.
|
||||
* @return @a mbs on success, #QSE_NULL on failure.
|
||||
*/
|
||||
qse_mbs_t* qse_mbs_init (
|
||||
qse_mbs_t* str,
|
||||
qse_mbs_t* mbs,
|
||||
qse_mmgr_t* mmgr,
|
||||
qse_size_t capa
|
||||
);
|
||||
@ -2156,7 +2157,7 @@ qse_mbs_t* qse_mbs_init (
|
||||
* The qse_mbs_fini() function finalizes a dynamically resizable string.
|
||||
*/
|
||||
void qse_mbs_fini (
|
||||
qse_mbs_t* str
|
||||
qse_mbs_t* mbs
|
||||
);
|
||||
|
||||
/**
|
||||
@ -2313,10 +2314,11 @@ void qse_wcs_close (
|
||||
/**
|
||||
* The qse_wcs_init() function initializes a dynamically resizable string
|
||||
* If the parameter capa is 0, it doesn't allocate the internal buffer
|
||||
* in advance.
|
||||
* in advance and always succeeds.
|
||||
* @return @a wcs on success, #QSE_NULL on failure.
|
||||
*/
|
||||
qse_wcs_t* qse_wcs_init (
|
||||
qse_wcs_t* str,
|
||||
qse_wcs_t* wcs,
|
||||
qse_mmgr_t* mmgr,
|
||||
qse_size_t capa
|
||||
);
|
||||
@ -2325,7 +2327,7 @@ qse_wcs_t* qse_wcs_init (
|
||||
* The qse_wcs_fini() function finalizes a dynamically resizable string.
|
||||
*/
|
||||
void qse_wcs_fini (
|
||||
qse_wcs_t* str
|
||||
qse_wcs_t* wcs
|
||||
);
|
||||
|
||||
/**
|
||||
|
127
qse/include/qse/http/htre.h
Normal file
127
qse/include/qse/http/htre.h
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright 2006-2011 Chung, Hyung-Hwan.
|
||||
This file is part of QSE.
|
||||
|
||||
QSE is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
QSE is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with QSE. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _QSE_HTTP_HTRE_H_
|
||||
#define _QSE_HTTP_HTRE_H_
|
||||
|
||||
#include <qse/types.h>
|
||||
#include <qse/macros.h>
|
||||
#include <qse/cmn/htb.h>
|
||||
#include <qse/cmn/str.h>
|
||||
|
||||
/*typedef qse_byte_t qse_htoc_t;*/
|
||||
typedef qse_mchar_t qse_htoc_t;
|
||||
|
||||
/* octet buffer */
|
||||
typedef qse_mbs_t qse_htob_t;
|
||||
|
||||
/* octet string */
|
||||
typedef qse_mxstr_t qse_htos_t;
|
||||
|
||||
typedef struct qse_htvr_t qse_htvr_t;
|
||||
struct qse_htvr_t
|
||||
{
|
||||
short major;
|
||||
short minor;
|
||||
};
|
||||
|
||||
/* header and contents of request/response */
|
||||
typedef struct qse_htre_t qse_htre_t;
|
||||
struct qse_htre_t
|
||||
{
|
||||
qse_mmgr_t* mmgr;
|
||||
|
||||
/* version */
|
||||
qse_htvr_t version;
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
enum
|
||||
{
|
||||
QSE_HTTP_REQ_GET,
|
||||
QSE_HTTP_REQ_HEAD,
|
||||
QSE_HTTP_REQ_POST,
|
||||
QSE_HTTP_REQ_PUT,
|
||||
QSE_HTTP_REQ_DELETE,
|
||||
QSE_HTTP_REQ_TRACE,
|
||||
QSE_HTTP_REQ_OPTIONS,
|
||||
QSE_HTTP_REQ_CONNECT
|
||||
} method;
|
||||
|
||||
qse_htos_t path;
|
||||
/* qse_htos_t args; */
|
||||
} quest;
|
||||
|
||||
struct
|
||||
{
|
||||
int code;
|
||||
qse_htos_t message;
|
||||
} sponse;
|
||||
} re;
|
||||
|
||||
/* special attributes derived from the header */
|
||||
struct
|
||||
{
|
||||
int chunked;
|
||||
int content_length;
|
||||
int connection_close;
|
||||
qse_htos_t content_type;
|
||||
qse_htos_t host;
|
||||
int expect_continue;
|
||||
} attr;
|
||||
|
||||
/* header table */
|
||||
qse_htb_t hdrtab;
|
||||
|
||||
/* content octets */
|
||||
qse_htob_t content;
|
||||
|
||||
/* if set, the rest of the contents are discarded */
|
||||
int discard;
|
||||
};
|
||||
|
||||
#define qse_htre_getversion(re) &((re)->version)
|
||||
#define qse_htre_setversion(re,v) QSE_BLOCK((re)->version = *(v);)
|
||||
#define qse_htre_setdiscard(re,v) QSE_BLOCK((re)->discard = (v);)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
qse_htre_t* qse_htre_init (
|
||||
qse_htre_t* re,
|
||||
qse_mmgr_t* mmgr
|
||||
);
|
||||
|
||||
void qse_htre_fini (
|
||||
qse_htre_t* re
|
||||
);
|
||||
|
||||
void qse_htre_clear (
|
||||
qse_htre_t* re
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,28 +1,30 @@
|
||||
/*
|
||||
* $Id: http.h 223 2008-06-26 06:44:41Z baconevi $
|
||||
*
|
||||
Copyright 2006-2011 Chung, Hyung-Hwan.
|
||||
This file is part of QSE.
|
||||
|
||||
QSE is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
QSE is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with QSE. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _QSE_UTL_HTTP_H_
|
||||
#define _QSE_UTL_HTTP_H_
|
||||
#ifndef _QSE_HTTP_HTTP_H_
|
||||
#define _QSE_HTTP_HTTP_H_
|
||||
|
||||
#include <qse/types.h>
|
||||
#include <qse/macros.h>
|
||||
#include <qse/cmn/htb.h>
|
||||
#include <qse/http/htre.h>
|
||||
|
||||
typedef struct qse_http_t qse_http_t;
|
||||
|
||||
/*typedef qse_byte_t qse_http_oct_t;*/
|
||||
typedef qse_mchar_t qse_http_oct_t;
|
||||
|
||||
typedef struct qse_http_octb_t qse_http_octb_t;
|
||||
|
||||
struct qse_http_octb_t
|
||||
{
|
||||
qse_size_t capa;
|
||||
qse_size_t size;
|
||||
qse_http_oct_t* data;
|
||||
};
|
||||
|
||||
enum qse_http_errnum_t
|
||||
{
|
||||
QSE_HTTP_ENOERR,
|
||||
@ -41,105 +43,13 @@ enum qse_http_option_t
|
||||
|
||||
typedef enum qse_http_option_t qse_http_option_t;
|
||||
|
||||
typedef struct qse_http_req_t qse_http_req_t;
|
||||
typedef struct qse_http_res_t qse_http_res_t;
|
||||
typedef struct qse_http_rhc_t qse_http_rhc_t;
|
||||
|
||||
/* header and contents of request/response */
|
||||
struct qse_http_rhc_t
|
||||
{
|
||||
/* header table */
|
||||
qse_htb_t hdrtab;
|
||||
|
||||
/* special attributes derived from the header */
|
||||
struct
|
||||
{
|
||||
int chunked;
|
||||
int content_length;
|
||||
int connection_close;
|
||||
struct
|
||||
{
|
||||
qse_http_oct_t* ptr;
|
||||
qse_size_t len;
|
||||
} content_type;
|
||||
struct
|
||||
{
|
||||
qse_http_oct_t* ptr;
|
||||
qse_size_t len;
|
||||
} host;
|
||||
|
||||
int expect_continue;
|
||||
} attr;
|
||||
|
||||
qse_http_octb_t con;
|
||||
|
||||
/* if set, the rest of the contents are discarded */
|
||||
int discard;
|
||||
};
|
||||
|
||||
struct qse_http_req_t
|
||||
{
|
||||
enum
|
||||
{
|
||||
QSE_HTTP_REQ_GET,
|
||||
QSE_HTTP_REQ_HEAD,
|
||||
QSE_HTTP_REQ_POST,
|
||||
QSE_HTTP_REQ_PUT,
|
||||
QSE_HTTP_REQ_DELETE,
|
||||
QSE_HTTP_REQ_TRACE,
|
||||
QSE_HTTP_REQ_OPTIONS,
|
||||
QSE_HTTP_REQ_CONNECT
|
||||
} method;
|
||||
|
||||
struct
|
||||
{
|
||||
qse_http_oct_t* ptr;
|
||||
qse_size_t len;
|
||||
} path;
|
||||
|
||||
#if 0
|
||||
struct
|
||||
{
|
||||
qse_http_oct_t* ptr;
|
||||
qse_size_t len;
|
||||
} args;
|
||||
#endif
|
||||
|
||||
struct
|
||||
{
|
||||
short major;
|
||||
short minor;
|
||||
} version;
|
||||
|
||||
qse_http_rhc_t* rhc;
|
||||
};
|
||||
|
||||
struct qse_http_res_t
|
||||
{
|
||||
struct
|
||||
{
|
||||
short major;
|
||||
short minor;
|
||||
} version;
|
||||
|
||||
int code;
|
||||
|
||||
struct
|
||||
{
|
||||
qse_http_oct_t* ptr;
|
||||
qse_size_t len;
|
||||
} message;
|
||||
|
||||
qse_http_rhc_t* rhc;
|
||||
};
|
||||
|
||||
typedef struct qse_http_recbs_t qse_http_recbs_t;
|
||||
|
||||
struct qse_http_recbs_t
|
||||
{
|
||||
int (*request) (qse_http_t* http, qse_http_req_t* req);
|
||||
int (*response) (qse_http_t* http, qse_http_res_t* rep);
|
||||
int (*expect_continue) (qse_http_t* http, qse_http_req_t* req);
|
||||
int (*request) (qse_http_t* http, qse_htre_t* req);
|
||||
int (*response) (qse_http_t* http, qse_htre_t* res);
|
||||
int (*expect_continue) (qse_http_t* http, qse_htre_t* req);
|
||||
};
|
||||
|
||||
struct qse_http_t
|
||||
@ -170,29 +80,22 @@ struct qse_http_t
|
||||
/* buffers needed to for processing a request */
|
||||
struct
|
||||
{
|
||||
qse_http_octb_t raw; /* buffer to hold raw octets */
|
||||
qse_http_octb_t tra; /* buffer for handling trailers */
|
||||
qse_http_octb_t pen; /* buffer for raw octets during pending period */
|
||||
qse_htob_t raw; /* buffer to hold raw octets */
|
||||
qse_htob_t tra; /* buffer for handling trailers */
|
||||
qse_htob_t pen; /* buffer for raw octets during pending period */
|
||||
} b;
|
||||
|
||||
/* points to the head of the combined header list */
|
||||
void* chl;
|
||||
} fed;
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
QSE_HTTP_RETYPE_Q,
|
||||
QSE_HTTP_RETYPE_S
|
||||
} retype;
|
||||
|
||||
union
|
||||
{
|
||||
qse_http_req_t q;
|
||||
qse_http_res_t s;
|
||||
} re;
|
||||
|
||||
qse_http_rhc_t rhc;
|
||||
qse_htre_t re;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -252,9 +155,9 @@ void qse_http_setrecbs (
|
||||
* callback function if it has processed a proper http request.
|
||||
*/
|
||||
int qse_http_feed (
|
||||
qse_http_t* http, /**< http */
|
||||
const qse_http_oct_t* req, /**< request octets */
|
||||
qse_size_t len /**< number of octets */
|
||||
qse_http_t* http, /**< http */
|
||||
const qse_htoc_t* req, /**< request octets */
|
||||
qse_size_t len /**< number of octets */
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -7,6 +7,7 @@ AM_CPPFLAGS = \
|
||||
|
||||
lib_LTLIBRARIES = libqsehttp.la
|
||||
libqsehttp_la_SOURCES = \
|
||||
htre.c \
|
||||
http.c
|
||||
|
||||
libqsehttp_la_LDFLAGS = -version-info 1:0:0 -no-undefined -L../cmn -L$(libdir)
|
||||
|
@ -71,7 +71,7 @@ am__base_list = \
|
||||
am__installdirs = "$(DESTDIR)$(libdir)"
|
||||
LTLIBRARIES = $(lib_LTLIBRARIES)
|
||||
libqsehttp_la_DEPENDENCIES =
|
||||
am_libqsehttp_la_OBJECTS = http.lo
|
||||
am_libqsehttp_la_OBJECTS = htre.lo http.lo
|
||||
libqsehttp_la_OBJECTS = $(am_libqsehttp_la_OBJECTS)
|
||||
libqsehttp_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
@ -239,6 +239,7 @@ AM_CPPFLAGS = \
|
||||
|
||||
lib_LTLIBRARIES = libqsehttp.la
|
||||
libqsehttp_la_SOURCES = \
|
||||
htre.c \
|
||||
http.c
|
||||
|
||||
libqsehttp_la_LDFLAGS = -version-info 1:0:0 -no-undefined -L../cmn -L$(libdir)
|
||||
@ -317,6 +318,7 @@ mostlyclean-compile:
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htre.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http.Plo@am__quote@
|
||||
|
||||
.c.o:
|
||||
|
99
qse/lib/http/htre.c
Normal file
99
qse/lib/http/htre.c
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
#include <qse/http/htre.h>
|
||||
#include "../cmn/mem.h"
|
||||
|
||||
qse_htre_t* qse_htre_init (qse_htre_t* re, qse_mmgr_t* mmgr)
|
||||
{
|
||||
QSE_MEMSET (re, 0, QSE_SIZEOF(*re));
|
||||
re->mmgr = mmgr;
|
||||
|
||||
if (qse_htb_init (&re->hdrtab, mmgr, 60, 70, 1, 1) == QSE_NULL)
|
||||
{
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
if (qse_mbs_init (&re->content, mmgr, 0) == QSE_NULL)
|
||||
{
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
return re;
|
||||
}
|
||||
|
||||
void qse_htre_fini (qse_htre_t* re)
|
||||
{
|
||||
qse_mbs_fini (&re->content);
|
||||
qse_htb_fini (&re->hdrtab);
|
||||
}
|
||||
|
||||
void qse_htre_clear (qse_htre_t* re)
|
||||
{
|
||||
QSE_MEMSET (&re->version, 0, QSE_SIZEOF(re->version));
|
||||
QSE_MEMSET (&re->re, 0, QSE_SIZEOF(re->re));
|
||||
QSE_MEMSET (&re->attr, 0, QSE_SIZEOF(re->attr));
|
||||
|
||||
qse_htb_clear (&re->hdrtab);
|
||||
qse_mbs_clear (&re->content);
|
||||
|
||||
re->discard = 0;
|
||||
}
|
||||
|
||||
static QSE_INLINE int xdigit_to_num (qse_htoc_t c)
|
||||
{
|
||||
if (c >= '0' && c <= '9') return c - '0';
|
||||
if (c >= 'A' && c <= 'Z') return c - 'A' + 10;
|
||||
if (c >= 'a' && c <= 'z') return c - 'a' + 10;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int qse_htre_decodereqpath (qse_htre_t* re, int )
|
||||
{
|
||||
qse_htoc_t* p = re->re.quest.path.ptr;
|
||||
qse_htoc_t* tmp = re->re.quest.path.ptr;
|
||||
|
||||
while (*p != '\0')
|
||||
{
|
||||
if (*p == '%')
|
||||
{
|
||||
int q = xdigit_to_num(*(p+1));
|
||||
int w = xdigit_to_num(*(p+2));
|
||||
|
||||
if (q >= 0 && w >= 0)
|
||||
{
|
||||
int t = (q << 4) + w;
|
||||
if (t == 0)
|
||||
{
|
||||
/* percent enconding contains a null character */
|
||||
return -1;
|
||||
}
|
||||
|
||||
*tmp++ = t;
|
||||
p += 3;
|
||||
}
|
||||
else *tmp++ = *p++;
|
||||
}
|
||||
else if (*p == '?')
|
||||
{
|
||||
#if 0
|
||||
if (!http->re.re.quest.args.ptr)
|
||||
{
|
||||
/* ? must be explicit to be a argument instroducer.
|
||||
* %3f is just a literal. */
|
||||
http->re.re.quest.path.len = tmp - http->re.re.quest.path.ptr;
|
||||
*tmp++ = '\0';
|
||||
http->re.re.quest.args.ptr = tmp;
|
||||
p++;
|
||||
}
|
||||
else *tmp++ = *p++;
|
||||
#endif
|
||||
}
|
||||
else *tmp++ = *p++;
|
||||
}
|
||||
*tmp = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -24,58 +24,58 @@
|
||||
|
||||
QSE_IMPLEMENT_COMMON_FUNCTIONS (http)
|
||||
|
||||
static const qse_http_oct_t NUL = '\0';
|
||||
static const qse_htoc_t NUL = '\0';
|
||||
|
||||
static QSE_INLINE int is_whspace_octet (qse_http_oct_t c)
|
||||
static QSE_INLINE int is_whspace_octet (qse_htoc_t c)
|
||||
{
|
||||
return c == ' ' || c == '\t' || c == '\r' || c == '\n';
|
||||
}
|
||||
|
||||
static QSE_INLINE int is_space_octet (qse_http_oct_t c)
|
||||
static QSE_INLINE int is_space_octet (qse_htoc_t c)
|
||||
{
|
||||
return c == ' ' || c == '\t' || c == '\r';
|
||||
}
|
||||
|
||||
static QSE_INLINE int is_purespace_octet (qse_http_oct_t c)
|
||||
static QSE_INLINE int is_purespace_octet (qse_htoc_t c)
|
||||
{
|
||||
return c == ' ' || c == '\t';
|
||||
}
|
||||
|
||||
static QSE_INLINE int is_upalpha_octet (qse_http_oct_t c)
|
||||
static QSE_INLINE int is_upalpha_octet (qse_htoc_t c)
|
||||
{
|
||||
return c >= 'A' && c <= 'Z';
|
||||
}
|
||||
|
||||
static QSE_INLINE int is_loalpha_octet (qse_http_oct_t c)
|
||||
static QSE_INLINE int is_loalpha_octet (qse_htoc_t c)
|
||||
{
|
||||
return c >= 'a' && c <= 'z';
|
||||
}
|
||||
|
||||
static QSE_INLINE int is_alpha_octet (qse_http_oct_t c)
|
||||
static QSE_INLINE int is_alpha_octet (qse_htoc_t c)
|
||||
{
|
||||
return (c >= 'A' && c <= 'Z') ||
|
||||
(c >= 'a' && c <= 'z');
|
||||
}
|
||||
|
||||
static QSE_INLINE int is_digit_octet (qse_http_oct_t c)
|
||||
static QSE_INLINE int is_digit_octet (qse_htoc_t c)
|
||||
{
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
static QSE_INLINE int is_xdigit_octet (qse_http_oct_t c)
|
||||
static QSE_INLINE int is_xdigit_octet (qse_htoc_t c)
|
||||
{
|
||||
return (c >= '0' && c <= '9') ||
|
||||
(c >= 'A' && c <= 'F') ||
|
||||
(c >= 'a' && c <= 'f');
|
||||
}
|
||||
|
||||
static QSE_INLINE int digit_to_num (qse_http_oct_t c)
|
||||
static QSE_INLINE int digit_to_num (qse_htoc_t c)
|
||||
{
|
||||
if (c >= '0' && c <= '9') return c - '0';
|
||||
return -1;
|
||||
}
|
||||
|
||||
static QSE_INLINE int xdigit_to_num (qse_http_oct_t c)
|
||||
static QSE_INLINE int xdigit_to_num (qse_htoc_t c)
|
||||
{
|
||||
if (c >= '0' && c <= '9') return c - '0';
|
||||
if (c >= 'A' && c <= 'Z') return c - 'A' + 10;
|
||||
@ -83,67 +83,15 @@ static QSE_INLINE int xdigit_to_num (qse_http_oct_t c)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static QSE_INLINE void init_buffer (qse_http_t* http, qse_http_octb_t* octb)
|
||||
{
|
||||
octb->size = 0;
|
||||
octb->capa = 0;
|
||||
octb->data = QSE_NULL;
|
||||
}
|
||||
|
||||
static QSE_INLINE void fini_buffer (qse_http_t* http, qse_http_octb_t* octb)
|
||||
{
|
||||
if (octb->data)
|
||||
{
|
||||
QSE_MMGR_FREE (http->mmgr, octb->data);
|
||||
octb->capa = 0;
|
||||
octb->size = 0;
|
||||
octb->data = QSE_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static QSE_INLINE_ALWAYS void clear_buffer (qse_http_t* http, qse_http_octb_t* octb)
|
||||
{
|
||||
octb->size = 0;
|
||||
}
|
||||
|
||||
static QSE_INLINE int push_to_buffer (
|
||||
qse_http_t* http, qse_http_octb_t* octb,
|
||||
const qse_http_oct_t* ptr, qse_size_t len)
|
||||
qse_http_t* http, qse_htob_t* octb,
|
||||
const qse_htoc_t* ptr, qse_size_t len)
|
||||
{
|
||||
qse_size_t nsize = (octb)->size + len;
|
||||
const qse_http_oct_t* end = ptr + len;
|
||||
|
||||
if (nsize > (octb)->capa)
|
||||
if (qse_mbs_ncat (octb, ptr, len) == (qse_size_t)-1)
|
||||
{
|
||||
/* TODO: enhance the resizing scheme */
|
||||
qse_size_t ncapa = (nsize > (octb)->capa * 2)? nsize: ((octb)->capa * 2);
|
||||
|
||||
do
|
||||
{
|
||||
void* tmp = QSE_MMGR_REALLOC (
|
||||
(http)->mmgr, (octb)->data, ncapa * QSE_SIZEOF(*ptr)
|
||||
);
|
||||
if (tmp)
|
||||
{
|
||||
(octb)->capa = ncapa;
|
||||
(octb)->data = tmp;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ncapa <= nsize)
|
||||
{
|
||||
(http)->errnum = QSE_HTTP_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* retry with a smaller size */
|
||||
ncapa--;
|
||||
}
|
||||
while (1);
|
||||
http->errnum = QSE_HTTP_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (ptr < end) (octb)->data[(octb)->size++] = *ptr++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -170,18 +118,13 @@ static QSE_INLINE void clear_feed (qse_http_t* http)
|
||||
{
|
||||
/* clear necessary part of the request/response before
|
||||
* reading the next request/response */
|
||||
QSE_MEMSET (&http->re, 0, QSE_SIZEOF(http->re));
|
||||
QSE_MEMSET (&http->rhc.attr, 0, QSE_SIZEOF(http->rhc.attr));
|
||||
qse_htre_clear (&http->re);
|
||||
|
||||
qse_htb_clear (&http->rhc.hdrtab);
|
||||
qse_mbs_clear (&http->fed.b.tra);
|
||||
qse_mbs_clear (&http->fed.b.raw);
|
||||
clear_combined_headers (http);
|
||||
|
||||
clear_buffer (http, &http->rhc.con);
|
||||
clear_buffer (http, &http->fed.b.tra);
|
||||
clear_buffer (http, &http->fed.b.raw);
|
||||
|
||||
QSE_MEMSET (&http->fed.s, 0, QSE_SIZEOF(http->fed.s));
|
||||
http->rhc.discard = 0;
|
||||
}
|
||||
|
||||
#define QSE_HTTP_STATE_REQ 1
|
||||
@ -229,17 +172,15 @@ qse_http_t* qse_http_init (qse_http_t* http, qse_mmgr_t* mmgr)
|
||||
QSE_MEMSET (http, 0, QSE_SIZEOF(*http));
|
||||
http->mmgr = mmgr;
|
||||
|
||||
init_buffer (http, &http->fed.b.raw);
|
||||
init_buffer (http, &http->fed.b.tra);
|
||||
init_buffer (http, &http->fed.b.pen);
|
||||
init_buffer (http, &http->rhc.con);
|
||||
qse_mbs_init (&http->fed.b.raw, http->mmgr, 0);
|
||||
qse_mbs_init (&http->fed.b.tra, http->mmgr, 0);
|
||||
qse_mbs_init (&http->fed.b.pen, http->mmgr, 0);
|
||||
|
||||
if (qse_htb_init (&http->rhc.hdrtab, mmgr, 60, 70, 1, 1) == QSE_NULL)
|
||||
if (qse_htre_init (&http->re, mmgr) == QSE_NULL)
|
||||
{
|
||||
fini_buffer (http, &http->rhc.con);
|
||||
fini_buffer (http, &http->fed.b.pen);
|
||||
fini_buffer (http, &http->fed.b.tra);
|
||||
fini_buffer (http, &http->fed.b.raw);
|
||||
qse_mbs_fini (&http->fed.b.pen);
|
||||
qse_mbs_fini (&http->fed.b.tra);
|
||||
qse_mbs_fini (&http->fed.b.raw);
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
@ -248,19 +189,19 @@ qse_http_t* qse_http_init (qse_http_t* http, qse_mmgr_t* mmgr)
|
||||
|
||||
void qse_http_fini (qse_http_t* http)
|
||||
{
|
||||
qse_htb_fini (&http->rhc.hdrtab);
|
||||
qse_htre_fini (&http->re);
|
||||
|
||||
clear_combined_headers (http);
|
||||
fini_buffer (http, &http->rhc.con);
|
||||
fini_buffer (http, &http->fed.b.pen);
|
||||
fini_buffer (http, &http->fed.b.tra);
|
||||
fini_buffer (http, &http->fed.b.raw);
|
||||
qse_mbs_fini (&http->fed.b.pen);
|
||||
qse_mbs_fini (&http->fed.b.tra);
|
||||
qse_mbs_fini (&http->fed.b.raw);
|
||||
}
|
||||
|
||||
static qse_http_oct_t* parse_initial_line (
|
||||
qse_http_t* http, qse_http_oct_t* line)
|
||||
static qse_htoc_t* parse_initial_line (
|
||||
qse_http_t* http, qse_htoc_t* line)
|
||||
{
|
||||
qse_http_oct_t* p = line;
|
||||
qse_http_oct_t* tmp;
|
||||
qse_htoc_t* p = line;
|
||||
qse_htoc_t* tmp;
|
||||
qse_size_t tmplen;
|
||||
|
||||
#if 0
|
||||
@ -285,12 +226,12 @@ static qse_http_oct_t* parse_initial_line (
|
||||
/* GET, PUT */
|
||||
if (tmp[0] == 'G' && tmp[1] == 'E' && tmp[2] == 'T')
|
||||
{
|
||||
http->re.q.method = QSE_HTTP_REQ_GET;
|
||||
http->re.re.quest.method = QSE_HTTP_REQ_GET;
|
||||
break;
|
||||
}
|
||||
else if (tmp[0] == 'P' && tmp[1] == 'U' && tmp[2] == 'T')
|
||||
{
|
||||
http->re.q.method = QSE_HTTP_REQ_PUT;
|
||||
http->re.re.quest.method = QSE_HTTP_REQ_PUT;
|
||||
break;
|
||||
}
|
||||
goto badre;
|
||||
@ -299,12 +240,12 @@ static qse_http_oct_t* parse_initial_line (
|
||||
/* POST, HEAD */
|
||||
if (tmp[0] == 'P' && tmp[1] == 'O' && tmp[2] == 'S' && tmp[3] == 'T')
|
||||
{
|
||||
http->re.q.method = QSE_HTTP_REQ_POST;
|
||||
http->re.re.quest.method = QSE_HTTP_REQ_POST;
|
||||
break;
|
||||
}
|
||||
else if (tmp[0] == 'H' && tmp[1] == 'E' && tmp[2] == 'A' && tmp[3] == 'D')
|
||||
{
|
||||
http->re.q.method = QSE_HTTP_REQ_HEAD;
|
||||
http->re.re.quest.method = QSE_HTTP_REQ_HEAD;
|
||||
break;
|
||||
}
|
||||
else if (tmp[0] == 'H' && tmp[1] == 'T' && tmp[2] == 'T' && tmp[3] == 'P')
|
||||
@ -319,7 +260,7 @@ static qse_http_oct_t* parse_initial_line (
|
||||
/* TRACE */
|
||||
if (tmp[0] == 'T' && tmp[1] == 'R' && tmp[2] == 'A' && tmp[3] == 'C' && tmp[4] == 'E')
|
||||
{
|
||||
http->re.q.method = QSE_HTTP_REQ_TRACE;
|
||||
http->re.re.quest.method = QSE_HTTP_REQ_TRACE;
|
||||
break;
|
||||
}
|
||||
goto badre;
|
||||
@ -328,7 +269,7 @@ static qse_http_oct_t* parse_initial_line (
|
||||
/* DELETE */
|
||||
if (tmp[0] == 'D' && tmp[1] == 'E' && tmp[2] == 'L' && tmp[3] == 'E' && tmp[4] == 'T' && tmp[5] == 'E')
|
||||
{
|
||||
http->re.q.method = QSE_HTTP_REQ_DELETE;
|
||||
http->re.re.quest.method = QSE_HTTP_REQ_DELETE;
|
||||
break;
|
||||
}
|
||||
goto badre;
|
||||
@ -337,12 +278,12 @@ static qse_http_oct_t* parse_initial_line (
|
||||
/* OPTIONS, CONNECT */
|
||||
if (tmp[0] == 'O' && tmp[1] == 'P' && tmp[2] == 'T' && tmp[3] == 'I' && tmp[4] == 'O' && tmp[5] == 'N' && tmp[6] == 'S')
|
||||
{
|
||||
http->re.q.method = QSE_HTTP_REQ_OPTIONS;
|
||||
http->re.re.quest.method = QSE_HTTP_REQ_OPTIONS;
|
||||
break;
|
||||
}
|
||||
else if (tmp[0] == 'C' && tmp[1] == 'O' && tmp[2] == 'N' && tmp[3] == 'N' && tmp[4] == 'E' && tmp[5] == 'C' && tmp[6] == 'T')
|
||||
{
|
||||
http->re.q.method = QSE_HTTP_REQ_OPTIONS;
|
||||
http->re.re.quest.method = QSE_HTTP_REQ_OPTIONS;
|
||||
break;
|
||||
}
|
||||
goto badre;
|
||||
@ -361,8 +302,8 @@ static qse_http_oct_t* parse_initial_line (
|
||||
int w = digit_to_num(p[3]);
|
||||
if (q >= 0 && w >= 0)
|
||||
{
|
||||
http->re.q.version.major = q;
|
||||
http->re.q.version.minor = w;
|
||||
http->re.version.major = q;
|
||||
http->re.version.minor = w;
|
||||
p += 4;
|
||||
}
|
||||
else goto badre;
|
||||
@ -380,7 +321,7 @@ static qse_http_oct_t* parse_initial_line (
|
||||
|
||||
do
|
||||
{
|
||||
http->re.s.code = http->re.s.code * 10 + n;
|
||||
http->re.re.sponse.code = http->re.re.sponse.code * 10 + n;
|
||||
p++;
|
||||
}
|
||||
while ((n = digit_to_num(*p)) >= 0);
|
||||
@ -390,15 +331,15 @@ static qse_http_oct_t* parse_initial_line (
|
||||
/* skip spaces */
|
||||
do p++; while (is_space_octet(*p));
|
||||
|
||||
http->re.s.message.ptr = p;
|
||||
http->re.re.sponse.message.ptr = p;
|
||||
while (*p != '\0' && *p != '\n') p++;
|
||||
http->re.s.message.len = p - http->re.s.message.ptr;
|
||||
http->re.re.sponse.message.len = p - http->re.re.sponse.message.ptr;
|
||||
|
||||
/* adjust Connection: close for HTTP 1.0 or eariler */
|
||||
if (http->re.s.version.major < 1 ||
|
||||
(http->re.s.version.major == 1 && http->re.s.version.minor == 0))
|
||||
if (http->re.version.major < 1 ||
|
||||
(http->re.version.major == 1 && http->re.version.minor == 0))
|
||||
{
|
||||
http->rhc.attr.connection_close = 1;
|
||||
http->re.attr.connection_close = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -410,9 +351,9 @@ static qse_http_oct_t* parse_initial_line (
|
||||
do p++; while (is_space_octet(*p));
|
||||
|
||||
/* process the url part */
|
||||
http->re.q.path.ptr = p;
|
||||
http->re.re.quest.path.ptr = p;
|
||||
#if 0
|
||||
http->re.q.args.ptr = QSE_NULL;
|
||||
http->re.re.quest.args.ptr = QSE_NULL;
|
||||
#endif
|
||||
|
||||
tmp = p;
|
||||
@ -440,13 +381,13 @@ static qse_http_oct_t* parse_initial_line (
|
||||
#if 0
|
||||
else if (*p == '?')
|
||||
{
|
||||
if (!http->re.q.args.ptr)
|
||||
if (!http->re.re.quest.args.ptr)
|
||||
{
|
||||
/* ? must be explicit to be a argument instroducer.
|
||||
* %3f is just a literal. */
|
||||
http->re.q.path.len = tmp - http->re.q.path.ptr;
|
||||
http->re.re.quest.path.len = tmp - http->re.re.quest.path.ptr;
|
||||
*tmp++ = '\0';
|
||||
http->re.q.args.ptr = tmp;
|
||||
http->re.re.quest.args.ptr = tmp;
|
||||
p++;
|
||||
}
|
||||
else *tmp++ = *p++;
|
||||
@ -459,11 +400,11 @@ static qse_http_oct_t* parse_initial_line (
|
||||
if (!is_space_octet(*p)) goto badre;
|
||||
|
||||
#if 0
|
||||
if (http->re.q.args.ptr)
|
||||
http->re.q.args.len = tmp - http->re.q.args.ptr;
|
||||
if (http->re.re.quest.args.ptr)
|
||||
http->re.re.quest.args.len = tmp - http->re.re.quest.args.ptr;
|
||||
else
|
||||
#endif
|
||||
http->re.q.path.len = tmp - http->re.q.path.ptr;
|
||||
http->re.re.quest.path.len = tmp - http->re.re.quest.path.ptr;
|
||||
/* null-terminate the url part though we record the length */
|
||||
*tmp = '\0';
|
||||
|
||||
@ -481,8 +422,8 @@ static qse_http_oct_t* parse_initial_line (
|
||||
int w = digit_to_num(p[7]);
|
||||
if (q >= 0 && w >= 0)
|
||||
{
|
||||
http->re.q.version.major = q;
|
||||
http->re.q.version.minor = w;
|
||||
http->re.version.major = q;
|
||||
http->re.version.minor = w;
|
||||
p += 8;
|
||||
}
|
||||
else goto badre;
|
||||
@ -493,10 +434,10 @@ static qse_http_oct_t* parse_initial_line (
|
||||
while (is_space_octet(*p)) p++;
|
||||
|
||||
/* adjust Connection: close for HTTP 1.0 or eariler */
|
||||
if (http->re.q.version.major < 1 ||
|
||||
(http->re.q.version.major == 1 && http->re.q.version.minor == 0))
|
||||
if (http->re.version.major < 1 ||
|
||||
(http->re.version.major == 1 && http->re.version.minor == 0))
|
||||
{
|
||||
http->rhc.attr.connection_close = 1;
|
||||
http->re.attr.connection_close = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -539,12 +480,12 @@ void qse_http_setrecbs (qse_http_t* http, const qse_http_recbs_t* recbs)
|
||||
#define octet_toupper(c) (((c) >= 'a' && (c) <= 'z') ? ((c) & ~0x20) : (c))
|
||||
|
||||
static QSE_INLINE int compare_octets (
|
||||
const qse_http_oct_t* s1, qse_size_t len1,
|
||||
const qse_http_oct_t* s2, qse_size_t len2)
|
||||
const qse_htoc_t* s1, qse_size_t len1,
|
||||
const qse_htoc_t* s2, qse_size_t len2)
|
||||
{
|
||||
qse_char_t c1, c2;
|
||||
const qse_http_oct_t* end1 = s1 + len1;
|
||||
const qse_http_oct_t* end2 = s2 + len2;
|
||||
const qse_htoc_t* end1 = s1 + len1;
|
||||
const qse_htoc_t* end2 = s2 + len2;
|
||||
|
||||
while (s1 < end1)
|
||||
{
|
||||
@ -570,14 +511,14 @@ static QSE_INLINE int capture_connection (
|
||||
n = compare_octets (QSE_HTB_VPTR(pair), QSE_HTB_VLEN(pair), "close", 5);
|
||||
if (n == 0)
|
||||
{
|
||||
http->rhc.attr.connection_close = 1;
|
||||
http->re.attr.connection_close = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = compare_octets (QSE_HTB_VPTR(pair), QSE_HTB_VLEN(pair), "Keep-Alive", 10);
|
||||
if (n == 0)
|
||||
{
|
||||
http->rhc.attr.connection_close = 0;
|
||||
http->re.attr.connection_close = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -589,7 +530,7 @@ static QSE_INLINE int capture_content_length (
|
||||
qse_http_t* http, qse_htb_pair_t* pair)
|
||||
{
|
||||
qse_size_t len = 0, off = 0, tmp;
|
||||
const qse_http_oct_t* ptr = QSE_HTB_VPTR(pair);
|
||||
const qse_htoc_t* ptr = QSE_HTB_VPTR(pair);
|
||||
|
||||
while (off < QSE_HTB_VLEN(pair))
|
||||
{
|
||||
@ -620,7 +561,7 @@ static QSE_INLINE int capture_content_length (
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (http->rhc.attr.chunked && len > 0)
|
||||
if (http->re.attr.chunked && len > 0)
|
||||
{
|
||||
/* content-length is greater than 0
|
||||
* while transfer-encoding: chunked is specified. */
|
||||
@ -628,15 +569,15 @@ static QSE_INLINE int capture_content_length (
|
||||
return -1;
|
||||
}
|
||||
|
||||
http->rhc.attr.content_length = len;
|
||||
http->re.attr.content_length = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static QSE_INLINE int capture_content_type (
|
||||
qse_http_t* http, qse_htb_pair_t* pair)
|
||||
{
|
||||
http->rhc.attr.content_type.ptr = QSE_HTB_VPTR(pair);
|
||||
http->rhc.attr.content_type.len = QSE_HTB_VLEN(pair);
|
||||
http->re.attr.content_type.ptr = QSE_HTB_VPTR(pair);
|
||||
http->re.attr.content_type.len = QSE_HTB_VLEN(pair);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -649,7 +590,7 @@ static QSE_INLINE int capture_expect (
|
||||
if (n == 0)
|
||||
{
|
||||
|
||||
http->rhc.attr.expect_continue = 1;
|
||||
http->re.attr.expect_continue = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -660,8 +601,8 @@ static QSE_INLINE int capture_expect (
|
||||
static QSE_INLINE int capture_host (
|
||||
qse_http_t* http, qse_htb_pair_t* pair)
|
||||
{
|
||||
http->rhc.attr.host.ptr = QSE_HTB_VPTR(pair);
|
||||
http->rhc.attr.host.len = QSE_HTB_VLEN(pair);
|
||||
http->re.attr.host.ptr = QSE_HTB_VPTR(pair);
|
||||
http->re.attr.host.len = QSE_HTB_VLEN(pair);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -673,14 +614,14 @@ static QSE_INLINE int capture_transfer_encoding (
|
||||
n = compare_octets (QSE_HTB_VPTR(pair), QSE_HTB_VLEN(pair), "chunked", 7);
|
||||
if (n == 0)
|
||||
{
|
||||
if (http->rhc.attr.content_length > 0)
|
||||
if (http->re.attr.content_length > 0)
|
||||
{
|
||||
/* content-length is greater than 0
|
||||
* while transfer-encoding: chunked is specified. */
|
||||
goto badre;
|
||||
}
|
||||
|
||||
http->rhc.attr.chunked = 1;
|
||||
http->re.attr.chunked = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -695,7 +636,7 @@ static QSE_INLINE int capture_key_header (
|
||||
{
|
||||
static struct
|
||||
{
|
||||
const qse_http_oct_t* ptr;
|
||||
const qse_htoc_t* ptr;
|
||||
qse_size_t len;
|
||||
int (*handler) (qse_http_t*, qse_htb_pair_t*);
|
||||
} hdrtab[] =
|
||||
@ -773,7 +714,7 @@ static qse_htb_pair_t* hdr_cbserter (
|
||||
/* the key exists. let's combine values, each separated
|
||||
* by a comma */
|
||||
struct hdr_cmb_t* cmb;
|
||||
qse_http_oct_t* ptr;
|
||||
qse_htoc_t* ptr;
|
||||
qse_size_t len;
|
||||
|
||||
/* TODO: reduce waste in case the same key appears again.
|
||||
@ -791,7 +732,7 @@ static qse_htb_pair_t* hdr_cbserter (
|
||||
cmb = (struct hdr_cmb_t*) QSE_MMGR_ALLOC (
|
||||
tx->http->mmgr,
|
||||
QSE_SIZEOF(*cmb) +
|
||||
QSE_SIZEOF(qse_http_oct_t) * (QSE_HTB_VLEN(pair) + 1 + tx->vlen + 1)
|
||||
QSE_SIZEOF(qse_htoc_t) * (QSE_HTB_VLEN(pair) + 1 + tx->vlen + 1)
|
||||
);
|
||||
if (cmb == QSE_NULL)
|
||||
{
|
||||
@ -800,7 +741,7 @@ static qse_htb_pair_t* hdr_cbserter (
|
||||
}
|
||||
|
||||
/* let 'ptr' point to the actual space for the combined value */
|
||||
ptr = (qse_http_oct_t*)(cmb + 1);
|
||||
ptr = (qse_htoc_t*)(cmb + 1);
|
||||
len = 0;
|
||||
|
||||
/* fill the space with the value */
|
||||
@ -844,12 +785,12 @@ Change it to doubly linked for this?
|
||||
}
|
||||
}
|
||||
|
||||
qse_http_oct_t* parse_header_fields (qse_http_t* http, qse_http_oct_t* line)
|
||||
qse_htoc_t* parse_header_fields (qse_http_t* http, qse_htoc_t* line)
|
||||
{
|
||||
qse_http_oct_t* p = line, * last;
|
||||
qse_htoc_t* p = line, * last;
|
||||
struct
|
||||
{
|
||||
qse_http_oct_t* ptr;
|
||||
qse_htoc_t* ptr;
|
||||
qse_size_t len;
|
||||
} name, value;
|
||||
|
||||
@ -887,7 +828,7 @@ qse_http_oct_t* parse_header_fields (qse_http_t* http, qse_http_oct_t* line)
|
||||
* the continuation */
|
||||
if (is_purespace_octet (*++p))
|
||||
{
|
||||
qse_http_oct_t* cpydst;
|
||||
qse_htoc_t* cpydst;
|
||||
|
||||
cpydst = p - 1;
|
||||
if (*(cpydst-1) == '\r') cpydst--;
|
||||
@ -920,7 +861,7 @@ qse_http_oct_t* parse_header_fields (qse_http_t* http, qse_http_oct_t* line)
|
||||
|
||||
http->errnum = QSE_HTTP_ENOERR;
|
||||
if (qse_htb_cbsert (
|
||||
&http->rhc.hdrtab, name.ptr, name.len,
|
||||
&http->re.hdrtab, name.ptr, name.len,
|
||||
hdr_cbserter, &ctx) == QSE_NULL)
|
||||
{
|
||||
if (http->errnum == QSE_HTTP_ENOERR)
|
||||
@ -936,18 +877,10 @@ badhdr:
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static qse_htb_walk_t walk (qse_htb_t* htb, qse_htb_pair_t* pair, void* ctx)
|
||||
{
|
||||
qse_printf (QSE_T("HEADER OK %d[%S] %d[%S]\n"), (int)QSE_HTB_KLEN(pair), QSE_HTB_KPTR(pair), (int)QSE_HTB_VLEN(pair), QSE_HTB_VPTR(pair));
|
||||
return QSE_HTB_WALK_FORWARD;
|
||||
}
|
||||
#endif
|
||||
|
||||
static QSE_INLINE int parse_initial_line_and_headers (
|
||||
qse_http_t* http, const qse_http_oct_t* req, qse_size_t rlen)
|
||||
qse_http_t* http, const qse_htoc_t* req, qse_size_t rlen)
|
||||
{
|
||||
qse_http_oct_t* p;
|
||||
qse_htoc_t* p;
|
||||
|
||||
/* add the actual request */
|
||||
if (push_to_buffer (http, &http->fed.b.raw, req, rlen) <= -1) return -1;
|
||||
@ -955,7 +888,7 @@ static QSE_INLINE int parse_initial_line_and_headers (
|
||||
/* add the terminating null for easier parsing */
|
||||
if (push_to_buffer (http, &http->fed.b.raw, &NUL, 1) <= -1) return -1;
|
||||
|
||||
p = http->fed.b.raw.data;
|
||||
p = QSE_MBS_PTR(&http->fed.b.raw);
|
||||
|
||||
if (http->option & QSE_HTTP_LEADINGEMPTYLINES)
|
||||
while (is_whspace_octet(*p)) p++;
|
||||
@ -992,9 +925,9 @@ static QSE_INLINE int parse_initial_line_and_headers (
|
||||
#define GET_CHUNK_CRLF 3
|
||||
#define GET_CHUNK_TRAILERS 4
|
||||
|
||||
static const qse_http_oct_t* getchunklen (qse_http_t* http, const qse_http_oct_t* ptr, qse_size_t len)
|
||||
static const qse_htoc_t* getchunklen (qse_http_t* http, const qse_htoc_t* ptr, qse_size_t len)
|
||||
{
|
||||
const qse_http_oct_t* end = ptr + len;
|
||||
const qse_htoc_t* end = ptr + len;
|
||||
|
||||
/* this function must be called in the GET_CHUNK_LEN context */
|
||||
QSE_ASSERT (http->fed.s.chunk.phase == GET_CHUNK_LEN);
|
||||
@ -1060,14 +993,14 @@ static const qse_http_oct_t* getchunklen (qse_http_t* http, const qse_http_oct_t
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static const qse_http_oct_t* get_trailing_headers (
|
||||
qse_http_t* http, const qse_http_oct_t* req, const qse_http_oct_t* end)
|
||||
static const qse_htoc_t* get_trailing_headers (
|
||||
qse_http_t* http, const qse_htoc_t* req, const qse_htoc_t* end)
|
||||
{
|
||||
const qse_http_oct_t* ptr = req;
|
||||
const qse_htoc_t* ptr = req;
|
||||
|
||||
while (ptr < end)
|
||||
{
|
||||
register qse_http_oct_t b = *ptr++;
|
||||
register qse_htoc_t b = *ptr++;
|
||||
|
||||
switch (b)
|
||||
{
|
||||
@ -1085,7 +1018,7 @@ static const qse_http_oct_t* get_trailing_headers (
|
||||
}
|
||||
else
|
||||
{
|
||||
qse_http_oct_t* p;
|
||||
qse_htoc_t* p;
|
||||
|
||||
QSE_ASSERT (http->fed.s.crlf <= 3);
|
||||
http->fed.s.crlf = 0;
|
||||
@ -1097,7 +1030,7 @@ static const qse_http_oct_t* get_trailing_headers (
|
||||
http, &http->fed.b.tra, &NUL, 1) <= -1)
|
||||
return QSE_NULL;
|
||||
|
||||
p = http->fed.b.tra.data;
|
||||
p = QSE_MBS_PTR(&http->fed.b.tra);
|
||||
|
||||
do
|
||||
{
|
||||
@ -1136,10 +1069,10 @@ done:
|
||||
}
|
||||
|
||||
/* feed the percent encoded string */
|
||||
int qse_http_feed (qse_http_t* http, const qse_http_oct_t* req, qse_size_t len)
|
||||
int qse_http_feed (qse_http_t* http, const qse_htoc_t* req, qse_size_t len)
|
||||
{
|
||||
const qse_http_oct_t* end = req + len;
|
||||
const qse_http_oct_t* ptr = req;
|
||||
const qse_htoc_t* end = req + len;
|
||||
const qse_htoc_t* ptr = req;
|
||||
|
||||
/* does this goto drop code maintainability? */
|
||||
if (http->fed.s.need > 0)
|
||||
@ -1169,7 +1102,7 @@ int qse_http_feed (qse_http_t* http, const qse_http_oct_t* req, qse_size_t len)
|
||||
|
||||
while (ptr < end)
|
||||
{
|
||||
register qse_http_oct_t b = *ptr++;
|
||||
register qse_htoc_t b = *ptr++;
|
||||
|
||||
if (http->option & QSE_HTTP_LEADINGEMPTYLINES &&
|
||||
http->fed.s.plen <= 0 && is_whspace_octet(b))
|
||||
@ -1221,7 +1154,7 @@ int qse_http_feed (qse_http_t* http, const qse_http_oct_t* req, qse_size_t len)
|
||||
return -1;
|
||||
|
||||
if (http->retype == QSE_HTTP_RETYPE_Q &&
|
||||
http->rhc.attr.expect_continue &&
|
||||
http->re.attr.expect_continue &&
|
||||
http->recbs.expect_continue && ptr >= end)
|
||||
{
|
||||
int n;
|
||||
@ -1233,9 +1166,7 @@ int qse_http_feed (qse_http_t* http, const qse_http_oct_t* req, qse_size_t len)
|
||||
* not fed here?
|
||||
*/
|
||||
|
||||
http->re.q.rhc = &http->rhc;
|
||||
n = http->recbs.expect_continue (
|
||||
http, &http->re.q);
|
||||
n = http->recbs.expect_continue (http, &http->re);
|
||||
|
||||
if (n <= -1)
|
||||
{
|
||||
@ -1249,14 +1180,14 @@ int qse_http_feed (qse_http_t* http, const qse_http_oct_t* req, qse_size_t len)
|
||||
|
||||
/* the expect_continue handler can set discard to non-zero
|
||||
* to force discard the contents body
|
||||
http->rhc.discard = 1;
|
||||
http->re.discard = 1;
|
||||
*/
|
||||
}
|
||||
|
||||
if (http->rhc.attr.chunked)
|
||||
if (http->re.attr.chunked)
|
||||
{
|
||||
/* transfer-encoding: chunked */
|
||||
QSE_ASSERT (http->rhc.attr.content_length <= 0);
|
||||
QSE_ASSERT (http->re.attr.content_length <= 0);
|
||||
|
||||
dechunk_start:
|
||||
http->fed.s.chunk.phase = GET_CHUNK_LEN;
|
||||
@ -1291,7 +1222,7 @@ int qse_http_feed (qse_http_t* http, const qse_http_oct_t* req, qse_size_t len)
|
||||
{
|
||||
/* we need to read as many octets as
|
||||
* Content-Length */
|
||||
http->fed.s.need = http->rhc.attr.content_length;
|
||||
http->fed.s.need = http->re.attr.content_length;
|
||||
}
|
||||
|
||||
if (http->fed.s.need > 0)
|
||||
@ -1307,7 +1238,7 @@ int qse_http_feed (qse_http_t* http, const qse_http_oct_t* req, qse_size_t len)
|
||||
if (avail < http->fed.s.need)
|
||||
{
|
||||
/* the data is not as large as needed */
|
||||
if (push_to_buffer (http, &http->rhc.con, ptr, avail) <= -1) return -1;
|
||||
if (push_to_buffer (http, &http->re.content, ptr, avail) <= -1) return -1;
|
||||
http->fed.s.need -= avail;
|
||||
/* we didn't get a complete content yet */
|
||||
goto feedme_more;
|
||||
@ -1316,7 +1247,7 @@ int qse_http_feed (qse_http_t* http, const qse_http_oct_t* req, qse_size_t len)
|
||||
{
|
||||
/* we got all or more than needed */
|
||||
if (push_to_buffer (
|
||||
http, &http->rhc.con, ptr,
|
||||
http, &http->re.content, ptr,
|
||||
http->fed.s.need) <= -1) return -1;
|
||||
ptr += http->fed.s.need;
|
||||
http->fed.s.need = 0;
|
||||
@ -1367,7 +1298,7 @@ int qse_http_feed (qse_http_t* http, const qse_http_oct_t* req, qse_size_t len)
|
||||
}
|
||||
}
|
||||
|
||||
if (!http->rhc.discard)
|
||||
if (!http->re.discard)
|
||||
{
|
||||
int n;
|
||||
|
||||
@ -1380,8 +1311,7 @@ int qse_http_feed (qse_http_t* http, const qse_http_oct_t* req, qse_size_t len)
|
||||
"set response callbacks before feeding"
|
||||
);
|
||||
|
||||
http->re.s.rhc = &http->rhc;
|
||||
n = http->recbs.response (http, &http->re.s);
|
||||
n = http->recbs.response (http, &http->re);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1390,8 +1320,7 @@ int qse_http_feed (qse_http_t* http, const qse_http_oct_t* req, qse_size_t len)
|
||||
"set request callbacks before feeding"
|
||||
);
|
||||
|
||||
http->re.q.rhc = &http->rhc;
|
||||
n = http->recbs.request (http, &http->re.q);
|
||||
n = http->recbs.request (http, &http->re);
|
||||
}
|
||||
|
||||
if (n <= -1)
|
||||
@ -1405,15 +1334,6 @@ int qse_http_feed (qse_http_t* http, const qse_http_oct_t* req, qse_size_t len)
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
qse_htb_walk (&http->req.hdrtab, walk, QSE_NULL);
|
||||
if (http->req.con.size > 0)
|
||||
{
|
||||
qse_printf (QSE_T("content = [%.*S]\n"), (int)http->req.con.size, http->req.con.data);
|
||||
}
|
||||
/* TODO: do the main job here... before the raw buffer is cleared out... */
|
||||
#endif
|
||||
|
||||
clear_feed (http);
|
||||
|
||||
/* let ptr point to the next character to LF or
|
||||
|
@ -39,13 +39,13 @@ struct client_action_t
|
||||
{
|
||||
struct
|
||||
{
|
||||
const qse_http_oct_t* ptr;
|
||||
qse_size_t left;
|
||||
const qse_htoc_t* ptr;
|
||||
qse_size_t left;
|
||||
} sendtext;
|
||||
struct
|
||||
{
|
||||
qse_http_oct_t* ptr;
|
||||
qse_size_t left;
|
||||
qse_htoc_t* ptr;
|
||||
qse_size_t left;
|
||||
} sendtextdup;
|
||||
struct
|
||||
{
|
||||
@ -215,23 +215,54 @@ static int enqueue_disconnect (client_t* client)
|
||||
return enqueue_client_action_locked (client, &action);
|
||||
}
|
||||
|
||||
static int handle_request (qse_http_t* http, qse_http_req_t* req)
|
||||
static qse_htb_walk_t walk (qse_htb_t* htb, qse_htb_pair_t* pair, void* ctx)
|
||||
{
|
||||
qse_printf (QSE_T("HEADER OK %d[%S] %d[%S]\n"), (int)QSE_HTB_KLEN(pair), QSE_HTB_KPTR(pair), (int)QSE_HTB_VLEN(pair), QSE_HTB_VPTR(pair));
|
||||
return QSE_HTB_WALK_FORWARD;
|
||||
}
|
||||
|
||||
static int handle_request (qse_http_t* http, qse_htre_t* req)
|
||||
{
|
||||
http_xtn_t* xtn = (http_xtn_t*) qse_http_getxtn (http);
|
||||
qse_printf (QSE_T("got a request... %S\n"), req->path.ptr);
|
||||
client_t* client = &xtn->array->data[xtn->index];
|
||||
|
||||
if (req->rhc->attr.host.ptr) qse_printf (QSE_T("host %S\n"), req->rhc->attr.host.ptr);
|
||||
qse_printf (QSE_T("================================\n"));
|
||||
qse_printf (QSE_T("REQUEST ==> [%S] version[%d.%d] method[%d]\n"),
|
||||
req->re.quest.path.ptr, req->version.major, req->version.minor, req->re.quest.method);
|
||||
|
||||
if (req->method == QSE_HTTP_REQ_GET)
|
||||
if (req->attr.host.ptr) qse_printf (QSE_T("HOST===> %S\n"), req->attr.host.ptr);
|
||||
qse_htb_walk (&http->re.hdrtab, walk, QSE_NULL);
|
||||
if (QSE_MBS_LEN(&http->re.content) > 0)
|
||||
{
|
||||
qse_printf (QSE_T("content = [%.*S]\n"),
|
||||
(int)QSE_MBS_LEN(&http->re.content),
|
||||
QSE_MBS_PTR(&http->re.content));
|
||||
}
|
||||
|
||||
|
||||
if (req->re.quest.method == QSE_HTTP_REQ_GET || req->re.quest.method == QSE_HTTP_REQ_POST)
|
||||
{
|
||||
int fd = open (req->path.ptr, O_RDONLY);
|
||||
qse_htre_decodereqpath (req, );
|
||||
/* original path not available anymore */
|
||||
|
||||
int fd = open (req->re.quest.path.ptr, O_RDONLY);
|
||||
if (fd <= -1)
|
||||
{
|
||||
qse_printf (QSE_T("open failure....\n"));
|
||||
/*
|
||||
qse_http_addtext (http,
|
||||
"<html><title>FILE NOT FOUND</title><body></body></html>");
|
||||
*/
|
||||
char text[256];
|
||||
const char* msg = "<html><head><title>NOT FOUND</title></head><body><b>REQUESTD FILE NOT FOUND</b></body></html>";
|
||||
snprintf (text, sizeof(text),
|
||||
"HTTP/%d.%d 404 Not found\r\nContent-Length: %d\r\n\r\n%s\r\n\r\n",
|
||||
req->version.major,
|
||||
req->version.minor,
|
||||
(int)strlen(msg) + 4, msg);
|
||||
|
||||
qse_printf (QSE_T("open failure.... sending 404 not found\n"));
|
||||
|
||||
if (enqueue_sendtextdup_locked (client, text) <= -1)
|
||||
{
|
||||
qse_printf (QSE_T("failed to push action....\n"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -248,7 +279,7 @@ qse_printf (QSE_T("fstat failure....\n"));
|
||||
|
||||
qse_printf (QSE_T("empty file....\n"));
|
||||
#if 0
|
||||
qse_http_req_t* res = qse_http_newresponse (http);
|
||||
qse_htre_t* res = qse_http_newresponse (http);
|
||||
if (req == QSE_NULL)
|
||||
{
|
||||
/* hard failure... can't answer */
|
||||
@ -270,8 +301,6 @@ qse_printf (QSE_T("empty file....\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
client_t* client = &xtn->array->data[xtn->index];
|
||||
|
||||
char text[128];
|
||||
snprintf (text, sizeof(text),
|
||||
"HTTP/%d.%d 200 OK\r\nContent-Length: %llu\r\n\r\n",
|
||||
@ -301,7 +330,7 @@ qse_printf (QSE_T("failed to push action....\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (req->rhc->attr.connection_close)
|
||||
if (req->attr.connection_close)
|
||||
{
|
||||
if (enqueue_disconnect (client) <= -1)
|
||||
{
|
||||
@ -312,21 +341,36 @@ qse_printf (QSE_T("failed to push action....\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char text[256];
|
||||
const char* msg = "<html><head><title>Method not allowed</title></head><body><b>METHOD NOT ALLOWED</b></body></html>";
|
||||
snprintf (text, sizeof(text),
|
||||
"HTTP/%d.%d 405 Method not allowed\r\nContent-Length: %d\r\n\r\n%s\r\n\r\n",
|
||||
req->version.major,
|
||||
req->version.minor, (int)strlen(msg)+4, msg);
|
||||
if (enqueue_sendtextdup_locked (client, text) <= -1)
|
||||
{
|
||||
qse_printf (QSE_T("failed to push action....\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pthread_cond_signal (&xtn->array->cond);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_expect_continue (qse_http_t* http, qse_http_req_t* req)
|
||||
static int handle_expect_continue (qse_http_t* http, qse_htre_t* req)
|
||||
{
|
||||
http_xtn_t* xtn = (http_xtn_t*) qse_http_getxtn (http);
|
||||
client_t* client = &xtn->array->data[xtn->index];
|
||||
|
||||
if (req->method == QSE_HTTP_REQ_GET)
|
||||
if (req->re.quest.method == QSE_HTTP_REQ_GET)
|
||||
{
|
||||
char text[32];
|
||||
|
||||
req->rhc->discard = 1;
|
||||
qse_htre_setdiscard (req, 1);
|
||||
|
||||
snprintf (text, sizeof(text),
|
||||
"HTTP/%d.%d 404 Not found\r\n\r\n",
|
||||
@ -354,7 +398,7 @@ static int handle_expect_continue (qse_http_t* http, qse_http_req_t* req)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_response (qse_http_t* http, qse_http_res_t* res)
|
||||
static int handle_response (qse_http_t* http, qse_htre_t* res)
|
||||
{
|
||||
#if 0
|
||||
if (res->code >= 100 && res->code <= 199)
|
||||
@ -364,8 +408,8 @@ static int handle_response (qse_http_t* http, qse_http_res_t* res)
|
||||
#endif
|
||||
|
||||
qse_printf (QSE_T("response received... HTTP/%d.%d %d %.*S\n"),
|
||||
res->version.major, res->version.minor, res->code,
|
||||
(int)res->message.len, res->message.ptr);
|
||||
res->version.major, res->version.minor, res->re.sponse.code,
|
||||
(int)res->re.sponse.message.len, res->re.sponse.message.ptr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -815,7 +859,7 @@ qse_printf (QSE_T("connection %d accepted\n"), c);
|
||||
{
|
||||
/* got input */
|
||||
|
||||
qse_http_oct_t buf[1024];
|
||||
qse_htoc_t buf[1024];
|
||||
ssize_t m;
|
||||
|
||||
reread:
|
||||
|
Loading…
x
Reference in New Issue
Block a user