Connection.cpp revision 9081ca65cb7959b6a06ba44823f84a6afa8bca2f
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_VERBOSE 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_V(" closing Connection..."); 73 if (socketDescriptor != -1) 74 close(socketDescriptor); 75 LOG_I(" Socket connection closed."); 76} 77 78 79//------------------------------------------------------------------------------ 80bool Connection::connect( 81 const char *dest 82) { 83 bool ret = false; 84 int32_t len; 85 86 assert(NULL != dest); 87 88 LOG_I(" Connecting to %s socket", dest); 89 do { 90 remote.sun_family = AF_UNIX; 91 strncpy(remote.sun_path, dest, sizeof(remote.sun_path) - 1); 92 if ((socketDescriptor = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { 93 LOG_ERRNO("Can't open stream socket."); 94 break; 95 } 96 len = strlen(remote.sun_path) + sizeof(remote.sun_family); 97 // The Daemon socket is in the Abstract Domain(LINUX ONLY!) 98 remote.sun_path[0] = 0; 99 if (::connect(socketDescriptor, (struct sockaddr *) &remote, len) < 0) { 100 LOG_ERRNO("connect()"); 101 break; 102 } 103 ret = true; 104 } while (false); 105 106 return ret; 107} 108 109 110//------------------------------------------------------------------------------ 111size_t Connection::readData( 112 void *buffer, 113 uint32_t len 114) { 115 return readData(buffer, len, -1); 116} 117 118 119//------------------------------------------------------------------------------ 120size_t Connection::readData( 121 void *buffer, 122 uint32_t len, 123 int32_t timeout 124) { 125 size_t ret; 126 struct timeval tv; 127 struct timeval *ptv = NULL; 128 fd_set readfds; 129 130 assert(NULL != buffer); 131 assert(-1 != socketDescriptor); 132 133 do{ 134 135 if(timeout >= 0){ 136 // Calculate timeout value 137 tv.tv_sec = timeout/1000; 138 tv.tv_usec = (timeout - (tv.tv_sec * 1000)) * 1000; 139 ptv = &tv; 140 } 141 142 FD_ZERO(&readfds); 143 FD_SET(socketDescriptor, &readfds); 144 ret = select(socketDescriptor + 1, &readfds, NULL, NULL, ptv); 145 146 // check for read error 147 if (-1 == (int)ret) { 148 LOG_ERRNO("select"); 149 break; 150 } 151 152 // Handle case of no descriptor ready 153 if (0 == ret) { 154 LOG_W(" Timeout during select() / No more notifications."); 155 ret = -2; 156 break; 157 } 158 159 // one or more descriptors are ready 160 161 // finally check if fd has been selected -> must socketDescriptor 162 if (!FD_ISSET(socketDescriptor, &readfds)) 163 { 164 LOG_ERRNO("no fd is set, select"); 165 break; 166 } 167 168 ret = recv(socketDescriptor, buffer, len, MSG_WAITALL); 169 if(0 == ret) 170 { 171 LOG_V(" readData(): peer orderly closed connection."); 172 break; 173 } 174// if (ret != len) 175// { 176// LOG_ERRNO("could not receive all requested data because read"); 177// LOG_E("ret = %d", ret); 178// ret = -1; 179// } 180 181 }while(false); 182 183 return ret; 184} 185 186 187//------------------------------------------------------------------------------ 188size_t Connection::writeData( 189 void *buffer, 190 uint32_t len 191) { 192 size_t ret; 193 194 assert(NULL != buffer); 195 assert(-1 != socketDescriptor); 196 197 ret = send(socketDescriptor, buffer, len, 0); 198 if (ret != len) 199 { 200 LOG_ERRNO("could not send all data, because send"); 201 LOG_E("ret = %d", ret); 202 ret = -1; 203 } 204 205 return ret; 206} 207 208/** @} */ 209