/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ extern "C" void *ril_socket_process_requests_loop(void *arg); #include "RilSocket.h" #include #include #include #define SOCKET_LISTEN_BACKLOG 0 int RilSocket::socketInit(void) { int ret; listenCb = &RilSocket::sSocketListener; commandCb = &RilSocket::sSocketRequestsHandler; listenFd = android_get_control_socket(name); //Start listening ret = listen(listenFd, SOCKET_LISTEN_BACKLOG); if (ret < 0) { RLOGE("Failed to listen on %s socket '%d': %s", name, listenFd, strerror(errno)); return ret; } //Add listen event to the event loop ril_event_set(&listenEvent, listenFd, false, listenCb, this); rilEventAddWakeup_helper(&listenEvent); return ret; } void RilSocket::sSocketListener(int fd, short flags, void *param) { RilSocket *theSocket = (RilSocket *) param; MySocketListenParam listenParam; listenParam.socket = theSocket; listenParam.sListenParam.type = RIL_SAP_SOCKET; listenCallback_helper(fd, flags, (void*)&listenParam); } void RilSocket::onNewCommandConnect() { pthread_attr_t attr; PthreadPtr pptr = ril_socket_process_requests_loop; int result; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); //Start socket request processing loop thread result = pthread_create(&socketThreadId, &attr, pptr, this); if(result < 0) { RLOGE("pthread_create failed with result:%d",result); } RLOGE("New socket command connected and socket request thread started"); } void RilSocket::sSocketRequestsHandler(int fd, short flags, void *param) { socketClient *sc = (socketClient *) param; RilSocket *theSocket = sc->socketPtr; RecordStream *rs = sc->rs; theSocket->socketRequestsHandler(fd, flags, rs); } void RilSocket::socketRequestsHandler(int fd, short flags, RecordStream *p_rs) { int ret; assert(fd == commandFd); void *p_record; size_t recordlen; for (;;) { /* loop until EAGAIN/EINTR, end of stream, or other error */ ret = record_stream_get_next(p_rs, &p_record, &recordlen); if (ret == 0 && p_record == NULL) { /* end-of-stream */ break; } else if (ret < 0) { break; } else if (ret == 0) { pushRecord(p_record, recordlen); } } if (ret == 0 || !(errno == EAGAIN || errno == EINTR)) { /* fatal error or end-of-stream */ if (ret != 0) { RLOGE("error on reading command socket errno:%d\n", errno); } else { RLOGW("EOS. Closing command socket."); } close(commandFd); commandFd = -1; ril_event_del(&callbackEvent); record_stream_free(p_rs); /* start listening for new connections again */ rilEventAddWakeup_helper(&listenEvent); onCommandsSocketClosed(); } } void RilSocket::setListenFd(int fd) { listenFd = fd; } void RilSocket::setCommandFd(int fd) { commandFd = fd; } int RilSocket::getListenFd(void) { return listenFd; } int RilSocket::getCommandFd(void) { return commandFd; } void RilSocket::setListenCb(ril_event_cb cb) { listenCb = cb; } void RilSocket::setCommandCb(ril_event_cb cb) { commandCb = cb; } ril_event_cb RilSocket::getListenCb(void) { return listenCb; } ril_event_cb RilSocket::getCommandCb(void) { return commandCb; } void RilSocket::setListenEvent(ril_event event) { listenEvent = event; } void RilSocket::setCallbackEvent(ril_event event) { callbackEvent = event; } ril_event* RilSocket::getListenEvent(void) { return &listenEvent; } ril_event* RilSocket::getCallbackEvent(void) { return &callbackEvent; } extern "C" void *ril_socket_process_requests_loop(void *arg) { RilSocket *socket = (RilSocket *)arg; socket->processRequestsLoop(); return NULL; }