]> git.sur5r.net Git - ngadmin/blob - raw/src/net.c
e5af939c39d72f89bd4aa91b2a7201f825dac7c7
[ngadmin] / raw / src / net.c
1
2 #ifdef HAVE_CONFIG_H
3 #include "config.h"
4 #endif
5
6 #include <stdio.h>
7 #include <errno.h>
8 #include <poll.h>
9
10 #include <nsdp/net.h>
11 #include <nsdp/encoding.h>
12
13
14 static inline void timespec_add (struct timespec *tsa, const struct timespec *tsb)
15 {
16         tsa->tv_sec += tsb->tv_sec;
17         tsa->tv_nsec += tsb->tv_nsec;
18         while (tsa->tv_nsec >= 1000000000) {
19                 tsa->tv_nsec -= 1000000000;
20                 tsa->tv_sec++;
21         }
22 }
23
24
25 static inline int timespec_diff_ms (const struct timespec *tsa, const struct timespec *tsb)
26 {
27         int diff = (tsb->tv_sec - tsa->tv_sec) * 1000;
28         
29         if (tsb->tv_sec > tsa->tv_sec)
30                 diff += (tsb->tv_nsec - tsa->tv_nsec) / 1000000;
31         else
32                 diff -= (tsb->tv_nsec - tsa->tv_nsec) / 1000000;
33         
34         return diff;
35 }
36
37
38 static inline void timeval_to_timespec (struct timespec *ts, const struct timeval *tv)
39 {
40         ts->tv_sec = tv->tv_sec;
41         ts->tv_nsec = tv->tv_usec * 1000;
42 }
43
44
45 int sendNsdpPacket (int sock, const struct nsdp_cmd *nc, const List *attr)
46 {
47         unsigned char buffer[1500];
48         struct nsdp_packet np;
49         int ret;
50         
51         
52         if (sock < 0 || nc == NULL)
53                 return -EINVAL;
54         
55         np.buffer = buffer;
56         np.maxlen = sizeof(buffer);
57         initNsdpPacket(&np);
58         initNsdpHeader(np.nh, nc);
59         
60         ret = addPacketAttributes(&np, attr, nc->ports);
61         if (ret < 0)
62                 return ret;
63         
64         ret = sendto(sock, buffer, getPacketTotalSize(&np), 0, (struct sockaddr*)&nc->remote_addr, sizeof(struct sockaddr_in));
65         if (ret < 0)
66                 perror("sendto");
67         
68         
69         return ret;
70 }
71
72
73 int recvNsdpPacket (int sock, struct nsdp_cmd *nc, List *attr, const struct timespec *timeout)
74 {
75         unsigned char buffer[1500];
76         struct nsdp_packet np;
77         socklen_t slen = sizeof(struct sockaddr_in);
78         int len = -1, timewait;
79         struct sockaddr_in remote;
80         struct timespec timecurrent, timeend;
81 #ifndef HAVE_CLOCK_GETTIME
82         struct timeval tv;
83 #endif
84         struct pollfd fds;
85         
86         
87         if (sock < 0 || nc == NULL || attr == NULL)
88                 return -EINVAL;
89         
90         np.buffer = buffer;
91         
92         memset(&remote, 0, sizeof(struct sockaddr_in));
93         remote.sin_family = AF_INET;
94         
95         if (timeout == NULL) {
96                 timewait = -1;
97         } else {
98 #ifdef HAVE_CLOCK_GETTIME
99                 clock_gettime(CLOCK_MONOTONIC, &timeend);
100 #else
101                 gettimeofday(&tv, NULL);
102                 timeval_to_timespec(&timeend, &tv);
103 #endif
104                 timespec_add(&timeend, timeout);
105         }
106         fds.fd = sock;
107         fds.events = POLLIN;
108         fds.revents = 0;
109         
110         while (1) {
111                 if (timeout != NULL) {
112 #ifdef HAVE_CLOCK_GETTIME
113                         clock_gettime(CLOCK_MONOTONIC, &timecurrent);
114 #else
115                         gettimeofday(&tv, NULL);
116                         timeval_to_timespec(&timeend, &tv);
117 #endif
118                         timewait = timespec_diff_ms(&timecurrent, &timeend);
119                         if (timewait <= 0)
120                                 break;
121                 }
122                 
123                 len = poll(&fds, 1, timewait);
124                 if (len < 0) {
125                         break;
126                 } else if (len == 0) {
127                         len = -ETIMEDOUT;
128                         break;
129                 }
130                 
131                 len = recvfrom(sock, buffer, sizeof(buffer), MSG_DONTWAIT, (struct sockaddr*)&remote, &slen);
132                 if (len < 0)
133                         break;
134                 
135                 np.maxlen = len;
136                 initNsdpPacket(&np);
137                 
138                 if ((nc->remote_addr.sin_addr.s_addr != 0 && remote.sin_addr.s_addr != nc->remote_addr.sin_addr.s_addr) ||
139                     (nc->remote_addr.sin_port != 0 && remote.sin_port != nc->remote_addr.sin_port) ||
140                     len < (int)sizeof(struct nsdp_header) ||
141                     !extractNsdpHeader(np.nh, nc) ||
142                     extractPacketAttributes(&np, attr, nc->ports) < 0)
143                         continue;
144                 
145                 nc->remote_addr = remote;
146                 
147                 len = 0;
148                 break;
149         }
150         
151         
152         return len;
153 }
154
155