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