aboutsummaryrefslogtreecommitdiff
path: root/picohttp.h
blob: 85eaf50383b0a77032c2188ad4e4e7e1cb64e11d (plain)
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
#pragma once
#ifndef PICOHTTP_H_HEADERGUARD
#define PICOHTTP_H_HEADERGUARD

#include <stddef.h>
#include <stdint.h>

/* max 70 for boundary + 4 chars for "<CR><LF>--" */
#define PICOHTTP_MULTIPARTBOUNDARY_MAX_LEN 74
#define PICOHTTP_DISPOSITION_NAME_MAX 48

#define PICOHTTP_METHOD_GET  1
#define PICOHTTP_METHOD_HEAD 2
#define PICOHTTP_METHOD_POST 4

#define PICOHTTP_CONTENTTYPE_APPLICATION	0x1000
#define PICOHTTP_CONTENTTYPE_APPLICATION_OCTETSTREAM 0x1000

#define PICOHTTP_CONTENTTYPE_AUDIO		0x2000
#define PICOHTTP_CONTENTTYPE_IMAGE		0x3000
#define PICOHTTP_CONTENTTYPE_MESSAGE		0x4000
#define PICOHTTP_CONTENTTYPE_MODEL		0x5000

#define PICOHTTP_CONTENTTYPE_MULTIPART		0x6000
#define PICOHTTP_CONTENTTYPE_MULTIPART_FORMDATA	0x6004

#define PICOHTTP_CONTENTTYPE_TEXT		0x7000
#define PICOHTTP_CONTENTTYPE_TEXT_CSV		0x7003
#define PICOHTTP_CONTENTTYPE_TEXT_HTML		0x7004
#define PICOHTTP_CONTENTTYPE_TEXT_PLAIN		0x7006

#define PICOHTTP_CONTENTTYPE_VIDEO		0x8000

#define PICOHTTP_CODING_IDENTITY 0
#define PICOHTTP_CODING_COMPRESS 1
#define PICOHTTP_CODING_DEFLATE  2
#define PICOHTTP_CODING_GZIP     4
#define PICOHTTP_CODING_CHUNKED  8

#define PICOHTTP_STATUS_200_OK 200
#define PICOHTTP_STATUS_400_BAD_REQUEST 400
#define PICOHTTP_STATUS_401_UNAUTHORIZED 401
#define PICOHTTP_STATUS_403_FORBIDDEN 402
#define PICOHTTP_STATUS_404_NOT_FOUND 404
#define PICOHTTP_STATUS_405_METHOD_NOT_ALLOWED 405
#define PICOHTTP_STATUS_414_REQUEST_URI_TOO_LONG 414
#define PICOHTTP_STATUS_500_INTERNAL_SERVER_ERROR 500
#define PICOHTTP_STATUS_501_NOT_IMPLEMENTED 501
#define PICOHTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED 505

struct picohttpIoOps {
	int (*read)(size_t /*count*/, void* /*buf*/, void*);
	int (*write)(size_t /*count*/, void const* /*buf*/, void*);
	int (*getch)(void*); // returns negative value on error
	int (*putch)(int, void*);
	int (*flush)(void*);
	void *data;
};

#define picohttpIoWrite(ioops,size,buf) (ioops->write(size, buf, ioops->data))
#define picohttpIoRead(ioops,size,buf)  (ioops->read(size, buf, ioops->data))
#define picohttpIoGetch(ioops)          (ioops->getch(ioops->data))
#define picohttpIoPutch(ioops,c)        (ioops->putch(c, ioops->data))
#define picohttpIoFlush(ioops)          (ioops->flush(ioops->data))

enum picohttpVarType {
	PICOHTTP_TYPE_UNDEFINED = 0,
	PICOHTTP_TYPE_INTEGER = 1,
	PICOHTTP_TYPE_REAL = 2,
	PICOHTTP_TYPE_BOOLEAN = 3,
	PICOHTTP_TYPE_TEXT = 4
};

struct picohttpVarSpec {
	char const * const name;
	enum picohttpVarType type;
	size_t max_len;
};

struct picohttpVar {
	struct picohttpVarSpec const *spec;
	union {
		char *text;
		float real;
		int integer;
		uint8_t boolean;
	} value;
	struct picohttpVar *next;
};

struct picohttpRequest;

typedef void (*picohttpHandler)(struct picohttpRequest*);

struct picohttpURLRoute {
	char const * urlhead;
	struct picohttpVarSpec const * get_vars;
	picohttpHandler handler;
	unsigned int max_urltail_len;
	int allowed_methods;
};

#define PICOHTTP_EPOCH_YEAR 1970

struct picohttpDateTime {
	unsigned int Y:7; /* EPOCH + 127 years */
	unsigned int M:4;
	unsigned int D:5;
	unsigned int h:5;
	unsigned int m:6;
	unsigned int s:5; /* seconds / 2 */
};

struct picohttpAuthData {
	size_t const username_maxlen;
	char  * const username;

	size_t const realm_maxlen;
	char* const realm;

	/* Basic auth password or Digest auth response */
	size_t const pwresponse_maxlen;
	char * const pwresponse;

#if 0
	size_t const uri_maxlen;
	char * const uri;
#endif

	unsigned int message_qop;
	uint32_t nonce_count;
};

struct picohttpRequest {
	struct picohttpIoOps const * ioops;
	struct picohttpURLRoute const * route;
	struct picohttpVar *get_vars;
	char *url;
	char *urltail;
	int status;
	int method;
	struct {
		uint8_t major;
		uint8_t minor;
	} httpversion;
	struct {
		int contenttype;
		size_t contentlength;
		uint8_t contentencoding;
		uint8_t transferencoding;
		char multipartboundary[PICOHTTP_MULTIPARTBOUNDARY_MAX_LEN+1];
		size_t chunklength;
		struct picohttpAuthData *auth;
	} query;
	struct {
		char const *contenttype;
		char const *disposition;
		char const *www_authenticate;
		struct picohttpDateTime lastmodified;
		int max_age;
		size_t contentlength;
		uint8_t contentencoding;
		uint8_t transferencoding;
	} response;
	size_t received_octets;
	struct {
		size_t octets;
		uint8_t header;
	} sent;
	void *userdata;
};

struct picohttpMultipart {
	struct picohttpRequest *req;
	uint8_t finished;
	int contenttype;
	struct {
		char name[PICOHTTP_DISPOSITION_NAME_MAX+1];
	} disposition;
	int in_boundary;
	int replay;
	int replayhead;
	int mismatch;
};

typedef void (*picohttpHeaderFieldCallback)(
	void * const data,
	char const *headername,
	char const *headervalue);

size_t picohttpRoutesMaxUrlLength(
	struct picohttpURLRoute const * const routes );

void picohttpProcessRequest(
	struct picohttpIoOps const * const ioops,
	struct picohttpURLRoute const * const routes,
	struct picohttpAuthData * const authdata,
	void *userdata );

void picohttpStatusResponse(
	struct picohttpRequest *req, int status );

void picohttpAuthRequired(
	struct picohttpRequest *req,
	char const * const realm );


int picohttpResponseSendHeader (
	struct picohttpRequest * const req );

int picohttpResponseWrite (
	struct picohttpRequest * const req,
	size_t len,
	void const *buf );

int picohttpGetch(struct picohttpRequest * const req);

struct picohttpMultipart picohttpMultipartStart(
	struct picohttpRequest * const req);

int picohttpMultipartNext(
	struct picohttpMultipart * const mp);

int picohttpMultipartGetch(
	struct picohttpMultipart * const mp);

int picohttpMultipartRead(
	struct picohttpMultipart * const mp,
	size_t len,
	char * const buf);

#endif/*PICOHTTP_H_HEADERGUARD*/