Skip to content

Commit 772d7ac

Browse files
committed
Expose the FD of seasocks, update test
1 parent ce39752 commit 772d7ac

File tree

2 files changed

+56
-4
lines changed

2 files changed

+56
-4
lines changed

src/app/c/ws_test_poll.cpp

+51-4
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
// suspicious means of sending raw JavaScript commands to be executed on other
3030
// clients.
3131

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

3435
#include "seasocks/PrintfLogger.h"
3536
#include "seasocks/Server.h"
@@ -43,6 +44,9 @@
4344
#include <set>
4445
#include <sstream>
4546
#include <string>
47+
#include <fcntl.h>
48+
#include <unistd.h>
49+
#include <sys/epoll.h>
4650

4751
using namespace seasocks;
4852
using namespace std;
@@ -114,10 +118,53 @@ int main(int argc, const char* argv[]) {
114118
cerr << "couldn't start listening" << endl;
115119
return 1;
116120
}
121+
int myEpoll = epoll_create(10);
122+
epoll_event wakeSeasocks = { EPOLLIN|EPOLLOUT|EPOLLERR, { &server } };
123+
epoll_ctl(myEpoll, EPOLL_CTL_ADD, server.fd(), &wakeSeasocks);
124+
125+
// Also poll stdin
126+
epoll_event wakeStdin = { EPOLLIN, { nullptr } };
127+
epoll_ctl(myEpoll, EPOLL_CTL_ADD, STDIN_FILENO, &wakeStdin);
128+
auto prevFlags = fcntl(STDIN_FILENO, F_GETFL, 0);
129+
fcntl(STDIN_FILENO, F_SETFL, prevFlags | O_NONBLOCK);
130+
131+
cout << "Will echo anything typed in stdin: " << flush;
117132
while (true) {
118-
auto result = server.poll(100);
119-
if (result == Server::PollResult::Terminated) return 0;
120-
if (result == Server::PollResult::Error) return 1;
133+
constexpr auto maxEvents = 2;
134+
epoll_event events[maxEvents];
135+
auto res = epoll_wait(myEpoll, events, maxEvents, -1);
136+
if (res < 0) {
137+
cerr << "epoll returned an error" << endl;
138+
return 1;
139+
}
140+
for (auto i = 0; i < res; ++i) {
141+
if (events[i].data.ptr == &server) {
142+
auto seasocksResult = server.poll(0);
143+
if (seasocksResult == Server::PollResult::Terminated) return 0;
144+
if (seasocksResult == Server::PollResult::Error) return 1;
145+
} else if (events[i].data.ptr == nullptr) {
146+
// Echo stdin to stdout to show we can read from that too.
147+
for (;;) {
148+
char buf[1024];
149+
auto numRead = ::read(STDIN_FILENO, buf, sizeof(buf));
150+
if (numRead < 0) {
151+
if (errno != EWOULDBLOCK && errno != EAGAIN) {
152+
cerr << "Error reading stdin" << endl;
153+
return 1;
154+
}
155+
break;
156+
} else if (numRead > 0) {
157+
auto written = write(STDOUT_FILENO, buf, numRead);
158+
if (written != numRead) {
159+
cerr << "Truncated write" << endl;
160+
}
161+
} else if (numRead == 0) {
162+
cerr << "EOF on stdin" << endl;
163+
return 0;
164+
}
165+
}
166+
}
167+
}
121168
}
122169
return 0;
123170
}

src/main/c/seasocks/Server.h

+5
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,11 @@ class Server : private ServerImpl {
9999
};
100100
PollResult poll(int millisToBlock);
101101

102+
// Returns a file descriptor that can be polled for changes (e.g. by
103+
// placing it in an epoll set. The poll() method above only need be called
104+
// when this file descriptor is readable.
105+
int fd() const { return _epollFd; }
106+
102107
// Terminate any loop() or poll(). May be called from any thread.
103108
void terminate();
104109

0 commit comments

Comments
 (0)