blob: 3e9369707422e675c97f66dd1bfb01ebfccc7098 [file] [log] [blame]
David Li28ca2ab2011-03-01 16:08:10 -08001/*
2 ** Copyright 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
David Li55c94cc2011-03-04 17:50:48 -080017#include <sys/ioctl.h>
18#include <unistd.h>
19#include <sys/socket.h>
David Li28ca2ab2011-03-01 16:08:10 -080020#include <fcntl.h>
21#include <netinet/in.h>
22#include <arpa/inet.h>
23#include <pthread.h>
24
25#include "header.h"
26
27namespace android
28{
29
David Li28ca2ab2011-03-01 16:08:10 -080030int serverSock = -1, clientSock = -1;
David Li27f130a2011-04-08 18:43:16 -070031FILE * file = NULL;
32unsigned int MAX_FILE_SIZE = 0;
David Li55c94cc2011-03-04 17:50:48 -080033int timeMode = SYSTEM_TIME_THREAD;
34
David Li28ca2ab2011-03-01 16:08:10 -080035static void Die(const char * msg)
36{
Steve Block5baa3a62011-12-20 16:23:08 +000037 ALOGD("\n*\n*\n* GLESv2_dbg: Die: %s \n*\n*", msg);
David Li28ca2ab2011-03-01 16:08:10 -080038 StopDebugServer();
39 exit(1);
40}
41
David Li27f130a2011-04-08 18:43:16 -070042void StartDebugServer(const unsigned short port, const bool forceUseFile,
43 const unsigned int maxFileSize, const char * const filePath)
David Li28ca2ab2011-03-01 16:08:10 -080044{
David Li27f130a2011-04-08 18:43:16 -070045 MAX_FILE_SIZE = maxFileSize;
46
Steve Block5baa3a62011-12-20 16:23:08 +000047 ALOGD("GLESv2_dbg: StartDebugServer");
David Li27f130a2011-04-08 18:43:16 -070048 if (serverSock >= 0 || file)
David Li28ca2ab2011-03-01 16:08:10 -080049 return;
50
Steve Block5baa3a62011-12-20 16:23:08 +000051 ALOGD("GLESv2_dbg: StartDebugServer create socket");
David Li28ca2ab2011-03-01 16:08:10 -080052 struct sockaddr_in server = {}, client = {};
53
54 /* Create the TCP socket */
David Li27f130a2011-04-08 18:43:16 -070055 if (forceUseFile || (serverSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
56 file = fopen(filePath, "wb");
57 if (!file)
58 Die("Failed to create socket and file");
59 else
60 return;
David Li28ca2ab2011-03-01 16:08:10 -080061 }
62 /* Construct the server sockaddr_in structure */
63 server.sin_family = AF_INET; /* Internet/IP */
David Li940c3f82011-03-10 19:07:42 -080064 server.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* Incoming addr */
65 server.sin_port = htons(port); /* server port */
David Li28ca2ab2011-03-01 16:08:10 -080066
67 /* Bind the server socket */
68 socklen_t sizeofSockaddr_in = sizeof(sockaddr_in);
69 if (bind(serverSock, (struct sockaddr *) &server,
70 sizeof(server)) < 0) {
71 Die("Failed to bind the server socket");
72 }
73 /* Listen on the server socket */
74 if (listen(serverSock, 1) < 0) {
75 Die("Failed to listen on server socket");
76 }
77
Steve Block5baa3a62011-12-20 16:23:08 +000078 ALOGD("server started on %d \n", server.sin_port);
David Li28ca2ab2011-03-01 16:08:10 -080079
80
81 /* Wait for client connection */
82 if ((clientSock =
83 accept(serverSock, (struct sockaddr *) &client,
84 &sizeofSockaddr_in)) < 0) {
85 Die("Failed to accept client connection");
86 }
87
Steve Block5baa3a62011-12-20 16:23:08 +000088 ALOGD("Client connected: %s\n", inet_ntoa(client.sin_addr));
David Li28ca2ab2011-03-01 16:08:10 -080089// fcntl(clientSock, F_SETFL, O_NONBLOCK);
David Li28ca2ab2011-03-01 16:08:10 -080090}
91
92void StopDebugServer()
93{
Steve Block5baa3a62011-12-20 16:23:08 +000094 ALOGD("GLESv2_dbg: StopDebugServer");
David Li28ca2ab2011-03-01 16:08:10 -080095 if (clientSock > 0) {
96 close(clientSock);
97 clientSock = -1;
98 }
99 if (serverSock > 0) {
100 close(serverSock);
101 serverSock = -1;
102 }
David Li27f130a2011-04-08 18:43:16 -0700103 if (file) {
104 fclose(file);
105 file = NULL;
106 }
David Li28ca2ab2011-03-01 16:08:10 -0800107}
108
David Li55c94cc2011-03-04 17:50:48 -0800109void Receive(glesv2debugger::Message & cmd)
David Li28ca2ab2011-03-01 16:08:10 -0800110{
David Li27f130a2011-04-08 18:43:16 -0700111 if (clientSock < 0)
112 return;
David Li55c94cc2011-03-04 17:50:48 -0800113 unsigned len = 0;
David Li55c94cc2011-03-04 17:50:48 -0800114 int received = recv(clientSock, &len, 4, MSG_WAITALL);
David Li28ca2ab2011-03-01 16:08:10 -0800115 if (received < 0)
David Li55c94cc2011-03-04 17:50:48 -0800116 Die("Failed to receive response length");
David Li28ca2ab2011-03-01 16:08:10 -0800117 else if (4 != received) {
Steve Block5baa3a62011-12-20 16:23:08 +0000118 ALOGD("received %dB: %.8X", received, len);
David Li28ca2ab2011-03-01 16:08:10 -0800119 Die("Received length mismatch, expected 4");
120 }
David Li28ca2ab2011-03-01 16:08:10 -0800121 static void * buffer = NULL;
122 static unsigned bufferSize = 0;
123 if (bufferSize < len) {
124 buffer = realloc(buffer, len);
David Li5c425f22011-03-10 16:40:37 -0800125 assert(buffer);
David Li28ca2ab2011-03-01 16:08:10 -0800126 bufferSize = len;
127 }
128 received = recv(clientSock, buffer, len, MSG_WAITALL);
129 if (received < 0)
130 Die("Failed to receive response");
131 else if (len != received)
132 Die("Received length mismatch");
133 cmd.Clear();
134 cmd.ParseFromArray(buffer, len);
David Li55c94cc2011-03-04 17:50:48 -0800135}
136
David Li940c3f82011-03-10 19:07:42 -0800137bool TryReceive(glesv2debugger::Message & cmd)
138{
David Li27f130a2011-04-08 18:43:16 -0700139 if (clientSock < 0)
140 return false;
David Li940c3f82011-03-10 19:07:42 -0800141 fd_set readSet;
142 FD_ZERO(&readSet);
143 FD_SET(clientSock, &readSet);
144 timeval timeout;
145 timeout.tv_sec = timeout.tv_usec = 0;
146
147 int rc = select(clientSock + 1, &readSet, NULL, NULL, &timeout);
148 if (rc < 0)
149 Die("failed to select clientSock");
150
151 bool received = false;
152 if (FD_ISSET(clientSock, &readSet)) {
Steve Block5baa3a62011-12-20 16:23:08 +0000153 ALOGD("TryReceive: avaiable for read");
David Li940c3f82011-03-10 19:07:42 -0800154 Receive(cmd);
155 return true;
156 }
157 return false;
158}
159
David Li55c94cc2011-03-04 17:50:48 -0800160float Send(const glesv2debugger::Message & msg, glesv2debugger::Message & cmd)
161{
David Li31918cc2011-04-15 15:35:10 -0700162 // TODO: use per DbgContext send/receive buffer and async socket
163 // instead of mutex and blocking io; watch out for large messages
David Li55c94cc2011-03-04 17:50:48 -0800164 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
David Li31918cc2011-04-15 15:35:10 -0700165 struct Autolock {
166 Autolock() {
167 pthread_mutex_lock(&mutex);
168 }
169 ~Autolock() {
170 pthread_mutex_unlock(&mutex);
171 }
172 } autolock;
David Li55c94cc2011-03-04 17:50:48 -0800173
David Li5c425f22011-03-10 16:40:37 -0800174 if (msg.function() != glesv2debugger::Message_Function_ACK)
175 assert(msg.has_context_id() && msg.context_id() != 0);
David Li55c94cc2011-03-04 17:50:48 -0800176 static std::string str;
David Li55c94cc2011-03-04 17:50:48 -0800177 msg.SerializeToString(&str);
David Li27f130a2011-04-08 18:43:16 -0700178 const uint32_t len = str.length();
179 if (clientSock < 0) {
180 if (file) {
181 fwrite(&len, sizeof(len), 1, file);
182 fwrite(str.data(), len, 1, file);
183 if (ftell(file) >= MAX_FILE_SIZE) {
184 fclose(file);
185 Die("MAX_FILE_SIZE reached");
186 }
187 }
David Li27f130a2011-04-08 18:43:16 -0700188 return 0;
189 }
David Li55c94cc2011-03-04 17:50:48 -0800190 int sent = -1;
David Lif9bc1242011-03-22 18:42:03 -0700191 sent = send(clientSock, &len, sizeof(len), 0);
David Li55c94cc2011-03-04 17:50:48 -0800192 if (sent != sizeof(len)) {
Steve Block5baa3a62011-12-20 16:23:08 +0000193 ALOGD("actual sent=%d expected=%d clientSock=%d", sent, sizeof(len), clientSock);
David Li55c94cc2011-03-04 17:50:48 -0800194 Die("Failed to send message length");
195 }
196 nsecs_t c0 = systemTime(timeMode);
David Lie9f619f2011-04-14 11:20:22 -0700197 sent = send(clientSock, str.data(), str.length(), 0);
David Li55c94cc2011-03-04 17:50:48 -0800198 float t = (float)ns2ms(systemTime(timeMode) - c0);
199 if (sent != str.length()) {
Steve Block5baa3a62011-12-20 16:23:08 +0000200 ALOGD("actual sent=%d expected=%d clientSock=%d", sent, str.length(), clientSock);
David Li55c94cc2011-03-04 17:50:48 -0800201 Die("Failed to send message");
202 }
David Li31918cc2011-04-15 15:35:10 -0700203 // TODO: factor Receive & TryReceive out and into MessageLoop, or add control argument.
204 // mean while, if server is sending a SETPROP then don't try to receive,
205 // because server will not be processing received command
206 if (msg.function() == msg.SETPROP)
207 return t;
David Li940c3f82011-03-10 19:07:42 -0800208 // try to receive commands even though not expecting response,
David Lie2ad4d02011-04-08 18:41:00 -0700209 // since client can send SETPROP and other commands anytime
David Li55c94cc2011-03-04 17:50:48 -0800210 if (!msg.expect_response()) {
David Li940c3f82011-03-10 19:07:42 -0800211 if (TryReceive(cmd)) {
David Li940c3f82011-03-10 19:07:42 -0800212 if (glesv2debugger::Message_Function_SETPROP == cmd.function())
Steve Block5baa3a62011-12-20 16:23:08 +0000213 ALOGD("Send: TryReceived SETPROP");
David Li940c3f82011-03-10 19:07:42 -0800214 else
Steve Block5baa3a62011-12-20 16:23:08 +0000215 ALOGD("Send: TryReceived %u", cmd.function());
David Li940c3f82011-03-10 19:07:42 -0800216 }
217 } else
218 Receive(cmd);
David Li55c94cc2011-03-04 17:50:48 -0800219 return t;
David Li28ca2ab2011-03-01 16:08:10 -0800220}
221
David Lifbfc7032011-03-21 16:25:58 -0700222void SetProp(DbgContext * const dbg, const glesv2debugger::Message & cmd)
David Li55c94cc2011-03-04 17:50:48 -0800223{
224 switch (cmd.prop()) {
David Lie7180e82011-04-08 18:45:45 -0700225 case glesv2debugger::Message_Prop_CaptureDraw:
Steve Block5baa3a62011-12-20 16:23:08 +0000226 ALOGD("SetProp Message_Prop_CaptureDraw %d", cmd.arg0());
David Lie7180e82011-04-08 18:45:45 -0700227 dbg->captureDraw = cmd.arg0();
David Li55c94cc2011-03-04 17:50:48 -0800228 break;
229 case glesv2debugger::Message_Prop_TimeMode:
Steve Block5baa3a62011-12-20 16:23:08 +0000230 ALOGD("SetProp Message_Prop_TimeMode %d", cmd.arg0());
David Li55c94cc2011-03-04 17:50:48 -0800231 timeMode = cmd.arg0();
232 break;
David Lifbfc7032011-03-21 16:25:58 -0700233 case glesv2debugger::Message_Prop_ExpectResponse:
Steve Block5baa3a62011-12-20 16:23:08 +0000234 ALOGD("SetProp Message_Prop_ExpectResponse %d=%d", cmd.arg0(), cmd.arg1());
David Lifbfc7032011-03-21 16:25:58 -0700235 dbg->expectResponse.Bit((glesv2debugger::Message_Function)cmd.arg0(), cmd.arg1());
236 break;
David Lie7180e82011-04-08 18:45:45 -0700237 case glesv2debugger::Message_Prop_CaptureSwap:
Steve Block5baa3a62011-12-20 16:23:08 +0000238 ALOGD("SetProp CaptureSwap %d", cmd.arg0());
David Lie7180e82011-04-08 18:45:45 -0700239 dbg->captureSwap = cmd.arg0();
240 break;
David Li55c94cc2011-03-04 17:50:48 -0800241 default:
242 assert(0);
243 }
244}
245
246int * MessageLoop(FunctionCall & functionCall, glesv2debugger::Message & msg,
David Lifbfc7032011-03-21 16:25:58 -0700247 const glesv2debugger::Message_Function function)
David Li55c94cc2011-03-04 17:50:48 -0800248{
David Li5c425f22011-03-10 16:40:37 -0800249 DbgContext * const dbg = getDbgContextThreadSpecific();
David Li55c94cc2011-03-04 17:50:48 -0800250 const int * ret = 0;
251 glesv2debugger::Message cmd;
David Li5c425f22011-03-10 16:40:37 -0800252 msg.set_context_id(reinterpret_cast<int>(dbg));
David Li55c94cc2011-03-04 17:50:48 -0800253 msg.set_type(glesv2debugger::Message_Type_BeforeCall);
David Lie2ad4d02011-04-08 18:41:00 -0700254 bool expectResponse = dbg->expectResponse.Bit(function);
David Li55c94cc2011-03-04 17:50:48 -0800255 msg.set_expect_response(expectResponse);
256 msg.set_function(function);
David Lie2ad4d02011-04-08 18:41:00 -0700257
258 // when not exectResponse, set cmd to CONTINUE then SKIP
David Lie9f619f2011-04-14 11:20:22 -0700259 // cmd will be overwritten by received command
David Lie2ad4d02011-04-08 18:41:00 -0700260 cmd.set_function(glesv2debugger::Message_Function_CONTINUE);
David Lie9f619f2011-04-14 11:20:22 -0700261 cmd.set_expect_response(expectResponse);
David Lie2ad4d02011-04-08 18:41:00 -0700262 glesv2debugger::Message_Function oldCmd = cmd.function();
David Li940c3f82011-03-10 19:07:42 -0800263 Send(msg, cmd);
David Lie2ad4d02011-04-08 18:41:00 -0700264 expectResponse = cmd.expect_response();
David Li55c94cc2011-03-04 17:50:48 -0800265 while (true) {
266 msg.Clear();
267 nsecs_t c0 = systemTime(timeMode);
268 switch (cmd.function()) {
269 case glesv2debugger::Message_Function_CONTINUE:
David Li5c425f22011-03-10 16:40:37 -0800270 ret = functionCall(&dbg->hooks->gl, msg);
David Li940c3f82011-03-10 19:07:42 -0800271 while (GLenum error = dbg->hooks->gl.glGetError())
Steve Block5baa3a62011-12-20 16:23:08 +0000272 ALOGD("Function=%u glGetError() = 0x%.4X", function, error);
David Li55c94cc2011-03-04 17:50:48 -0800273 if (!msg.has_time()) // some has output data copy, so time inside call
274 msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
David Li5c425f22011-03-10 16:40:37 -0800275 msg.set_context_id(reinterpret_cast<int>(dbg));
David Li55c94cc2011-03-04 17:50:48 -0800276 msg.set_function(function);
277 msg.set_type(glesv2debugger::Message_Type_AfterCall);
278 msg.set_expect_response(expectResponse);
David Lie2ad4d02011-04-08 18:41:00 -0700279 if (!expectResponse) {
David Li55c94cc2011-03-04 17:50:48 -0800280 cmd.set_function(glesv2debugger::Message_Function_SKIP);
David Lie2ad4d02011-04-08 18:41:00 -0700281 cmd.set_expect_response(false);
282 }
283 oldCmd = cmd.function();
David Li940c3f82011-03-10 19:07:42 -0800284 Send(msg, cmd);
David Lie2ad4d02011-04-08 18:41:00 -0700285 expectResponse = cmd.expect_response();
David Li55c94cc2011-03-04 17:50:48 -0800286 break;
287 case glesv2debugger::Message_Function_SKIP:
288 return const_cast<int *>(ret);
289 case glesv2debugger::Message_Function_SETPROP:
David Lifbfc7032011-03-21 16:25:58 -0700290 SetProp(dbg, cmd);
David Lie2ad4d02011-04-08 18:41:00 -0700291 expectResponse = cmd.expect_response();
292 if (!expectResponse) // SETPROP is "out of band"
293 cmd.set_function(oldCmd);
294 else
295 Receive(cmd);
David Li55c94cc2011-03-04 17:50:48 -0800296 break;
297 default:
David Li291f5fe2011-03-21 17:42:50 -0700298 ret = GenerateCall(dbg, cmd, msg, ret);
299 msg.set_expect_response(expectResponse);
David Lie2ad4d02011-04-08 18:41:00 -0700300 if (!expectResponse) {
David Li291f5fe2011-03-21 17:42:50 -0700301 cmd.set_function(cmd.SKIP);
David Lie2ad4d02011-04-08 18:41:00 -0700302 cmd.set_expect_response(expectResponse);
303 }
304 oldCmd = cmd.function();
David Li291f5fe2011-03-21 17:42:50 -0700305 Send(msg, cmd);
David Lie2ad4d02011-04-08 18:41:00 -0700306 expectResponse = cmd.expect_response();
David Li55c94cc2011-03-04 17:50:48 -0800307 break;
308 }
309 }
310 return 0;
311}
David Li28ca2ab2011-03-01 16:08:10 -0800312}; // namespace android {