Home | History | Annotate | Download | only in cpp
      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(...) LOGD(__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 
     53 using communication::MsgHeader;
     54 
     55 class CtrlServerThread;
     56 static CtrlServerThread *g_ctrl_server;
     57 
     58 class 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             LOGE("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             LOGE("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             LOGE("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             LOGE("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                 LOGE("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             LOGE("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                         LOGD("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  */
    392 v8::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         LOGE("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 
    445 void 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         LOGE("mock_ril control server could not start");
    452     } else {
    453         LOGD("CtrlServer started");
    454     }
    455 
    456 #if 0
    457     LOGD("Test CtrlServerThread stop sleeping 10 seconds...");
    458     v8::Unlocker unlocker;
    459     sleep(10);
    460     LOGD("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         LOGE("mock_ril control server could not start");
    469     } else {
    470         DBG("mock_ril control server started");
    471     }
    472 #endif
    473 }
    474