3D-ICE 3.0.0
network_socket.c
1/******************************************************************************
2 * This file is part of 3D-ICE, version 3.1.0 . *
3 * *
4 * 3D-ICE is free software: you can redistribute it and/or modify it under *
5 * the terms of the GNU General Public License as published by the Free *
6 * Software Foundation, either version 3 of the License, or any later *
7 * version. *
8 * *
9 * 3D-ICE is distributed in the hope that it will be useful, but WITHOUT *
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for *
12 * more details. *
13 * *
14 * You should have received a copy of the GNU General Public License along *
15 * with 3D-ICE. If not, see <http://www.gnu.org/licenses/>. *
16 * *
17 * Copyright (C) 2021 *
18 * Embedded Systems Laboratory - Ecole Polytechnique Federale de Lausanne *
19 * All Rights Reserved. *
20 * *
21 * Authors: Arvind Sridhar Alessandro Vincenzi *
22 * Giseong Bak Martino Ruggiero *
23 * Thomas Brunschwiler Eder Zulian *
24 * Federico Terraneo Darong Huang *
25 * Luis Costero Marina Zapater *
26 * David Atienza *
27 * *
28 * For any comment, suggestion or request about 3D-ICE, please register and *
29 * write to the mailing list (see http://listes.epfl.ch/doc.cgi?liste=3d-ice) *
30 * Any usage of 3D-ICE for research, commercial or other purposes must be *
31 * properly acknowledged in the resulting products or publications. *
32 * *
33 * EPFL-STI-IEL-ESL Mail : 3d-ice@listes.epfl.ch *
34 * Batiment ELG, ELG 130 (SUBSCRIPTION IS NECESSARY) *
35 * Station 11 *
36 * 1015 Lausanne, Switzerland Url : http://esl.epfl.ch/3d-ice *
37 ******************************************************************************/
38
39#include <stdio.h> // For the function perror
40#include <errno.h> // For the function perror
41#include <string.h> // For the memory function memset
42#include <unistd.h>
43#include <errno.h>
44
45#include <arpa/inet.h>
46#include <sys/socket.h>
47
48#include "network_socket.h"
49
50/******************************************************************************/
51
52void socket_init (Socket_t *socket)
53{
54 socket->Id = 0 ;
55
56 memset ((void *) &(socket->Address), 0, sizeof (struct sockaddr_in)) ;
57
58 memset ((void *) &(socket->HostName), '\0', sizeof (socket->HostName)) ;
59
60 socket->PortNumber = 0u ;
61}
62
63/******************************************************************************/
64
66{
67 csocket->Id = socket (AF_INET, SOCK_STREAM, 0) ;
68
69 if (csocket->Id < 0)
70 {
71 perror ("ERROR :: client socket creation") ;
72
73 return TDICE_FAILURE ;
74 }
75
76 return TDICE_SUCCESS ;
77}
78
79/******************************************************************************/
80
82(
83 Socket_t *ssocket,
84 PortNumber_t port_number
85)
86{
87 ssocket->Id = socket (AF_INET, SOCK_STREAM, 0) ;
88
89 if (ssocket->Id < 0)
90 {
91 perror ("ERROR :: server socket creation") ;
92
93 return TDICE_FAILURE ;
94 }
95
96 ssocket->Address.sin_family = AF_INET ;
97 ssocket->Address.sin_port = htons (port_number) ;
98 ssocket->Address.sin_addr.s_addr = htonl (INADDR_ANY) ;
99
100 if (bind (ssocket->Id, (struct sockaddr *) &ssocket->Address,
101 sizeof (struct sockaddr_in)) < 0)
102 {
103 perror ("ERROR :: server bind") ;
104
105 socket_close (ssocket) ;
106
107 return TDICE_FAILURE ;
108 }
109
110 if (listen (ssocket->Id, 1) < 0)
111 {
112 perror ("ERROR :: server listen") ;
113
114 socket_close (ssocket) ;
115
116 return TDICE_FAILURE ;
117 }
118
119 return TDICE_SUCCESS ;
120}
121
122/******************************************************************************/
123
125(
126 Socket_t *csocket,
127 String_t host_name,
128 PortNumber_t port_number
129)
130{
131 strcpy (csocket->HostName, host_name) ;
132
133 csocket->PortNumber = port_number ;
134
135 csocket->Address.sin_family = AF_INET ;
136 csocket->Address.sin_port = htons (port_number) ;
137
138 if (inet_pton (AF_INET, host_name, &(csocket->Address).sin_addr) <= 0)
139 {
140 perror ("ERROR :: server address creation") ;
141
142 socket_close (csocket) ;
143
144 return TDICE_FAILURE ;
145 }
146
147 if (connect (csocket->Id, (struct sockaddr *) &csocket->Address,
148 sizeof (struct sockaddr_in)) < 0)
149 {
150 perror ("ERROR :: client to server connection") ;
151
152 socket_close (csocket) ;
153
154 return TDICE_FAILURE ;
155 }
156
157 return TDICE_SUCCESS ;
158}
159
160/******************************************************************************/
161
163{
164 socklen_t length = sizeof (struct sockaddr_in) ;
165
166 client->Id = accept
167
168 (ssocket->Id, (struct sockaddr *) &(client->Address), &length) ;
169
170 if (client->Id < 0)
171 {
172 perror ("ERROR :: server accept") ;
173
174 socket_close (ssocket) ;
175
176 return TDICE_FAILURE ;
177 }
178
179 client->PortNumber = ntohs (client->Address.sin_port) ;
180
181 if (inet_ntop (AF_INET, &client->Address.sin_addr,
182 client->HostName, sizeof (client->HostName)) == NULL)
183 {
184 perror ("ERROR :: client name translation") ;
185
186 socket_close (client) ;
187 socket_close (ssocket) ;
188
189 return TDICE_FAILURE ;
190 }
191
192 return TDICE_SUCCESS ;
193}
194
195/******************************************************************************/
196
198(
199 Socket_t *socket,
200 NetworkMessage_t *message
201)
202{
203 // length stores the total number of bytes to send
204 // --> The length of the message times the size of a word
205
206 size_t length = (size_t) *message->Length * sizeof (MessageWord_t) ;
207
208 // Begin points to th beginning of the message ...
209
210 MessageWord_t *begin = (MessageWord_t *) message->Memory ;
211
212 while (length > 0)
213 {
214
215 // sends "length" bytes ...
216
217 ssize_t bwritten = write (socket->Id, begin, length) ;
218
219 // and check how many bytes are actually sent
220
221 if (bwritten < 0)
222 {
223 if (errno == EINTR)
224
225 continue ;
226
227 else
228 {
229 perror ("ERROR :: write message failure") ;
230
231 return TDICE_FAILURE ;
232 }
233 }
234
235 // decreases by the #bytes sent
236
237 length -= (size_t) bwritten ;
238
239 // moves the pointer forward (# of words sent)
240
241 begin += (MessageWord_t) (bwritten / sizeof (MessageWord_t)) ;
242 }
243
244 return TDICE_SUCCESS ;
245}
246
247/******************************************************************************/
248
250(
251 Socket_t *socket,
252 NetworkMessage_t *message
253)
254{
255 MessageWord_t message_length ;
256
257 // reads the first word : the number of words to receive
258
259 ssize_t bread = read (socket->Id, &message_length, sizeof(message_length)) ;
260
261 if (bread < 0 || bread != sizeof(message_length))
262 {
263 perror ("ERROR :: read message length failure") ;
264
265 return TDICE_FAILURE ;
266 }
267
268 if (message_length > message->MaxLength)
269
270 increase_message_memory (message, message_length) ;
271
272 // stores the length of the message
273
274 *message->Length = (MessageWord_t) message_length ;
275
276 // now one whord has already been read !
277
278 message_length-- ;
279
280 // scale the remaining number of words to read to the number of bytes
281
282 message_length *= sizeof (MessageWord_t) ;
283
284 MessageWord_t *begin = message->MType ;
285
286 while (message_length > 0)
287 {
288 bread = read (socket->Id, begin, message_length) ;
289
290 if (bread < 0)
291 {
292 if (errno == EINTR)
293
294 continue ;
295
296 else
297 {
298 perror ("ERROR :: read failure") ;
299
300 return TDICE_FAILURE ;
301 }
302 }
303
304 // decreases by the #bytes read
305
306 message_length -= (size_t) bread ;
307
308 // moves the pointer forward (# of words received)
309
310 begin += (MessageWord_t) (bread / sizeof(MessageWord_t)) ;
311 }
312
313 return TDICE_SUCCESS ;
314}
315
316/******************************************************************************/
317
319{
320 if (close (socket->Id) != 0)
321 {
322 perror ("ERROR :: Closing network socket") ;
323
324 return TDICE_FAILURE ;
325 }
326
327 return TDICE_SUCCESS ;
328}
329
330/******************************************************************************/
void increase_message_memory(NetworkMessage_t *message, Quantity_t new_size)
Error_t open_client_socket(Socket_t *csocket)
Error_t receive_message_from_socket(Socket_t *socket, NetworkMessage_t *message)
Error_t socket_close(Socket_t *socket)
Error_t connect_client_to_server(Socket_t *csocket, String_t host_name, PortNumber_t port_number)
Error_t send_message_to_socket(Socket_t *socket, NetworkMessage_t *message)
void socket_init(Socket_t *socket)
Error_t open_server_socket(Socket_t *ssocket, PortNumber_t port_number)
Error_t wait_for_client(Socket_t *ssocket, Socket_t *client)
char * String_t
Definition: string_t.h:55
Structure used to store messages to be sent over network.
MessageWord_t * MType
MessageWord_t * Memory
Quantity_t MaxLength
MessageWord_t * Length
Structure used to set up and use network connections.
NetworkSocket_t Id
char HostName[32]
struct sockaddr_in Address
PortNumber_t PortNumber
Error_t
Definition: types.h:401
@ TDICE_SUCCESS
The function returns with success.
Definition: types.h:402
@ TDICE_FAILURE
The function retuerns with a generic error.
Definition: types.h:403
uint32_t MessageWord_t
Definition: types.h:717
uint16_t PortNumber_t
Definition: types.h:548