Added Linux example and updated release notes
[keystone-rtos/rm-lld.git] / test / k2k / armv7 / linux / sockutils.c
1 /*
2  * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
3  *
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions
7  *  are met:
8  *
9  *    Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  *    Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the
15  *    distribution.
16  *
17  *    Neither the name of Texas Instruments Incorporated nor the names of
18  *    its contributors may be used to endorse or promote products derived
19  *    from this software without specific prior written permission.
20  *
21  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  */
35 #include <string.h>
36 #include <unistd.h>
37 #include <errno.h>
38 #include <malloc.h>
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 #include <sys/ioctl.h>
43 #include "sockutils.h"
45 #define error_msg printf
47 typedef struct sock_data {
48         struct sockaddr_un addr;
49         fd_set  readfds;
50         int fd;
51 } sock_data_t;
53 int check_and_create_path (char *path)
54 {
55         char *d = path;
56         if (!d)
57                 return -1;
59         while (d = strchr(d + 1, '/')) {
60                 *d = 0;
61                 if (mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0) {
62                         if (errno != EEXIST) {
63                                 *d = '/';
64                                 error_msg("can't create path %s (error: %s)",
65                                                 path, strerror(errno));
66                                 return -1;
67                         }
68                 }
69                 *d = '/';
70         }
71         return 0;
72 }
74 sock_h sock_open (sock_name_t *sock_name)
75 {
76         sock_data_t *sd = 0;
77         int retval = 0;
79         if (!sock_name) {
80                 return 0;
81         }
83         sd = calloc (1, sizeof(sock_data_t));
85         if (sock_name->type == sock_addr_e) {
86                 memcpy (&sd->addr, sock_name->s.addr, sizeof(struct sockaddr_un));
87         } else {
88                 if (check_and_create_path(sock_name->s.name) < 0) {
89                         goto check_n_return;
90                 }
91                 sd->addr.sun_family = AF_UNIX;
92                 strncpy(sd->addr.sun_path, sock_name->s.name, UNIX_PATH_MAX);
93         }
95         sd->fd =  socket(AF_UNIX, SOCK_DGRAM, 0);
96         if (sd->fd < 0) {
97                 error_msg("can't open socket (error: %s)",
98                                 sd->addr.sun_path, strerror(errno));
99                 goto check_n_return;
100         }
102         unlink(sd->addr.sun_path);
103         if (bind(sd->fd, (struct sockaddr *) &sd->addr, sizeof(struct sockaddr_un)) < 0) {
104                 error_msg("can't bind socket (error: %s)",
105                                 sd->addr.sun_path, strerror(errno));
106                 goto check_n_return;
107         }
109         FD_ZERO(&sd->readfds);
110         FD_SET(sd->fd, &sd->readfds);
112         retval = (int) sd;
114 check_n_return:
115         if (!retval) {
116                 sock_close ((sock_h) &sd);
117         }
119         return ((sock_h) retval);
122 int sock_close (sock_h handle)
124         sock_data_t *sd = (sock_data_t *) handle;
126         if (!sd) {
127                 return -1;
128         }
130         if (sd->fd)
131                 close (sd->fd);
132         free (sd);
134         return 0;       
137 int sock_send (sock_h handle, const char *data, int length,
138                         sock_name_t *to)
140         int fd;
141         sock_data_t *sd = (sock_data_t *) handle;
142         struct sockaddr_un to_addr;
144         if (!to) {
145                 return -1;
146         }
148         if (to->type == sock_addr_e) {
149                 memcpy (&to_addr, to->s.addr, sizeof(struct sockaddr_un));
150         } else {
151                 to_addr.sun_family = AF_UNIX;
152                 strncpy(to_addr.sun_path, to->s.name, UNIX_PATH_MAX);
153         }
155         if (sd) {
156                 fd = sd->fd;
157         } else {
158                 fd =  socket(AF_UNIX, SOCK_DGRAM, 0);
159                 if (fd < 0) {
160                         error_msg("can't open socket (error: %s)",
161                                         to_addr.sun_path, strerror(errno));
162                         return -1;
163                 }
164         }
166         if (sendto (fd, data, length, 0, (struct sockaddr *) &to_addr,
167                                 sizeof(struct sockaddr_un)) < 0) {
168                 error_msg("can't send data to %s (error: %s)",
169                                 to_addr.sun_path, strerror(errno));
170                 return -1;
172         }
174         return 0;
177 int sock_wait (sock_h handle, int *size, struct timeval *timeout, int extern_fd)
179         sock_data_t *sd = (sock_data_t *) handle;
180         int retval;
181         fd_set fds;
183         if (!sd) {
184                 error_msg("invalid hanlde");
185                 return -1;
186         }
188         fds = sd->readfds;
190         if (extern_fd != -1) {
191                 FD_SET(extern_fd, &fds);
192         }
194         retval = select(FD_SETSIZE, &fds, NULL, NULL, timeout);
195         if (retval == -1) {
196                 error_msg("select failed for %s (error: %s)",
197                                 sd->addr.sun_path, strerror(errno));
198                 return -1;
199         }
201         if ((extern_fd != -1) && (FD_ISSET(extern_fd, &fds))) {
202                 return 1;
203         }
205         if (!FD_ISSET(sd->fd, &fds)) {
206                 /* Wait timedout */
207                 return -2;
208         }
210         if (!retval) {
211                 return 0;
212         }
214         if (size != 0) {
215                 retval = ioctl(sd->fd, FIONREAD, size);
216                 if (retval == -1) {
217                         error_msg("can't read datagram size for %s (error: %s)",
218                                         sd->addr.sun_path, strerror(errno));
219                         return -1;
220                 }
221         }
223         return 0;
226 int sock_recv (sock_h handle, char *data, int length, sock_name_t *from)
228         int size;
229         int retval;
230         fd_set fds;
231         sock_data_t *sd = (sock_data_t *) handle;
232         socklen_t from_length = 0;
234         if (!sd) {
235                 error_msg("invalid hanlde");
236                 return -1;
237         }
239         if (from) {
240                 if((from->type = sock_addr_e) && (from->s.addr))
241                         from_length = sizeof(struct sockaddr_un);
242                 else {
243                         error_msg("invalid from parameter");
244                         return -1;
245                 }
246         }
248         size = recvfrom(sd->fd, data, length, 0, (struct sockaddr *)((from_length) ? from->s.addr : NULL), &from_length);
249         if (size < 1) {
250                 error_msg("can't read datagram from socket for %s (error: %s), size %d",
251                                 sd->addr.sun_path, strerror(errno), size);
252                 return -1;
253         }
255         return size;
256