1/** 2 * Copyright (C) 2010 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 17#include <alloca.h> 18#include <pthread.h> 19#include <stdio.h> 20#include <string.h> 21#include <sys/endian.h> 22#include <sys/types.h> 23#include <sys/socket.h> 24#include <unistd.h> 25 26#include <cutils/sockets.h> 27 28#include "logging.h" 29#include "node_buffer.h" 30#include "status.h" 31#include "util.h" 32#include "worker.h" 33 34#include "hardware/ril/mock-ril/src/proto/msgheader.pb.h" 35 36#include "hardware/ril/mock-ril/src/proto/ctrl.pb.h" 37#include "ctrl_server.h" 38 39//#define CONTROL_SERVER_DEBUG 40#ifdef CONTROL_SERVER_DEBUG 41 42#define DBG(...) ALOGD(__VA_ARGS__) 43 44#else 45 46#define DBG(...) 47 48#endif 49 50#define MOCK_RIL_CONTROL_SERVER_STOPPING_SOCKET 54311 51#define MOCK_RIL_CONTROL_SERVER_SOCKET 54312 52 53using communication::MsgHeader; 54 55class CtrlServerThread; 56static CtrlServerThread *g_ctrl_server; 57 58class CtrlServerThread : public WorkerThread { 59 private: 60 #define SOCKET_NAME_MOCK_RIL_CST_STOPPER "mock-ril-cst-stopper" 61 v8::Handle<v8::Context> context_; 62 int server_accept_socket_; 63 int server_to_client_socket_; 64 int stop_server_fd_; 65 int stop_client_fd_; 66 int stopper_fd_; 67 fd_set rd_fds_; 68 fd_set wr_fds_; 69 bool done_; 70 71 Buffer *ObtainBuffer(int length) { 72 Buffer *b = Buffer::New(length); 73 return b; 74 } 75 76 int WriteAll(int s, void *data, int length) { 77 int ret_value; 78 uint8_t *bytes = (uint8_t *)data; 79 int count = length; 80 81 while (length > 0) { 82 ret_value = send(s, bytes, length, 0); 83 if (ret_value < 0) { 84 return STATUS_ERR; 85 } 86 if (ret_value == 0) { 87 return STATUS_CLIENT_CLOSED_CONNECTION; 88 } 89 bytes += ret_value; 90 length -= ret_value; 91 } 92 93 return STATUS_OK; 94 } 95 96 int ReadAll(int s, void *data, int length) { 97 int ret_value; 98 uint8_t *bytes = (uint8_t *)data; 99 int count = length; 100 101 while (length != 0) { 102 ret_value = recv(s, bytes, length, 0); 103 if (ret_value < 0) { 104 return STATUS_ERR; 105 } 106 if (ret_value == 0) { 107 return STATUS_CLIENT_CLOSED_CONNECTION; 108 } 109 bytes += ret_value; 110 length -= ret_value; 111 } 112 113 return STATUS_OK; 114 } 115 116 int ReadMessage(MsgHeader *mh, Buffer **pBuffer) { 117 int status; 118 int32_t len_msg_header; 119 120 // Reader header length 121 status = ReadAll(server_to_client_socket_, &len_msg_header, sizeof(len_msg_header)); 122 len_msg_header = letoh32(len_msg_header); 123 DBG("rm: read len_msg_header=%d status=%d", len_msg_header, status); 124 if (status != STATUS_OK) return status; 125 126 // Read header into an array allocated on the stack and unmarshall 127 uint8_t *msg_header_raw = (uint8_t *)alloca(len_msg_header); 128 status = ReadAll(server_to_client_socket_, msg_header_raw, len_msg_header); 129 DBG("rm: read msg_header_raw=%p status=%d", msg_header_raw, status); 130 if (status != STATUS_OK) return status; 131 mh->ParseFromArray(msg_header_raw, len_msg_header); 132 133 // Read auxillary data 134 Buffer *buffer; 135 if (mh->length_data() > 0) { 136 buffer = ObtainBuffer(mh->length_data()); 137 status = ReadAll(server_to_client_socket_, buffer->data(), buffer->length()); 138 DBG("rm: read protobuf status=%d", status); 139 if (status != STATUS_OK) return status; 140 } else { 141 DBG("rm: NO protobuf"); 142 buffer = NULL; 143 } 144 145 *pBuffer = buffer; 146 return STATUS_OK; 147 } 148 149 public: 150 int WriteMessage(MsgHeader *mh, Buffer *buffer) { 151 int status; 152 uint32_t i; 153 uint64_t l; 154 155 // Set length of data 156 if (buffer == NULL) { 157 mh->set_length_data(0); 158 } else { 159 mh->set_length_data(buffer->length()); 160 } 161 162 // Serialize header 163 uint32_t len_msg_header = mh->ByteSize(); 164 uint8_t *msg_header_raw = (uint8_t *)alloca(len_msg_header); 165 mh->SerializeToArray(msg_header_raw, len_msg_header); 166 167 // Write length in little endian followed by the header 168 i = htole32(len_msg_header); 169 status = WriteAll(server_to_client_socket_, &i, 4); 170 DBG("wm: write len_msg_header=%d status=%d", len_msg_header, status); 171 if (status != 0) return status; 172 status = WriteAll(server_to_client_socket_, msg_header_raw, len_msg_header); 173 DBG("wm: write msg_header_raw=%p status=%d", msg_header_raw, status); 174 if (status != 0) return status; 175 176 // Write data 177 if (mh->length_data() > 0) { 178 status = WriteAll(server_to_client_socket_, buffer->data(), buffer->length()); 179 DBG("wm: protobuf data=%p len=%d status=%d", 180 buffer->data(), buffer->length(), status); 181 if (status != 0) return status; 182 } 183 184 return STATUS_OK; 185 } 186 187 CtrlServerThread(v8::Handle<v8::Context> context) : 188 context_(context), 189 server_accept_socket_(-1), 190 server_to_client_socket_(-1), 191 done_(false) { 192 } 193 194 virtual int Run() { 195 DBG("CtrlServerThread::Run E"); 196 197 // Create a server socket. 198 server_accept_socket_ = socket_inaddr_any_server( 199 MOCK_RIL_CONTROL_SERVER_SOCKET, SOCK_STREAM); 200 if (server_accept_socket_ < 0) { 201 ALOGE("CtrlServerThread::Run error creating server_accept_socket_ '%s'", 202 strerror(errno)); 203 return STATUS_ERR; 204 } 205 206 // Create a server socket that will be used for stopping 207 stop_server_fd_ = socket_loopback_server( 208 MOCK_RIL_CONTROL_SERVER_STOPPING_SOCKET, SOCK_STREAM); 209 if (stop_server_fd_ < 0) { 210 ALOGE("CtrlServerThread::Run error creating stop_server_fd_ '%s'", 211 strerror(errno)); 212 return STATUS_ERR; 213 } 214 215 // Create a client socket that will be used for sending a stop 216 stop_client_fd_ = socket_loopback_client( 217 MOCK_RIL_CONTROL_SERVER_STOPPING_SOCKET, SOCK_STREAM); 218 if (stop_client_fd_ < 0) { 219 ALOGE("CtrlServerThread::Run error creating stop_client_fd_ '%s'", 220 strerror(errno)); 221 return STATUS_ERR; 222 } 223 224 // Accept the connection of the stop_client_fd_ 225 stopper_fd_ = accept(stop_server_fd_, NULL, NULL); 226 if (stopper_fd_ < 0) { 227 ALOGE("CtrlServerThread::Run error accepting stop_client_fd '%s'", 228 strerror(errno)); 229 return STATUS_ERR; 230 } 231 232 // Run the new thread 233 int ret_value = WorkerThread::Run(NULL); 234 DBG("CtrlServerThread::Run X"); 235 return ret_value; 236 } 237 238 virtual void Stop() { 239 DBG("CtrlServerThread::Stop E"); 240 if (BeginStopping()) { 241 done_ = true; 242 int rv = send(stop_client_fd_, &done_, sizeof(done_), 0); 243 if (rv <= 0) { 244 ALOGE("CtrlServerThread::Stop could not send stop" 245 "WE WILL PROBABLY HANG"); 246 } 247 WaitUntilStopped(); 248 } 249 DBG("CtrlServerThread::Stop X"); 250 } 251 252 virtual bool isRunning() { 253 bool rv = done_ || WorkerThread::isRunning(); 254 return rv; 255 } 256 257 int WaitOnSocketOrStopping(fd_set *rfds, int s) { 258 DBG("WaitOnSocketOrStopping E s=%d stopper_fd_=%d", s, stopper_fd_); 259 FD_ZERO(rfds); 260 FD_SET(s, rfds); 261 FD_SET(stopper_fd_, rfds); 262 int fd_number = s > stopper_fd_ ? s + 1 : stopper_fd_ + 1; 263 v8::Unlocker unlocker; 264 int rv = select(fd_number, rfds, NULL, NULL, NULL); 265 v8::Locker locker; 266 DBG("WaitOnSocketOrStopping X rv=%d s=%d stopper_fd_=%d", rv, s, stopper_fd_); 267 return rv; 268 } 269 270 int sendToCtrlServer(MsgHeader *mh, Buffer *buffer) { 271 DBG("sendToCtrlServer E: cmd=%d token=%lld", mh->cmd(), mh->token()); 272 273 int status = STATUS_OK; 274 v8::HandleScope handle_scope; 275 v8::TryCatch try_catch; 276 try_catch.SetVerbose(true); 277 278 // Get the onRilRequest Function 279 v8::Handle<v8::String> name = v8::String::New("onCtrlServerCmd"); 280 v8::Handle<v8::Value> onCtrlServerCmdFunctionValue = 281 context_->Global()->Get(name); 282 v8::Handle<v8::Function> onCtrlServerCmdFunction = 283 v8::Handle<v8::Function>::Cast(onCtrlServerCmdFunctionValue); 284 285 // Create the CmdValue and TokenValue 286 v8::Handle<v8::Value> v8CmdValue = v8::Number::New(mh->cmd()); 287 v8::Handle<v8::Value> v8TokenValue = v8::Number::New(mh->token()); 288 289 // Invoke onRilRequest 290 const int argc = 3; 291 v8::Handle<v8::Value> buf; 292 if (mh->length_data() == 0) { 293 buf = v8::Undefined(); 294 } else { 295 buf = buffer->handle_; 296 } 297 v8::Handle<v8::Value> argv[argc] = { 298 v8CmdValue, v8TokenValue, buf }; 299 v8::Handle<v8::Value> result = 300 onCtrlServerCmdFunction->Call(context_->Global(), argc, argv); 301 if (try_catch.HasCaught()) { 302 ReportException(&try_catch); 303 status = STATUS_ERR; 304 } else { 305 v8::String::Utf8Value result_string(result); 306 DBG("sendToCtrlServer result=%s", ToCString(result_string)); 307 status = STATUS_OK; 308 } 309 310 if (status != STATUS_OK) { 311 ALOGE("sendToCtrlServer Error: status=%d", status); 312 // An error report complete now 313 mh->set_length_data(0); 314 mh->set_status(ril_proto::CTRL_STATUS_ERR); 315 g_ctrl_server->WriteMessage(mh, NULL); 316 } 317 318 DBG("sendToCtrlServer X: status=%d", status); 319 return status; 320 } 321 322 virtual void * Worker(void *param) { 323 DBG("CtrlServerThread::Worker E param=%p stopper_fd_=%d", 324 param, stopper_fd_); 325 326 v8::Locker locker; 327 v8::HandleScope handle_scope; 328 v8::Context::Scope context_scope(context_); 329 330 while (isRunning()) { 331 int ret_value; 332 333 // Wait on either server_accept_socket_ or stopping 334 DBG("CtrlServerThread::Worker wait on server for a client"); 335 WaitOnSocketOrStopping(&rd_fds_, server_accept_socket_); 336 if (isRunning() != true) { 337 break; 338 } 339 340 if (FD_ISSET(server_accept_socket_, &rd_fds_)) { 341 server_to_client_socket_ = accept(server_accept_socket_, NULL, NULL); 342 DBG("CtrlServerThread::Worker accepted server_to_client_socket_=%d isRunning()=%d", 343 server_to_client_socket_, isRunning()); 344 345 int status; 346 Buffer *buffer; 347 MsgHeader mh; 348 while ((server_to_client_socket_ > 0) && isRunning()) { 349 DBG("CtrlServerThread::Worker wait on client for message"); 350 WaitOnSocketOrStopping(&rd_fds_, server_to_client_socket_); 351 if (isRunning() != true) { 352 break; 353 } 354 355 status = ReadMessage(&mh, &buffer); 356 if (status != STATUS_OK) break; 357 358 if (mh.cmd() == ril_proto::CTRL_CMD_ECHO) { 359 ALOGD("CtrlServerThread::Worker echo"); 360 status = WriteMessage(&mh, buffer); 361 if (status != STATUS_OK) break; 362 } else { 363 DBG("CtrlServerThread::Worker sendToCtrlServer"); 364 status = sendToCtrlServer(&mh, buffer); 365 if (status != STATUS_OK) break; 366 } 367 } 368 close(server_to_client_socket_); 369 server_to_client_socket_ = -1; 370 } 371 } 372 close(stop_server_fd_); 373 stop_server_fd_ = -1; 374 375 close(stop_client_fd_); 376 stop_client_fd_ = -1; 377 378 close(stopper_fd_); 379 stopper_fd_ = -1; 380 381 close(server_accept_socket_); 382 server_accept_socket_ = -1; 383 384 DBG("CtrlServerThread::Worker X param=%p", param); 385 return NULL; 386 } 387}; 388 389/** 390 * Send a control request complete response. 391 */ 392v8::Handle<v8::Value> SendCtrlRequestComplete(const v8::Arguments& args) { 393 DBG("SendCtrlRequestComplete E:"); 394 v8::HandleScope handle_scope; 395 v8::Handle<v8::Value> retValue; 396 397 void *data; 398 size_t datalen; 399 400 Buffer* buffer; 401 MsgHeader mh; 402 403 /** 404 * Get the arguments. There should be at least 3, reqNum, 405 * ril error code and token. Optionally a Buffer containing 406 * the protobuf representation of the data to return. 407 */ 408 if (args.Length() < 3) { 409 // Expecting a reqNum, ERROR and token 410 ALOGE("SendCtrlRequestComplete X %d parameters" 411 " expecting at least 3: status, reqNum, and token", 412 args.Length()); 413 return v8::Undefined(); 414 } 415 v8::Handle<v8::Value> v8CtrlStatus(args[0]->ToObject()); 416 mh.set_status(ril_proto::CtrlStatus(v8CtrlStatus->NumberValue())); 417 DBG("SendCtrlRequestComplete: status=%d", mh.status()); 418 419 v8::Handle<v8::Value> v8ReqNum(args[1]->ToObject()); 420 mh.set_cmd(int(v8ReqNum->NumberValue())); 421 DBG("SendCtrlRequestComplete: cmd=%d", mh.cmd()); 422 423 v8::Handle<v8::Value> v8Token(args[2]->ToObject()); 424 mh.set_token(int64_t(v8Token->NumberValue())); 425 DBG("SendCtrlRequestComplete: token=%lld", mh.token()); 426 427 if (args.Length() >= 4) { 428 buffer = ObjectWrap::Unwrap<Buffer>(args[3]->ToObject()); 429 mh.set_length_data(buffer->length()); 430 DBG("SendCtrlRequestComplete: mh.length_data=%d", 431 mh.length_data()); 432 } else { 433 mh.set_length_data(0); 434 buffer = NULL; 435 DBG("SendCtrlRequestComplete: NO PROTOBUF"); 436 } 437 438 DBG("SendCtrlRequestComplete: WriteMessage"); 439 int status = g_ctrl_server->WriteMessage(&mh, buffer); 440 441 DBG("SendCtrlRequestComplete E:"); 442 return v8::Undefined(); 443} 444 445void ctrlServerInit(v8::Handle<v8::Context> context) { 446 int status; 447 448 g_ctrl_server = new CtrlServerThread(context); 449 status = g_ctrl_server->Run(); 450 if (status != STATUS_OK) { 451 ALOGE("mock_ril control server could not start"); 452 } else { 453 ALOGD("CtrlServer started"); 454 } 455 456#if 0 457 ALOGD("Test CtrlServerThread stop sleeping 10 seconds..."); 458 v8::Unlocker unlocker; 459 sleep(10); 460 ALOGD("Test CtrlServerThread call Stop"); 461 g_ctrl_server->Stop(); 462 v8::Locker locker; 463 464 // Restart 465 g_ctrl_server = new CtrlServerThread(context); 466 status = g_ctrl_server->Run(); 467 if (status != STATUS_OK) { 468 ALOGE("mock_ril control server could not start"); 469 } else { 470 DBG("mock_ril control server started"); 471 } 472#endif 473} 474