evdispatch 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. data/History.txt +3 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +96 -0
  4. data/README.txt +73 -0
  5. data/Rakefile +4 -0
  6. data/config/hoe.rb +70 -0
  7. data/config/requirements.rb +15 -0
  8. data/ext/revdispatch/extconf.rb +31 -0
  9. data/ext/revdispatch/libevdispatch/Changelog +0 -0
  10. data/ext/revdispatch/libevdispatch/LICENSE +0 -0
  11. data/ext/revdispatch/libevdispatch/Makefile.am +10 -0
  12. data/ext/revdispatch/libevdispatch/Makefile.in +637 -0
  13. data/ext/revdispatch/libevdispatch/README +3 -0
  14. data/ext/revdispatch/libevdispatch/TODO +5 -0
  15. data/ext/revdispatch/libevdispatch/aclocal.m4 +7459 -0
  16. data/ext/revdispatch/libevdispatch/autogen.sh +11 -0
  17. data/ext/revdispatch/libevdispatch/confdefs.h +32 -0
  18. data/ext/revdispatch/libevdispatch/config.guess +1516 -0
  19. data/ext/revdispatch/libevdispatch/config.h.in +112 -0
  20. data/ext/revdispatch/libevdispatch/config.sub +1626 -0
  21. data/ext/revdispatch/libevdispatch/configure +21949 -0
  22. data/ext/revdispatch/libevdispatch/configure.ac +40 -0
  23. data/ext/revdispatch/libevdispatch/depcomp +584 -0
  24. data/ext/revdispatch/libevdispatch/install-sh +507 -0
  25. data/ext/revdispatch/libevdispatch/libev/Changes +54 -0
  26. data/ext/revdispatch/libevdispatch/libev/LICENSE +25 -0
  27. data/ext/revdispatch/libevdispatch/libev/Makefile.am +18 -0
  28. data/ext/revdispatch/libevdispatch/libev/Makefile.in +677 -0
  29. data/ext/revdispatch/libevdispatch/libev/README +130 -0
  30. data/ext/revdispatch/libevdispatch/libev/aclocal.m4 +7430 -0
  31. data/ext/revdispatch/libevdispatch/libev/autogen.sh +7 -0
  32. data/ext/revdispatch/libevdispatch/libev/config.guess +1516 -0
  33. data/ext/revdispatch/libevdispatch/libev/config.h.in +106 -0
  34. data/ext/revdispatch/libevdispatch/libev/config.sub +1626 -0
  35. data/ext/revdispatch/libevdispatch/libev/configure +21636 -0
  36. data/ext/revdispatch/libevdispatch/libev/configure.ac +18 -0
  37. data/ext/revdispatch/libevdispatch/libev/ev++.h +779 -0
  38. data/ext/revdispatch/libevdispatch/libev/ev.3 +3276 -0
  39. data/ext/revdispatch/libevdispatch/libev/ev.c +2547 -0
  40. data/ext/revdispatch/libevdispatch/libev/ev.h +608 -0
  41. data/ext/revdispatch/libevdispatch/libev/ev.pod +3192 -0
  42. data/ext/revdispatch/libevdispatch/libev/ev_epoll.c +182 -0
  43. data/ext/revdispatch/libevdispatch/libev/ev_kqueue.c +194 -0
  44. data/ext/revdispatch/libevdispatch/libev/ev_poll.c +135 -0
  45. data/ext/revdispatch/libevdispatch/libev/ev_port.c +163 -0
  46. data/ext/revdispatch/libevdispatch/libev/ev_select.c +244 -0
  47. data/ext/revdispatch/libevdispatch/libev/ev_vars.h +157 -0
  48. data/ext/revdispatch/libevdispatch/libev/ev_win32.c +125 -0
  49. data/ext/revdispatch/libevdispatch/libev/ev_wrap.h +144 -0
  50. data/ext/revdispatch/libevdispatch/libev/event.c +404 -0
  51. data/ext/revdispatch/libevdispatch/libev/event.h +152 -0
  52. data/ext/revdispatch/libevdispatch/libev/install-sh +294 -0
  53. data/ext/revdispatch/libevdispatch/libev/libev.m4 +28 -0
  54. data/ext/revdispatch/libevdispatch/libev/ltmain.sh +6930 -0
  55. data/ext/revdispatch/libevdispatch/libev/missing +336 -0
  56. data/ext/revdispatch/libevdispatch/libev/mkinstalldirs +111 -0
  57. data/ext/revdispatch/libevdispatch/ltmain.sh +6930 -0
  58. data/ext/revdispatch/libevdispatch/missing +367 -0
  59. data/ext/revdispatch/libevdispatch/src/Makefile.am +11 -0
  60. data/ext/revdispatch/libevdispatch/src/Makefile.in +486 -0
  61. data/ext/revdispatch/libevdispatch/src/ev_dispatch.cc +264 -0
  62. data/ext/revdispatch/libevdispatch/src/ev_dispatch.h +300 -0
  63. data/ext/revdispatch/libevdispatch/src/ev_http.cc +238 -0
  64. data/ext/revdispatch/libevdispatch/src/ev_http.h +65 -0
  65. data/ext/revdispatch/libevdispatch/test/Makefile.am +16 -0
  66. data/ext/revdispatch/libevdispatch/test/Makefile.in +513 -0
  67. data/ext/revdispatch/libevdispatch/test/helper.rb +94 -0
  68. data/ext/revdispatch/libevdispatch/test/key_test.cc +52 -0
  69. data/ext/revdispatch/libevdispatch/test/next_test.cc +86 -0
  70. data/ext/revdispatch/libevdispatch/test/next_test.rb +8 -0
  71. data/ext/revdispatch/libevdispatch/test/server.rb +9 -0
  72. data/ext/revdispatch/revdispatch.cc +151 -0
  73. data/ext/revdispatch/server.rb +60 -0
  74. data/ext/revdispatch/test.rb +100 -0
  75. data/lib/evdispatch/loop.rb +16 -0
  76. data/lib/evdispatch/version.rb +9 -0
  77. data/lib/evdispatch.rb +8 -0
  78. data/log/debug.log +0 -0
  79. data/script/console +10 -0
  80. data/script/destroy +14 -0
  81. data/script/generate +14 -0
  82. data/script/txt2html +74 -0
  83. data/setup.rb +1585 -0
  84. data/tasks/deployment.rake +34 -0
  85. data/tasks/environment.rake +7 -0
  86. data/tasks/extconf/revdispatch.rake +43 -0
  87. data/tasks/extconf.rake +13 -0
  88. data/tasks/website.rake +17 -0
  89. data/test/test_evdispatch.rb +11 -0
  90. data/test/test_helper.rb +3 -0
  91. data/test/test_revdispatch_extn.rb +14 -0
  92. data/website/index.html +128 -0
  93. data/website/index.txt +55 -0
  94. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  95. data/website/stylesheets/screen.css +138 -0
  96. data/website/template.html.erb +49 -0
  97. metadata +157 -0
@@ -0,0 +1,238 @@
1
+ #include "config.h"
2
+ #include "ev_http.h"
3
+
4
+ namespace EVD {
5
+
6
+ #define DEBUG
7
+
8
+ #ifdef DEBUG
9
+ #include <assert.h>
10
+ #define ASSERT_IS_D_THRAD(id)\
11
+ {\
12
+ pthread_t tid = pthread_self();\
13
+ assert( tid == id );\
14
+ }
15
+ #else
16
+ #define ASSERT_IS_D_THRAD
17
+ #endif
18
+
19
+ void HttpClient::SocketInfo::response_cb(struct ev_loop *loop, struct ev_io *w, int revents)
20
+ {
21
+ CURLMcode rc;
22
+ HttpClient::SocketInfo *res = ((HttpClient::SocketInfo*)w->data);
23
+ HttpClient *client = res->m_client;
24
+ int ev_bitmask = 0;
25
+ ASSERT_IS_D_THRAD(client->m_disp->get_thread_id());
26
+ do {
27
+ ev_bitmask |= ((revents & EV_READ)?CURL_CSELECT_IN:0) | ((revents & EV_WRITE)?CURL_CSELECT_OUT:0);
28
+ rc = curl_multi_socket_action( client->m_handle, w->fd, ev_bitmask, &(client->m_active) );
29
+ } while( rc == CURLM_CALL_MULTI_PERFORM );
30
+ client->check_handles();
31
+ }
32
+
33
+ HttpClient::SocketInfo::SocketInfo( HttpClient *client, curl_socket_t sock, CURL *e, int action )
34
+ : m_action(action), m_timeout(0), m_watcher(0), m_handle(e), m_client( client )
35
+ {
36
+ m_watcher = (struct ev_io*)calloc(1,sizeof(struct ev_io));
37
+ int kind = (action&CURL_POLL_IN?EV_READ:0)|(action&CURL_POLL_OUT?EV_WRITE:0);
38
+
39
+ m_watcher->data = this;
40
+ ev_io_init( m_watcher, response_cb, sock, kind );
41
+ ev_io_start( m_client->m_disp->get_loop(), m_watcher );
42
+ }
43
+ void HttpClient::SocketInfo::set_sock( curl_socket_t sock, CURL *e, int action )
44
+ {
45
+ int kind = (action&CURL_POLL_IN?EV_READ:0)|(action&CURL_POLL_OUT?EV_WRITE:0);
46
+ ev_io_set( m_watcher, sock, kind );
47
+ }
48
+ void HttpClient::SocketInfo::finish()
49
+ {
50
+ ev_io_stop( m_client->m_disp->get_loop(), m_watcher );
51
+ }
52
+ HttpClient::SocketInfo::~SocketInfo()
53
+ {
54
+ free(m_watcher);
55
+ }
56
+
57
+ // CURLMOPT_SOCKETFUNCTION
58
+ int HttpClient::sock_cb(CURL *e, curl_socket_t sock, int action, void *cbp, void *sockp)
59
+ {
60
+ HttpClient *client = (HttpClient*)cbp;
61
+ HttpClient::SocketInfo *sockinfo = (HttpClient::SocketInfo *)sockp;
62
+ ASSERT_IS_D_THRAD(client->m_disp->get_thread_id());
63
+ if( !sockinfo ) {
64
+ sockinfo = new HttpClient::SocketInfo( client, sock, e, action );
65
+ curl_multi_assign(client->m_handle, sock, sockinfo);
66
+ }
67
+
68
+ switch( action ){
69
+ case CURL_POLL_REMOVE: // (4) unregister
70
+ // make sure we clear it out
71
+ curl_multi_assign(client->m_handle, sock, NULL);
72
+ sockinfo->finish();
73
+ delete sockinfo;
74
+ break;
75
+ case CURL_POLL_NONE: // (0) register, not interested in readiness (yet)
76
+ case CURL_POLL_IN: // (1) register, interested in read readiness
77
+ case CURL_POLL_OUT: // (2) register, interested in write readiness
78
+ case CURL_POLL_INOUT: // (3) register, interested in both read and write readiness
79
+ default:
80
+ sockinfo->set_sock( sock, e, action );
81
+ client->check_handles();
82
+ break;
83
+ }
84
+ return 0;
85
+ }
86
+
87
+ // called on the event loop thread
88
+ void HttpClient::timeout_cb(struct ev_loop *loop, struct ev_timer *w, int revents)
89
+ {
90
+ CURLMcode rc;
91
+ HttpClient *client = (HttpClient*)w->data;
92
+ do {
93
+ rc = curl_multi_socket(client->m_handle, CURL_SOCKET_TIMEOUT, &(client->m_active));
94
+ } while( rc == CURLM_CALL_MULTI_PERFORM );
95
+ client->check_handles();
96
+ }
97
+
98
+ int HttpClient::update_timeout_cb(CURLM *multi, long timeout_ms, void *userp)
99
+ {
100
+ //struct timeval timeout;
101
+ //timeout.tv_sec = timeout_ms/1000;
102
+ //timeout.tv_usec = (timeout_ms%1000)*1000;
103
+ HttpClient *client = (HttpClient*)userp;
104
+
105
+ // update the timer
106
+ ev_tstamp timeout = ev_now(client->m_disp->get_loop()) + (timeout_ms * 0.001);
107
+ if( client->m_timer_set ) {
108
+ ev_timer_set( &(client->m_timer), timeout, 0.0 );
109
+ ev_timer_again( client->m_disp->get_loop(), &(client->m_timer) );
110
+ }
111
+ else {
112
+ ev_timer_init( &(client->m_timer), timeout_cb, timeout, 0.0 );
113
+ client->m_timer.data = client;
114
+ ev_timer_start( client->m_disp->get_loop(), &(client->m_timer) );
115
+ }
116
+
117
+ return 0;
118
+ }
119
+
120
+ HttpClient::HttpClient( Dispatch *disp )
121
+ : m_active(0),
122
+ m_handle( curl_multi_init() ),
123
+ m_disp(disp), m_timer_set(false)
124
+ {
125
+ memset(&m_timer, 0, sizeof(struct ev_timer));
126
+ curl_multi_setopt( m_handle, CURLMOPT_SOCKETFUNCTION, sock_cb );
127
+ curl_multi_setopt( m_handle, CURLMOPT_SOCKETDATA, this );
128
+ curl_multi_setopt( m_handle, CURLMOPT_TIMERFUNCTION, update_timeout_cb );
129
+ curl_multi_setopt( m_handle, CURLMOPT_TIMERDATA, this );
130
+ }
131
+ HttpClient::~HttpClient()
132
+ {
133
+ //printf("cleaning up client\n");
134
+ this->check_handles();
135
+ curl_multi_cleanup( m_handle );
136
+ }
137
+
138
+ void HttpClient::check_handles()
139
+ {
140
+ //see: http://curl.haxx.se/lxr/source/docs/examples/ghiper.c
141
+ HttpRequest *req;
142
+ CURL *easy;
143
+ int msgs_left;
144
+ CURLcode rc;
145
+ CURLMsg *msg;
146
+
147
+ do {
148
+ easy = NULL;
149
+ while( (msg = curl_multi_info_read( m_handle, &msgs_left )) ) {
150
+ if( msg->msg == CURLMSG_DONE ) {
151
+ easy = msg->easy_handle;
152
+ rc = msg->data.result;
153
+ break;
154
+ }
155
+ }
156
+ // it's unclear whether it's okay to remove a curl handle while looping through the
157
+ // handles above, to avoid this we break out and loop again
158
+ if( easy ) {
159
+ curl_easy_getinfo( easy, CURLINFO_PRIVATE, &req );
160
+ req->finish(rc);
161
+ delete req;
162
+ }
163
+
164
+ } while( easy );
165
+ }
166
+
167
+ // CURLOPT_WRITEFUNCTION
168
+ size_t HttpRequest::write_cb(void *ptr, size_t size, size_t nmemb, void *data)
169
+ {
170
+ size_t realsize = size * nmemb;
171
+ HttpRequest *req = (HttpRequest *)data;
172
+
173
+ req->response->body.append((const char*)ptr,realsize);
174
+ //fprintf(stderr, "Write: %s (%lu) => (%d)%s\n", req->url.c_str(), realsize, (int)req->response, req->response->body.c_str() );
175
+
176
+ return realsize;
177
+ }
178
+
179
+ // CURLOPT_PROGRESSFUNCTION
180
+ int HttpRequest::prog_cb(void *p, double dltotal, double dlnow, double ult, double uln)
181
+ {
182
+ HttpRequest *req = (HttpRequest *)p;
183
+ //fprintf(stderr, "Progress: %s (%g/%g)\n", req->url.c_str(), dlnow, dltotal);
184
+ return 0;
185
+ }
186
+
187
+ HttpRequest::HttpRequest( HttpClient* client, request_t k, const std::string &url )
188
+ : Request( k, url ), response(NULL), m_handle(curl_easy_init()), m_client(client)
189
+ {
190
+ memset(error,'\0', CURL_ERROR_SIZE);
191
+ curl_easy_setopt(m_handle, CURLOPT_URL, url.c_str());
192
+ curl_easy_setopt(m_handle, CURLOPT_WRITEFUNCTION, write_cb);
193
+ curl_easy_setopt(m_handle, CURLOPT_WRITEDATA, this);
194
+ curl_easy_setopt(m_handle, CURLOPT_VERBOSE, 0);
195
+ curl_easy_setopt(m_handle, CURLOPT_ERRORBUFFER, error);
196
+ curl_easy_setopt(m_handle, CURLOPT_PRIVATE, this);
197
+ curl_easy_setopt(m_handle, CURLOPT_NOPROGRESS, 0);
198
+ curl_easy_setopt(m_handle, CURLOPT_PROGRESSFUNCTION, prog_cb);
199
+ curl_easy_setopt(m_handle, CURLOPT_PROGRESSDATA, this);
200
+ this->response = new Response();
201
+ this->response->name = url;
202
+ this->response->id = k;
203
+ }
204
+
205
+ HttpRequest::~HttpRequest()
206
+ {
207
+ curl_easy_cleanup( m_handle );
208
+ #ifdef DEBUG
209
+ response = NULL;
210
+ m_handle = NULL;
211
+ m_client = NULL;
212
+ #endif
213
+ }
214
+
215
+ bool HttpRequest::enable()
216
+ {
217
+ CURLMcode rc = curl_multi_add_handle( m_client->m_handle, m_handle );
218
+ do {
219
+ rc = curl_multi_socket_all( m_client->m_handle, &m_client->m_active );
220
+ } while( rc == CURLM_CALL_MULTI_PERFORM );
221
+
222
+ m_client->check_handles();
223
+
224
+ return (rc == CURLM_OK);
225
+ }
226
+
227
+ void HttpRequest::finish(CURLcode rc)
228
+ {
229
+ curl_multi_remove_handle( m_client->m_handle, m_handle );
230
+
231
+ // add the response object here to the responses queue in the dispatcher?
232
+ // signaling to any waiting clients that their response is available
233
+ this->response->response_time = difftime( time(NULL), this->start_time );
234
+ m_client->m_disp->send_response( this->response );
235
+ //fprintf( stderr, "DONE: (%s/%s) => (%d), body(%d): '%s'\n", url.c_str(), url.c_str(), rc, (int)this->response, this->response->body.c_str() );
236
+ }
237
+
238
+ }
@@ -0,0 +1,65 @@
1
+ #ifndef EV_HTTP_H
2
+ #define EV_HTTP_H
3
+
4
+ #include "config.h"
5
+ #include "ev_dispatch.h"
6
+ #include <curl/curl.h>
7
+
8
+ namespace EVD {
9
+
10
+ struct HttpClient {
11
+ HttpClient( Dispatch *disp );
12
+ ~HttpClient();
13
+
14
+ // created to manage the socket transitions
15
+ struct SocketInfo {
16
+ SocketInfo( HttpClient *client, curl_socket_t sock, CURL *e, int action );
17
+ virtual ~SocketInfo();
18
+
19
+ static void response_cb(struct ev_loop *loop, struct ev_io *w, int revents);
20
+ void set_sock( curl_socket_t sock, CURL *e, int action );
21
+ void finish();
22
+
23
+ int m_action;
24
+ long m_timeout;
25
+ struct ev_io *m_watcher;
26
+ CURL *m_handle;
27
+ HttpClient *m_client;
28
+ Dispatch *m_dispatch;
29
+ };
30
+
31
+ void check_handles();
32
+
33
+ static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp);
34
+ static int update_timeout_cb(CURLM *multi, long timeout_ms, void *userp);
35
+ static void timeout_cb(struct ev_loop *loop, struct ev_timer *w, int revents);
36
+
37
+ int m_active; // number of active requests
38
+ CURLM *m_handle;
39
+ Dispatch *m_disp;
40
+ bool m_timer_set;
41
+ struct ev_timer m_timer;
42
+ };
43
+
44
+ // follow the curl handle for the duration of it's request
45
+ struct HttpRequest : public Request {
46
+ HttpRequest( HttpClient* client, request_t k, const std::string &url );
47
+ virtual ~HttpRequest();
48
+
49
+ virtual bool enable();
50
+
51
+ void finish( CURLcode rc );
52
+
53
+ static size_t write_cb(void *ptr, size_t size, size_t nmemb, void *data);
54
+ static int prog_cb(void *p, double dltotal, double dlnow, double ult, double uln);
55
+
56
+ Response *response;
57
+
58
+ CURL *m_handle;
59
+ HttpClient *m_client;
60
+ char error[CURL_ERROR_SIZE];
61
+ };
62
+
63
+ }
64
+
65
+ #endif
@@ -0,0 +1,16 @@
1
+ bin_PROGRAMS = next_test key_test
2
+ next_test_SOURCES = next_test.cc
3
+ next_test_CPPFLAGS = -I$(top_srcdir)/src/ -I$(LIBEV_PATH)
4
+ next_test_LDADD = -ldispatch -lev
5
+ next_test_LDFLAGS = -L$(top_srcdir)/src/.libs/ `curl-config --libs` -L$(LIBEV_PATH)/.libs/
6
+
7
+ key_test_SOURCES = key_test.cc
8
+ key_test_CPPFLAGS = -I$(top_srcdir)/src/ -I$(LIBEV_PATH)
9
+ key_test_LDADD = -ldispatch -lev
10
+ key_test_LDFLAGS = -L$(top_srcdir)/src/.libs/ `curl-config --libs` -L$(LIBEV_PATH)/.libs/
11
+
12
+ test_next: next_test
13
+ .libs/next_test
14
+
15
+ test_key: key_test
16
+ .libs/key_test