summaryrefslogtreecommitdiffstats
path: root/src/fluent-bit/lib/monkey/include/monkey/mk_http.h
blob: 42204f9c6febdacaaaad9d37c72a40594ca28d4e (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
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

/*  Monkey HTTP Server
 *  ==================
 *  Copyright 2001-2017 Eduardo Silva <eduardo@monkey.io>
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#ifndef MK_HTTP_H
#define MK_HTTP_H

#include <monkey/mk_scheduler.h>
#include <monkey/mk_core.h>
#include <monkey/mk_http_parser.h>

#define MK_CRLF "\r\n"

/* Request buffer chunks = 4KB */
#define MK_REQUEST_CHUNK (int) 4096
#define MK_REQUEST_DEFAULT_PAGE  "<HTML><HEAD><STYLE type=\"text/css\"> body {font-size: 12px;} </STYLE></HEAD><BODY><H1>%s</H1>%s<BR><HR><ADDRESS>Powered by %s</ADDRESS></BODY></HTML>"

/* Hard coded restrictions */
#define MK_HTTP_DIRECTORY_BACKWARD ".."

#define MK_METHOD_GET_STR       "GET"
#define MK_METHOD_POST_STR      "POST"
#define MK_METHOD_HEAD_STR      "HEAD"
#define MK_METHOD_PUT_STR       "PUT"
#define MK_METHOD_DELETE_STR    "DELETE"
#define MK_METHOD_OPTIONS_STR   "OPTIONS"

/* Headers */
#define RH_ACCEPT "Accept:"
#define RH_ACCEPT_CHARSET "Accept-Charset:"
#define RH_ACCEPT_ENCODING "Accept-Encoding:"
#define RH_ACCEPT_LANGUAGE "Accept-Language:"
#define RH_CONNECTION "Connection:"
#define RH_COOKIE "Cookie:"
#define RH_CONTENT_LENGTH "Content-Length:"
#define RH_CONTENT_RANGE "Content-Range:"
#define RH_CONTENT_TYPE	"Content-Type:"
#define RH_IF_MODIFIED_SINCE "If-Modified-Since:"
#define RH_HOST	"Host:"
#define RH_LAST_MODIFIED "Last-Modified:"
#define RH_LAST_MODIFIED_SINCE "Last-Modified-Since:"
#define RH_REFERER "Referer:"
#define RH_RANGE "Range:"
#define RH_USER_AGENT "User-Agent:"

#define MK_REQUEST_STATUS_INCOMPLETE -1
#define MK_REQUEST_STATUS_COMPLETED 0

#define MK_EXIT_OK           0
#define MK_EXIT_ERROR       -1
#define MK_EXIT_ABORT       -2
#define MK_EXIT_PCONNECTION 24

/* Available methods */
#define MK_HTTP_METHOD_AVAILABLE   \
    MK_HTTP_METHOD_GET_STR "," MK_HTTP_METHOD_POST_STR "," \
    MK_HTTP_METHOD_HEAD_STR "," MK_HTTP_METHOD_PUT_STR "," \
    MK_HTTP_METHOD_DELETE_STR "," MK_HTTP_METHOD_OPTIONS_STR  \
    MK_CRLF

#define MK_HTTP_PROTOCOL_UNKNOWN (-1)
#define MK_HTTP_PROTOCOL_09 (9)
#define MK_HTTP_PROTOCOL_10 (10)
#define MK_HTTP_PROTOCOL_11 (11)

#define MK_HTTP_PROTOCOL_09_STR "HTTP/0.9"
#define MK_HTTP_PROTOCOL_10_STR "HTTP/1.0"
#define MK_HTTP_PROTOCOL_11_STR "HTTP/1.1"

extern const mk_ptr_t mk_http_method_get_p;
extern const mk_ptr_t mk_http_method_post_p;
extern const mk_ptr_t mk_http_method_head_p;
extern const mk_ptr_t mk_http_method_put_p;
extern const mk_ptr_t mk_http_method_delete_p;
extern const mk_ptr_t mk_http_method_options_p;
extern const mk_ptr_t mk_http_method_null_p;

extern const mk_ptr_t mk_http_protocol_09_p;
extern const mk_ptr_t mk_http_protocol_10_p;
extern const mk_ptr_t mk_http_protocol_11_p;
extern const mk_ptr_t mk_http_protocol_null_p;

/*
 * A HTTP session represents an incoming session
 * from a client, a session can be used for pipelined or
 * keepalive requests.
 */

struct mk_http_session
{
    /*
     * The first field of the struct appended to the sched_conn memory
     * space needs to be an integer, the scheduler will set this flag
     * to MK_FALSE to indicate it was just created. This work as a helper
     * to the protocol handler.
     *
     * C rule: a pointer to a structure always points to it's first member.
     */
    int _sched_init;           /* initialized ?     */

    int socket;                 /* socket associated */
    int pipelined;              /* Pipelined request */
    int counter_connections;    /* Count persistent connections */
    int status;                 /* Request status */
    int close_now;              /* Close the session ASAP */

    struct mk_channel *channel;
    struct mk_sched_conn *conn;

    unsigned int body_size;
    unsigned int body_length;

    /* head for mk_http_request list nodes, each request is linked here */
    struct mk_list request_list;

    /* creation time for this HTTP session */
    time_t init_time;

    /* request body buffer */
    char *body;

    /* Initial fixed size buffer for small requests */
    char body_fixed[MK_REQUEST_CHUNK];

    /*
     * FIXME: in previous versions of Monkey we used to parse the complete request
     * for pipelined requests and generate a linked lists of request. With the new
     * parser we are taking the approach to parse one request and process it before
     * parsing others, from that point of view we should not need a linked list
     * of requests.
     *
     * Still testing...
     */
    struct mk_http_request sr_fixed;

    /*
     * Parser context: we only held one parser per connection
     * which is re-used everytime we have a new request.
     */
    struct mk_http_parser parser;

    /* Server context */
    struct mk_server *server;
};

static inline int mk_http_status_completed(struct mk_http_session *cs,
                                           struct mk_sched_conn *conn)
{
    (void) conn;

    if (cs->status == MK_REQUEST_STATUS_COMPLETED) {
        MK_TRACE("HTTP Completed but already completed, aborting conx");
        return -1;
    }

    cs->status = MK_REQUEST_STATUS_COMPLETED;
    return 0;
}

int mk_http_error(int http_status, struct mk_http_session *cs,
                  struct mk_http_request *sr,
                  struct mk_server *server);

int mk_http_method_check(mk_ptr_t method);
mk_ptr_t mk_http_method_check_str(int method);
int mk_http_method_get(char *body);

int mk_http_protocol_check(char *protocol, int len);
mk_ptr_t mk_http_protocol_check_str(int protocol);

int mk_http_init(struct mk_http_session *cs, struct mk_http_request *sr,
                 struct mk_server *server);

int mk_http_keepalive_check(struct mk_http_session *cs,
                            struct mk_http_request *sr,
                            struct mk_server *server);

int mk_http_pending_request(struct mk_http_session *cs);
int mk_http_send_file(struct mk_http_session *cs, struct mk_http_request *sr);

/* http session */
int mk_http_session_init(struct mk_http_session *cs,
                         struct mk_sched_conn *conn,
                         struct mk_server *server);
void mk_http_session_remove(struct mk_http_session *cs,
                            struct mk_server *server);

/* event handlers */
int mk_http_handler_read(struct mk_sched_conn *conn, struct mk_http_session *cs,
                         struct mk_server *server);

int mk_http_handler_write(int socket, struct mk_http_session *cs);

void mk_http_request_free(struct mk_http_request *sr, struct mk_server *server);
void mk_http_request_free_list(struct mk_http_session *cs,
                               struct mk_server *server);

void mk_http_request_init(struct mk_http_session *session,
                          struct mk_http_request *request,
                          struct mk_server *server);
struct mk_http_header *mk_http_header_get(int name, struct mk_http_request *req,
                                          const char *key, unsigned int len);

int mk_http_request_end(struct mk_http_session *cs, struct mk_server *server);

#define mk_http_session_get(conn)               \
    (struct mk_http_session *)                  \
    (((uint8_t *) conn) + sizeof(struct mk_sched_conn))

#endif