5992bd35d1cbc668bfb93811734277cc66742555
[keystone-rtos/netapi.git] / ti / runtime / netapi / utils / 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 %s (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 %s (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 %s (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     sock_data_t *sd = (sock_data_t *) handle;
230     socklen_t from_length = 0;
232     if (!sd) {
233         error_msg("invalid hanlde");
234         return -1;
235     }
237     if (from) {
238         if((from->type == sock_addr_e) && (from->s.addr))
239             from_length = sizeof(struct sockaddr_un);
240         else {
241             error_msg("invalid from parameter");
242             return -1;
243         }
244     }
246     size = recvfrom(sd->fd, data, length, 0, (struct sockaddr *)((from_length) ? from->s.addr : NULL), &from_length);
247     if (size < 1) {
248         error_msg("can't read datagram from socket for %s (error: %s), size %d",
249                 sd->addr.sun_path, strerror(errno), size);
250         return -1;
251     }
253     return size;
254