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 29 RenderServer::RenderServer() : 30 m_listenSock(NULL), 31 m_exiting(false) 32 { 33 } 34 35 RenderServer::~RenderServer() 36 { 37 delete m_listenSock; 38 } 39 40 41 extern "C" int gRendererStreamMode; 42 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 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 stream = NULL; 110 } else if (!rt->start()) { 111 fprintf(stderr,"Failed to start RenderThread\n"); 112 delete rt; 113 rt = NULL; 114 } 115 116 // 117 // remove from the threads list threads which are 118 // no longer running 119 // 120 for (RenderThreadsSet::iterator n,t = threads.begin(); 121 t != threads.end(); 122 t = n) { 123 // first find next iterator 124 n = t; 125 n++; 126 127 // delete and erase the current iterator 128 // if thread is no longer running 129 if ((*t)->isFinished()) { 130 delete (*t); 131 threads.erase(t); 132 } 133 } 134 135 // if the thread has been created and started, insert it to the list 136 if (rt) { 137 threads.insert(rt); 138 DBG("Started new RenderThread\n"); 139 } 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