Skip to content

Commit beda1e3

Browse files
author
Sebastiano Merlino
committed
Added -D_REENTRANT to configuration.
Aligned debian changelog. Added comet capabilities to the server.
1 parent b4209eb commit beda1e3

File tree

7 files changed

+447
-88
lines changed

7 files changed

+447
-88
lines changed

configure.ac

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121

2222
AC_PREREQ(2.57)
2323
m4_define([libhttpserver_MAJOR_VERSION],[0])dnl
24-
m4_define([libhttpserver_MINOR_VERSION],[3])dnl
25-
m4_define([libhttpserver_REVISION],[0])dnl
24+
m4_define([libhttpserver_MINOR_VERSION],[4])dnl
25+
m4_define([libhttpserver_REVISION],[1])dnl
2626
m4_define([libhttpserver_PKG_VERSION],[libhttpserver_MAJOR_VERSION.libhttpserver_MINOR_VERSION.libhttpserver_REVISION])dnl
2727
m4_define([libhttpserver_LDF_VERSION],[libhttpserver_MAJOR_VERSION:libhttpserver_MINOR_VERSION:libhttpserver_REVISION])dnl
2828
AC_INIT([libhttpserver], libhttpserver_PKG_VERSION, [electrictwister2000@gmail.com])
@@ -72,9 +72,7 @@ PKG_CHECK_MODULES([LIBMICROHTTPD],[libmicrohttpd >= 0.9.7],[],[AC_MSG_ERROR("lib
7272
#AC_CHECK_HEADER([microhttpd.h],[],[AC_MSG_ERROR("Microhttpd header files not found. Please use a version >= 0.9.9.")])
7373
#AC_CHECK_LIB([microhttpd],[MHD_start_daemon],[],[AC_MSG_ERROR("Microhttpd header files not found. Please use a version >= 0.9.9.")])
7474

75-
CXXFLAGS="-DHTTPSERVER_COMPILATION $CXXFLAGS"
76-
77-
CXXFLAGS="$LIBMICROHTTPD_CFLAGS $CXXFLAGS"
75+
CXXFLAGS="-DHTTPSERVER_COMPILATION -D_REENTRANT $LIBMICROHTTPD_CFLAGS $CXXFLAGS"
7876
LDFLAGS="$LIBMICROHTTPD_LIBS $LD_FLAGS"
7977

8078
m4_pattern_allow([AC_TYPE_SIZE_T])

debian/changelog.in

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
libhttpserver (0.4.0) unstable; urgency=low
2+
* Added support to Comet
3+
4+
-- Sebastiano Merlino <electrictwister2000@gmail.com> Tue, 25 Sep 2012 11:42:23 +0200
5+
16
libhttpserver (0.3.0) unstable; urgency=low
27
* Improved performaces
38
* Added capability to register default error pages

src/http_response.cpp

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,6 @@ using namespace std;
2929
namespace httpserver
3030
{
3131

32-
struct data_closure
33-
{
34-
webserver* ws;
35-
string connection_id;
36-
string topic;
37-
};
38-
3932
const std::vector<std::pair<std::string, std::string> > http_response::get_headers()
4033
{
4134
std::vector<std::pair<std::string, std::string> > to_ret;
@@ -107,38 +100,41 @@ void http_file_response::get_raw_response(MHD_Response** response, bool* found,
107100

108101
void long_polling_receive_response::get_raw_response(MHD_Response** response, bool* found, webserver* ws)
109102
{
110-
data_closure* dc = new data_closure();
111-
dc->ws = ws;
112-
dc->topic = topic;
113-
generate_random_uuid(dc->connection_id);
103+
#ifdef USE_COMET
104+
this->ws = ws;
105+
this->connection_id = MHD_get_connection_info(this->underlying_connection, MHD_CONNECTION_INFO_FD)->socket_fd;
114106
*response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, 80,
115-
&long_polling_receive_response::data_generator, (void*) dc, &long_polling_receive_response::free_callback);
116-
ws->register_to_topic(dc->topic, dc->connection_id);
107+
&long_polling_receive_response::data_generator, (void*) this, NULL);
108+
ws->register_to_topics(topics, connection_id, keepalive_secs, keepalive_msg);
109+
#else //USE_COMET
110+
http_response::get_raw_response(response, found, ws);
111+
#endif //USE_COMET
117112
}
118113

119114
ssize_t long_polling_receive_response::data_generator (void* cls, uint64_t pos, char* buf, size_t max)
120115
{
121-
data_closure* dc = static_cast<data_closure*>(cls);
122-
if(dc->ws->pop_signaled(dc->connection_id))
116+
#ifdef USE_COMET
117+
long_polling_receive_response* _this = static_cast<long_polling_receive_response*>(cls);
118+
if(_this->ws->pop_signaled(_this->connection_id))
123119
{
124120
string message;
125-
int size = dc->ws->read_message_from_topic(dc->topic, message);
121+
int size = _this->ws->read_message(_this->connection_id, message);
126122
memcpy(buf, message.c_str(), size);
127123
return size;
128124
}
129125
else
130126
return 0;
131-
}
132-
133-
void long_polling_receive_response::free_callback(void* cls)
134-
{
135-
delete static_cast<data_closure*>(cls);
127+
#else //USE_COMET
128+
return 0;
129+
#endif //USE_COMET
136130
}
137131

138132
void long_polling_send_response::get_raw_response(MHD_Response** response, bool* found, webserver* ws)
139133
{
140134
http_response::get_raw_response(response, found, ws);
141-
ws->send_message_to_topic(topic, content);
135+
#ifdef USE_COMET
136+
ws->send_message_to_topic(send_topic, content);
137+
#endif //USE_COMET
142138
}
143139

144140
void clone_response(const http_response& hr, http_response** dhrs)

src/httpserver/http_response.hpp

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
#include <utility>
2929
#include <string>
3030

31+
struct MHD_Connection;
32+
3133
namespace httpserver
3234
{
3335

@@ -77,7 +79,10 @@ class http_response
7779
const std::string& realm = "",
7880
const std::string& opaque = "",
7981
bool reload_nonce = false,
80-
const std::string& topic = ""
82+
const std::vector<std::string>& topics = std::vector<std::string>(),
83+
int keepalive_secs = -1,
84+
const std::string keepalive_msg = "",
85+
const std::string send_topic = ""
8186
):
8287
response_type(response_type),
8388
content(content),
@@ -87,7 +92,10 @@ class http_response
8792
reload_nonce(reload_nonce),
8893
fp(-1),
8994
filename(content),
90-
topic(topic)
95+
topics(topics),
96+
keepalive_secs(keepalive_secs),
97+
keepalive_msg(keepalive_msg),
98+
send_topic(send_topic)
9199
{
92100
set_header(http_utils::http_header_content_type, content_type);
93101
}
@@ -106,7 +114,10 @@ class http_response
106114
filename(b.filename),
107115
headers(b.headers),
108116
footers(b.footers),
109-
topic(b.topic)
117+
topics(b.topics),
118+
keepalive_secs(b.keepalive_secs),
119+
keepalive_msg(b.keepalive_msg),
120+
send_topic(b.send_topic)
110121
{
111122
}
112123
virtual ~http_response()
@@ -270,9 +281,11 @@ class http_response
270281
{
271282
return 0;
272283
}
273-
const std::string get_topic() const
284+
size_t get_topics(std::vector<std::string>& topics) const
274285
{
275-
return this->topic;
286+
for(std::vector<std::string>::const_iterator it = this->topics.begin(); it != this->topics.end(); ++it)
287+
topics.push_back(*it);
288+
return topics.size();
276289
}
277290
protected:
278291
response_type_T response_type;
@@ -285,7 +298,11 @@ class http_response
285298
std::string filename;
286299
std::map<std::string, std::string, header_comparator> headers;
287300
std::map<std::string, std::string, header_comparator> footers;
288-
std::string topic;
301+
std::vector<std::string> topics;
302+
int keepalive_secs;
303+
std::string keepalive_msg;
304+
std::string send_topic;
305+
struct MHD_Connection* underlying_connection;
289306

290307
virtual void get_raw_response(MHD_Response** res, bool* found, webserver* ws = 0x0);
291308

@@ -393,8 +410,10 @@ class long_polling_receive_response : public http_response
393410
const std::string& content,
394411
int response_code,
395412
const std::string& content_type,
396-
const std::string& topic
397-
) : http_response(http_response::LONG_POLLING_RECEIVE, content, response_code, content_type, "", "", false, topic)
413+
const std::vector<std::string>& topics,
414+
int keepalive_secs = -1,
415+
std::string keepalive_msg = ""
416+
) : http_response(http_response::LONG_POLLING_RECEIVE, content, response_code, content_type, "", "", false, topics, keepalive_secs, keepalive_msg)
398417
{
399418
}
400419

@@ -403,7 +422,9 @@ class long_polling_receive_response : public http_response
403422
virtual void get_raw_response(MHD_Response** res, bool* found, webserver* ws = 0x0);
404423
private:
405424
static ssize_t data_generator (void* cls, uint64_t pos, char* buf, size_t max);
406-
static void free_callback(void* cls);
425+
426+
int connection_id;
427+
webserver* ws;
407428
};
408429

409430
class long_polling_send_response : public http_response
@@ -413,7 +434,7 @@ class long_polling_send_response : public http_response
413434
(
414435
const std::string& content,
415436
const std::string& topic
416-
) : http_response(http_response::LONG_POLLING_SEND, content, 200, "", "", "", false, topic)
437+
) : http_response(http_response::LONG_POLLING_SEND, content, 200, "", "", "", false, std::vector<std::string>(), -1, "", topic)
417438
{
418439
}
419440

src/httpserver/modded_request.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ struct modded_request
3838
{
3939
struct MHD_PostProcessor *pp;
4040
std::string* complete_uri;
41-
std::string* st_url;
4241
webserver* ws;
4342
void(http_resource::*callback)(const http_request&, http_response**);
4443
http_request* dhr;

src/httpserver/webserver.hpp

Lines changed: 30 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include <string>
4444
#include <utility>
4545
#include <memory>
46+
#include <deque>
4647

4748
#include <pthread.h>
4849

@@ -237,42 +238,16 @@ class webserver
237238
void unban_ip(const std::string& ip);
238239
void disallow_ip(const std::string& ip);
239240

240-
void send_message_to_topic(const std::string& topic, const std::string& message)
241-
{
242-
q_messages[topic] = message;
243-
for(std::set<std::string>::const_iterator it = q_waitings[topic].begin(); it != q_waitings[topic].end(); ++it)
244-
q_signal.insert((*it));
245-
}
241+
void send_message_to_topic(const std::string& topic, const std::string& message);
242+
void send_message_to_consumer(int connection_id, const std::string& message, bool to_lock = true);
246243

247-
void register_to_topic(const std::string& topic, const std::string& connection_id)
248-
{
249-
q_waitings[topic].insert(connection_id);
250-
}
244+
void register_to_topics(const std::vector<std::string>& topics, int connection_id, int keepalive_secs = -1, std::string keepalive_msg = "");
251245

252-
size_t read_message_from_topic(const std::string& topic, std::string& message)
253-
{
254-
message = q_messages[topic];
255-
return message.size();
256-
}
246+
size_t read_message(int connection_id, std::string& message);
257247

258-
size_t get_topic_consumers(const std::string& topic, std::set<std::string>& consumers)
259-
{
260-
for(std::set<std::string>::const_iterator it = q_waitings[topic].begin(); it != q_waitings[topic].end(); ++it)
261-
consumers.insert((*it));
262-
return consumers.size();
263-
}
248+
size_t get_topic_consumers(const std::string& topic, std::set<int>& consumers);
264249

265-
bool pop_signaled(const std::string& consumer)
266-
{
267-
std::set<std::string>::iterator it = q_signal.find(consumer);
268-
if(it != q_signal.end())
269-
{
270-
q_signal.erase(it);
271-
return true;
272-
}
273-
else
274-
return false;
275-
}
250+
bool pop_signaled(int consumer);
276251

277252
/**
278253
* Method used to kill the webserver waiting for it to terminate
@@ -312,7 +287,10 @@ class webserver
312287
bool post_process_enabled;
313288
bool single_resource;
314289
pthread_mutex_t mutexwait;
290+
pthread_mutex_t runguard;
291+
pthread_mutex_t cleanmux;
315292
pthread_cond_t mutexcond;
293+
pthread_cond_t cleancond;
316294
http_resource* not_found_resource;
317295
http_resource* method_not_allowed_resource;
318296
http_resource* method_not_acceptable_resource;
@@ -322,19 +300,28 @@ class webserver
322300
#ifdef USE_CPP_ZEROX
323301
std::unordered_set<ip_representation> bans;
324302
std::unordered_set<ip_representation> allowances;
325-
std::unordered_map<std::string, std::string> q_messages;
326-
std::unordered_map<std::string, std::unordered_set<std::string> > q_waitings;
327-
std::unordered_set<std::string> q_signal;
328303
#else
329304
std::set<ip_representation> bans;
330305
std::set<ip_representation> allowances;
331-
std::map<std::string, std::string> q_messages;
332-
std::map<std::string, std::set<std::string> > q_waitings;
333-
std::set<std::string> q_signal;
334306
#endif
307+
308+
// std::map<std::string, std::string> q_messages;
309+
std::map<int, std::deque<std::string> > q_messages;
310+
std::map<std::string, std::set<int> > q_waitings;
311+
std::map<int, std::pair<pthread_mutex_t, pthread_cond_t> > q_blocks;
312+
std::set<int> q_signal;
313+
std::map<int, long> q_keepalives;
314+
std::map<int, std::pair<int, std::string> > q_keepalives_mem;
315+
pthread_rwlock_t comet_guard;
316+
335317
struct MHD_Daemon *daemon;
318+
std::vector<pthread_t> threads;
336319

337320
void init(http_resource* single_resource);
321+
static void* select(void* self);
322+
void schedule_fd(int fd, fd_set* schedule_list, int* max);
323+
static void* cleaner(void* self);
324+
void clean_connections();
338325

339326
void method_not_allowed_page(http_response** dhrs, modded_request* mr);
340327
void internal_error_page(http_response** dhrs, modded_request* mr);
@@ -403,6 +390,11 @@ class webserver
403390
const char* st_url, const char* method
404391
);
405392

393+
bool use_internal_select()
394+
{
395+
return this->start_method == http_utils::INTERNAL_SELECT;
396+
}
397+
406398
friend int policy_callback (void *cls, const struct sockaddr* addr, socklen_t addrlen);
407399
friend void error_log(void* cls, const char* fmt, va_list ap);
408400
friend void access_log(webserver* cls, std::string uri);

0 commit comments

Comments
 (0)