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