blob: c22f075a2421fd531ce05aa1239946c74b0d389a [file] [log] [blame]
Steve Kondik961b4cc2017-06-22 18:10:50 -07001#define LOG_TAG "VNCFlinger"
2#include <utils/Log.h>
Steve Kondik95027ea2017-06-14 17:22:58 -07003
Steve Kondik961b4cc2017-06-22 18:10:50 -07004#include <fcntl.h>
Steve Kondik46798992017-06-15 23:58:54 -07005
Steve Kondik961b4cc2017-06-22 18:10:50 -07006#include "AndroidDesktop.h"
Steve Kondik3db07472017-06-19 22:13:45 -07007
Steve Kondik961b4cc2017-06-22 18:10:50 -07008#include <network/Socket.h>
9#include <network/TcpSocket.h>
10#include <rfb/Configuration.h>
11#include <rfb/Logger_android.h>
12#include <rfb/VNCServerST.h>
13#include <rfb/util.h>
Steve Kondik55db0532017-06-12 11:27:18 -070014
Steve Kondik961b4cc2017-06-22 18:10:50 -070015using namespace vncflinger;
Steve Kondik55db0532017-06-12 11:27:18 -070016
Steve Kondik961b4cc2017-06-22 18:10:50 -070017static char* gProgramName;
18static bool gCaughtSignal = false;
Steve Kondik5c8655c2017-06-19 00:28:47 -070019
Steve Kondik961b4cc2017-06-22 18:10:50 -070020static rfb::IntParameter rfbport("rfbport", "TCP port to listen for RFB protocol", 5900);
Steve Kondik46798992017-06-15 23:58:54 -070021
Steve Kondik961b4cc2017-06-22 18:10:50 -070022static void printVersion(FILE* fp) {
23 fprintf(fp, "VNCFlinger 1.0");
Steve Kondik5c8655c2017-06-19 00:28:47 -070024}
25
Steve Kondik961b4cc2017-06-22 18:10:50 -070026static void usage() {
27 printVersion(stderr);
28 fprintf(stderr, "\nUsage: %s [<parameters>]\n", gProgramName);
29 fprintf(stderr, " %s --version\n", gProgramName);
30 fprintf(stderr,
31 "\n"
32 "Parameters can be turned on with -<param> or off with -<param>=0\n"
33 "Parameters which take a value can be specified as "
34 "-<param> <value>\n"
35 "Other valid forms are <param>=<value> -<param>=<value> "
36 "--<param>=<value>\n"
37 "Parameter names are case-insensitive. The parameters are:\n\n");
38 rfb::Configuration::listParams(79, 14);
Steve Kondik5c8655c2017-06-19 00:28:47 -070039 exit(1);
40}
41
Steve Kondik2c9d0cf2017-06-15 23:39:29 -070042int main(int argc, char** argv) {
Steve Kondik961b4cc2017-06-22 18:10:50 -070043 rfb::initAndroidLogger();
44 rfb::LogWriter::setLogParams("*:android:30");
Steve Kondik46798992017-06-15 23:58:54 -070045
Steve Kondik961b4cc2017-06-22 18:10:50 -070046 gProgramName = argv[0];
Steve Kondik5c8655c2017-06-19 00:28:47 -070047
Steve Kondik961b4cc2017-06-22 18:10:50 -070048 rfb::Configuration::enableServerParams();
Steve Kondik5c8655c2017-06-19 00:28:47 -070049
Steve Kondik961b4cc2017-06-22 18:10:50 -070050 for (int i = 1; i < argc; i++) {
51 if (rfb::Configuration::setParam(argv[i])) continue;
Steve Kondik3db07472017-06-19 22:13:45 -070052
Steve Kondik961b4cc2017-06-22 18:10:50 -070053 if (argv[i][0] == '-') {
54 if (i + 1 < argc) {
55 if (rfb::Configuration::setParam(&argv[i][1], argv[i + 1])) {
56 i++;
57 continue;
58 }
59 }
60 if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "-version") == 0 ||
61 strcmp(argv[i], "--version") == 0) {
62 printVersion(stdout);
63 return 0;
64 }
65 usage();
66 }
67 usage();
68 }
69
70 std::list<network::TcpListener*> listeners;
71
72 try {
73 sp<AndroidDesktop> desktop = new AndroidDesktop();
74 rfb::VNCServerST server("vncflinger", desktop.get());
75 network::createTcpListeners(&listeners, 0, (int)rfbport);
76
77 int eventFd = desktop->getEventFd();
78 fcntl(eventFd, F_SETFL, O_NONBLOCK);
79
80 ALOGI("Listening on port %d", (int)rfbport);
81
82 while (!gCaughtSignal) {
83 int wait_ms;
84 struct timeval tv;
85 fd_set rfds, wfds;
86 std::list<network::Socket*> sockets;
87 std::list<network::Socket*>::iterator i;
88
89 FD_ZERO(&rfds);
90 FD_ZERO(&wfds);
91
92 FD_SET(eventFd, &rfds);
93 for (std::list<network::TcpListener*>::iterator i = listeners.begin();
94 i != listeners.end(); i++)
95 FD_SET((*i)->getFd(), &rfds);
96
97 server.getSockets(&sockets);
98 int clients_connected = 0;
99 for (i = sockets.begin(); i != sockets.end(); i++) {
100 if ((*i)->isShutdown()) {
101 server.removeSocket(*i);
102 delete (*i);
103 } else {
104 FD_SET((*i)->getFd(), &rfds);
105 if ((*i)->outStream().bufferUsage() > 0) FD_SET((*i)->getFd(), &wfds);
106 clients_connected++;
107 }
108 }
109
110 wait_ms = 0;
111
112 rfb::soonestTimeout(&wait_ms, server.checkTimeouts());
113
114 tv.tv_sec = wait_ms / 1000;
115 tv.tv_usec = (wait_ms % 1000) * 1000;
116
117 int n = select(FD_SETSIZE, &rfds, &wfds, 0, wait_ms ? &tv : NULL);
118
119 if (n < 0) {
120 if (errno == EINTR) {
121 ALOGV("Interrupted select() system call");
122 continue;
123 } else {
124 throw rdr::SystemException("select", errno);
125 }
126 }
127
128 // Accept new VNC connections
129 for (std::list<network::TcpListener*>::iterator i = listeners.begin();
130 i != listeners.end(); i++) {
131 if (FD_ISSET((*i)->getFd(), &rfds)) {
132 network::Socket* sock = (*i)->accept();
133 if (sock) {
134 sock->outStream().setBlocking(false);
135 server.addSocket(sock);
136 } else {
137 ALOGW("Client connection rejected");
138 }
139 }
140 }
141
142 server.checkTimeouts();
143
144 // Client list could have been changed.
145 server.getSockets(&sockets);
146
147 // Nothing more to do if there are no client connections.
148 if (sockets.empty()) continue;
149
150 // Process events on existing VNC connections
151 for (i = sockets.begin(); i != sockets.end(); i++) {
152 if (FD_ISSET((*i)->getFd(), &rfds)) server.processSocketReadEvent(*i);
153 if (FD_ISSET((*i)->getFd(), &wfds)) server.processSocketWriteEvent(*i);
154 }
155
156 // Process events from the display
157 uint64_t eventVal;
158 int status = read(eventFd, &eventVal, sizeof(eventVal));
159 if (status > 0 && eventVal > 0) {
160 desktop->processFrames();
161 }
162 }
163
164 } catch (rdr::Exception& e) {
165 ALOGE("%s", e.str());
166 return 1;
167 }
Steve Kondik55db0532017-06-12 11:27:18 -0700168}