-
Notifications
You must be signed in to change notification settings - Fork 0
/
connection.h
197 lines (148 loc) · 6.32 KB
/
connection.h
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
/*!
* \file connection.h
* \brief Public interface for managing connections.
* \author Henrique Nascimento Gouveia <h.gouveia@icloud.com>
*/
#ifndef _AKWBS_MT_CONNECTION_H_
#define _AKWBS_MT_CONNECTION_H_
#include "ringbuffer.h"
#include "io.h"
#include "requestio.h"
#include "daemon.h"
/*!
* HTTP Status Code
*/
#define AKWBS_HTTP_200 "HTTP/1.0 200 OK\r\n\r\n"
#define AKWBS_HTTP_201 "HTTP/1.0 201 CREATED\r\n\r\n"
#define AKWBS_HTTP_202 "HTTP/1.0 202 ACCEPTED\r\n\r\n"
#define AKWBS_HTTP_400 "HTTP/1.0 400 BAD REQUEST\r\n\r\n"
#define AKWBS_HTTP_411 "HTTP/1.0 411 LENGTH REQUIRED\r\n\r\n"
#define AKWBS_HTTP_413 "HTTP/1.0 413 REQUEST ENTITY TOO LARGE\r\n\r\n"
#define AKWBS_HTTP_414 "HTTP/1.0 414 REQUESTED-URI TOO LONG\r\n\r\n"
#define AKWBS_HTTP_404 "HTTP/1.0 404 NOT FOUND\r\n\r\n"
#define AKWBS_HTTP_505 "HTTP/1.0 505 HTTP VERSION NOT SUPPORTED\r\n\r\n"
#define AKWBS_SIZE_HEADER_TOO_BIG 8000 /*!< Beyond this limit, the requested header is
* considered as too big, and an error message is
* sent back to the client. Being more specific,
* an HTTP 400 BAD REQUEST error.
*/
#define AKWBS_TIMEOUT_SECONDS 120 /*!< After this limit, the connection will be
* dropped.
*/
/*!
* States in a state machine for a connection.
*
* Transitions are any-state to CLOSED, any state to state+1.
* CLOSED is the terminal state and
* INIT the initial state.
*/
enum akwbs_connection_state
{
/*!
* 1: Connection just started (no headers received).
* Waiting for the line with the request type, URL and version.
*/
AKWBS_CONNECTION_INIT = 0,
/*!
* 2: We have received some part of the request header, but not everyhting.
*/
AKWBS_CONNECTION_HEADERS_RECEIVING = AKWBS_CONNECTION_INIT + 1,
/*!
* 3: We have received all the request header. Now we must process it.
*/
AKWBS_CONNECTION_HEADERS_RECEIVED = AKWBS_CONNECTION_HEADERS_RECEIVING + 1,
/*!
* 4: The headers received was proccessed.
*/
AKWBS_CONNECTION_HEADERS_PROCESSED = AKWBS_CONNECTION_HEADERS_RECEIVED + 1,
/*!
* 5: We are currently on transmission of data.
*/
AKWBS_CONNECTION_ON_TRANSMISSION = AKWBS_CONNECTION_HEADERS_PROCESSED + 1,
/*!
* 6: We have closed this connection.
*/
AKWBS_CONNECTION_CLOSED = AKWBS_CONNECTION_ON_TRANSMISSION + 1,
/*!
* 7: This connection is marked for cleanup.
*/
AKWBS_CONNECTION_CLEANUP = AKWBS_CONNECTION_CLOSED + 1
};
/*!
* States in a state machine for storing information
* about final elements of the requested header (aka
* CRLFCRLF). The transitions are from any-state to
* INITIAL. The states should follow the natural sequence
* of the enum, in case some unexpected shows, the machine
* state is reseted back to the INITIAL state.
*/
enum akwbs_header_state
{
/*!
* Primary and initial state. None relevant
* information has been found.
*/
AKWBS_HEADER_INITIAL = 0,
/*!
* First carriage return "\r" has been found. We should expect
* a linefeed later on.
*/
AKWBS_HEADER_FIRST_CARRIAGE_RETURN,
/*!
* First linefeed "\n" has been found. This indicates that we
* reached the end of a header line. We should expect another
* carriage return "\r" (LAST_CARRIAGE_RETURN) if we are at
* the end of the request header, or we may found other character,
* and this indicates that another potentially new header line is
* going to be read.
*/
AKWBS_HEADER_FIRST_LINEFEED,
/*!
* This one indicates that we are at the end of the header. We have
* the last carriage return "\r", but we still need one more linefeed
* to consider that as an end of the header.
*/
AKWBS_HEADER_LAST_CARRIAGE_RETURN,
/*!
* This is it. We have reached the end of the request header. Beyond this,
* we MUST find data only on PUT requests. In case of GET method request,
* do not even bother checking ahead.
*/
AKWBS_HEADER_LAST_LINEFEED
};
/*!
* Structure representing a connection with client through a socket.
*/
struct akwbs_connection
{
struct ring_buffer buffer; /*!< Buffer for this connection. */
struct akwbs_connection *next; /*!< Pointer to the next connection. */
struct akwbs_connection *prev; /*!< Pointer to the previous connection. */
int file_descriptor; /*!< File descriptor of requested resource. */
int client_socket; /*!< Client socket descriptor. */
int has_request_pending; /*!< A previous request could not be sent. */
int is_waiting_result; /*!< Waiting for a result. */
int has_opening_fd_pending; /*!< Resource could not be opened in last attempt. */
char *file_name; /*!< Resource name. */
off_t file_total_offset; /*!< Total offset for the reuested file. */
off_t file_cur_offset; /*!< Current offset in the requested file. */
struct akwbs_request_io_msg
pending_io_msg; /*!< Pending I/O message. */
enum akwbs_connection_state
connection_state; /*!< State of this connection. */
enum akwbs_header_state
header_state; /*!< State related to the request header. */
struct akwbs_daemon *daemon_ref; /*!< Reference to the daemon handling this conn. */
enum akwbs_io_type io_type; /*!< Type of I/O that must be performed. */
struct timeval last_time_io; /*!< Last time we performed some transmission. */
struct timeval last_activity; /*!< Last time that this connection was used. */
size_t bytes_sent_last_io; /*!< Bytes on last I/O operation. */
char *end_of_first_header_line; /*!< Pointer to the end of first line on header. */
char *end_of_header; /*!< Pointer to the end of the header. */
};
/*
* Public interface.
*/
int akwbs_handle_connection(struct akwbs_connection *connection);
int akwbs_create_new_connection(struct akwbs_connection **connection);
#endif /* END OF CONNECTION.H */