#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/epoll.h>
+#include <time.h>
+#include <signal.h>
#include <errno.h>
#include <vector>
#include <string>
Client::Client(int sock)
: sock(sock),
+ connect_time(time(NULL)),
state(Client::READING_REQUEST),
stream(NULL),
header_or_error_bytes_sent(0),
bytes_sent(0)
{
request.reserve(1024);
+
+ // Find the remote address, and convert it to ASCII.
+ sockaddr_in6 addr;
+ socklen_t addr_len = sizeof(addr);
+
+ if (getpeername(sock, reinterpret_cast<sockaddr *>(&addr), &addr_len) == -1) {
+ perror("getpeername");
+ remote_addr = "";
+ } else {
+ char buf[INET6_ADDRSTRLEN];
+ if (inet_ntop(addr.sin6_family, &addr.sin6_addr, buf, sizeof(buf)) == NULL) {
+ perror("inet_ntop");
+ remote_addr = "";
+ } else {
+ remote_addr = buf;
+ }
+ }
}
Client::Client(const ClientProto &serialized, Stream *stream)
: sock(serialized.sock()),
+ remote_addr(serialized.remote_addr()),
+ connect_time(serialized.connect_time()),
state(State(serialized.state())),
request(serialized.request()),
stream_id(serialized.stream_id()),
{
ClientProto serialized;
serialized.set_sock(sock);
+ serialized.set_remote_addr(remote_addr);
+ serialized.set_connect_time(connect_time);
serialized.set_state(state);
serialized.set_request(request);
serialized.set_stream_id(stream_id);
serialized.set_bytes_sent(bytes_sent);
return serialized;
}
+
+ClientStats Client::get_stats() const
+{
+ ClientStats stats;
+ stats.stream_id = stream_id;
+ stats.remote_addr = remote_addr;
+ stats.connect_time = connect_time;
+ stats.bytes_sent = bytes_sent;
+ return stats;
+}
Stream::Stream(const string &stream_id)
: stream_id(stream_id),
should_stop = true;
}
+ pthread_kill(worker_thread, SIGHUP);
if (pthread_join(worker_thread, NULL) == -1) {
perror("pthread_join");
exit(1);
}
}
+
+vector<ClientStats> Server::get_client_stats() const
+{
+ vector<ClientStats> ret;
+
+ MutexLock lock(&mutex);
+ for (map<int, Client>::const_iterator client_it = clients.begin();
+ client_it != clients.end();
+ ++client_it) {
+ ret.push_back(client_it->second.get_stats());
+ }
+ return ret;
+}
void *Server::do_work_thunk(void *arg)
{
for ( ;; ) {
int nfds = epoll_wait(epoll_fd, events, EPOLL_MAX_EVENTS, EPOLL_TIMEOUT_MS);
if (nfds == -1 && errno == EINTR) {
+ if (should_stop) {
+ return;
+ }
continue;
}
if (nfds == -1) {
MutexLock lock(&mutex); // We release the mutex between iterations.
- if (should_stop) {
- return;
- }
-
process_queued_data();
for (int i = 0; i < nfds; ++i) {
process_client(to_process[i]);
}
}
+
+ if (should_stop) {
+ return;
+ }
}
}