Skip to content

Commit

Permalink
Expose the FD of seasocks, update test
Browse files Browse the repository at this point in the history
  • Loading branch information
mattgodbolt committed Mar 13, 2015
1 parent ce39752 commit 772d7ac
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 4 deletions.
55 changes: 51 additions & 4 deletions src/app/c/ws_test_poll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
// suspicious means of sending raw JavaScript commands to be executed on other
// clients.

// Same as ws_test, but uses the poll() method.
// Same as ws_test, but uses the poll() method and a separate epoll set to
// demonstrate how Seasocks can be used with another polling system.

#include "seasocks/PrintfLogger.h"
#include "seasocks/Server.h"
Expand All @@ -43,6 +44,9 @@
#include <set>
#include <sstream>
#include <string>
#include <fcntl.h>
#include <unistd.h>
#include <sys/epoll.h>

using namespace seasocks;
using namespace std;
Expand Down Expand Up @@ -114,10 +118,53 @@ int main(int argc, const char* argv[]) {
cerr << "couldn't start listening" << endl;
return 1;
}
int myEpoll = epoll_create(10);
epoll_event wakeSeasocks = { EPOLLIN|EPOLLOUT|EPOLLERR, { &server } };
epoll_ctl(myEpoll, EPOLL_CTL_ADD, server.fd(), &wakeSeasocks);

// Also poll stdin
epoll_event wakeStdin = { EPOLLIN, { nullptr } };
epoll_ctl(myEpoll, EPOLL_CTL_ADD, STDIN_FILENO, &wakeStdin);
auto prevFlags = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, prevFlags | O_NONBLOCK);

cout << "Will echo anything typed in stdin: " << flush;
while (true) {
auto result = server.poll(100);
if (result == Server::PollResult::Terminated) return 0;
if (result == Server::PollResult::Error) return 1;
constexpr auto maxEvents = 2;
epoll_event events[maxEvents];
auto res = epoll_wait(myEpoll, events, maxEvents, -1);
if (res < 0) {
cerr << "epoll returned an error" << endl;
return 1;
}
for (auto i = 0; i < res; ++i) {
if (events[i].data.ptr == &server) {
auto seasocksResult = server.poll(0);
if (seasocksResult == Server::PollResult::Terminated) return 0;
if (seasocksResult == Server::PollResult::Error) return 1;
} else if (events[i].data.ptr == nullptr) {
// Echo stdin to stdout to show we can read from that too.
for (;;) {
char buf[1024];
auto numRead = ::read(STDIN_FILENO, buf, sizeof(buf));
if (numRead < 0) {
if (errno != EWOULDBLOCK && errno != EAGAIN) {
cerr << "Error reading stdin" << endl;
return 1;
}
break;
} else if (numRead > 0) {
auto written = write(STDOUT_FILENO, buf, numRead);
if (written != numRead) {
cerr << "Truncated write" << endl;
}
} else if (numRead == 0) {
cerr << "EOF on stdin" << endl;
return 0;
}
}
}
}
}
return 0;
}
5 changes: 5 additions & 0 deletions src/main/c/seasocks/Server.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ class Server : private ServerImpl {
};
PollResult poll(int millisToBlock);

// Returns a file descriptor that can be polled for changes (e.g. by
// placing it in an epoll set. The poll() method above only need be called
// when this file descriptor is readable.
int fd() const { return _epollFd; }

// Terminate any loop() or poll(). May be called from any thread.
void terminate();

Expand Down

0 comments on commit 772d7ac

Please sign in to comment.