eventmachine_httpserver_update 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,117 @@
1
+ /*****************************************************************************
2
+
3
+ File: http.h
4
+ Date: 21Apr06
5
+
6
+ Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
7
+ Gmail: garbagecat10
8
+
9
+ This program is free software; you can redistribute it and/or modify
10
+ it under the terms of the GNU General Public License as published by
11
+ the Free Software Foundation; either version 2 of the License, or
12
+ (at your option) any later version.
13
+
14
+ This program is distributed in the hope that it will be useful,
15
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ GNU General Public License for more details.
18
+
19
+ You should have received a copy of the GNU General Public License
20
+ along with this program; if not, write to the Free Software
21
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
+
23
+ *****************************************************************************/
24
+
25
+
26
+ #ifndef __HttpPersonality__H_
27
+ #define __HttpPersonality__H_
28
+
29
+ #define RESPONSE_CODE_405 "405 Method Not Allowed"
30
+ #define RESPONSE_CODE_406 "406 Not Acceptable"
31
+ #define RESPONSE_CODE_505 "505 HTTP Version Not Supported"
32
+
33
+ /**********************
34
+ class HttpConnection_t
35
+ **********************/
36
+
37
+ class HttpConnection_t
38
+ {
39
+ public:
40
+ HttpConnection_t();
41
+ virtual ~HttpConnection_t();
42
+
43
+ void ConsumeData (const char*, int);
44
+
45
+ virtual void SendData (const char*, int);
46
+ virtual void CloseConnection (bool after_writing);
47
+ virtual void ProcessRequest (const char *method,
48
+ const char *cookie,
49
+ const char *ifnonematch,
50
+ const char *content_type,
51
+ const char *query_string,
52
+ const char *path_info,
53
+ const char *request_uri,
54
+ const char *protocol,
55
+ int postlength,
56
+ const char *postdata,
57
+ const char* hdrblock,
58
+ int hdrblksize);
59
+
60
+ virtual void ReceivePostData(const char *data, int len);
61
+ virtual void SetNoEnvironmentStrings() {bSetEnvironmentStrings = false;}
62
+ virtual void SetDontAccumulatePost() {bAccumulatePost = false;}
63
+
64
+ private:
65
+
66
+ enum {
67
+ BaseState,
68
+ PreheaderState,
69
+ HeaderState,
70
+ ReadingContentState,
71
+ DispatchState,
72
+ EndState
73
+ } ProtocolState;
74
+
75
+ enum {
76
+ MaxLeadingBlanks = 12,
77
+ MaxHeaderLineLength = 8 * 1024,
78
+ MaxContentLength = 20 * 1024 * 1024,
79
+ HeaderBlockSize = 16 * 1024
80
+ };
81
+ int nLeadingBlanks;
82
+
83
+ char HeaderLine [MaxHeaderLineLength];
84
+ int HeaderLinePos;
85
+
86
+ char HeaderBlock [HeaderBlockSize];
87
+ int HeaderBlockPos;
88
+
89
+ int ContentLength;
90
+ int ContentPos;
91
+ char *_Content;
92
+
93
+ bool bSetEnvironmentStrings;
94
+ bool bAccumulatePost;
95
+ bool bRequestSeen;
96
+ bool bContentLengthSeen;
97
+
98
+ const char *RequestMethod;
99
+ std::string Cookie;
100
+ std::string IfNoneMatch;
101
+ std::string ContentType;
102
+ std::string PathInfo;
103
+ std::string RequestUri;
104
+ std::string QueryString;
105
+ std::string Protocol;
106
+
107
+ private:
108
+ bool _InterpretHeaderLine (const char*);
109
+ bool _InterpretRequest (const char*);
110
+ bool _DetectVerbAndSetEnvString (const char*, int);
111
+ void _SendError (const char*);
112
+ };
113
+
114
+ #endif // __HttpPersonality__H_
115
+
116
+
117
+
@@ -0,0 +1,305 @@
1
+ /*****************************************************************************
2
+
3
+ File: libmain.cpp
4
+ Date: 06Apr06
5
+
6
+ Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
7
+ Gmail: garbagecat10
8
+
9
+ This program is free software; you can redistribute it and/or modify
10
+ it under the terms of the GNU General Public License as published by
11
+ the Free Software Foundation; either version 2 of the License, or
12
+ (at your option) any later version.
13
+
14
+ This program is distributed in the hope that it will be useful,
15
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ GNU General Public License for more details.
18
+
19
+ You should have received a copy of the GNU General Public License
20
+ along with this program; if not, write to the Free Software
21
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
+
23
+ *****************************************************************************/
24
+
25
+ #include <iostream>
26
+ #include <string>
27
+ #include <stdexcept>
28
+
29
+ using namespace std;
30
+
31
+ #include <ruby.h>
32
+ #include "http.h"
33
+
34
+
35
+
36
+ /**************************
37
+ class RubyHttpConnection_t
38
+ **************************/
39
+
40
+ class RubyHttpConnection_t: public HttpConnection_t
41
+ {
42
+ public:
43
+ RubyHttpConnection_t (VALUE v): Myself(v) {}
44
+ virtual ~RubyHttpConnection_t() {}
45
+
46
+ virtual void SendData (const char*, int);
47
+ virtual void CloseConnection (bool after_writing);
48
+ virtual void ProcessRequest (const char *request_method,
49
+ const char *cookie,
50
+ const char *ifnonematch,
51
+ const char *contenttype,
52
+ const char *query_string,
53
+ const char *path_info,
54
+ const char *request_uri,
55
+ const char *protocol,
56
+ int postlength,
57
+ const char *postdata,
58
+ const char *hdrblock,
59
+ int hdrblocksize);
60
+ virtual void ReceivePostData (const char *data, int len);
61
+
62
+ private:
63
+ VALUE Myself;
64
+ };
65
+
66
+
67
+ /******************************
68
+ RubyHttpConnection_t::SendData
69
+ ******************************/
70
+
71
+ void RubyHttpConnection_t::SendData (const char *data, int length)
72
+ {
73
+ rb_funcall (Myself, rb_intern ("send_data"), 1, rb_str_new (data, length));
74
+ }
75
+
76
+
77
+ /*************************************
78
+ RubyHttpConnection_t::CloseConnection
79
+ *************************************/
80
+
81
+ void RubyHttpConnection_t::CloseConnection (bool after_writing)
82
+ {
83
+ VALUE v = rb_intern (after_writing ? "close_connection_after_writing" : "close_connection");
84
+ rb_funcall (Myself, v, 0);
85
+ }
86
+
87
+
88
+ /*************************************
89
+ RubyHttpConnection_t::ReceivePostData
90
+ *************************************/
91
+
92
+ void RubyHttpConnection_t::ReceivePostData (const char *data, int len)
93
+ {
94
+ VALUE data_val = Qnil;
95
+
96
+ if ((len > 0) && data) {
97
+ data_val = rb_str_new(data,len);
98
+ rb_funcall (Myself, rb_intern ("receive_post_data"), 1, data_val);
99
+ }
100
+ }
101
+
102
+ /************************************
103
+ RubyHttpConnection_t::ProcessRequest
104
+ ************************************/
105
+
106
+ void RubyHttpConnection_t::ProcessRequest (const char *request_method,
107
+ const char *cookie,
108
+ const char *ifnonematch,
109
+ const char *contenttype,
110
+ const char *query_string,
111
+ const char *path_info,
112
+ const char *request_uri,
113
+ const char *protocol,
114
+ int post_length,
115
+ const char *post_content,
116
+ const char *hdr_block,
117
+ int hdr_block_size)
118
+ {
119
+ VALUE post = Qnil;
120
+ VALUE headers = Qnil;
121
+ VALUE req_method = Qnil;
122
+ VALUE cookie_val = Qnil;
123
+ VALUE ifnonematch_val = Qnil;
124
+ VALUE contenttype_val = Qnil;
125
+ VALUE path_info_val = Qnil;
126
+ VALUE query_string_val = Qnil;
127
+ VALUE request_uri_val = Qnil;
128
+ VALUE protocol_val = Qnil;
129
+
130
+ if ((post_length > 0) && post_content)
131
+ post = rb_str_new (post_content, post_length);
132
+
133
+ if (hdr_block && (hdr_block_size > 0))
134
+ headers = rb_str_new (hdr_block, hdr_block_size);
135
+ else
136
+ headers = rb_str_new ("", 0);
137
+
138
+ if (request_method && *request_method)
139
+ req_method = rb_str_new (request_method, strlen (request_method));
140
+ if (cookie && *cookie)
141
+ cookie_val = rb_str_new (cookie, strlen (cookie));
142
+ if (ifnonematch && *ifnonematch)
143
+ ifnonematch_val = rb_str_new (ifnonematch, strlen (ifnonematch));
144
+ if (contenttype && *contenttype)
145
+ contenttype_val = rb_str_new (contenttype, strlen (contenttype));
146
+ if (path_info && *path_info)
147
+ path_info_val = rb_str_new (path_info, strlen (path_info));
148
+ if (query_string && *query_string)
149
+ query_string_val = rb_str_new (query_string, strlen (query_string));
150
+ if (request_uri && *request_uri)
151
+ request_uri_val = rb_str_new (request_uri, strlen (request_uri));
152
+ if (protocol && *protocol)
153
+ protocol_val = rb_str_new (protocol, strlen (protocol));
154
+
155
+ rb_ivar_set (Myself, rb_intern ("@http_request_method"), req_method);
156
+ rb_ivar_set (Myself, rb_intern ("@http_cookie"), cookie_val);
157
+ rb_ivar_set (Myself, rb_intern ("@http_if_none_match"), ifnonematch_val);
158
+ rb_ivar_set (Myself, rb_intern ("@http_content_type"), contenttype_val);
159
+ rb_ivar_set (Myself, rb_intern ("@http_path_info"), path_info_val);
160
+ rb_ivar_set (Myself, rb_intern ("@http_request_uri"), request_uri_val);
161
+ rb_ivar_set (Myself, rb_intern ("@http_query_string"), query_string_val);
162
+ rb_ivar_set (Myself, rb_intern ("@http_post_content"), post);
163
+ rb_ivar_set (Myself, rb_intern ("@http_headers"), headers);
164
+ rb_ivar_set (Myself, rb_intern ("@http_protocol"), protocol_val);
165
+ rb_funcall (Myself, rb_intern ("process_http_request"), 0);
166
+ }
167
+
168
+
169
+ /*******
170
+ Statics
171
+ *******/
172
+
173
+ VALUE Intern_http_conn;
174
+
175
+ /********************
176
+ t_get_http_connection
177
+ ********************/
178
+
179
+ static RubyHttpConnection_t *t_get_http_connection(VALUE self)
180
+ {
181
+ RubyHttpConnection_t *hc;
182
+ VALUE ivar = rb_ivar_get (self, Intern_http_conn);
183
+ if (ivar != Qnil)
184
+ Data_Get_Struct (ivar, RubyHttpConnection_t, hc);
185
+ else
186
+ hc = NULL;
187
+ return hc;
188
+ }
189
+
190
+ /********************
191
+ t_delete_http_connection
192
+ ********************/
193
+
194
+ void t_delete_http_connection(RubyHttpConnection_t *hc)
195
+ {
196
+ delete hc;
197
+ }
198
+
199
+ /***********
200
+ t_post_init
201
+ ***********/
202
+
203
+ static VALUE t_post_init (VALUE self)
204
+ {
205
+ RubyHttpConnection_t *hc = new RubyHttpConnection_t (self);
206
+ if (!hc)
207
+ throw std::runtime_error ("no http-connection object");
208
+
209
+ /*
210
+ HACK: http_connection should be given an actual type. No one should
211
+ be touching it from inside ruby, but still
212
+ */
213
+ VALUE http_connection = Data_Wrap_Struct(CLASS_OF(self), 0, t_delete_http_connection, hc);
214
+ rb_ivar_set (self, Intern_http_conn, http_connection);
215
+ return Qnil;
216
+ }
217
+
218
+
219
+ /**************
220
+ t_receive_data
221
+ **************/
222
+
223
+ static VALUE t_receive_data (VALUE self, VALUE data)
224
+ {
225
+ int length = NUM2INT (rb_funcall (data, rb_intern ("length"), 0));
226
+ RubyHttpConnection_t *hc = t_get_http_connection (self);
227
+ if (hc)
228
+ hc->ConsumeData (StringValuePtr (data), length);
229
+ return Qnil;
230
+ }
231
+
232
+ /*******************
233
+ t_receive_post_data
234
+ *******************/
235
+
236
+ static VALUE t_receive_post_data (VALUE self, VALUE data)
237
+ {
238
+ /** This is a NOOP. It should be overridden. **/
239
+ return Qnil;
240
+ }
241
+
242
+ /********
243
+ t_unbind
244
+ ********/
245
+
246
+ static VALUE t_unbind (VALUE self)
247
+ {
248
+ return Qnil;
249
+ }
250
+
251
+
252
+ /**********************
253
+ t_process_http_request
254
+ **********************/
255
+
256
+ static VALUE t_process_http_request (VALUE self)
257
+ {
258
+ // This is a stub in case the caller doesn't define it.
259
+ rb_funcall (self, rb_intern ("send_data"), 1, rb_str_new2 ("HTTP/1.1 200 OK\r\nContent-type: text/plain\r\nContent-length: 8\r\n\r\nMonorail"));
260
+ return Qnil;
261
+ }
262
+
263
+ /************************
264
+ t_no_environment_strings
265
+ ************************/
266
+
267
+ static VALUE t_no_environment_strings (VALUE self)
268
+ {
269
+ RubyHttpConnection_t *hc = t_get_http_connection (self);
270
+ if (hc)
271
+ hc->SetNoEnvironmentStrings();
272
+ return Qnil;
273
+ }
274
+
275
+ /**********************
276
+ t_dont_accumulate_post
277
+ **********************/
278
+
279
+ static VALUE t_dont_accumulate_post (VALUE self)
280
+ {
281
+ RubyHttpConnection_t *hc = t_get_http_connection (self);
282
+ if (hc)
283
+ hc->SetDontAccumulatePost();
284
+ return Qnil;
285
+ }
286
+
287
+
288
+ /****************************
289
+ Init_eventmachine_httpserver
290
+ ****************************/
291
+
292
+ extern "C" void Init_eventmachine_httpserver()
293
+ {
294
+ Intern_http_conn = rb_intern ("http_conn");
295
+
296
+ VALUE EmModule = rb_define_module ("EventMachine");
297
+ VALUE HttpServer = rb_define_module_under (EmModule, "HttpServer");
298
+ rb_define_method (HttpServer, "post_init", (VALUE(*)(...))t_post_init, 0);
299
+ rb_define_method (HttpServer, "receive_data", (VALUE(*)(...))t_receive_data, 1);
300
+ rb_define_method (HttpServer, "receive_post_data", (VALUE(*)(...))t_receive_post_data, 1);
301
+ rb_define_method (HttpServer, "unbind", (VALUE(*)(...))t_unbind, 0);
302
+ rb_define_method (HttpServer, "process_http_request", (VALUE(*)(...))t_process_http_request, 0);
303
+ rb_define_method (HttpServer, "no_environment_strings", (VALUE(*)(...))t_no_environment_strings, 0);
304
+ rb_define_method (HttpServer, "dont_accumulate_post", (VALUE(*)(...))t_dont_accumulate_post, 0);
305
+ }
@@ -0,0 +1,35 @@
1
+ # EventMachine HTTP Server
2
+ #
3
+ # Author:: blackhedd (gmail address: garbagecat10).
4
+ #
5
+ # Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
6
+ #
7
+ # This program is made available under the terms of the GPL version 2.
8
+ #
9
+ #----------------------------------------------------------------------------
10
+ #
11
+ # Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
12
+ #
13
+ # Gmail: garbagecat10
14
+ #
15
+ # This program is free software; you can redistribute it and/or modify
16
+ # it under the terms of the GNU General Public License as published by
17
+ # the Free Software Foundation; either version 2 of the License, or
18
+ # (at your option) any later version.
19
+ #
20
+ # This program is distributed in the hope that it will be useful,
21
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
22
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
+ # GNU General Public License for more details.
24
+ #
25
+ # You should have received a copy of the GNU General Public License
26
+ # along with this program; if not, write to the Free Software
27
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28
+ #
29
+ #---------------------------------------------------------------------------
30
+ #
31
+
32
+
33
+ require 'eventmachine_httpserver'
34
+ require 'evma_httpserver/response'
35
+