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@4
|
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@4
|
43 if(send_request(sock, &msg, opt_timeout) == -1) {
|
nuclear@4
|
44 return -1;
|
nuclear@4
|
45 }
|
nuclear@4
|
46 return msg.magic == MAGIC && msg.type == RSP_OK ? 0 : -1;
|
nuclear@2
|
47 }
|
nuclear@2
|
48
|
nuclear@2
|
49 int netinp_stop()
|
nuclear@2
|
50 {
|
nuclear@3
|
51 struct message msg;
|
nuclear@3
|
52
|
nuclear@3
|
53 if(sock == -1) {
|
nuclear@3
|
54 return -1;
|
nuclear@3
|
55 }
|
nuclear@3
|
56
|
nuclear@3
|
57 memset(&msg, 0, sizeof msg);
|
nuclear@3
|
58 msg.magic = MAGIC;
|
nuclear@3
|
59 msg.type = REQ_STOP;
|
nuclear@4
|
60
|
nuclear@4
|
61 if(send_request(sock, &msg, opt_timeout) == -1) {
|
nuclear@4
|
62 return -1;
|
nuclear@4
|
63 }
|
nuclear@4
|
64 return msg.magic == MAGIC && msg.type == RSP_OK ? 0 : -1;
|
nuclear@3
|
65 }
|
nuclear@3
|
66
|
nuclear@4
|
67 int netinp_read(float *pos, unsigned int *bnmask)
|
nuclear@3
|
68 {
|
nuclear@3
|
69 struct message msg;
|
nuclear@3
|
70
|
nuclear@3
|
71 if(sock == -1) {
|
nuclear@3
|
72 return -1;
|
nuclear@3
|
73 }
|
nuclear@3
|
74
|
nuclear@3
|
75 if(recv(sock, &msg, sizeof msg, 0) == -1) {
|
nuclear@3
|
76 perror("netinp_read failed");
|
nuclear@3
|
77 return -1;
|
nuclear@3
|
78 }
|
nuclear@3
|
79
|
nuclear@4
|
80 if(msg.magic != MAGIC || msg.type != MAGIC) {
|
nuclear@4
|
81 fprintf(stderr, "not enough magic in the message\n");
|
nuclear@4
|
82 return -1;
|
nuclear@4
|
83 }
|
nuclear@4
|
84
|
nuclear@4
|
85 pos[0] = msg.data.event.x;
|
nuclear@4
|
86 pos[1] = msg.data.event.y;
|
nuclear@4
|
87 pos[2] = msg.data.event.z;
|
nuclear@4
|
88 *bnmask = msg.data.event.bnmask;
|
nuclear@3
|
89 return 0;
|
nuclear@3
|
90 }
|
nuclear@3
|
91
|
nuclear@3
|
92 int netinp_reset()
|
nuclear@3
|
93 {
|
nuclear@4
|
94 struct message msg;
|
nuclear@4
|
95
|
nuclear@4
|
96 if(sock == -1) {
|
nuclear@4
|
97 return -1;
|
nuclear@4
|
98 }
|
nuclear@4
|
99
|
nuclear@4
|
100 memset(&msg, 0, sizeof msg);
|
nuclear@4
|
101 msg.magic = MAGIC;
|
nuclear@4
|
102 msg.type = REQ_STOP;
|
nuclear@4
|
103
|
nuclear@4
|
104 if(send_request(sock, &msg, opt_timeout) == -1) {
|
nuclear@4
|
105 return -1;
|
nuclear@4
|
106 }
|
nuclear@4
|
107 return msg.magic == MAGIC && msg.type == RSP_OK ? 0 : -1;
|
nuclear@2
|
108 }
|
nuclear@2
|
109
|
nuclear@2
|
110 static int discover(struct sockaddr_in *srv_sa)
|
nuclear@2
|
111 {
|
nuclear@2
|
112 int s, true_val = 1;
|
nuclear@2
|
113 struct sockaddr_in sa;
|
nuclear@2
|
114 long timeout = opt_timeout;
|
nuclear@2
|
115 struct message msg;
|
nuclear@2
|
116 struct timeval tv0, tv, tv_timeout;
|
nuclear@2
|
117
|
nuclear@2
|
118 if((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
|
nuclear@2
|
119 perror("failed to create discover datagram socket");
|
nuclear@2
|
120 return -1;
|
nuclear@2
|
121 }
|
nuclear@2
|
122 setsockopt(s, SOL_SOCKET, SO_BROADCAST, &true_val, sizeof true_val);
|
nuclear@2
|
123
|
nuclear@2
|
124 memset(&sa, 0, sizeof sa);
|
nuclear@2
|
125 sa.sin_family = AF_INET;
|
nuclear@2
|
126 sa.sin_port = htons(opt_dport);
|
nuclear@2
|
127 sa.sin_addr.s_addr = htonl(INADDR_ANY);
|
nuclear@2
|
128
|
nuclear@2
|
129 if(bind(s, (struct sockaddr*)&sa, sizeof sa) == -1) {
|
nuclear@2
|
130 perror("failed to bind datagram socket");
|
nuclear@2
|
131 close(s);
|
nuclear@2
|
132 return -1;
|
nuclear@2
|
133 }
|
nuclear@2
|
134
|
nuclear@2
|
135 do {
|
nuclear@2
|
136 fd_set rdset;
|
nuclear@2
|
137
|
nuclear@2
|
138 msg.magic = MAGIC;
|
nuclear@2
|
139 msg.type = REQ_DISCOVER;
|
nuclear@2
|
140
|
nuclear@2
|
141 memset(&sa, 0, sizeof sa);
|
nuclear@2
|
142 sa.sin_family = AF_INET;
|
nuclear@2
|
143 sa.sin_port = htons(opt_dport);
|
nuclear@2
|
144 sa.sin_addr.s_addr = 0xffffffff;
|
nuclear@2
|
145
|
nuclear@2
|
146 if(sendto(s, &msg, sizeof msg, 0, (struct sockaddr*)&sa, sizeof sa) == -1) {
|
nuclear@2
|
147 perror("failed to send discovery bcast dgram");
|
nuclear@2
|
148 close(s);
|
nuclear@2
|
149 return -1;
|
nuclear@2
|
150 }
|
nuclear@2
|
151
|
nuclear@2
|
152 tv_timeout.tv_sec = timeout / 1000;
|
nuclear@2
|
153 tv_timeout.tv_usec = (timeout % 1000) * 1000;
|
nuclear@2
|
154
|
nuclear@2
|
155 FD_ZERO(&rdset);
|
nuclear@2
|
156 FD_SET(s, &rdset);
|
nuclear@2
|
157
|
nuclear@2
|
158 gettimeofday(&tv0, 0);
|
nuclear@2
|
159
|
nuclear@2
|
160 while(select(s + 1, &rdset, 0, 0, &tv_timeout) == -1 && errno == EINTR);
|
nuclear@2
|
161
|
nuclear@2
|
162 gettimeofday(&tv, 0);
|
nuclear@2
|
163 timeout -= (tv.tv_sec - tv0.tv_sec) * 1000 + (tv.tv_usec - tv0.tv_usec) / 1000;
|
nuclear@2
|
164
|
nuclear@2
|
165 if(FD_ISSET(s, &rdset)) {
|
nuclear@2
|
166 socklen_t sa_size = sizeof *srv_sa;
|
nuclear@2
|
167 if(recvfrom(s, &msg, sizeof msg, 0, (struct sockaddr*)srv_sa, &sa_size) == -1) {
|
nuclear@2
|
168 perror("failed to receive datagram\n");
|
nuclear@2
|
169 }
|
nuclear@2
|
170 if(msg.magic == MAGIC && msg.type == RSP_OK) {
|
nuclear@4
|
171 printf("found input server \"%s\" at: %s:%d\n", msg.data.raw,
|
nuclear@2
|
172 inet_ntoa(srv_sa->sin_addr), ntohs(srv_sa->sin_port));
|
nuclear@2
|
173 return s;
|
nuclear@2
|
174 }
|
nuclear@2
|
175 }
|
nuclear@2
|
176
|
nuclear@2
|
177 } while(timeout > 0);
|
nuclear@2
|
178
|
nuclear@2
|
179 close(s);
|
nuclear@2
|
180 return -1;
|
nuclear@2
|
181 }
|
nuclear@2
|
182
|
nuclear@3
|
183 static int send_request(int s, struct message *msg, long timeout)
|
nuclear@2
|
184 {
|
nuclear@3
|
185 fd_set rdset;
|
nuclear@3
|
186 struct timeval tv, tv0, tv_timeout;
|
nuclear@3
|
187 struct message resp;
|
nuclear@2
|
188
|
nuclear@3
|
189 do {
|
nuclear@3
|
190 if(send(s, msg, sizeof *msg, 0) == -1) {
|
nuclear@3
|
191 perror("failed to send message");
|
nuclear@3
|
192 return -1;
|
nuclear@3
|
193 }
|
nuclear@3
|
194
|
nuclear@3
|
195 tv_timeout.tv_sec = timeout / 1000;
|
nuclear@3
|
196 tv_timeout.tv_usec = (timeout % 1000) * 1000;
|
nuclear@3
|
197
|
nuclear@3
|
198 FD_ZERO(&rdset);
|
nuclear@3
|
199 FD_SET(s, &rdset);
|
nuclear@3
|
200
|
nuclear@3
|
201 gettimeofday(&tv0, 0);
|
nuclear@3
|
202 while(select(s + 1, &rdset, 0, 0, &tv_timeout) == -1 && errno == EINTR);
|
nuclear@3
|
203 gettimeofday(&tv, 0);
|
nuclear@3
|
204
|
nuclear@3
|
205 if(FD_ISSET(s, &rdset)) {
|
nuclear@3
|
206 if(recv(s, &resp, sizeof resp, 0) == -1) {
|
nuclear@3
|
207 perror("failed to recieve message");
|
nuclear@3
|
208 return -1;
|
nuclear@3
|
209 }
|
nuclear@3
|
210 if(resp.magic != MAGIC) {
|
nuclear@3
|
211 fprintf(stderr, "got invalid response\n");
|
nuclear@3
|
212 return -1;
|
nuclear@3
|
213 }
|
nuclear@3
|
214 memcpy(msg, &resp, sizeof resp);
|
nuclear@3
|
215 return 0;
|
nuclear@3
|
216 }
|
nuclear@3
|
217
|
nuclear@3
|
218 timeout -= (tv.tv_sec - tv0.tv_sec) * 1000 + (tv.tv_usec - tv0.tv_usec) / 1000;
|
nuclear@3
|
219 } while(timeout > 0);
|
nuclear@3
|
220
|
nuclear@3
|
221 return -1;
|
nuclear@2
|
222 }
|