Connection.cpp revision 4e9e8c9c0169b40318386436d762c3d73cf4c328
1/** @addtogroup MCD_MCDIMPL_DAEMON_SRV 2 * @{ 3 * @file 4 * 5 * Connection data. 6 * 7 * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote 18 * products derived from this software without specific prior 19 * written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 22 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33#include <unistd.h> 34#include <assert.h> 35#include <cstring> 36#include <errno.h> 37 38#include "Connection.h" 39 40#define LOG_TAG "McClient" 41#include "log.h" 42 43 44//------------------------------------------------------------------------------ 45Connection::Connection( 46 void 47) { 48 connectionData = NULL; 49 // Set invalid socketDescriptor 50 socketDescriptor = -1; 51} 52 53 54//------------------------------------------------------------------------------ 55Connection::Connection( 56 int socketDescriptor, 57 sockaddr_un *remote 58) { 59 assert(NULL != remote); 60 assert(-1 != socketDescriptor); 61 62 this->socketDescriptor = socketDescriptor; 63 this->remote = *remote; 64 connectionData = NULL; 65} 66 67 68//------------------------------------------------------------------------------ 69Connection::~Connection( 70 void 71) { 72 LOG_I("%s: Connection closed!", __func__); 73 if (socketDescriptor != -1) 74 close(socketDescriptor); 75} 76 77 78//------------------------------------------------------------------------------ 79bool Connection::connect( 80 const char *dest 81) { 82 bool ret = false; 83 int32_t len; 84 85 assert(NULL != dest); 86 87 LOG_I("connect(): Connecting to %s", dest); 88 do { 89 remote.sun_family = AF_UNIX; 90 strncpy(remote.sun_path, dest, sizeof(remote.sun_path) - 1); 91 if ((socketDescriptor = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { 92 LOG_E("Can't open stream socket - errno: %d", errno); 93 break; 94 } 95 len = strlen(remote.sun_path) + sizeof(remote.sun_family); 96 // The Daemon socket is in the Abstract Domain(LINUX ONLY!) 97 remote.sun_path[0] = 0; 98 if (::connect(socketDescriptor, (struct sockaddr *) &remote, len) < 0) { 99 LOG_E("connect() failed - errno: %d", errno); 100 break; 101 } 102 ret = true; 103 } while (false); 104 105 return ret; 106} 107 108 109//------------------------------------------------------------------------------ 110size_t Connection::readData( 111 void *buffer, 112 uint32_t len 113) { 114 return readData(buffer, len, -1); 115} 116 117 118//------------------------------------------------------------------------------ 119size_t Connection::readData( 120 void *buffer, 121 uint32_t len, 122 int32_t timeout 123) { 124 size_t ret; 125 struct timeval tv; 126 struct timeval *ptv = NULL; 127 fd_set readfds; 128 129 assert(NULL != buffer); 130 assert(-1 != socketDescriptor); 131 132 do{ 133 134 if(timeout >= 0){ 135 // Calculate timeout value 136 tv.tv_sec = timeout/1000; 137 tv.tv_usec = (timeout - (tv.tv_sec * 1000)) * 1000; 138 ptv = &tv; 139 } 140 141 FD_ZERO(&readfds); 142 FD_SET(socketDescriptor, &readfds); 143 ret = select(socketDescriptor + 1, &readfds, NULL, NULL, ptv); 144 145 // check for read error 146 if (-1 == (int)ret) { 147 LOG_E("readData(): select() failed, ret=%d, errno=%d", ret,errno); 148 break; 149 } 150 151 // Handle case of no descriptor ready 152 if (0 == ret) { 153 LOG_W("readData(): select() timed out"); 154 ret = -2; 155 break; 156 } 157 158 // one or more descriptors are ready 159 160 // finally check if fd has been selected -> must socketDescriptor 161 if (!FD_ISSET(socketDescriptor, &readfds)) 162 { 163 LOG_E("readData(): failure, errno=%d", errno); 164 break; 165 } 166 167 ret = recv(socketDescriptor, buffer, len, MSG_WAITALL); 168 if(0 == ret) 169 { 170 LOG_I("readData(): peer orderly closed connection."); 171 break; 172 } 173 174 }while(false); 175 176 return ret; 177} 178 179 180//------------------------------------------------------------------------------ 181size_t Connection::writeData( 182 void *buffer, 183 uint32_t len 184) { 185 size_t ret; 186 187 assert(NULL != buffer); 188 assert(-1 != socketDescriptor); 189 190 ret = send(socketDescriptor, buffer, len, 0); 191 if (ret != len) 192 { 193 LOG_E( "writeData(): could no send all data, ret=%d, errno: %d", ret,errno); 194 ret = -1; 195 } 196 197 return ret; 198} 199 200/** @} */ 201