1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "RenderServer.h"
17 #include "TcpStream.h"
18 #ifdef _WIN32
19 #include "Win32PipeStream.h"
20 #else
21 #include "UnixStream.h"
22 #endif
23 #include "RenderThread.h"
24 #include "FrameBuffer.h"
25 #include <set>
26
27 typedef std::set<RenderThread *> RenderThreadsSet;
28
RenderServer()29 RenderServer::RenderServer() :
30 m_listenSock(NULL),
31 m_exiting(false)
32 {
33 }
34
~RenderServer()35 RenderServer::~RenderServer()
36 {
37 delete m_listenSock;
38 }
39
40
41 extern "C" int gRendererStreamMode;
42
create(char * addr,size_t addrLen)43 RenderServer *RenderServer::create(char* addr, size_t addrLen)
44 {
45 RenderServer *server = new RenderServer();
46 if (!server) {
47 return NULL;
48 }
49
50 if (gRendererStreamMode == STREAM_MODE_TCP) {
51 server->m_listenSock = new TcpStream();
52 } else {
53 #ifdef _WIN32
54 server->m_listenSock = new Win32PipeStream();
55 #else
56 server->m_listenSock = new UnixStream();
57 #endif
58 }
59
60 char addrstr[SocketStream::MAX_ADDRSTR_LEN];
61 if (server->m_listenSock->listen(addrstr) < 0) {
62 ERR("RenderServer::create failed to listen\n");
63 delete server;
64 return NULL;
65 }
66
67 size_t len = strlen(addrstr) + 1;
68 if (len > addrLen) {
69 ERR("RenderServer address name too big for provided buffer: %zu > %zu\n",
70 len, addrLen);
71 delete server;
72 return NULL;
73 }
74 memcpy(addr, addrstr, len);
75
76 return server;
77 }
78
Main()79 int RenderServer::Main()
80 {
81 RenderThreadsSet threads;
82
83 while(1) {
84 SocketStream *stream = m_listenSock->accept();
85 if (!stream) {
86 fprintf(stderr,"Error accepting connection, aborting\n");
87 break;
88 }
89
90 unsigned int clientFlags;
91 if (!stream->readFully(&clientFlags, sizeof(unsigned int))) {
92 fprintf(stderr,"Error reading clientFlags\n");
93 delete stream;
94 continue;
95 }
96
97 DBG("RenderServer: Got new stream!\n");
98
99 // check if we have been requested to exit while waiting on accept
100 if ((clientFlags & IOSTREAM_CLIENT_EXIT_SERVER) != 0) {
101 m_exiting = true;
102 break;
103 }
104
105 RenderThread *rt = RenderThread::create(stream);
106 if (!rt) {
107 fprintf(stderr,"Failed to create RenderThread\n");
108 delete stream;
109 }
110
111 if (!rt->start()) {
112 fprintf(stderr,"Failed to start RenderThread\n");
113 delete stream;
114 delete rt;
115 }
116
117 //
118 // remove from the threads list threads which are
119 // no longer running
120 //
121 for (RenderThreadsSet::iterator n,t = threads.begin();
122 t != threads.end();
123 t = n) {
124 // first find next iterator
125 n = t;
126 n++;
127
128 // delete and erase the current iterator
129 // if thread is no longer running
130 if ((*t)->isFinished()) {
131 delete (*t);
132 threads.erase(t);
133 }
134 }
135
136 // insert the added thread to the list
137 threads.insert(rt);
138
139 DBG("Started new RenderThread\n");
140 }
141
142 //
143 // Wait for all threads to finish
144 //
145 for (RenderThreadsSet::iterator t = threads.begin();
146 t != threads.end();
147 t++) {
148 int exitStatus;
149 (*t)->wait(&exitStatus);
150 delete (*t);
151 }
152 threads.clear();
153
154 //
155 // de-initialize the FrameBuffer object
156 //
157 FrameBuffer::finalize();
158 return 0;
159 }
160