blob: 3debdc4aa96f6ecf3d90c7f9b635134c01a6ba65 [file] [log] [blame]
Lukas Häneldb4b53e2012-10-22 13:49:41 +02001/** @addtogroup MCD_MCDIMPL_DAEMON_SRV
2 * @{
3 * @file
4 *
5 * Connection data.
Oana Medvesanedfb7202013-02-06 21:58:30 +01006 */
7
8/* <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
Lukas Häneldb4b53e2012-10-22 13:49:41 +02009 *
Lukas Hänelf6f0f3d2012-05-21 11:21:57 +020010 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. The name of the author may not be used to endorse or promote
19 * products derived from this software without specific prior
20 * written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
23 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
26 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
28 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Lukas Häneldb4b53e2012-10-22 13:49:41 +020032 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34#include <unistd.h>
35#include <assert.h>
36#include <cstring>
37#include <errno.h>
38
39#include "Connection.h"
Oana Medvesanedfb7202013-02-06 21:58:30 +010040#include <sys/ioctl.h>
41#include <poll.h>
Lukas Häneldb4b53e2012-10-22 13:49:41 +020042
43//#define LOG_VERBOSE
44#include "log.h"
45
46
47//------------------------------------------------------------------------------
48Connection::Connection(void)
49{
50 connectionData = NULL;
51 // Set invalid socketDescriptor
52 socketDescriptor = -1;
53}
54
55
56//------------------------------------------------------------------------------
57Connection::Connection(int socketDescriptor, 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(void)
70{
71 LOG_V(" closing Connection...");
72 if (socketDescriptor != -1)
73 close(socketDescriptor);
74 LOG_I(" Socket connection closed.");
75}
76
77
78//------------------------------------------------------------------------------
79bool Connection::connect(const char *dest)
80{
81 int32_t len;
82
83 assert(NULL != dest);
Oana Medvesanedfb7202013-02-06 21:58:30 +010084 if (sizeof(remote.sun_path) - 1 < strlen(dest)) {
85 LOG_E("Invalid destination socket %s", dest);
86 return false;
87 }
Lukas Häneldb4b53e2012-10-22 13:49:41 +020088 LOG_I(" Connecting to %s socket", dest);
89 remote.sun_family = AF_UNIX;
Oana Medvesanedfb7202013-02-06 21:58:30 +010090 memset(remote.sun_path, 0, sizeof(remote.sun_path));
91 strncpy(remote.sun_path, dest, strlen(dest));
Lukas Häneldb4b53e2012-10-22 13:49:41 +020092 if ((socketDescriptor = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
93 LOG_ERRNO("Can't open stream socket.");
94 return false;
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 return false;
102 }
103 return true;
104}
105
106
107//------------------------------------------------------------------------------
108size_t Connection::readData(void *buffer, uint32_t len)
109{
110 return readData(buffer, len, -1);
111}
112
113
114//------------------------------------------------------------------------------
115size_t Connection::readData(void *buffer, uint32_t len, int32_t timeout)
116{
117 size_t ret = 0;
118 struct timeval tv;
119 struct timeval *ptv = NULL;
120 fd_set readfds;
121
122 assert(NULL != buffer);
123 assert(socketDescriptor != -1);
124
125 if (timeout >= 0) {
126 // Calculate timeout value
127 tv.tv_sec = timeout / 1000;
128 tv.tv_usec = (timeout - (tv.tv_sec * 1000)) * 1000;
129 ptv = &tv;
130 }
131
132 FD_ZERO(&readfds);
133 FD_SET(socketDescriptor, &readfds);
134 ret = select(socketDescriptor + 1, &readfds, NULL, NULL, ptv);
135
136 // check for read error
137 if ((int)ret == -1) {
138 LOG_ERRNO("select");
139 return -1;
140 }
141
142 // Handle case of no descriptor ready
Oana Medvesanedfb7202013-02-06 21:58:30 +0100143 if (ret == 0) {
Lukas Häneldb4b53e2012-10-22 13:49:41 +0200144 LOG_W(" Timeout during select() / No more notifications.");
145 return -2;
146 }
147
148 // one or more descriptors are ready
149
150 // finally check if fd has been selected -> must socketDescriptor
151 if (!FD_ISSET(socketDescriptor, &readfds)) {
152 LOG_ERRNO("no fd is set, select");
153 return ret;
154 }
155
156 ret = recv(socketDescriptor, buffer, len, MSG_DONTWAIT);
157 if (ret == 0) {
158 LOG_V(" readData(): peer orderly closed connection.");
159 }
160
161 return ret;
162}
163
164
165//------------------------------------------------------------------------------
166size_t Connection::writeData(void *buffer, uint32_t len)
167{
Oana Medvesanedfb7202013-02-06 21:58:30 +0100168 assert(buffer != NULL);
169 assert(socketDescriptor != -1);
Lukas Häneldb4b53e2012-10-22 13:49:41 +0200170
Oana Medvesanedfb7202013-02-06 21:58:30 +0100171 size_t ret = send(socketDescriptor, buffer, len, 0);
Lukas Häneldb4b53e2012-10-22 13:49:41 +0200172 if (ret != len) {
173 LOG_ERRNO("could not send all data, because send");
174 LOG_E("ret = %d", ret);
175 ret = -1;
176 }
177
178 return ret;
179}
180
181
182//------------------------------------------------------------------------------
183int Connection::waitData(int32_t timeout)
184{
185 size_t ret;
186 struct timeval tv;
187 struct timeval *ptv = NULL;
188 fd_set readfds;
189
190 assert(socketDescriptor != -1);
191
192 if (timeout >= 0) {
193 // Calculate timeout value
194 tv.tv_sec = timeout / 1000;
195 tv.tv_usec = (timeout - (tv.tv_sec * 1000)) * 1000;
196 ptv = &tv;
197 }
198
199 FD_ZERO(&readfds);
200 FD_SET(socketDescriptor, &readfds);
201 ret = select(socketDescriptor + 1, &readfds, NULL, NULL, ptv);
202
203 // check for read error
204 if ((int)ret == -1) {
205 LOG_ERRNO("select");
206 return ret;
207 } else if (ret == 0) {
208 LOG_E("select() timed out");
209 return -1;
210 }
211
212 return 0;
213}
214
Oana Medvesanedfb7202013-02-06 21:58:30 +0100215//------------------------------------------------------------------------------
216bool Connection::isConnectionAlive(void)
217{
218 assert(socketDescriptor != -1);
219 int retval;
220 struct pollfd ufds[1];
221 ufds[0].fd = socketDescriptor;
222 ufds[0].events = POLLRDHUP;
223
224 retval = poll(ufds, 1, 10);
225 if (retval < 0 || retval > 0) {
226 LOG_ERRNO("poll");
227 return false;
228 }
229 return true;
230}
231
Lukas Häneldb4b53e2012-10-22 13:49:41 +0200232/** @} */