summaryrefslogtreecommitdiff
path: root/apps/netutils/thttpd/libhttpd.h
blob: b245a6edf1f7163f35c1a22ffbea4223a2154886 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
/****************************************************************************
 * netutils/thttpd/libhttpd.h
 * HTTP Protocol Library Definitions
 *
 *   Copyright (C) 2009 Gregory Nutt. All rights reserved.
 *   Author: Gregory Nutt <gnutt@nuttx.org>
 *
 * Derived from the file of the same name in the original THTTPD package:
 *
 *   Copyright � 1995,1998,1999,2000,2001 by Jef Poskanzer <jef@mail.acme.com>.
 *   All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 ****************************************************************************/

#ifndef __NETUTILS_THTTPD_LIBHTTPD_H
#define __NETUTILS_THTTPD_LIBHTTPD_H

/****************************************************************************
 * Included Files
 ****************************************************************************/

#include <nuttx/config.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <stdint.h>
#include <stdbool.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <time.h>

#include "config.h"
#ifdef CONFIG_THTTPD

/****************************************************************************
 * Pre-processor Definitions
 ****************************************************************************/

/* A few convenient defines. */

#ifndef MAX
#  define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
#ifndef MIN
#  define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif

/* Enable special instrumentation to track down "400 Bad Request" problems */

#undef CONFIG_THTTPD_BADREQUEST /* Define to enable "Bad Request" instrumentation */

#ifdef CONFIG_THTTPD_BADREQUEST
#  if !defined(CONFIG_DEBUG_VERBOSE) || !defined(CONFIG_DEBUG_NET)
#    undef CONFIG_THTTPD_BADREQUEST
#  else
#    define BADREQUEST(s) nvdbg("Bad Request: \"%s\"\n", s)
#  endif
#endif

#ifndef CONFIG_THTTPD_BADREQUEST
#  undef  BADREQUEST
#  define BADREQUEST(s)
#endif

/* Enable special instrumentation to track down "501 Not Implemented" problems */

#undef CONFIG_THTTPD_NOTIMPLEMENTED /* Define to enable "Not Implemented" instrumentation */

#ifdef CONFIG_THTTPD_NOTIMPLEMENTED
#  if !defined(CONFIG_DEBUG_VERBOSE) || !defined(CONFIG_DEBUG_NET)
#    undef CONFIG_THTTPD_NOTIMPLEMENTED
#  else
#    define NOTIMPLEMENTED(s) nvdbg("Not Implemented: \"%s\"\n", s)
#  endif
#endif

#ifndef CONFIG_THTTPD_NOTIMPLEMENTED
#  undef  NOTIMPLEMENTED
#  define NOTIMPLEMENTED(s)
#endif

/* Enable special instrumentation to track down "500 Internal Error" problems */

#undef CONFIG_THTTPD_INTERNALERROR /* Define to enable "Internal Error" instrumentation */

#ifdef CONFIG_THTTPD_INTERNALERROR
#  if !defined(CONFIG_DEBUG_VERBOSE) || !defined(CONFIG_DEBUG_NET)
#    undef CONFIG_THTTPD_INTERNALERROR
#  else
#    define INTERNALERROR(s) nvdbg("Internal Error: \"%s\"\n", s)
#  endif
#endif

#ifndef CONFIG_THTTPD_INTERNALERROR
#  undef  INTERNALERROR
#  define INTERNALERROR(s)
#endif

/* Methods */

#define METHOD_UNKNOWN 0
#define METHOD_GET 1
#define METHOD_HEAD 2
#define METHOD_POST 3

/* States for checked_state. */

#define CHST_FIRSTWORD  0
#define CHST_FIRSTWS    1
#define CHST_SECONDWORD 2
#define CHST_SECONDWS   3
#define CHST_THIRDWORD  4
#define CHST_THIRDWS    5
#define CHST_LINE       6
#define CHST_LF         7
#define CHST_CR         8
#define CHST_CRLF       9
#define CHST_CRLFCR     10
#define CHST_BOGUS      11

#define GC_FAIL 0
#define GC_OK 1
#define GC_NO_MORE 2

#define GR_NO_REQUEST 0
#define GR_GOT_REQUEST 1
#define GR_BAD_REQUEST 2

/****************************************************************************
 * Public Type Definitions
 ****************************************************************************/

/* A multi-family sockaddr. */

#ifdef  CONFIG_NET_IPv6
typedef struct sockaddr_in6 httpd_sockaddr;
#else
typedef struct sockaddr_in httpd_sockaddr;
#endif

/* A server. */

typedef struct
{
  char *hostname;
  int   cgi_count;
  int   listen_fd;
} httpd_server;

/* A connection. */

typedef struct
{
  int initialized;
  httpd_server *hs;
  httpd_sockaddr client_addr;
  char *read_buf;
  size_t read_size, read_idx, checked_idx;
  int checked_state;
  int method;
  off_t bytes_to_send;
  off_t bytes_sent;
  char *encodedurl;
  char *decodedurl;
  char *protocol;
  char *origfilename;
  char *expnfilename;
  char *encodings;
  char *pathinfo;
  char *query;
  char *referer;
  char *useragent;
  char *accept;
  char *accepte;
  char *acceptl;
  char *cookie;
  char *contenttype;
  char *reqhost;
  char *hdrhost;
  char *hostdir;
  char *authorization;
  char *remoteuser;
  size_t maxdecodedurl, maxorigfilename, maxexpnfilename, maxencodings,
    maxpathinfo, maxquery, maxaccept, maxaccepte, maxreqhost, maxhostdir,
    maxremoteuser, maxresponse;
#ifdef CONFIG_THTTPD_TILDE_MAP2
  char *altdir;
  size_t maxaltdir;
#endif
  time_t if_modified_since, range_if;
  size_t contentlength;
  char *type;                  /* not malloc()ed */
#ifdef CONFIG_THTTPD_VHOST
  char *vhostname;             /* not malloc()ed */
#endif
  bool mime_flag;
  bool one_one;                /* HTTP/1.1 or better */
  bool got_range;
  bool tildemapped;            /* this connection got tilde-mapped */
  bool keep_alive;
  bool should_linger;
  int conn_fd;                 /* Connection to the client */
  int file_fd;                 /* Descriptor for open, outgoing file */
  off_t range_start;           /* File range start from Range= */
  off_t range_end;             /* File range end from Range= */
  struct stat sb;

  /* This is the I/O buffer that is used to buffer portions of outgoing files */

  uint16_t buflen;             /* Index to first valid data in buffer */
  uint8_t buffer[CONFIG_THTTPD_IOBUFFERSIZE];
} httpd_conn;

/****************************************************************************
 * Public Function Prototypes
 ****************************************************************************/

/* Initializes.  Does the socket(), bind(), and listen().   Returns an
 * httpd_server* which includes a socket fd that you can select() on.
 * Return (httpd_server*) 0 on error.
 */

extern FAR httpd_server *httpd_initialize(FAR httpd_sockaddr *sa);

/* Call to unlisten/close socket(s) listening for new connections. */

extern void httpd_unlisten(httpd_server *hs);

/* Call to shut down. */

extern void httpd_terminate(httpd_server *hs);

/* When a listen fd is ready to read, call this.  It does the accept() and
 * returns an httpd_conn* which includes the fd to read the request from and
 * write the response to.  Returns an indication of whether the accept()
 * failed, succeeded, or if there were no more connections to accept.
 *
 * In order to minimize malloc()s, the caller passes in the httpd_conn.
 * The caller is also responsible for setting initialized to zero before the
 * first call using each different httpd_conn.
 */

extern int httpd_get_conn(httpd_server *hs, int listen_fd, httpd_conn *hc);

/* Checks whether the data in hc->read_buf constitutes a complete request
 * yet.  The caller reads data into hc->read_buf[hc->read_idx] and advances
 * hc->read_idx.  This routine checks what has been read so far, using
 * hc->checked_idx and hc->checked_state to keep track, and returns an
 * indication of whether there is no complete request yet, there is a
 * complete request, or there won't be a valid request due to a syntax error.
 */

extern int httpd_got_request(httpd_conn *hc);

/* Parses the request in hc->read_buf.  Fills in lots of fields in hc,
 * like the URL and the various headers.
 *
 * Returns -1 on error.
 */

extern int httpd_parse_request(httpd_conn *hc);

/* Starts sending data back to the client.  In some cases (directories,
 * CGI programs), finishes sending by itself - in those cases, hc->file_fd
 * is negative.  If there is more data to be sent, then hc->file_fd is a file
 * stream for the file to send.  If you don't have a current timeval
 * handy just pass in 0.
 *
 * Returns -1 on error.
 */

extern int httpd_start_request(httpd_conn *hc, struct timeval *nowP);

/* Actually sends any buffered response text. */

extern void httpd_write_response(httpd_conn *hc);

/* Call this to close down a connection and free the data. */

extern void httpd_close_conn(httpd_conn *hc);

/* Call this to de-initialize a connection struct and *really* free the
 * mallocced strings.
 */

extern void httpd_destroy_conn(httpd_conn *hc);

/* Send an error message back to the client. */

extern void httpd_send_err(httpd_conn *hc, int status, const char *title,
                           const char *extraheads, const char *form, const char *arg);

/* Generate a string representation of a method number. */

extern const char *httpd_method_str(int method);

/* Format a network socket to a string representation. */

extern char *httpd_ntoa(httpd_sockaddr * saP);

/* Set NDELAY mode on a socket. */

extern void httpd_set_ndelay(int fd);

/* Clear NDELAY mode on a socket. */

extern void httpd_clear_ndelay(int fd);

/* Read to requested buffer, accounting for interruptions and EOF */

extern int httpd_read(int fd, const void *buf, size_t nbytes);

/* Write the buffer completely, accounting for interruptions */

extern int httpd_write(int fd, const void *buf, size_t nbytes);

#endif /* CONFIG_THTTPD */
#endif /* __NETUTILS_THTTPD_LIBHTTPD_H */