cmake_minimum_required (VERSION 2.6)
add_subdirectory(IpcModuleLoader)
-add_subdirectory(DbusIpcModule)
+
+#==============================================================================
+# TCP Socket IPC MODULE
+#==============================================================================
+option (WITH_IPC_MODULE_TCP "Build with TCP Ipc Module" OFF)
+
+if (WITH_IPC_MODULE_TCP)
+ add_subdirectory(TcpIpcModule)
+endif (WITH_IPC_MODULE_TCP)
+
+#==============================================================================
+# DBUS IPC MODULE
+#==============================================================================
+option (WITH_IPC_MODULE_DBUS "Build with D-Bus Ipc Module" ON)
+
+if (WITH_IPC_MODULE_DBUS)
+ add_subdirectory(DbusIpcModule)
+endif (WITH_IPC_MODULE_DBUS)
--- /dev/null
+############################################################################
+#
+# Copyright 2012 BMW Car IT GmbH
+#
+#
+# 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.
+#
+############################################################################
+
+cmake_minimum_required (VERSION 2.6)
+
+project (TcpIpcModule)
+
+include_directories(
+ include
+ ${CMAKE_SOURCE_DIR}/LayerManagerClient/ilmClient/include
+ ${CMAKE_SOURCE_DIR}/LayerManagerPlugins/IpcModules/IpcModuleLoader/include
+)
+
+add_library(${PROJECT_NAME} SHARED
+ src/append.c
+ src/get.c
+ src/initialization.c
+ src/message.c
+)
+
+set(LIBS
+ ${LIBS}
+)
+
+target_link_libraries(${PROJECT_NAME} ${LIBS})
+
+install (TARGETS ${PROJECT_NAME}
+ LIBRARY DESTINATION lib/layermanager/ipcmodules
+)
+
+if (WITH_TESTS)
+ add_executable(${PROJECT_NAME}_Test tests/LoopbackTest.cpp)
+ target_link_libraries(${PROJECT_NAME}_Test ${LIBS} IpcModuleLoader gtest gmock pthread)
+ enable_testing()
+ add_test(${PROJECT_NAME} ${PROJECT_NAME}_Test)
+endif(WITH_TESTS)
\ No newline at end of file
--- /dev/null
+/***************************************************************************
+ *
+ * Copyright 2012 BMW Car IT GmbH
+ *
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef _TCPSOCKETCONFIGURATION_H_
+#define _TCPSOCKETCONFIGURATION_H_
+
+//=============================================================================
+// tcp socket configuration
+//=============================================================================
+#define SOCKET_TCP_HOST "localhost"
+#define SOCKET_TCP_PORT 22232
+#define SOCKET_MAX_MESSAGE_SIZE 1024
+#define SOCKET_MAX_PENDING_CONNECTIONS 10
+
+#define SOCKET_MESSAGE_TYPE_NORMAL 'n'
+#define SOCKET_MESSAGE_TYPE_ERROR 'e'
+
+#define SOCKET_MESSAGE_TYPE_INT 'i'
+#define SOCKET_MESSAGE_TYPE_UINT 'u'
+#define SOCKET_MESSAGE_TYPE_BOOL 'b'
+#define SOCKET_MESSAGE_TYPE_DOUBLE 'd'
+#define SOCKET_MESSAGE_TYPE_STRING 's'
+#define SOCKET_MESSAGE_TYPE_ARRAY 'a'
+
+#define ENV_TCP_HOST "LM_TCP_HOST"
+#define ENV_TCP_PORT "LM_TCP_PORT"
+
+#endif // _TCPSOCKETCONFIGURATION_H_
--- /dev/null
+/***************************************************************************
+ *
+ * Copyright 2012 BMW Car IT GmbH
+ *
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef __SOCKETSHARED_H__
+#define __SOCKETSHARED_H__
+
+#include "socketConfiguration.h"
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h> // struct hostent
+#include <string.h>
+#include <stdio.h>
+
+//=============================================================================
+// type definitions
+//=============================================================================
+struct SocketState
+{
+ t_ilm_bool isClient;
+ int server;
+ int client;
+ struct sockaddr_in serverAddrIn;
+ struct sockaddr_in clientAddrIn;
+ fd_set monitoredSockets;
+ int monitoredSocketMax;
+};
+
+struct SocketMessage
+{
+ int size;
+ int type;
+ char data[SOCKET_MAX_MESSAGE_SIZE];
+};
+
+struct State
+{
+ struct SocketState socket;
+ struct SocketMessage message;
+ unsigned int writeIndex;
+ unsigned int readIndex;
+ int senderSocket;
+ char messageName[128];
+};
+
+
+//=============================================================================
+// global variables
+//=============================================================================
+struct State gState;
+
+
+//=============================================================================
+// logging / debugging
+//=============================================================================
+//#define LOG_ENTER_FUNCTION printf(" --> TcpSocketIpcModule::%s()\n", __FUNCTION__)
+#define LOG_ENTER_FUNCTION
+
+void printMessage();
+
+
+#endif // __SOCKETSHARED_H__
--- /dev/null
+/***************************************************************************
+ *
+ * Copyright 2012 BMW Car IT GmbH
+ *
+ *
+ * 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.
+ *
+ ****************************************************************************/
+#include "IpcModule.h"
+#include "socketShared.h"
+
+//-----------------------------------------------------------------------------
+// append simple data types
+//-----------------------------------------------------------------------------
+
+t_ilm_bool appendGenericValue(const char protocolType, const char size, const void* value)
+{
+ LOG_ENTER_FUNCTION;
+
+ // TODO: size check: is message size reached?
+
+ // append protocol type
+ gState.message.data[gState.writeIndex] = protocolType;
+ gState.writeIndex += sizeof(protocolType);
+
+ // append size of data
+ gState.message.data[gState.writeIndex] = size;
+ gState.writeIndex += sizeof(size);
+
+ // append data
+ memcpy(&gState.message.data[gState.writeIndex], value, size);
+ gState.writeIndex += size;
+
+ return ILM_TRUE;
+}
+
+t_ilm_bool appendUint(const t_ilm_uint value)
+{
+ return appendGenericValue(SOCKET_MESSAGE_TYPE_UINT, sizeof(t_ilm_uint), &value);
+}
+
+t_ilm_bool appendInt(const t_ilm_int value)
+{
+ return appendGenericValue(SOCKET_MESSAGE_TYPE_INT, sizeof(t_ilm_int), &value);
+}
+
+t_ilm_bool appendBool(const t_ilm_bool value)
+{
+ return appendGenericValue(SOCKET_MESSAGE_TYPE_BOOL, sizeof(t_ilm_bool), &value);
+}
+
+t_ilm_bool appendDouble(const t_ilm_float value)
+{
+ return appendGenericValue(SOCKET_MESSAGE_TYPE_DOUBLE, sizeof(t_ilm_float), &value);
+}
+
+t_ilm_bool appendString(t_ilm_const_string value)
+{
+ return appendGenericValue(SOCKET_MESSAGE_TYPE_STRING, strlen(value), value);
+}
+
+//-----------------------------------------------------------------------------
+// append array data types
+//-----------------------------------------------------------------------------
+
+t_ilm_bool appendGenericArray(const char arraySize, const char protocolType, const char size, const void* value)
+{
+ LOG_ENTER_FUNCTION;
+ t_ilm_bool result = ILM_TRUE;
+
+ // TODO: size check: is message size reached?
+
+ // append array type
+ gState.message.data[gState.writeIndex] = SOCKET_MESSAGE_TYPE_ARRAY;
+ gState.writeIndex += sizeof(protocolType);
+
+ // append size of array
+ gState.message.data[gState.writeIndex] = arraySize;
+ gState.writeIndex += sizeof(arraySize);
+
+ // append data for each array entry
+ char i = 0;
+ for (i = 0; i < arraySize; ++i)
+ {
+ result &= appendGenericValue(protocolType, size, value + i * size);
+ }
+
+ return result;
+}
+
+t_ilm_bool appendUintArray(const t_ilm_uint* valueArray, t_ilm_int arraySize)
+{
+ return appendGenericArray(arraySize, SOCKET_MESSAGE_TYPE_UINT, sizeof(t_ilm_uint), valueArray);
+}
+
+t_ilm_bool appendIntArray(const t_ilm_int* valueArray, t_ilm_int arraySize)
+{
+ return appendGenericArray(arraySize, SOCKET_MESSAGE_TYPE_INT, sizeof(t_ilm_int), valueArray);
+}
+
+t_ilm_bool appendBoolArray(const t_ilm_bool* valueArray, t_ilm_int arraySize)
+{
+ return appendGenericArray(arraySize, SOCKET_MESSAGE_TYPE_BOOL, sizeof(t_ilm_bool), valueArray);
+}
+
+t_ilm_bool appendDoubleArray(const t_ilm_float* valueArray, t_ilm_int arraySize)
+{
+ return appendGenericArray(arraySize, SOCKET_MESSAGE_TYPE_DOUBLE, sizeof(t_ilm_float), valueArray);
+}
+
+// TODO appendStringArray()
--- /dev/null
+/***************************************************************************
+ *
+ * Copyright 2012 BMW Car IT GmbH
+ *
+ *
+ * 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.
+ *
+ ****************************************************************************/
+#include "IpcModule.h"
+#include "socketShared.h"
+#include <stdio.h>
+#include <stdlib.h> // malloc
+
+//-----------------------------------------------------------------------------
+// get simple data types
+//-----------------------------------------------------------------------------
+
+t_ilm_bool getGenericValue(void* value, const char protocolType, const char expectedSize)
+{
+ LOG_ENTER_FUNCTION;
+ t_ilm_bool result = ILM_FALSE;
+
+ // get protocol value from message
+ char readType = gState.message.data[gState.readIndex];
+ gState.readIndex += sizeof(readType);
+
+ // if type mismatch, return to previous state, return with error
+ if (readType != protocolType)
+ {
+ gState.readIndex -= sizeof(readType);
+ printf("command value type mismatch: expected '%s', got '%s'.\n",
+ &protocolType, &readType);
+ return ILM_FALSE;
+ }
+
+ // get size of value
+ char size = gState.message.data[gState.readIndex];
+ gState.readIndex += sizeof(size);
+
+ // if size mismatch, return to previous state, return with error
+ // exception: strings have varying length
+ if (protocolType != SOCKET_MESSAGE_TYPE_STRING
+ && size != expectedSize)
+ {
+ gState.readIndex -= sizeof(readType);
+ gState.readIndex -= sizeof(size);
+ printf("command value size mismatch for type '%s': "
+ "expected %d bytes, got %d bytes.\n",
+ &protocolType, expectedSize, size);
+ return ILM_FALSE;
+ }
+
+ // copy data to caller
+ memcpy(value, &gState.message.data[gState.readIndex], size);
+ gState.readIndex += size;
+
+ // if value is string, add end of string
+ if (protocolType == SOCKET_MESSAGE_TYPE_STRING)
+ {
+ char* str = value;
+ str[size] = '\0';
+ }
+
+ return ILM_TRUE;
+}
+
+t_ilm_bool getUint(t_ilm_uint* value)
+{
+ LOG_ENTER_FUNCTION;
+ return getGenericValue(value, SOCKET_MESSAGE_TYPE_UINT, sizeof(t_ilm_uint));
+}
+
+t_ilm_bool getInt(t_ilm_int* value)
+{
+ LOG_ENTER_FUNCTION;
+ return getGenericValue(value, SOCKET_MESSAGE_TYPE_INT, sizeof(t_ilm_int));
+}
+
+t_ilm_bool getBool(t_ilm_bool* value)
+{
+ LOG_ENTER_FUNCTION;
+ return getGenericValue(value, SOCKET_MESSAGE_TYPE_BOOL, sizeof(t_ilm_bool));
+}
+
+t_ilm_bool getDouble(t_ilm_float* value)
+{
+ LOG_ENTER_FUNCTION;
+ return getGenericValue(value, SOCKET_MESSAGE_TYPE_DOUBLE, sizeof(t_ilm_float));
+}
+
+t_ilm_bool getString(char* value)
+{
+ LOG_ENTER_FUNCTION;
+ return getGenericValue(value, SOCKET_MESSAGE_TYPE_STRING, sizeof(t_ilm_const_string));
+}
+
+//-----------------------------------------------------------------------------
+// get array data types
+//-----------------------------------------------------------------------------
+
+t_ilm_bool getGenericArray(t_ilm_int* arraySize, void** value, const char protocolType, const char expectedSize)
+{
+ LOG_ENTER_FUNCTION;
+ t_ilm_bool result = ILM_TRUE;
+
+ // get protocol value from message
+ char readType = gState.message.data[gState.readIndex];
+ gState.readIndex += sizeof(readType);
+
+ // if type mismatch, return to previous state, return with error
+ if (readType != SOCKET_MESSAGE_TYPE_ARRAY)
+ {
+ gState.readIndex -= sizeof(readType);
+ printf("command value type mismatch: expected '%c', got '%s'.\n",
+ SOCKET_MESSAGE_TYPE_ARRAY, &readType);
+ return ILM_FALSE;
+ }
+
+ // get size of array
+ *arraySize = gState.message.data[gState.readIndex];
+ gState.readIndex += sizeof(gState.message.data[gState.readIndex]);
+
+ // create array for result and set callers pointer
+ *value = malloc(*arraySize * expectedSize);
+
+ // get all values from array
+ char i = 0;
+ for (i = 0; i < *arraySize; ++i)
+ {
+ result &= getGenericValue(((*value) + expectedSize * i), protocolType, expectedSize);
+ }
+
+ return result;
+}
+
+t_ilm_bool getIntArray(t_ilm_int** valueArray, t_ilm_int* arraySize)
+{
+ LOG_ENTER_FUNCTION;
+ return getGenericArray(arraySize, (void**)valueArray, SOCKET_MESSAGE_TYPE_INT, sizeof(t_ilm_int));
+}
+
+t_ilm_bool getUintArray(t_ilm_uint** valueArray, t_ilm_int* arraySize)
+{
+ LOG_ENTER_FUNCTION;
+ return getGenericArray(arraySize, (void**)valueArray, SOCKET_MESSAGE_TYPE_UINT, sizeof(t_ilm_uint));
+}
+
--- /dev/null
+/***************************************************************************
+ *
+ * Copyright 2012 BMW Car IT GmbH
+ *
+ *
+ * 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.
+ *
+ ****************************************************************************/
+#include "IpcModule.h"
+#include "socketShared.h"
+#include <stdio.h>
+#include <stdlib.h> // getenv
+#include <string.h> // memset
+
+
+t_ilm_bool init(t_ilm_bool isClient)
+{
+ LOG_ENTER_FUNCTION;
+ t_ilm_bool result = ILM_TRUE;
+
+ struct SocketState* sock = &gState.socket;
+
+ sock->isClient = isClient;
+
+ sock->server = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+ if (sock->server < 0)
+ {
+ printf("TcpIpcModule: socket()...failed\n");
+ result = ILM_FALSE;
+ }
+
+ const char* portString = getenv(ENV_TCP_PORT);
+ int port = SOCKET_TCP_PORT;
+ if (portString)
+ {
+ port = atoi(portString);
+ }
+
+ sock->serverAddrIn.sin_family = AF_INET;
+ sock->serverAddrIn.sin_port = htons(port);
+ memset(&(sock->serverAddrIn.sin_zero), '\0', 8);
+
+ if (sock->isClient) // Client
+ {
+ const char* hostname = getenv(ENV_TCP_HOST);
+ if (!hostname)
+ {
+ hostname = SOCKET_TCP_HOST;
+ }
+
+ struct hostent* server;
+ server = gethostbyname(hostname);
+ if (!server)
+ {
+ printf("TcpIpcModule: error: could not resolve host '%s'.\n", hostname);
+ result = ILM_FALSE;
+ }
+ else
+ {
+ memcpy(&sock->serverAddrIn.sin_addr.s_addr, server->h_addr, server->h_length);
+ }
+
+ if (0 != connect(sock->server,
+ (struct sockaddr *) &sock->serverAddrIn,
+ sizeof(sock->serverAddrIn)))
+ {
+ result = ILM_FALSE;
+ }
+
+ printf("TcpIpcModule: connection to %s:%d %s.\n",
+ hostname, port,
+ (ILM_TRUE == result) ? "established" : "failed");
+
+ FD_SET(sock->server, &sock->monitoredSockets);
+ sock->monitoredSocketMax = sock->server;
+ }
+ else // LayerManagerService
+ {
+ int on = 1;
+ setsockopt(sock->server, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+
+ sock->serverAddrIn.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ if (0 > bind(sock->server,
+ (struct sockaddr *) &sock->serverAddrIn,
+ sizeof(sock->serverAddrIn)))
+ {
+ printf("TcpIpcModule: bind()...failed\n");
+ result = ILM_FALSE;
+ }
+
+ if (listen(sock->server, SOCKET_MAX_PENDING_CONNECTIONS) < 0)
+ {
+ printf("TcpIpcModule: listen()...failed\n");
+ result = ILM_FALSE;
+ }
+
+ FD_SET(sock->server, &sock->monitoredSockets);
+ sock->monitoredSocketMax = sock->server;
+
+ printf("TcpIpcModule: listening to TCP port: %d\n", port);
+ }
+
+ return result;
+}
+
+t_ilm_bool destroy()
+{
+ LOG_ENTER_FUNCTION;
+ int socketNumber;
+ for (socketNumber = 0; socketNumber <= gState.socket.monitoredSocketMax; ++socketNumber)
+ {
+ if (FD_ISSET(socketNumber, &gState.socket.monitoredSockets))
+ {
+ printf("TcpIpcModule: Closing socket %d\n", socketNumber);
+ close(socketNumber);
+ }
+ }
+ return ILM_TRUE;
+}
+
--- /dev/null
+/***************************************************************************
+ *
+ * Copyright 2012 BMW Car IT GmbH
+ *
+ *
+ * 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.
+ *
+ ****************************************************************************/
+#include "IpcModule.h"
+#include "socketShared.h"
+#include <errno.h>
+#include <stdio.h>
+#include <sys/select.h>
+
+
+//=============================================================================
+// prototypes
+//=============================================================================
+t_ilm_bool acceptClientConnection();
+int receiveFromSocket();
+
+
+//=============================================================================
+// message handling
+//=============================================================================
+t_ilm_bool createMessage(t_ilm_const_string name)
+{
+ LOG_ENTER_FUNCTION;
+
+ memset(&gState.message, 0, sizeof(gState.message));
+
+ gState.message.type = SOCKET_MESSAGE_TYPE_NORMAL;
+ gState.readIndex = 0;
+ gState.writeIndex = 0;
+
+ return appendString(name);
+}
+
+t_ilm_bool sendMessage()
+{
+ LOG_ENTER_FUNCTION;
+ int activesocket = 0;
+ int sentBytes = 0;
+ int retVal = 0;
+
+ int headerSize = sizeof(gState.message) - sizeof(gState.message.data);
+ gState.message.size = gState.writeIndex + headerSize;
+
+ if (gState.socket.isClient)
+ {
+ activesocket = gState.socket.server;
+ }
+ else
+ {
+ activesocket = gState.senderSocket;
+ }
+
+ int sendSize = gState.message.size;
+
+ do
+ {
+ retVal += send(activesocket,
+ &gState.message + sentBytes,
+ sendSize - sentBytes,
+ 0);
+ sentBytes += retVal;
+ } while (retVal > 0 && sentBytes < sendSize);
+
+ //printf(" --> TcpIpcModule: %d bytes sent to socket %d\n", sentBytes, activesocket);
+
+ return (sentBytes == sendSize) ? ILM_TRUE : ILM_FALSE;
+}
+
+t_ilm_bool sendError(t_ilm_const_string desc)
+{
+ LOG_ENTER_FUNCTION;
+
+ gState.message.type = SOCKET_MESSAGE_TYPE_ERROR;
+
+ // reset content to error description
+ gState.writeIndex = 0;
+ appendString(desc);
+
+ return sendMessage();
+}
+
+enum IpcMessageType receiveMessage(t_ilm_int timeoutInMs)
+{
+ LOG_ENTER_FUNCTION;
+ enum IpcMessageType result = IpcMessageTypeNone;
+
+ gState.readIndex = 0;
+ gState.writeIndex = 0;
+
+ fd_set readFds = gState.socket.monitoredSockets;
+
+ struct timeval timeoutValue;
+ timeoutValue.tv_sec = timeoutInMs / 1000;
+ timeoutValue.tv_usec = (timeoutInMs % 1000) * 1000;
+
+ int numberOfFdsReady = select(gState.socket.monitoredSocketMax + 1, &readFds, 0, 0, &timeoutValue);
+
+ if (-1 == numberOfFdsReady)
+ {
+ printf("TcpIpcModule: select() failed\n");
+ }
+ else if (0 < numberOfFdsReady)
+ {
+ int socketNumber;
+ for (socketNumber = 0; socketNumber <= gState.socket.monitoredSocketMax; ++socketNumber)
+ {
+ if (FD_ISSET(socketNumber, &readFds))
+ {
+ if (!gState.socket.isClient)
+ {
+ if (gState.socket.server == socketNumber)
+ {
+ // New client connected
+ acceptClientConnection();
+ result = IpcMessageTypeNone; // no data received
+ continue;
+ }
+
+ // receive data from socket
+ gState.senderSocket = socketNumber;
+ receiveFromSocket();
+
+ if(gState.message.size > 0)
+ {
+ // new message from client
+ getString(gState.messageName);
+ result = IpcMessageTypeCommand;
+ continue;
+ }
+
+ if(gState.message.size == 0)
+ {
+ // client disconnected
+ close(socketNumber);
+ FD_CLR(socketNumber, &gState.socket.monitoredSockets);
+ result = IpcMessageTypeDisconnect;
+ continue;
+ }
+
+ // error
+ const char* errorMsg = (char*)strerror(errno);
+ printf(" --> TcpIpcModule: Error receiving data from socket %d (%s)\n",
+ gState.senderSocket, errorMsg);
+ result = IpcMessageTypeError;
+ }
+ else
+ {
+ // receive LayerManager response
+ gState.senderSocket = socketNumber;
+ receiveFromSocket(gState.senderSocket);
+ getString(gState.messageName);
+ result = IpcMessageTypeCommand;
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+t_ilm_const_string getMessageName()
+{
+ LOG_ENTER_FUNCTION;
+ return gState.messageName;
+}
+
+t_ilm_bool isErrorMessage()
+{
+ LOG_ENTER_FUNCTION;
+ return (SOCKET_MESSAGE_TYPE_ERROR == gState.message.type);
+}
+
+t_ilm_const_string getSenderName()
+{
+ LOG_ENTER_FUNCTION;
+ char buffer[16];
+ sprintf(buffer, "socket %d", gState.senderSocket);
+ return strdup(buffer);
+}
+
+//=============================================================================
+//private
+//=============================================================================
+t_ilm_bool acceptClientConnection()
+{
+ LOG_ENTER_FUNCTION;
+
+ t_ilm_bool result = ILM_TRUE;
+ unsigned int clientlen = sizeof(gState.socket.clientAddrIn);
+
+ gState.socket.client = accept(gState.socket.server, (struct sockaddr *) &gState.socket.clientAddrIn, &clientlen);
+
+ if (gState.socket.client < 0)
+ {
+ printf("TcpIpcModule: accept() failed.\n");
+ result = ILM_FALSE;
+ }
+
+ FD_SET(gState.socket.client, &gState.socket.monitoredSockets);
+ gState.socket.monitoredSocketMax = (gState.socket.monitoredSocketMax > gState.socket.client) ? gState.socket.monitoredSocketMax : gState.socket.client;
+
+ return result;
+}
+
+int receiveFromSocket()
+{
+ LOG_ENTER_FUNCTION;
+ int receivedBytes = 0;
+ int retVal = 0;
+
+ // receive header in first run (contains message size)
+ gState.message.size = sizeof(gState.message) - sizeof(gState.message.data);
+
+ char* messageBuffer = (char*)&gState.message;
+
+ do
+ {
+ retVal = recv(gState.senderSocket,
+ &messageBuffer[receivedBytes],
+ gState.message.size - receivedBytes,
+ 0);
+ receivedBytes += retVal;
+ } while ((retVal > 0) && (receivedBytes < gState.message.size));
+
+ if (0 == retVal)
+ {
+ // client disconnect
+ gState.message.size = 0;
+ }
+}
+
+
+//=============================================================================
+// logging / debugging
+//=============================================================================
+void printMessage()
+{
+ LOG_ENTER_FUNCTION;
+
+ printf(" --> Message type: %s\n", (gState.message.type == SOCKET_MESSAGE_TYPE_NORMAL) ? "normal" : "error");
+ printf(" --> Message size: %d\n", gState.message.size);
+
+ int i = 0;
+
+ char headersize = sizeof(gState.message) - sizeof(gState.message.data);
+
+ // iterate over message data
+ while (i < gState.message.size - headersize)
+ {
+ // read type information
+ char type = gState.message.data[i++];
+ char datasize = gState.message.data[i++];
+
+ // set pointer to value data
+ char* data = &gState.message.data[i];
+
+ // print data
+ switch (type)
+ {
+ case SOCKET_MESSAGE_TYPE_ARRAY:
+ printf(" --> Array, %d entries:\n", datasize);
+ datasize = 0;
+ break;
+
+ case SOCKET_MESSAGE_TYPE_STRING:
+ printf(" --> String: '%s' (%d bytes)\n", data, datasize);
+ break;
+
+ case SOCKET_MESSAGE_TYPE_UINT:
+ printf(" --> UInt: %u (%d bytes)\n", *(t_ilm_uint*)data, datasize);
+ break;
+
+ case SOCKET_MESSAGE_TYPE_INT:
+ printf(" --> Int: %d (%d bytes)\n", *(t_ilm_int*)data, datasize);
+ break;
+
+ case SOCKET_MESSAGE_TYPE_DOUBLE:
+ printf(" --> Double: %lf (%d bytes)\n", *(t_ilm_float*)data, datasize);
+ break;
+
+ case SOCKET_MESSAGE_TYPE_BOOL:
+ printf(" --> Bool: %d (%d bytes)\n", *data, datasize);
+ break;
+
+ default:
+ printf(" --> Unknown type (%s), %d bytes\n", (char*)&type, datasize);
+ break;
+ }
+
+ // skip already processed data
+ i += datasize;
+ }
+}
+
--- /dev/null
+/***************************************************************************
+ *
+ * Copyright 2012 BMW Car IT GmbH
+ *
+ *
+ * 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.
+ *
+ ****************************************************************************/
+#include "IpcModuleLoader.h"
+#include <gtest/gtest.h>
+
+#define PLATFORM_PTR_SIZE sizeof(unsigned int*)
+
+class Loopback : public ::testing::Test
+{
+public:
+ void SetUp()
+ {
+ loadAndCheckIpcModule(&mService);
+ //loadAndCheckIpcModule(&mClient);
+ }
+
+ void loadAndCheckIpcModule(IpcModule* ipcModule)
+ {
+ memset(ipcModule, 0, sizeof(*ipcModule));
+ ASSERT_EQ(ILM_TRUE, loadIpcModule(ipcModule));
+
+ int apiEntryCount = sizeof(*ipcModule) / PLATFORM_PTR_SIZE;
+ unsigned int* base = (unsigned int*)ipcModule;
+ for (int i = 0; i < apiEntryCount; ++i)
+ {
+ ASSERT_NE(0, base[i]);
+ }
+ }
+
+ void TearDown()
+ {
+ //memset(&mClient, 0, sizeof(mClient));
+ memset(&mService, 0, sizeof(mService));
+ }
+
+protected:
+ IpcModule mService;
+ //IpcModule mClient;
+};
+
+TEST_F(Loopback, DISABLE_lifecycle)
+{
+ ASSERT_TRUE(mService.init(ILM_FALSE));
+ //ASSERT_TRUE(mClient.init(ILM_TRUE));
+
+ //ASSERT_TRUE(mClient.destroy());
+ ASSERT_TRUE(mService.destroy());
+}