summaryrefslogtreecommitdiffstats
path: root/cnd/src/cnd_process.cpp
diff options
context:
space:
mode:
authorSusheel Yadagiri <syadagir@quicinc.com>2010-01-25 10:42:28 -0800
committerSusheel Yadagiri <syadagir@quicinc.com>2010-01-26 18:52:43 -0800
commit7b3afc04f3ad11c10d964762684caef66f3f5b4d (patch)
treec7d7400d25f5cfe715afe7dc1e557a6890dcac38 /cnd/src/cnd_process.cpp
parent71c3655cc81e8898526ab8d26d79bab26dd3a049 (diff)
downloadandroid_external_connectivity-7b3afc04f3ad11c10d964762684caef66f3f5b4d.tar.gz
android_external_connectivity-7b3afc04f3ad11c10d964762684caef66f3f5b4d.tar.bz2
android_external_connectivity-7b3afc04f3ad11c10d964762684caef66f3f5b4d.zip
Pushing changes from development branch.
Major changes include: Fixed file permissions and line endings Logging to diag instead of Logcat Add support to iproute2 Bug fix that allows cnd to make the correct call to iproute2 Fixed bug caused by using variable length arguments. Made changes to account for the kernel automatically setting the default interface. Added more debug statements in CneSvc, CRefCne & CRefCneRadio classess Changes made to handle timer expiration call backs in cne thread Add Ip Address to Rat status event Add IpAddress and TimeStamp to wwan and wlan info. Added ip address and estimated bandwidth info to be sent to apps.
Diffstat (limited to 'cnd/src/cnd_process.cpp')
-rw-r--r--[-rwxr-xr-x]cnd/src/cnd_process.cpp2366
1 files changed, 1243 insertions, 1123 deletions
diff --git a/cnd/src/cnd_process.cpp b/cnd/src/cnd_process.cpp
index 45f687f..7a9edc0 100755..100644
--- a/cnd/src/cnd_process.cpp
+++ b/cnd/src/cnd_process.cpp
@@ -1,1123 +1,1243 @@
-/*
-** Copyright 2006, The Android Open Source Project
-** Copyright (c) 2009, Code Aurora Forum. All rights reserved.
-**
-** 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.
-*/
-#define LOG_TAG "CND_PROCESS"
-
-#include <cutils/sockets.h>
-#include <cutils/jstring.h>
-#include <cutils/record_stream.h>
-#include <utils/Log.h>
-#include <utils/SystemClock.h>
-#include <pthread.h>
-//#include <utils/Parcel.h>
-#include <binder/Parcel.h>
-#include <cutils/jstring.h>
-
-#include <sys/types.h>
-#include <pwd.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <time.h>
-#include <errno.h>
-#include <assert.h>
-#include <ctype.h>
-#include <alloca.h>
-#include <sys/un.h>
-#include <assert.h>
-#include <netinet/in.h>
-#include <cutils/properties.h>
-#include <dirent.h>
-#include <cnd_event.h>
-#include <cnd.h>
-#include <cne_svc.h>
-
-
-
-
-namespace android {
-
-#define SOCKET_NAME_CND "cnd"
-
-// match with constant in .java
-#define MAX_COMMAND_BYTES (8 * 1024)
-
-// Basically: memset buffers that the client library
-// shouldn't be using anymore in an attempt to find
-// memory usage issues sooner.
-#define MEMSET_FREED 1
-
-#define NUM_ELEMS(a) (sizeof (a) / sizeof (a)[0])
-
-/* Constants for response types */
-#define SOLICITED_RESPONSE 0
-#define UNSOLICITED_MESSAGE 1
-
-typedef struct {
- int commandNumber;
- void (*dispatchFunction) (Parcel &p, struct RequestInfo *pRI);
- int(*responseFunction) (Parcel &p, void *response, size_t responselen);
-} CommandInfo;
-
-typedef struct {
- int messageNumber;
- int (*responseFunction) (Parcel &p, void *response, size_t responselen);
-} UnsolMessageInfo;
-
-typedef struct RequestInfo {
- int32_t token; //this is not CND_Token
- int fd;
- CommandInfo *pCI;
- struct RequestInfo *p_next;
- char cancelled;
- char local; // responses to local commands do not go back to command process
-} RequestInfo;
-
-
-/*******************************************************************/
-
-static int s_registerCalled = 0;
-
-static pthread_t s_tid_dispatch;
-
-static int s_started = 0;
-
-static int s_fdListen = -1;
-static int s_fdCommand = -1;
-
-static int cnmSvcFd = -1;
-
-static struct cnd_event s_commands_event[MAX_FD_EVENTS];
-static struct cnd_event s_listen_event;
-static int command_index = 0;
-
-static pthread_mutex_t s_pendingRequestsMutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t s_writeMutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t s_startupMutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t s_startupCond = PTHREAD_COND_INITIALIZER;
-
-static pthread_mutex_t s_dispatchMutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t s_dispatchCond = PTHREAD_COND_INITIALIZER;
-
-static RequestInfo *s_pendingRequests = NULL;
-
-static RequestInfo *s_toDispatchHead = NULL;
-static RequestInfo *s_toDispatchTail = NULL;
-
-
-/*******************************************************************/
-static void dispatchVoid (Parcel& p, RequestInfo *pRI);
-static void dispatchString (Parcel& p, RequestInfo *pRI);
-static void dispatchStrings (Parcel& p, RequestInfo *pRI);
-static void dispatchInts (Parcel& p, RequestInfo *pRI);
-static void dispatchWlanInfo(Parcel &p, RequestInfo *pRI);
-static void dispatchWlanScanResults(Parcel &p, RequestInfo *pRI);
-static void dispatchRaw(Parcel& p, RequestInfo *pRI);
-static int responseInts(Parcel &p, void *response, size_t responselen);
-static int responseStrings(Parcel &p, void *response, size_t responselen);
-static int responseString(Parcel &p, void *response, size_t responselen);
-static int responseVoid(Parcel &p, void *response, size_t responselen);
-static int responseRaw(Parcel &p, void *response, size_t responselen);
-static int responseStartTrans(Parcel &p, void *response, size_t responselen);
-static int sendResponseRaw (const void *data, size_t dataSize, int fdCommand);
-static int sendResponse (Parcel &p, int fd);
-static int eventRatChange (Parcel &p, void *response, size_t responselen);
-static char *strdupReadString(Parcel &p);
-static void writeStringToParcel(Parcel &p, const char *s);
-static void memsetString (char *s);
-static int writeData(int fd, const void *buffer, size_t len);
-static void unsolicitedMessage(int unsolMessage, void *data, size_t datalen, int fd);
-static void processCommand (int command, void *data, size_t datalen, CND_Token t);
-static int processCommandBuffer(void *buffer, size_t buflen, int fd);
-static void invalidCommandBlock (RequestInfo *pRI);
-static void onCommandsSocketClosed(void);
-static void processCommandsCallback(int fd, void *param);
-static void listenCallback (int fd, void *param);
-static void *eventLoop(void *param);
-static int checkAndDequeueRequestInfo(struct RequestInfo *pRI);
-static void cnd_commandComplete(CND_Token t, CND_Errno e, void *response, size_t responselen);
-
-extern "C" const char * requestToString(int request);
-extern "C" void cne_processCommand (int command, void *data, size_t datalen);
-extern "C" void cne_regMessageCb(cne_messageCbType cbFn);
-
-/** Index == commandNumber */
-static CommandInfo s_commands[] = {
-#include "cnd_commands.h"
-};
-
-static UnsolMessageInfo s_unsolMessages[] = {
-#include "cnd_unsol_messages.h"
-};
-
-#define TEMP_BUFFER_SIZE (80)
-
-
-void cnd_sendUnsolicitedMsg(int targetFd, int msgType, int dataLen, void *data)
-{
- int fd;
-
- if (targetFd == 0) // TODO find the correct fd, who keeps track of it?
- fd = cnmSvcFd;
- else
- fd = targetFd;
-
- LOGD ("cnd_sendUnsolicitedMsg: Fd=%d, msgType=%d, datalen=%d\n",
- targetFd, msgType, dataLen);
-
- unsolicitedMessage(msgType, data, dataLen, fd);
-
-
-}
-
-static void
-processCommand (int command, void *data, size_t datalen, CND_Token t)
-{
-
- LOGD ("processCommand: command=%d, datalen=%d", command, datalen);
-
- /* Special handling for iproute2 command to setup iproute2 table */
- if (command == CNE_REQUEST_CONFIG_IPROUTE2_CMD)
- {
- char **pStrings;
- *pStrings = (char *)data;
- LOGD ("processCommand: str1=%s, str2=%s", pStrings[0], pStrings[1]);
- // Call iproute2 API
-
- }
- cne_processCommand(command, data, datalen);
- cnd_commandComplete(t, CND_E_SUCCESS, NULL, 0);
-}
-
-static char *
-strdupReadString(Parcel &p)
-{
- size_t stringlen;
- const char16_t *s16;
-
- s16 = p.readString16Inplace(&stringlen);
-
- return strndup16to8(s16, stringlen);
-}
-
-static void writeStringToParcel(Parcel &p, const char *s)
-{
- char16_t *s16;
- size_t s16_len;
- s16 = strdup8to16(s, &s16_len);
- p.writeString16(s16, s16_len);
- free(s16);
-}
-
-
-static void
-memsetString (char *s)
-{
- if (s != NULL) {
- memset (s, 0, strlen(s));
- }
-}
-
-
-static void
-invalidCommandBlock (RequestInfo *pRI)
-{
- //LOGE("invalid command block for token %d request %s",
- // pRI->token, requestToString(pRI->pCI->commandNumber));
-}
-
-/** Callee expects NULL */
-static void
-dispatchVoid (Parcel& p, RequestInfo *pRI)
-{
-
- processCommand(pRI->pCI->commandNumber, NULL, 0, pRI);
-}
-
-/** Callee expects const char * */
-static void
-dispatchString (Parcel& p, RequestInfo *pRI)
-{
- status_t status;
- size_t datalen;
- size_t stringlen;
- char *string8 = NULL;
-
- string8 = strdupReadString(p);
-
- processCommand(pRI->pCI->commandNumber, string8,
- sizeof(char *), pRI);
-
-#ifdef MEMSET_FREED
- memsetString(string8);
-#endif
-
- free(string8);
- return;
-}
-
-/** Callee expects const char ** */
-static void
-dispatchStrings (Parcel &p, RequestInfo *pRI)
-{
- int32_t countStrings;
- status_t status;
- size_t datalen;
- char **pStrings;
-
- status = p.readInt32 (&countStrings);
-
- if (status != NO_ERROR) {
- goto invalid;
- }
-
-
- if (countStrings == 0) {
- // just some non-null pointer
- pStrings = (char **)alloca(sizeof(char *));
- datalen = 0;
- } else if (((int)countStrings) == -1) {
- pStrings = NULL;
- datalen = 0;
- } else {
- datalen = sizeof(char *) * countStrings;
-
- pStrings = (char **)alloca(datalen);
-
- for (int i = 0 ; i < countStrings ; i++) {
- pStrings[i] = strdupReadString(p);
-
- }
- }
-
- processCommand(pRI->pCI->commandNumber, pStrings, datalen, pRI);
-
- if (pStrings != NULL) {
- for (int i = 0 ; i < countStrings ; i++) {
-#ifdef MEMSET_FREED
- memsetString (pStrings[i]);
-#endif
- free(pStrings[i]);
- }
-
-#ifdef MEMSET_FREED
- memset(pStrings, 0, datalen);
-#endif
- }
-
- return;
-invalid:
- invalidCommandBlock(pRI);
- return;
-}
-
-/** Callee expects const int * */
-static void
-dispatchInts (Parcel &p, RequestInfo *pRI)
-{
- int32_t count;
- status_t status;
- size_t datalen;
- int *pInts;
-
- status = p.readInt32 (&count);
-
- LOGD ("dispatchInts: status=%d, count=%d", status, count);
-
- if (status != NO_ERROR || count == 0) {
- goto invalid;
- }
-
- datalen = sizeof(int) * count;
- pInts = (int *)alloca(datalen);
-
-
- for (int i = 0 ; i < count ; i++) {
- int32_t t;
-
- status = p.readInt32(&t);
- pInts[i] = (int)t;
-
-
- if (status != NO_ERROR) {
- goto invalid;
- }
- }
-
- processCommand(pRI->pCI->commandNumber, const_cast<int *>(pInts),
- datalen, pRI);
-
-#ifdef MEMSET_FREED
- memset(pInts, 0, datalen);
-#endif
-
- return;
-invalid:
- invalidCommandBlock(pRI);
- return;
-}
-
-
-static void
-dispatchWlanInfo(Parcel &p, RequestInfo *pRI)
-{
- int32_t t;
- status_t status;
- CneWlanInfoType args;
-
- memset(&args, 0, sizeof(args));
-
- status = p.readInt32 (&t);
- args.status = (int)t;
- status = p.readInt32 (&t);
- args.rssi = (int)t;
- args.ssid = strdupReadString(p);
-
- LOGD ("dispatchWlanInfo: status=%ld, rssi=%ld, ssid=%s",
- args.status, args.rssi, args.ssid);
-
-
- processCommand(pRI->pCI->commandNumber, &args, sizeof(args), pRI);
-
- return;
-}
-
-static void
-dispatchWlanScanResults(Parcel &p, RequestInfo *pRI)
-{
- int32_t t;
- status_t status;
- CneWlanScanResultsType args;
- int32_t numItems;
-
- status = p.readInt32 (&t);
- //args = (CneWlanScanResultsType *)malloc(sizeof(CneWlanScanResultsType)*numItems);
- args.numItems = (int)t;
- int max = (t < CNE_MAX_SCANLIST_SIZE)? t:CNE_MAX_SCANLIST_SIZE;
-
- for (int i = 0; i < max; i++)
- {
- //args->numItems = numItems;
- status = p.readInt32 (&t);
- args.scanList[i].level = (int)t;
- status = p.readInt32 (&t);
- args.scanList[i].frequency = (int)t;
- args.scanList[i].ssid = strdupReadString(p);
- args.scanList[i].bssid = strdupReadString(p);
- args.scanList[i].capabilities = strdupReadString(p);
-
- LOGD ("dispatchWlanScanResults: max=%d, level=%ld, freq=%ld, ssid=%s, bssid=%s, cap=%s",
- args.numItems, args.scanList[i].level, args.scanList[i].frequency,
- args.scanList[i].ssid, args.scanList[i].bssid, args.scanList[i].capabilities);
-
- }
-
-
- processCommand(pRI->pCI->commandNumber, &args, sizeof(args), pRI);
-
- return;
-}
-
-static void
-dispatchRaw(Parcel &p, RequestInfo *pRI)
-{
- int32_t len;
- status_t status;
- const void *data;
-
- status = p.readInt32(&len);
-
- if (status != NO_ERROR) {
- goto invalid;
- }
-
- // The java code writes -1 for null arrays
- if (((int)len) == -1) {
- data = NULL;
- len = 0;
- }
-
- data = p.readInplace(len);
-
- processCommand(pRI->pCI->commandNumber, const_cast<void *>(data), len, pRI);
-
- return;
-invalid:
- invalidCommandBlock(pRI);
- return;
-}
-
-static int
-writeData(int fd, const void *buffer, size_t len)
-{
- size_t writeOffset = 0;
- const uint8_t *toWrite;
-
- toWrite = (const uint8_t *)buffer;
-
- LOGD ("writeData: len=%d",len);
- while (writeOffset < len) {
- ssize_t written;
- do {
- written = write (fd, toWrite + writeOffset,
- len - writeOffset);
- } while (written < 0 && errno == EINTR);
-
- if (written >= 0) {
- writeOffset += written;
- } else { // written < 0
- LOGE ("writeData: unexpected error on write errno:%d", errno);
- close(fd);
- return -1;
- }
- }
-
- return 0;
-}
-
-static int
-sendResponseRaw (const void *data, size_t dataSize, int fdCommand)
-{
- int fd = fdCommand;
- int ret;
- uint32_t header;
-
-
- LOGD ("sendResponseRaw: fdCommand=%d", fdCommand);
- if (fdCommand < 0) {
- return -1;
- }
-
- if (dataSize > MAX_COMMAND_BYTES) {
- LOGE("sendResponseRaw: packet larger than %u (%u)",
- MAX_COMMAND_BYTES, (unsigned int )dataSize);
-
- return -1;
- }
-
- pthread_mutex_lock(&s_writeMutex);
-
- header = htonl(dataSize);
-
- ret = writeData(fd, (void *)&header, sizeof(header));
-
- if (ret < 0) {
- return ret;
- }
-
- writeData(fd, data, dataSize);
-
- if (ret < 0) {
- pthread_mutex_unlock(&s_writeMutex);
- return ret;
- }
-
- pthread_mutex_unlock(&s_writeMutex);
-
- return 0;
-}
-
-static int
-sendResponse (Parcel &p, int fd)
-{
-
- return sendResponseRaw(p.data(), p.dataSize(), fd);
-}
-
-static int
-responseStartTrans(Parcel &p, void *response, size_t responselen)
-{
- int numInts;
-
-
- LOGD ("responseStartTrans: len=%d",responselen);
-
- if (response == NULL && responselen != 0) {
- LOGE("invalid response: NULL");
- return CND_E_INVALID_RESPONSE;
- }
-
-
- int *p_int = (int *) response;
- //bool tmp = p_int[1];
- char *p_char = (char *)response;
-
- p.writeInt32(p_int[0]);
- //writeStringToParcel(p, (const char *)p_char[4]);
-
-
- //p.write(&tmp, 1);
-
- LOGD ("responseStartTrans: int=%d, bool=%d",p_int[0], p_char[4]);
-
- return 0;
-}
-
-/** response is an int* pointing to an array of ints*/
-
-static int
-responseInts(Parcel &p, void *response, size_t responselen)
-{
- int numInts;
-
-
- LOGD ("responseInts: len=%d",responselen);
-
- if (response == NULL && responselen != 0) {
- LOGE("invalid response: NULL");
- return CND_E_INVALID_RESPONSE;
- }
- if (responselen % sizeof(int) != 0) {
- LOGE("invalid response length %d expected multiple of %d\n",
- (int)responselen, (int)sizeof(int));
- return CND_E_INVALID_RESPONSE;
- }
-
- int *p_int = (int *) response;
-
- numInts = responselen / sizeof(int *);
- p.writeInt32 (numInts);
-
- /* each int*/
-
- for (int i = 0 ; i < numInts ; i++) {
-
- p.writeInt32(p_int[i]);
- }
-
-
-
- return 0;
-}
-
-/** response is a char **, pointing to an array of char *'s */
-static int responseStrings(Parcel &p, void *response, size_t responselen)
-{
- int numStrings;
-
- if (response == NULL && responselen != 0) {
- LOGE("invalid response: NULL");
- return CND_E_INVALID_RESPONSE;
- }
- if (responselen % sizeof(char *) != 0) {
- LOGE("invalid response length %d expected multiple of %d\n",
- (int)responselen, (int)sizeof(char *));
- return CND_E_INVALID_RESPONSE;
- }
-
- if (response == NULL) {
- p.writeInt32 (0);
- } else {
- char **p_cur = (char **) response;
-
- numStrings = responselen / sizeof(char *);
- p.writeInt32 (numStrings);
-
- /* each string*/
-
- for (int i = 0 ; i < numStrings ; i++) {
-
- writeStringToParcel (p, p_cur[i]);
- }
-
-
- }
- return 0;
-}
-
-
-/**
- * NULL strings are accepted
- * FIXME currently ignores responselen
- */
-static int responseString(Parcel &p, void *response, size_t responselen)
-{
-
- LOGD ("responseString called");
- /* one string only */
- writeStringToParcel(p, (const char *)response);
-
- return 0;
-}
-
-static int responseVoid(Parcel &p, void *response, size_t responselen)
-{
- return 0;
-}
-
-static int responseRaw(Parcel &p, void *response, size_t responselen)
-{
- if (response == NULL && responselen != 0) {
- LOGE("invalid response: NULL with responselen != 0");
- return CND_E_INVALID_RESPONSE;
- }
-
- // The java code reads -1 size as null byte array
- if (response == NULL) {
- p.writeInt32(-1);
- } else {
- p.writeInt32(responselen);
- p.write(response, responselen);
- }
-
- return 0;
-}
-
-static int eventRatChange(Parcel &p, void *response, size_t responselen)
-{
- if (response == NULL && responselen != 0)
- {
- LOGE("invalid response: NULL");
- return CND_E_INVALID_RESPONSE;
- }
-
- CneRatInfoType *p_cur = ((CneRatInfoType *) response);
- p.writeInt32((int)p_cur->rat);
-
- /* if ((p_cur->rat == CNE_RAT_WLAN_HOME) ||
- (p_cur->rat == CNE_RAT_WLAN_ENTERPRISE) ||
- (p_cur->rat == CNE_RAT_WLAN_OPERATOR) ||
- (p_cur->rat == CNE_RAT_WLAN_OTHER) ||
- (p_cur->rat == CNE_RAT_WLAN_ANY))
- {
- writeStringToParcel (p, p_cur->wlan.ssid);
- }
- */
- if (p_cur->rat == CNE_RAT_WLAN)
- {
- writeStringToParcel (p, p_cur->wlan.ssid);
- }
- return 0;
-}
-
-static int
-checkAndDequeueRequestInfo(struct RequestInfo *pRI)
-{
- int ret = 0;
-
- if (pRI == NULL) {
- return 0;
- }
-
- pthread_mutex_lock(&s_pendingRequestsMutex);
-
- for(RequestInfo **ppCur = &s_pendingRequests
- ; *ppCur != NULL
- ; ppCur = &((*ppCur)->p_next)
- ) {
- if (pRI == *ppCur) {
- ret = 1;
-
- *ppCur = (*ppCur)->p_next;
- break;
- }
- }
-
- pthread_mutex_unlock(&s_pendingRequestsMutex);
-
- return ret;
-}
-
-static void onCommandsSocketClosed()
-{
- int ret;
- RequestInfo *p_cur;
-
- /* mark pending requests as "cancelled" so we dont report responses */
-
- ret = pthread_mutex_lock(&s_pendingRequestsMutex);
- assert (ret == 0);
-
- p_cur = s_pendingRequests;
-
- for (p_cur = s_pendingRequests
- ; p_cur != NULL
- ; p_cur = p_cur->p_next
- ) {
- p_cur->cancelled = 1;
- }
-
- ret = pthread_mutex_unlock(&s_pendingRequestsMutex);
- assert (ret == 0);
-}
-
-static void unsolicitedMessage(int unsolMessage, void *data, size_t datalen, int fd)
-{
- int unsolMessageIndex;
- int ret;
-
- if (s_registerCalled == 0) {
- // Ignore RIL_onUnsolicitedResponse before cnd_int
- LOGW("unsolicitedMessage called before cnd_init");
- return;
- }
-
- Parcel p;
-
- p.writeInt32 (UNSOLICITED_MESSAGE);
- p.writeInt32 (unsolMessage);
-
- ret = s_unsolMessages[unsolMessage]
- .responseFunction(p, data, datalen);
-
- if (ret != 0) {
- // Problem with the response. Don't continue;
- LOGE("unsolicitedMessage: problem with response");
- return;
- }
-
- LOGD ("unsolicitedMessage: sending Response");
- ret = sendResponse(p, fd);
-
- return;
-
-}
-
-static int
-processCommandBuffer(void *buffer, size_t buflen, int fd)
-{
- Parcel p;
- status_t status;
- int32_t request;
- int32_t token;
- RequestInfo *pRI;
- int ret;
-
- p.setData((uint8_t *) buffer, buflen);
-
- // status checked at end
- status = p.readInt32(&request);
- status = p.readInt32 (&token);
-
- LOGD ("processCommandBuffer: request=%d, token=%d, fd=%d", request, token, fd);
- if (status != NO_ERROR) {
- LOGE("invalid request block");
- return 0;
- }
-
- if (request < 1 || request >= (int32_t)NUM_ELEMS(s_commands)) {
- LOGE("unsupported request code %d token %d", request, token);
- // TBD: this should return a response
- return 0;
- }
-
-
- pRI = (RequestInfo *)calloc(1, sizeof(RequestInfo));
-
- pRI->token = token;
- pRI->fd = fd;
- pRI->pCI = &(s_commands[request]);
-
- ret = pthread_mutex_lock(&s_pendingRequestsMutex);
- assert (ret == 0);
-
- pRI->p_next = s_pendingRequests;
- s_pendingRequests = pRI;
-
- ret = pthread_mutex_unlock(&s_pendingRequestsMutex);
- assert (ret == 0);
-
- pRI->pCI->dispatchFunction(p, pRI);
-
- return 0;
-}
-
-static void processCommandsCallback(int fd, void *param)
-{
- RecordStream *p_rs;
- void *p_record;
- size_t recordlen;
- int ret;
-
- LOGD ("processCommandsCallback: fd=%d, s_fdCommand=%d", fd, s_fdCommand);
-
- p_rs = (RecordStream *)param;
-
-
- for (;;) {
- /* loop until EAGAIN/EINTR, end of stream, or other error */
- ret = record_stream_get_next(p_rs, &p_record, &recordlen);
-
- LOGD ("processCommandsCallback: len=%d, ret=%d", recordlen, ret);
- if (ret == 0 && p_record == NULL) {
- LOGD ("processCommandsCallback: end of stream");
- /* end-of-stream */
- break;
- } else if (ret < 0) {
- break;
- } else if (ret == 0) { /* && p_record != NULL */
- processCommandBuffer(p_record, recordlen, fd);
-
- }
- }
-
- //LOGD ("processCommandsCallback: errno=%d, ret=%d", errno, ret);
- if (ret == 0 || !(errno == EAGAIN || errno == EINTR)) {
- /* fatal error or end-of-stream */
- if (ret != 0) {
- LOGE("error on reading command socket errno:%d\n", errno);
- } else {
- LOGW("EOS. Closing command socket.");
- }
-
- LOGD ("processCommandsCallback: Closing");
- close(s_fdCommand);
- s_fdCommand = -1;
-
- // cnd_event_del(&s_commands_event); // TODO - need to clean up properly
-
- command_index = 0;
-
- record_stream_free(p_rs);
-
- /* start listening for new connections again */
- cnd_event_add(&s_listen_event);
-
- onCommandsSocketClosed();
- }
-
-}
-
-static void listenCallback (int fd, void *param)
-{
- int ret;
- int err;
- int is_cnm_svc_socket;
- RecordStream *p_rs;
- int i;
- char tmpBuf[10];
- int32_t pid, pid2, pid3, pid4;
-
- struct sockaddr_un peeraddr;
- socklen_t socklen = sizeof (peeraddr);
-
- struct ucred creds;
- socklen_t szCreds = sizeof(creds);
-
-
- struct passwd *pwd = NULL;
-
- assert (s_fdCommand < 0);
- assert (fd == s_fdListen);
-
- LOGD ("listenCallback: called");
-
-
- s_fdCommand = accept(s_fdListen, (sockaddr *) &peeraddr, &socklen);
-
-
- if (s_fdCommand < 0 ) {
- LOGE("Error on accept() errno:%d", errno);
- /* start listening for new connections again */
- cnd_event_add(&s_listen_event);
- return;
- }
-
- errno = 0;
-
- err = getsockopt(s_fdCommand, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds);
-
- cnmSvcFd = s_fdCommand; // save command descriptor to be used for communication
-
- ret = fcntl(s_fdCommand, F_SETFL, O_NONBLOCK);
-
- if (ret < 0) {
- LOGE ("Error setting O_NONBLOCK errno = %d", errno);
- }
-
- LOGI("listenCallback: accept new connection, fd=%d", s_fdCommand);
-
- p_rs = record_stream_new(s_fdCommand, MAX_COMMAND_BYTES);
-
-
- // note: persistent = 1, not removed from table
- if (command_index >= MAX_FD_EVENTS)
- {
- LOGE ("Error: exceeding number of supported connection");
- return;
- }
- cnd_event_set (&s_commands_event[command_index], s_fdCommand, 1, processCommandsCallback, p_rs);
-
- cnd_event_add (&s_commands_event[command_index]);
-
- command_index++;
-
- return;
-
-}
-
-
-static void *
-eventLoop(void *param)
-{
- int ret;
- int filedes[2];
-
- LOGD ("eventLoop: s_started=%d", s_started);
-
- pthread_mutex_lock(&s_startupMutex);
-
- s_started = 1;
- pthread_cond_broadcast(&s_startupCond);
-
- pthread_mutex_unlock(&s_startupMutex);
-
- cnd_event_loop();
-
-
- return NULL;
-}
-
-extern "C" void
-cnd_startEventLoop(void)
-{
- int ret;
- pthread_attr_t attr;
-
- /* spin up eventLoop thread and wait for it to get started */
- s_started = 0;
- pthread_mutex_lock(&s_startupMutex);
-
- pthread_attr_init (&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- ret = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);
-
-
- while (s_started == 0) {
- pthread_cond_wait(&s_startupCond, &s_startupMutex);
- }
-
-
- pthread_mutex_unlock(&s_startupMutex);
-
- if (ret < 0) {
- LOGE("Failed to create dispatch thread errno:%d", errno);
- return;
- }
-}
-
-extern "C" void
-cnd_init (void)
-{
- int ret;
-
- if (s_registerCalled > 0) {
- LOGE("cnd_init has been called more than once. "
- "Subsequent call ignored");
- return;
- }
-
- s_registerCalled = 1;
-
- cnd_event_init();
-
- cne_regMessageCb(cnd_sendUnsolicitedMsg);
-
-
- s_fdListen = android_get_control_socket(SOCKET_NAME_CND);
- if (s_fdListen < 0) {
- LOGE("Failed to get socket '" SOCKET_NAME_CND "'");
- exit(-1);
- }
-
- ret = listen(s_fdListen, 4);
-
- if (ret < 0) {
- LOGE("Failed to listen on control socket '%d': %s",
- s_fdListen, strerror(errno));
- exit(-1);
- }
-
-
- LOGD ("cnd_init: adding listenCallback event, fd=%d",s_fdListen);
-
- /* note: non-persistent to accept only one connection at a time */
- //cnd_event_set (&s_listen_event, s_fdListen, 0, listenCallback, NULL);
-
- // persistent to accept multiple connections at same time
- cnd_event_set (&s_listen_event, s_fdListen, 1, listenCallback, NULL);
-
- cnd_event_add (&s_listen_event);
-
-
-}
-
-
-//extern "C" void - TBD -may want to change this function to extern "C" and
-// be called from CneCet where Cne components (SRM/SPM/CDE) may send the
-// response to Cne java
-static void
-cnd_commandComplete(CND_Token t, CND_Errno e, void *response, size_t responselen)
-{
- RequestInfo *pRI;
- int ret;
- size_t errorOffset;
-
- pRI = (RequestInfo *)t;
-
- LOGD ("cnd_commandComplete: started");
-
- if (!checkAndDequeueRequestInfo(pRI)) {
- LOGE ("cnd_commandComplete: invalid CND_Token");
- return;
- }
-
- if (pRI->local > 0) {
- goto done;
- }
-
-
- if (pRI->cancelled == 0) {
- Parcel p;
-
- p.writeInt32 (SOLICITED_RESPONSE);
- p.writeInt32 (pRI->token);
- errorOffset = p.dataPosition();
-
- p.writeInt32 (e);
-
-
- if (e == CND_E_SUCCESS) {
- /* process response on success */
- ret = pRI->pCI->responseFunction(p, response, responselen);
- LOGD ("cnd_commandComplete: ret = %d", ret);
- /* if an error occurred, rewind and mark it */
- if (ret != 0) {
- p.setDataPosition(errorOffset);
- p.writeInt32 (ret);
- }
- } else {
- LOGE ("cnd_commandComplete: Error");
- }
-
- if (pRI->fd < 0) {
- LOGE ("cnd_commandComplete: Command channel closed");
- }
- LOGD ("cnd_commandComplete: sending Response");
- sendResponse(p, pRI->fd);
- }
-
-done:
- free(pRI);
-}
-
-} /* namespace android */
-
-
+/*
+** Copyright 2006, The Android Open Source Project
+** Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+**
+** 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.
+*/
+#define LOG_TAG "CND_PROCESS"
+
+#include <cutils/sockets.h>
+#include <cutils/jstring.h>
+#include <cutils/record_stream.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+#include <pthread.h>
+//#include <utils/Parcel.h>
+#include <binder/Parcel.h>
+#include <cutils/jstring.h>
+
+#include <sys/types.h>
+#include <pwd.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+#include <errno.h>
+#include <assert.h>
+#include <ctype.h>
+#include <alloca.h>
+#include <sys/un.h>
+#include <assert.h>
+#include <netinet/in.h>
+#include <cutils/properties.h>
+#include <dirent.h>
+#include <cnd_event.h>
+#include <cnd.h>
+#include <cne.h>
+#include <cnd_iproute2.h>
+
+
+
+
+namespace android {
+
+#define SOCKET_NAME_CND "cnd"
+
+// match with constant in .java
+#define MAX_COMMAND_BYTES (8 * 1024)
+
+// Basically: memset buffers that the client library
+// shouldn't be using anymore in an attempt to find
+// memory usage issues sooner.
+#define MEMSET_FREED 1
+
+#define NUM_ELEMS(a) (sizeof (a) / sizeof (a)[0])
+
+/* Constants for response types */
+#define SOLICITED_RESPONSE 0
+#define UNSOLICITED_MESSAGE 1
+
+typedef struct {
+ int commandNumber;
+ void (*dispatchFunction) (Parcel &p, struct RequestInfo *pRI);
+ int(*responseFunction) (Parcel &p, void *response, size_t responselen);
+} CommandInfo;
+
+typedef struct {
+ int messageNumber;
+ int (*responseFunction) (Parcel &p, void *response, size_t responselen);
+} UnsolMessageInfo;
+
+typedef struct RequestInfo {
+ int32_t token; //this is not CND_Token
+ int fd;
+ CommandInfo *pCI;
+ struct RequestInfo *p_next;
+ char cancelled;
+ char local; // responses to local commands do not go back to command process
+} RequestInfo;
+
+
+/*******************************************************************/
+
+static int s_registerCalled = 0;
+
+static pthread_t s_tid_dispatch;
+
+static int s_started = 0;
+
+static int s_fdListen = -1;
+static int s_fdCommand = -1;
+
+static int cnmSvcFd = -1;
+
+static struct cnd_event s_commands_event[MAX_FD_EVENTS];
+static struct cnd_event s_listen_event;
+static int command_index = 0;
+
+static pthread_mutex_t s_pendingRequestsMutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t s_writeMutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t s_startupMutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t s_startupCond = PTHREAD_COND_INITIALIZER;
+
+static pthread_mutex_t s_dispatchMutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t s_dispatchCond = PTHREAD_COND_INITIALIZER;
+
+static RequestInfo *s_pendingRequests = NULL;
+
+static RequestInfo *s_toDispatchHead = NULL;
+static RequestInfo *s_toDispatchTail = NULL;
+
+
+/*******************************************************************/
+static void dispatchVoid (Parcel& p, RequestInfo *pRI);
+static void dispatchString (Parcel& p, RequestInfo *pRI);
+static void dispatchStrings (Parcel& p, RequestInfo *pRI);
+static void dispatchInts (Parcel& p, RequestInfo *pRI);
+static void dispatchWlanInfo(Parcel &p, RequestInfo *pRI);
+static void dispatchWwanInfo(Parcel &p, RequestInfo *pRI);
+static void dispatchWlanScanResults(Parcel &p, RequestInfo *pRI);
+static void dispatchRaw(Parcel& p, RequestInfo *pRI);
+static void dispatchRatStatus(Parcel &p, RequestInfo *pRI);
+static int responseInts(Parcel &p, void *response, size_t responselen);
+static int responseStrings(Parcel &p, void *response, size_t responselen);
+static int responseString(Parcel &p, void *response, size_t responselen);
+static int responseVoid(Parcel &p, void *response, size_t responselen);
+static int responseRaw(Parcel &p, void *response, size_t responselen);
+static int responseStartTrans(Parcel &p, void *response, size_t responselen);
+static int sendResponseRaw (const void *data, size_t dataSize, int fdCommand);
+static int sendResponse (Parcel &p, int fd);
+static int rspCompatibleNws(Parcel &p, void *response, size_t responselen);
+static int evtMorePrefNw(Parcel &p, void *response, size_t responselen);
+static int eventRatChange (Parcel &p, void *response, size_t responselen);
+static char *strdupReadString(Parcel &p);
+static void writeStringToParcel(Parcel &p, const char *s);
+static void memsetString (char *s);
+static int writeData(int fd, const void *buffer, size_t len);
+static void unsolicitedMessage(int unsolMessage, void *data, size_t datalen, int fd);
+static void processCommand (int command, void *data, size_t datalen, CND_Token t);
+static int processCommandBuffer(void *buffer, size_t buflen, int fd);
+static void invalidCommandBlock (RequestInfo *pRI);
+static void onCommandsSocketClosed(void);
+static void processCommandsCallback(int fd, void *param);
+static void listenCallback (int fd, void *param);
+static void *eventLoop(void *param);
+static int checkAndDequeueRequestInfo(struct RequestInfo *pRI);
+static void cnd_commandComplete(CND_Token t, CND_Errno e, void *response, size_t responselen);
+
+extern "C" const char * requestToString(int request);
+extern "C" void cne_processCommand (int command, void *data, size_t datalen);
+extern "C" void cne_regMessageCb(cne_messageCbType cbFn);
+
+/** Index == commandNumber */
+static CommandInfo s_commands[] = {
+#include "cnd_commands.h"
+};
+
+static UnsolMessageInfo s_unsolMessages[] = {
+#include "cnd_unsol_messages.h"
+};
+
+#define TEMP_BUFFER_SIZE (80)
+
+
+void cnd_sendUnsolicitedMsg(int targetFd, int msgType, int dataLen, void *data)
+{
+ int fd;
+
+ if (targetFd == 0) // TODO find the correct fd, who keeps track of it?
+ fd = cnmSvcFd;
+ else
+ fd = targetFd;
+
+ LOGD ("cnd_sendUnsolicitedMsg: Fd=%d, msgType=%d, datalen=%d\n",
+ targetFd, msgType, dataLen);
+
+ unsolicitedMessage(msgType, data, dataLen, fd);
+
+
+}
+
+static void
+processCommand (int command, void *data, size_t datalen, CND_Token t)
+{
+
+ LOGD ("processCommand: command=%d, datalen=%d", command, datalen);
+
+ /* Special handling for iproute2 command to setup iproute2 table */
+ if (command == CNE_REQUEST_CONFIG_IPROUTE2_CMD)
+ {
+ unsigned char *ipAddr = NULL;
+ unsigned char *gatewayAddr = NULL;
+ unsigned char *ifName = NULL;
+
+
+ ifName = ((unsigned char **)data)[0];
+ ipAddr = ((unsigned char **)data)[1];
+ gatewayAddr = ((unsigned char **)data)[2];
+
+ LOGD ("processCommand: ipAddr=%s, gatewayAddr=%s, ifName=%s", ipAddr, gatewayAddr, ifName);
+
+ // Call iproute2 API
+ if(ipAddr != NULL)
+ cnd_iproute2::getInstance()->addRoutingTable(ifName, ipAddr, gatewayAddr);
+ else
+ cnd_iproute2::getInstance()->deleteRoutingTable(ifName);
+
+ return;
+
+ }
+
+ cne_processCommand(command, data, datalen);
+ cnd_commandComplete(t, CND_E_SUCCESS, NULL, 0);
+ return;
+}
+
+static char *
+strdupReadString(Parcel &p)
+{
+ size_t stringlen;
+ const char16_t *s16;
+
+ s16 = p.readString16Inplace(&stringlen);
+
+ return strndup16to8(s16, stringlen);
+}
+
+static void writeStringToParcel(Parcel &p, const char *s)
+{
+ char16_t *s16;
+ size_t s16_len;
+ s16 = strdup8to16(s, &s16_len);
+ p.writeString16(s16, s16_len);
+ free(s16);
+}
+
+
+static void
+memsetString (char *s)
+{
+ if (s != NULL) {
+ memset (s, 0, strlen(s));
+ }
+}
+
+
+static void
+invalidCommandBlock (RequestInfo *pRI)
+{
+ //LOGE("invalid command block for token %d request %s",
+ // pRI->token, requestToString(pRI->pCI->commandNumber));
+}
+
+/** Callee expects NULL */
+static void
+dispatchVoid (Parcel& p, RequestInfo *pRI)
+{
+
+ processCommand(pRI->pCI->commandNumber, NULL, 0, pRI);
+}
+
+/** Callee expects const char * */
+static void
+dispatchString (Parcel& p, RequestInfo *pRI)
+{
+ status_t status;
+ size_t datalen;
+ size_t stringlen;
+ char *string8 = NULL;
+
+ string8 = strdupReadString(p);
+
+ processCommand(pRI->pCI->commandNumber, string8,
+ sizeof(char *), pRI);
+
+#ifdef MEMSET_FREED
+ memsetString(string8);
+#endif
+
+ free(string8);
+ return;
+}
+
+/** Callee expects const char ** */
+static void
+dispatchStrings (Parcel &p, RequestInfo *pRI)
+{
+ int32_t countStrings;
+ status_t status;
+ size_t datalen;
+ char **pStrings;
+
+ status = p.readInt32 (&countStrings);
+
+ if (status != NO_ERROR) {
+ goto invalid;
+ }
+
+
+ if (countStrings == 0) {
+ // just some non-null pointer
+ pStrings = (char **)alloca(sizeof(char *));
+ datalen = 0;
+ } else if (((int)countStrings) == -1) {
+ pStrings = NULL;
+ datalen = 0;
+ } else {
+ datalen = sizeof(char *) * countStrings;
+
+ pStrings = (char **)alloca(datalen);
+
+ for (int i = 0 ; i < countStrings ; i++) {
+ pStrings[i] = strdupReadString(p);
+
+ }
+ }
+
+ processCommand(pRI->pCI->commandNumber, pStrings, datalen, pRI);
+
+ if (pStrings != NULL) {
+ for (int i = 0 ; i < countStrings ; i++) {
+#ifdef MEMSET_FREED
+ memsetString (pStrings[i]);
+#endif
+ free(pStrings[i]);
+ }
+
+#ifdef MEMSET_FREED
+ memset(pStrings, 0, datalen);
+#endif
+ }
+
+ return;
+invalid:
+ invalidCommandBlock(pRI);
+ return;
+}
+
+/** Callee expects const int * */
+static void
+dispatchInts (Parcel &p, RequestInfo *pRI)
+{
+ int32_t count;
+ status_t status;
+ size_t datalen;
+ int *pInts;
+
+ status = p.readInt32 (&count);
+
+ LOGD ("dispatchInts: status=%d, count=%d", status, count);
+
+ if (status != NO_ERROR || count == 0) {
+ goto invalid;
+ }
+
+ datalen = sizeof(int) * count;
+ pInts = (int *)alloca(datalen);
+
+
+ for (int i = 0 ; i < count ; i++) {
+ int32_t t;
+
+ status = p.readInt32(&t);
+ pInts[i] = (int)t;
+
+
+ if (status != NO_ERROR) {
+ goto invalid;
+ }
+ }
+
+ processCommand(pRI->pCI->commandNumber, const_cast<int *>(pInts),
+ datalen, pRI);
+
+#ifdef MEMSET_FREED
+ memset(pInts, 0, datalen);
+#endif
+
+ return;
+invalid:
+ invalidCommandBlock(pRI);
+ return;
+}
+
+
+static void
+dispatchWlanInfo(Parcel &p, RequestInfo *pRI)
+{
+ int32_t t;
+ status_t status;
+ CneWlanInfoType args;
+
+ memset(&args, 0, sizeof(args));
+
+ status = p.readInt32 (&t);
+ args.status = (int)t;
+ status = p.readInt32 (&t);
+ args.rssi = (int)t;
+ args.ssid = strdupReadString(p);
+ args.ipAddr = strdupReadString(p);
+ args.timeStamp = strdupReadString(p);
+
+ LOGD ("dispatchWlanInfo: state=%ld, rssi=%ld, ssid=%s, ipAddr=%s, timeStamp=%s",
+ args.status, args.rssi, args.ssid, args.ipAddr, args.timeStamp);
+
+
+ processCommand(pRI->pCI->commandNumber, &args, sizeof(args), pRI);
+
+ return;
+}
+
+static void
+dispatchWlanScanResults(Parcel &p, RequestInfo *pRI)
+{
+ int32_t t;
+ status_t status;
+ CneWlanScanResultsType args;
+ int32_t numItems;
+
+ status = p.readInt32 (&t);
+ //args = (CneWlanScanResultsType *)malloc(sizeof(CneWlanScanResultsType)*numItems);
+ args.numItems = (int)t;
+ int max = (t < CNE_MAX_SCANLIST_SIZE)? t:CNE_MAX_SCANLIST_SIZE;
+
+ for (int i = 0; i < max; i++)
+ {
+ //args->numItems = numItems;
+ status = p.readInt32 (&t);
+ args.scanList[i].level = (int)t;
+ status = p.readInt32 (&t);
+ args.scanList[i].frequency = (int)t;
+ args.scanList[i].ssid = strdupReadString(p);
+ args.scanList[i].bssid = strdupReadString(p);
+ args.scanList[i].capabilities = strdupReadString(p);
+
+ LOGD ("dispatchWlanScanResults: max=%d, level=%ld, freq=%ld, ssid=%s, bssid=%s, cap=%s",
+ args.numItems, args.scanList[i].level, args.scanList[i].frequency,
+ args.scanList[i].ssid, args.scanList[i].bssid, args.scanList[i].capabilities);
+
+ }
+
+
+ processCommand(pRI->pCI->commandNumber, &args, sizeof(args), pRI);
+
+ return;
+}
+
+static void
+dispatchWwanInfo(Parcel &p, RequestInfo *pRI)
+{
+ int32_t t;
+ status_t status;
+ CneWwanInfoType args;
+
+ memset(&args, 0, sizeof(args));
+
+ status = p.readInt32 (&t);
+ args.type = (int)t;
+ status = p.readInt32 (&t);
+ args.status = (int)t;
+ status = p.readInt32 (&t);
+ args.rssi = (int)t;
+ status = p.readInt32 (&t);
+ args.roaming = (int)t;
+ args.ipAddr = strdupReadString(p);
+ args.timeStamp = strdupReadString(p);
+
+ LOGD ("dispatchWwanInfo: type=%ld, state=%ld, rssi=%ld, roaming=%ld, ipAddr=%s, timeStamp=%s",
+ args.type, args.status, args.rssi, args.roaming, args.ipAddr, args.timeStamp);
+
+
+ processCommand(pRI->pCI->commandNumber, &args, sizeof(args), pRI);
+
+ return;
+}
+
+static void
+dispatchRatStatus(Parcel &p, RequestInfo *pRI)
+{
+ int32_t t;
+ status_t status;
+ CneRatStatusType args;
+
+ memset(&args, 0, sizeof(args));
+
+ status = p.readInt32 (&t);
+ args.rat = (cne_rat_type)t;
+ status = p.readInt32 (&t);
+ args.ratStatus = (cne_network_state_enum_type)t;
+ args.ipAddr = strdupReadString(p);
+
+ LOGD ("dispatchRatStatus: type=%ld, ratStatus=%ld, ipAddr=%s",
+ args.rat, args.ratStatus, args.ipAddr);
+
+
+ processCommand(pRI->pCI->commandNumber, &args, sizeof(args), pRI);
+
+ return;
+}
+
+static void
+dispatchRaw(Parcel &p, RequestInfo *pRI)
+{
+ int32_t len;
+ status_t status;
+ const void *data;
+
+ status = p.readInt32(&len);
+
+ if (status != NO_ERROR) {
+ goto invalid;
+ }
+
+ // The java code writes -1 for null arrays
+ if (((int)len) == -1) {
+ data = NULL;
+ len = 0;
+ }
+
+ data = p.readInplace(len);
+
+ processCommand(pRI->pCI->commandNumber, const_cast<void *>(data), len, pRI);
+
+ return;
+invalid:
+ invalidCommandBlock(pRI);
+ return;
+}
+
+static int
+writeData(int fd, const void *buffer, size_t len)
+{
+ size_t writeOffset = 0;
+ const uint8_t *toWrite;
+
+ toWrite = (const uint8_t *)buffer;
+
+ LOGD ("writeData: len=%d",len);
+ while (writeOffset < len) {
+ ssize_t written;
+ do {
+ written = write (fd, toWrite + writeOffset,
+ len - writeOffset);
+ } while (written < 0 && errno == EINTR);
+
+ if (written >= 0) {
+ writeOffset += written;
+ } else { // written < 0
+ LOGE ("writeData: unexpected error on write errno:%d", errno);
+ close(fd);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+sendResponseRaw (const void *data, size_t dataSize, int fdCommand)
+{
+ int fd = fdCommand;
+ int ret;
+ uint32_t header;
+
+
+ LOGD ("sendResponseRaw: fdCommand=%d", fdCommand);
+ if (fdCommand < 0) {
+ return -1;
+ }
+
+ if (dataSize > MAX_COMMAND_BYTES) {
+ LOGE("sendResponseRaw: packet larger than %u (%u)",
+ MAX_COMMAND_BYTES, (unsigned int )dataSize);
+
+ return -1;
+ }
+
+ pthread_mutex_lock(&s_writeMutex);
+
+ header = htonl(dataSize);
+
+ ret = writeData(fd, (void *)&header, sizeof(header));
+
+ if (ret < 0) {
+ return ret;
+ }
+
+ writeData(fd, data, dataSize);
+
+ if (ret < 0) {
+ pthread_mutex_unlock(&s_writeMutex);
+ return ret;
+ }
+
+ pthread_mutex_unlock(&s_writeMutex);
+
+ return 0;
+}
+
+static int
+sendResponse (Parcel &p, int fd)
+{
+
+ return sendResponseRaw(p.data(), p.dataSize(), fd);
+}
+
+static int
+responseStartTrans(Parcel &p, void *response, size_t responselen)
+{
+ int numInts;
+
+
+ LOGD ("responseStartTrans: len=%d",responselen);
+
+ if (response == NULL && responselen != 0) {
+ LOGE("invalid response: NULL");
+ return CND_E_INVALID_RESPONSE;
+ }
+
+
+ int *p_int = (int *) response;
+ //bool tmp = p_int[1];
+ char *p_char = (char *)response;
+
+ p.writeInt32(p_int[0]);
+ //writeStringToParcel(p, (const char *)p_char[4]);
+
+
+ //p.write(&tmp, 1);
+
+ LOGD ("responseStartTrans: int=%d, bool=%d",p_int[0], p_char[4]);
+
+ return 0;
+}
+
+/** response is an int* pointing to an array of ints*/
+
+static int
+responseInts(Parcel &p, void *response, size_t responselen)
+{
+ int numInts;
+
+
+ LOGD ("responseInts: len=%d",responselen);
+
+ if (response == NULL && responselen != 0) {
+ LOGE("invalid response: NULL");
+ return CND_E_INVALID_RESPONSE;
+ }
+ if (responselen % sizeof(int) != 0) {
+ LOGE("invalid response length %d expected multiple of %d\n",
+ (int)responselen, (int)sizeof(int));
+ return CND_E_INVALID_RESPONSE;
+ }
+
+ int *p_int = (int *) response;
+
+ numInts = responselen / sizeof(int *);
+ p.writeInt32 (numInts);
+
+ /* each int*/
+
+ for (int i = 0 ; i < numInts ; i++) {
+
+ p.writeInt32(p_int[i]);
+ }
+
+
+
+ return 0;
+}
+
+/** response is a char **, pointing to an array of char *'s */
+static int responseStrings(Parcel &p, void *response, size_t responselen)
+{
+ int numStrings;
+
+ if (response == NULL && responselen != 0) {
+ LOGE("invalid response: NULL");
+ return CND_E_INVALID_RESPONSE;
+ }
+ if (responselen % sizeof(char *) != 0) {
+ LOGE("invalid response length %d expected multiple of %d\n",
+ (int)responselen, (int)sizeof(char *));
+ return CND_E_INVALID_RESPONSE;
+ }
+
+ if (response == NULL) {
+ p.writeInt32 (0);
+ } else {
+ char **p_cur = (char **) response;
+
+ numStrings = responselen / sizeof(char *);
+ p.writeInt32 (numStrings);
+
+ /* each string*/
+
+ for (int i = 0 ; i < numStrings ; i++) {
+
+ writeStringToParcel (p, p_cur[i]);
+ }
+
+
+ }
+ return 0;
+}
+
+
+/**
+ * NULL strings are accepted
+ * FIXME currently ignores responselen
+ */
+static int responseString(Parcel &p, void *response, size_t responselen)
+{
+
+ LOGD ("responseString called");
+ /* one string only */
+ writeStringToParcel(p, (const char *)response);
+
+ return 0;
+}
+
+static int responseVoid(Parcel &p, void *response, size_t responselen)
+{
+ return 0;
+}
+
+static int responseRaw(Parcel &p, void *response, size_t responselen)
+{
+ if (response == NULL && responselen != 0) {
+ LOGE("invalid response: NULL with responselen != 0");
+ return CND_E_INVALID_RESPONSE;
+ }
+
+ // The java code reads -1 size as null byte array
+ if (response == NULL) {
+ p.writeInt32(-1);
+ } else {
+ p.writeInt32(responselen);
+ p.write(response, responselen);
+ }
+
+ return 0;
+}
+
+
+static int rspCompatibleNws(Parcel &p, void *response, size_t responselen)
+{
+ if (response == NULL && responselen != 0)
+ {
+ LOGE("invalid response: NULL");
+ return CND_E_INVALID_RESPONSE;
+ }
+
+ cne_get_compatible_nws_evt_rsp_data_type *p_cur =
+ ((cne_get_compatible_nws_evt_rsp_data_type *) response);
+
+ p.writeInt32((int)p_cur->reg_id);
+ p.writeInt32((int)p_cur->is_success);
+ p.writeInt32((int)p_cur->best_rat);
+ for(int index = 0; index<CNE_RAT_MAX; index++)
+ {
+ p.writeInt32((int)p_cur->rat_pref_order[index]);
+ }
+ writeStringToParcel(p,p_cur->ip_addr);
+ p.writeInt32((int)p_cur->fl_bw_est);
+ p.writeInt32((int)p_cur->rl_bw_est);
+ return 0;
+}
+
+static int evtMorePrefNw(Parcel &p, void *response, size_t responselen)
+{
+ if (response == NULL && responselen != 0)
+ {
+ LOGE("invalid response: NULL");
+ return CND_E_INVALID_RESPONSE;
+ }
+
+ cne_pref_rat_avail_evt_data_type *p_cur =
+ ((cne_pref_rat_avail_evt_data_type *) response);
+
+ p.writeInt32((int)p_cur->reg_id);
+ p.writeInt32((int)p_cur->rat);
+ writeStringToParcel(p,p_cur->ip_addr);
+ p.writeInt32((int)p_cur->fl_bw_est);
+ p.writeInt32((int)p_cur->rl_bw_est);
+ return 0;
+}
+
+static int eventRatChange(Parcel &p, void *response, size_t responselen)
+{
+ if (response == NULL && responselen != 0)
+ {
+ LOGE("invalid response: NULL");
+ return CND_E_INVALID_RESPONSE;
+ }
+
+ CneRatInfoType *p_cur = ((CneRatInfoType *) response);
+ p.writeInt32((int)p_cur->rat);
+
+ /* if ((p_cur->rat == CNE_RAT_WLAN_HOME) ||
+ (p_cur->rat == CNE_RAT_WLAN_ENTERPRISE) ||
+ (p_cur->rat == CNE_RAT_WLAN_OPERATOR) ||
+ (p_cur->rat == CNE_RAT_WLAN_OTHER) ||
+ (p_cur->rat == CNE_RAT_WLAN_ANY))
+ {
+ writeStringToParcel (p, p_cur->wlan.ssid);
+ }
+ */
+ if (p_cur->rat == CNE_RAT_WLAN)
+ {
+ writeStringToParcel (p, p_cur->wlan.ssid);
+ }
+ return 0;
+}
+
+static int
+checkAndDequeueRequestInfo(struct RequestInfo *pRI)
+{
+ int ret = 0;
+
+ if (pRI == NULL) {
+ return 0;
+ }
+
+ pthread_mutex_lock(&s_pendingRequestsMutex);
+
+ for(RequestInfo **ppCur = &s_pendingRequests
+ ; *ppCur != NULL
+ ; ppCur = &((*ppCur)->p_next)
+ ) {
+ if (pRI == *ppCur) {
+ ret = 1;
+
+ *ppCur = (*ppCur)->p_next;
+ break;
+ }
+ }
+
+ pthread_mutex_unlock(&s_pendingRequestsMutex);
+
+ return ret;
+}
+
+static void onCommandsSocketClosed()
+{
+ int ret;
+ RequestInfo *p_cur;
+
+ /* mark pending requests as "cancelled" so we dont report responses */
+
+ ret = pthread_mutex_lock(&s_pendingRequestsMutex);
+ assert (ret == 0);
+
+ p_cur = s_pendingRequests;
+
+ for (p_cur = s_pendingRequests
+ ; p_cur != NULL
+ ; p_cur = p_cur->p_next
+ ) {
+ p_cur->cancelled = 1;
+ }
+
+ ret = pthread_mutex_unlock(&s_pendingRequestsMutex);
+ assert (ret == 0);
+}
+
+static void unsolicitedMessage(int unsolMessage, void *data, size_t datalen, int fd)
+{
+ int unsolMessageIndex;
+ int ret;
+
+ if (s_registerCalled == 0) {
+ // Ignore RIL_onUnsolicitedResponse before cnd_int
+ LOGW("unsolicitedMessage called before cnd_init");
+ return;
+ }
+
+ Parcel p;
+
+ p.writeInt32 (UNSOLICITED_MESSAGE);
+ p.writeInt32 (unsolMessage);
+
+ ret = s_unsolMessages[unsolMessage]
+ .responseFunction(p, data, datalen);
+
+ if (ret != 0) {
+ // Problem with the response. Don't continue;
+ LOGE("unsolicitedMessage: problem with response");
+ return;
+ }
+
+ LOGD ("unsolicitedMessage: sending Response");
+ ret = sendResponse(p, fd);
+
+ return;
+
+}
+
+static int
+processCommandBuffer(void *buffer, size_t buflen, int fd)
+{
+ Parcel p;
+ status_t status;
+ int32_t request;
+ int32_t token;
+ RequestInfo *pRI;
+ int ret;
+
+ p.setData((uint8_t *) buffer, buflen);
+
+ // status checked at end
+ status = p.readInt32(&request);
+ status = p.readInt32 (&token);
+
+ LOGD ("processCommandBuffer: request=%d, token=%d, fd=%d", request, token, fd);
+ if (status != NO_ERROR) {
+ LOGE("invalid request block");
+ return 0;
+ }
+
+ if (request < 1 || request >= (int32_t)NUM_ELEMS(s_commands)) {
+ LOGE("unsupported request code %d token %d", request, token);
+ // TBD: this should return a response
+ return 0;
+ }
+
+
+ pRI = (RequestInfo *)calloc(1, sizeof(RequestInfo));
+
+ pRI->token = token;
+ pRI->fd = fd;
+ pRI->pCI = &(s_commands[request]);
+
+ ret = pthread_mutex_lock(&s_pendingRequestsMutex);
+ assert (ret == 0);
+
+ pRI->p_next = s_pendingRequests;
+ s_pendingRequests = pRI;
+
+ ret = pthread_mutex_unlock(&s_pendingRequestsMutex);
+ assert (ret == 0);
+
+ pRI->pCI->dispatchFunction(p, pRI);
+
+ return 0;
+}
+
+static void processCommandsCallback(int fd, void *param)
+{
+ RecordStream *p_rs;
+ void *p_record;
+ size_t recordlen;
+ int ret;
+
+ LOGD ("processCommandsCallback: fd=%d, s_fdCommand=%d", fd, s_fdCommand);
+
+ p_rs = (RecordStream *)param;
+
+
+ for (;;) {
+ /* loop until EAGAIN/EINTR, end of stream, or other error */
+ ret = record_stream_get_next(p_rs, &p_record, &recordlen);
+
+ LOGD ("processCommandsCallback: len=%d, ret=%d", recordlen, ret);
+ if (ret == 0 && p_record == NULL) {
+ LOGD ("processCommandsCallback: end of stream");
+ /* end-of-stream */
+ break;
+ } else if (ret < 0) {
+ break;
+ } else if (ret == 0) { /* && p_record != NULL */
+ processCommandBuffer(p_record, recordlen, fd);
+
+ }
+ }
+
+ //LOGD ("processCommandsCallback: errno=%d, ret=%d", errno, ret);
+ if (ret == 0 || !(errno == EAGAIN || errno == EINTR)) {
+ /* fatal error or end-of-stream */
+ if (ret != 0) {
+ LOGE("error on reading command socket errno:%d\n", errno);
+ } else {
+ LOGW("EOS. Closing command socket.");
+ }
+
+ LOGD ("processCommandsCallback: Closing");
+ close(s_fdCommand);
+ s_fdCommand = -1;
+
+ // cnd_event_del(&s_commands_event); // TODO - need to clean up properly
+
+ command_index = 0;
+
+ record_stream_free(p_rs);
+
+ /* start listening for new connections again */
+ cnd_event_add(&s_listen_event);
+
+ onCommandsSocketClosed();
+ }
+
+}
+
+static void listenCallback (int fd, void *param)
+{
+ int ret;
+ int err;
+ int is_cnm_svc_socket;
+ RecordStream *p_rs;
+ int i;
+ char tmpBuf[10];
+ int32_t pid, pid2, pid3, pid4;
+
+ struct sockaddr_un peeraddr;
+ socklen_t socklen = sizeof (peeraddr);
+
+ struct ucred creds;
+ socklen_t szCreds = sizeof(creds);
+
+
+ struct passwd *pwd = NULL;
+
+ assert (s_fdCommand < 0);
+ assert (fd == s_fdListen);
+
+ LOGD ("listenCallback: called");
+
+
+ s_fdCommand = accept(s_fdListen, (sockaddr *) &peeraddr, &socklen);
+
+
+ if (s_fdCommand < 0 ) {
+ LOGE("Error on accept() errno:%d", errno);
+ /* start listening for new connections again */
+ cnd_event_add(&s_listen_event);
+ return;
+ }
+
+ errno = 0;
+
+ err = getsockopt(s_fdCommand, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds);
+
+ cnmSvcFd = s_fdCommand; // save command descriptor to be used for communication
+
+ ret = fcntl(s_fdCommand, F_SETFL, O_NONBLOCK);
+
+ if (ret < 0) {
+ LOGE ("Error setting O_NONBLOCK errno = %d", errno);
+ }
+
+ LOGI("listenCallback: accept new connection, fd=%d", s_fdCommand);
+
+ p_rs = record_stream_new(s_fdCommand, MAX_COMMAND_BYTES);
+
+
+ // note: persistent = 1, not removed from table
+ if (command_index >= MAX_FD_EVENTS)
+ {
+ LOGE ("Error: exceeding number of supported connection");
+ return;
+ }
+ cnd_event_set (&s_commands_event[command_index], s_fdCommand, 1, processCommandsCallback, p_rs);
+
+ cnd_event_add (&s_commands_event[command_index]);
+
+ command_index++;
+
+ return;
+
+}
+
+
+static void *
+eventLoop(void *param)
+{
+ int ret;
+ int filedes[2];
+
+ LOGD ("eventLoop: s_started=%d", s_started);
+
+ pthread_mutex_lock(&s_startupMutex);
+
+ s_started = 1;
+ pthread_cond_broadcast(&s_startupCond);
+
+ pthread_mutex_unlock(&s_startupMutex);
+
+ cnd_event_loop();
+
+
+ return NULL;
+}
+
+extern "C" void
+cnd_startEventLoop(void)
+{
+ int ret;
+ pthread_attr_t attr;
+
+ /* spin up eventLoop thread and wait for it to get started */
+ s_started = 0;
+ pthread_mutex_lock(&s_startupMutex);
+
+ pthread_attr_init (&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ ret = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);
+
+
+ while (s_started == 0) {
+ pthread_cond_wait(&s_startupCond, &s_startupMutex);
+ }
+
+
+ pthread_mutex_unlock(&s_startupMutex);
+
+ if (ret < 0) {
+ LOGE("Failed to create dispatch thread errno:%d", errno);
+ return;
+ }
+}
+
+extern "C" void
+cnd_init (void)
+{
+ int ret;
+
+ if (s_registerCalled > 0) {
+ LOGE("cnd_init has been called more than once. "
+ "Subsequent call ignored");
+ return;
+ }
+
+ s_registerCalled = 1;
+
+ cnd_event_init();
+
+ cne_regMessageCb(cnd_sendUnsolicitedMsg);
+
+
+ s_fdListen = android_get_control_socket(SOCKET_NAME_CND);
+ if (s_fdListen < 0) {
+ LOGE("Failed to get socket '" SOCKET_NAME_CND "'");
+ exit(-1);
+ }
+
+ ret = listen(s_fdListen, 4);
+
+ if (ret < 0) {
+ LOGE("Failed to listen on control socket '%d': %s",
+ s_fdListen, strerror(errno));
+ exit(-1);
+ }
+
+
+ LOGD ("cnd_init: adding listenCallback event, fd=%d",s_fdListen);
+
+ /* note: non-persistent to accept only one connection at a time */
+ //cnd_event_set (&s_listen_event, s_fdListen, 0, listenCallback, NULL);
+
+ // persistent to accept multiple connections at same time
+ cnd_event_set (&s_listen_event, s_fdListen, 1, listenCallback, NULL);
+
+ cnd_event_add (&s_listen_event);
+
+
+}
+
+
+//extern "C" void - TBD -may want to change this function to extern "C" and
+// be called from CneCet where Cne components (SRM/SPM/CDE) may send the
+// response to Cne java
+static void
+cnd_commandComplete(CND_Token t, CND_Errno e, void *response, size_t responselen)
+{
+ RequestInfo *pRI;
+ int ret;
+ size_t errorOffset;
+
+ pRI = (RequestInfo *)t;
+
+ LOGD ("cnd_commandComplete: started");
+
+ if (!checkAndDequeueRequestInfo(pRI)) {
+ LOGE ("cnd_commandComplete: invalid CND_Token");
+ return;
+ }
+
+ if (pRI->local > 0) {
+ goto done;
+ }
+
+
+ if (pRI->cancelled == 0) {
+ Parcel p;
+
+ p.writeInt32 (SOLICITED_RESPONSE);
+ p.writeInt32 (pRI->token);
+ errorOffset = p.dataPosition();
+
+ p.writeInt32 (e);
+
+
+ if (e == CND_E_SUCCESS) {
+ /* process response on success */
+ ret = pRI->pCI->responseFunction(p, response, responselen);
+ LOGD ("cnd_commandComplete: ret = %d", ret);
+ /* if an error occurred, rewind and mark it */
+ if (ret != 0) {
+ p.setDataPosition(errorOffset);
+ p.writeInt32 (ret);
+ }
+ } else {
+ LOGE ("cnd_commandComplete: Error");
+ }
+
+ if (pRI->fd < 0) {
+ LOGE ("cnd_commandComplete: Command channel closed");
+ }
+ LOGD ("cnd_commandComplete: sending Response");
+ sendResponse(p, pRI->fd);
+ }
+
+done:
+ free(pRI);
+}
+
+} /* namespace android */
+
+