rev |
line source |
nuclear@2
|
1 #include <stdio.h>
|
nuclear@2
|
2 #include <stdlib.h>
|
nuclear@2
|
3 #include <string.h>
|
nuclear@2
|
4 #include <errno.h>
|
nuclear@2
|
5 #include <unistd.h>
|
nuclear@2
|
6 #include <sys/types.h>
|
nuclear@2
|
7 #include <sys/socket.h>
|
nuclear@2
|
8 #include <arpa/inet.h>
|
nuclear@2
|
9 #include <sys/time.h>
|
nuclear@2
|
10 #include <sys/select.h>
|
nuclear@2
|
11 #include "inpclient.h"
|
nuclear@2
|
12 #include "proto.h"
|
nuclear@2
|
13
|
nuclear@2
|
14 static int discover(struct sockaddr_in *srv_sa);
|
nuclear@3
|
15 static int send_request(int s, struct message *msg, long timeout);
|
nuclear@2
|
16
|
nuclear@2
|
17 static int opt_dport = DEF_PORT; /* discover broadcast port */
|
nuclear@2
|
18 static long opt_timeout = 5000; /* 10 sec discovery timeout */
|
nuclear@2
|
19
|
nuclear@2
|
20 static int sock = -1;
|
nuclear@2
|
21
|
nuclear@2
|
22
|
nuclear@2
|
23 int netinp_start()
|
nuclear@2
|
24 {
|
nuclear@2
|
25 struct message msg;
|
nuclear@2
|
26 struct sockaddr_in srv_sa;
|
nuclear@2
|
27
|
nuclear@2
|
28 if(sock == -1) {
|
nuclear@2
|
29 if((sock = discover(&srv_sa)) == -1) {
|
nuclear@2
|
30 return -1;
|
nuclear@2
|
31 }
|
nuclear@2
|
32
|
nuclear@2
|
33 if(connect(sock, (struct sockaddr*)&srv_sa, sizeof srv_sa) == -1) {
|
nuclear@2
|
34 perror("failed to connect socket");
|
nuclear@2
|
35 close(sock);
|
nuclear@2
|
36 return -1;
|
nuclear@2
|
37 }
|
nuclear@2
|
38 }
|
nuclear@2
|
39
|
nuclear@2
|
40 memset(&msg, 0, sizeof msg);
|
nuclear@2
|
41 msg.magic = MAGIC;
|
nuclear@3
|
42 msg.type = REQ_START;
|
nuclear@3
|
43 return send_request(sock, &msg, opt_timeout);
|
nuclear@2
|
44 }
|
nuclear@2
|
45
|
nuclear@2
|
46 int netinp_stop()
|
nuclear@2
|
47 {
|
nuclear@3
|
48 struct message msg;
|
nuclear@3
|
49
|
nuclear@3
|
50 if(sock == -1) {
|
nuclear@3
|
51 return -1;
|
nuclear@3
|
52 }
|
nuclear@3
|
53
|
nuclear@3
|
54 memset(&msg, 0, sizeof msg);
|
nuclear@3
|
55 msg.magic = MAGIC;
|
nuclear@3
|
56 msg.type = REQ_STOP;
|
nuclear@3
|
57 return send_request(sock, &msg, opt_timeout);
|
nuclear@3
|
58 }
|
nuclear@3
|
59
|
nuclear@3
|
60 int netinp_read(float *pos)
|
nuclear@3
|
61 {
|
nuclear@3
|
62 struct message msg;
|
nuclear@3
|
63
|
nuclear@3
|
64 if(sock == -1) {
|
nuclear@3
|
65 return -1;
|
nuclear@3
|
66 }
|
nuclear@3
|
67
|
nuclear@3
|
68 if(recv(sock, &msg, sizeof msg, 0) == -1) {
|
nuclear@3
|
69 perror("netinp_read failed");
|
nuclear@3
|
70 return -1;
|
nuclear@3
|
71 }
|
nuclear@3
|
72
|
nuclear@3
|
73 pos[0] = ((float*)msg.data)[0];
|
nuclear@3
|
74 pos[1] = ((float*)msg.data)[1];
|
nuclear@3
|
75 pos[2] = ((float*)msg.data)[3];
|
nuclear@3
|
76 return 0;
|
nuclear@3
|
77 }
|
nuclear@3
|
78
|
nuclear@3
|
79 int netinp_reset()
|
nuclear@3
|
80 {
|
nuclear@3
|
81 return -1; // TODO
|
nuclear@2
|
82 }
|
nuclear@2
|
83
|
nuclear@2
|
84 static int discover(struct sockaddr_in *srv_sa)
|
nuclear@2
|
85 {
|
nuclear@2
|
86 int s, true_val = 1;
|
nuclear@2
|
87 struct sockaddr_in sa;
|
nuclear@2
|
88 long timeout = opt_timeout;
|
nuclear@2
|
89 struct message msg;
|
nuclear@2
|
90 struct timeval tv0, tv, tv_timeout;
|
nuclear@2
|
91
|
nuclear@2
|
92 if((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
|
nuclear@2
|
93 perror("failed to create discover datagram socket");
|
nuclear@2
|
94 return -1;
|
nuclear@2
|
95 }
|
nuclear@2
|
96 setsockopt(s, SOL_SOCKET, SO_BROADCAST, &true_val, sizeof true_val);
|
nuclear@2
|
97
|
nuclear@2
|
98 memset(&sa, 0, sizeof sa);
|
nuclear@2
|
99 sa.sin_family = AF_INET;
|
nuclear@2
|
100 sa.sin_port = htons(opt_dport);
|
nuclear@2
|
101 sa.sin_addr.s_addr = htonl(INADDR_ANY);
|
nuclear@2
|
102
|
nuclear@2
|
103 if(bind(s, (struct sockaddr*)&sa, sizeof sa) == -1) {
|
nuclear@2
|
104 perror("failed to bind datagram socket");
|
nuclear@2
|
105 close(s);
|
nuclear@2
|
106 return -1;
|
nuclear@2
|
107 }
|
nuclear@2
|
108
|
nuclear@2
|
109 do {
|
nuclear@2
|
110 fd_set rdset;
|
nuclear@2
|
111
|
nuclear@2
|
112 msg.magic = MAGIC;
|
nuclear@2
|
113 msg.type = REQ_DISCOVER;
|
nuclear@2
|
114
|
nuclear@2
|
115 memset(&sa, 0, sizeof sa);
|
nuclear@2
|
116 sa.sin_family = AF_INET;
|
nuclear@2
|
117 sa.sin_port = htons(opt_dport);
|
nuclear@2
|
118 sa.sin_addr.s_addr = 0xffffffff;
|
nuclear@2
|
119
|
nuclear@2
|
120 if(sendto(s, &msg, sizeof msg, 0, (struct sockaddr*)&sa, sizeof sa) == -1) {
|
nuclear@2
|
121 perror("failed to send discovery bcast dgram");
|
nuclear@2
|
122 close(s);
|
nuclear@2
|
123 return -1;
|
nuclear@2
|
124 }
|
nuclear@2
|
125
|
nuclear@2
|
126 tv_timeout.tv_sec = timeout / 1000;
|
nuclear@2
|
127 tv_timeout.tv_usec = (timeout % 1000) * 1000;
|
nuclear@2
|
128
|
nuclear@2
|
129 FD_ZERO(&rdset);
|
nuclear@2
|
130 FD_SET(s, &rdset);
|
nuclear@2
|
131
|
nuclear@2
|
132 gettimeofday(&tv0, 0);
|
nuclear@2
|
133
|
nuclear@2
|
134 while(select(s + 1, &rdset, 0, 0, &tv_timeout) == -1 && errno == EINTR);
|
nuclear@2
|
135
|
nuclear@2
|
136 gettimeofday(&tv, 0);
|
nuclear@2
|
137 timeout -= (tv.tv_sec - tv0.tv_sec) * 1000 + (tv.tv_usec - tv0.tv_usec) / 1000;
|
nuclear@2
|
138
|
nuclear@2
|
139 if(FD_ISSET(s, &rdset)) {
|
nuclear@2
|
140 socklen_t sa_size = sizeof *srv_sa;
|
nuclear@2
|
141 if(recvfrom(s, &msg, sizeof msg, 0, (struct sockaddr*)srv_sa, &sa_size) == -1) {
|
nuclear@2
|
142 perror("failed to receive datagram\n");
|
nuclear@2
|
143 }
|
nuclear@2
|
144 if(msg.magic == MAGIC && msg.type == RSP_OK) {
|
nuclear@2
|
145 printf("found input server \"%s\" at: %s:%d\n", msg.data,
|
nuclear@2
|
146 inet_ntoa(srv_sa->sin_addr), ntohs(srv_sa->sin_port));
|
nuclear@2
|
147 return s;
|
nuclear@2
|
148 }
|
nuclear@2
|
149 }
|
nuclear@2
|
150
|
nuclear@2
|
151 } while(timeout > 0);
|
nuclear@2
|
152
|
nuclear@2
|
153 close(s);
|
nuclear@2
|
154 return -1;
|
nuclear@2
|
155 }
|
nuclear@2
|
156
|
nuclear@3
|
157 static int send_request(int s, struct message *msg, long timeout)
|
nuclear@2
|
158 {
|
nuclear@3
|
159 fd_set rdset;
|
nuclear@3
|
160 struct timeval tv, tv0, tv_timeout;
|
nuclear@3
|
161 struct message resp;
|
nuclear@2
|
162
|
nuclear@3
|
163 do {
|
nuclear@3
|
164 if(send(s, msg, sizeof *msg, 0) == -1) {
|
nuclear@3
|
165 perror("failed to send message");
|
nuclear@3
|
166 return -1;
|
nuclear@3
|
167 }
|
nuclear@3
|
168
|
nuclear@3
|
169 tv_timeout.tv_sec = timeout / 1000;
|
nuclear@3
|
170 tv_timeout.tv_usec = (timeout % 1000) * 1000;
|
nuclear@3
|
171
|
nuclear@3
|
172 FD_ZERO(&rdset);
|
nuclear@3
|
173 FD_SET(s, &rdset);
|
nuclear@3
|
174
|
nuclear@3
|
175 gettimeofday(&tv0, 0);
|
nuclear@3
|
176 while(select(s + 1, &rdset, 0, 0, &tv_timeout) == -1 && errno == EINTR);
|
nuclear@3
|
177 gettimeofday(&tv, 0);
|
nuclear@3
|
178
|
nuclear@3
|
179 if(FD_ISSET(s, &rdset)) {
|
nuclear@3
|
180 if(recv(s, &resp, sizeof resp, 0) == -1) {
|
nuclear@3
|
181 perror("failed to recieve message");
|
nuclear@3
|
182 return -1;
|
nuclear@3
|
183 }
|
nuclear@3
|
184 if(resp.magic != MAGIC) {
|
nuclear@3
|
185 fprintf(stderr, "got invalid response\n");
|
nuclear@3
|
186 return -1;
|
nuclear@3
|
187 }
|
nuclear@3
|
188 memcpy(msg, &resp, sizeof resp);
|
nuclear@3
|
189 return 0;
|
nuclear@3
|
190 }
|
nuclear@3
|
191
|
nuclear@3
|
192 timeout -= (tv.tv_sec - tv0.tv_sec) * 1000 + (tv.tv_usec - tv0.tv_usec) / 1000;
|
nuclear@3
|
193 } while(timeout > 0);
|
nuclear@3
|
194
|
nuclear@3
|
195 return -1;
|
nuclear@2
|
196 }
|