aboutsummaryrefslogtreecommitdiff
path: root/picohttp.h
blob: 59e792eca0ff41e68f477a9237e2a8ec42cf60d8 (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
#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_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;
};

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 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;
		unsigned char multipartboundary[PICOHTTP_MULTIPARTBOUNDARY_MAX_LEN+1];
		unsigned char prev_ch[5];
		size_t chunklength;
	} query;
	struct {
		char const *contenttype;
		char const *disposition;
		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;
};

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);

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

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

int picohttpResponseSendHeader (
	struct picohttpRequest * const req );

int picohttpResponseWrite (
	struct picohttpRequest * const req,
	size_t len,
	char 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*/