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