vrmodel

view src/inpclient.cc @ 4:a32b151fb3c6

moving along slowly
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 11 Sep 2014 00:08:23 +0300
parents a1784a4290c2
children 9e260c091f75
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <unistd.h>
6 #include <sys/types.h>
7 #include <sys/socket.h>
8 #include <arpa/inet.h>
9 #include <sys/time.h>
10 #include <sys/select.h>
11 #include "inpclient.h"
12 #include "proto.h"
14 static int discover(struct sockaddr_in *srv_sa);
15 static int send_request(int s, struct message *msg, long timeout);
17 static int opt_dport = DEF_PORT; /* discover broadcast port */
18 static long opt_timeout = 5000; /* 10 sec discovery timeout */
20 static int sock = -1;
23 int netinp_start()
24 {
25 struct message msg;
26 struct sockaddr_in srv_sa;
28 if(sock == -1) {
29 if((sock = discover(&srv_sa)) == -1) {
30 return -1;
31 }
33 if(connect(sock, (struct sockaddr*)&srv_sa, sizeof srv_sa) == -1) {
34 perror("failed to connect socket");
35 close(sock);
36 return -1;
37 }
38 }
40 memset(&msg, 0, sizeof msg);
41 msg.magic = MAGIC;
42 msg.type = REQ_START;
43 if(send_request(sock, &msg, opt_timeout) == -1) {
44 return -1;
45 }
46 return msg.magic == MAGIC && msg.type == RSP_OK ? 0 : -1;
47 }
49 int netinp_stop()
50 {
51 struct message msg;
53 if(sock == -1) {
54 return -1;
55 }
57 memset(&msg, 0, sizeof msg);
58 msg.magic = MAGIC;
59 msg.type = REQ_STOP;
61 if(send_request(sock, &msg, opt_timeout) == -1) {
62 return -1;
63 }
64 return msg.magic == MAGIC && msg.type == RSP_OK ? 0 : -1;
65 }
67 int netinp_read(float *pos, unsigned int *bnmask)
68 {
69 struct message msg;
71 if(sock == -1) {
72 return -1;
73 }
75 if(recv(sock, &msg, sizeof msg, 0) == -1) {
76 perror("netinp_read failed");
77 return -1;
78 }
80 if(msg.magic != MAGIC || msg.type != MAGIC) {
81 fprintf(stderr, "not enough magic in the message\n");
82 return -1;
83 }
85 pos[0] = msg.data.event.x;
86 pos[1] = msg.data.event.y;
87 pos[2] = msg.data.event.z;
88 *bnmask = msg.data.event.bnmask;
89 return 0;
90 }
92 int netinp_reset()
93 {
94 struct message msg;
96 if(sock == -1) {
97 return -1;
98 }
100 memset(&msg, 0, sizeof msg);
101 msg.magic = MAGIC;
102 msg.type = REQ_STOP;
104 if(send_request(sock, &msg, opt_timeout) == -1) {
105 return -1;
106 }
107 return msg.magic == MAGIC && msg.type == RSP_OK ? 0 : -1;
108 }
110 static int discover(struct sockaddr_in *srv_sa)
111 {
112 int s, true_val = 1;
113 struct sockaddr_in sa;
114 long timeout = opt_timeout;
115 struct message msg;
116 struct timeval tv0, tv, tv_timeout;
118 if((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
119 perror("failed to create discover datagram socket");
120 return -1;
121 }
122 setsockopt(s, SOL_SOCKET, SO_BROADCAST, &true_val, sizeof true_val);
124 memset(&sa, 0, sizeof sa);
125 sa.sin_family = AF_INET;
126 sa.sin_port = htons(opt_dport);
127 sa.sin_addr.s_addr = htonl(INADDR_ANY);
129 if(bind(s, (struct sockaddr*)&sa, sizeof sa) == -1) {
130 perror("failed to bind datagram socket");
131 close(s);
132 return -1;
133 }
135 do {
136 fd_set rdset;
138 msg.magic = MAGIC;
139 msg.type = REQ_DISCOVER;
141 memset(&sa, 0, sizeof sa);
142 sa.sin_family = AF_INET;
143 sa.sin_port = htons(opt_dport);
144 sa.sin_addr.s_addr = 0xffffffff;
146 if(sendto(s, &msg, sizeof msg, 0, (struct sockaddr*)&sa, sizeof sa) == -1) {
147 perror("failed to send discovery bcast dgram");
148 close(s);
149 return -1;
150 }
152 tv_timeout.tv_sec = timeout / 1000;
153 tv_timeout.tv_usec = (timeout % 1000) * 1000;
155 FD_ZERO(&rdset);
156 FD_SET(s, &rdset);
158 gettimeofday(&tv0, 0);
160 while(select(s + 1, &rdset, 0, 0, &tv_timeout) == -1 && errno == EINTR);
162 gettimeofday(&tv, 0);
163 timeout -= (tv.tv_sec - tv0.tv_sec) * 1000 + (tv.tv_usec - tv0.tv_usec) / 1000;
165 if(FD_ISSET(s, &rdset)) {
166 socklen_t sa_size = sizeof *srv_sa;
167 if(recvfrom(s, &msg, sizeof msg, 0, (struct sockaddr*)srv_sa, &sa_size) == -1) {
168 perror("failed to receive datagram\n");
169 }
170 if(msg.magic == MAGIC && msg.type == RSP_OK) {
171 printf("found input server \"%s\" at: %s:%d\n", msg.data.raw,
172 inet_ntoa(srv_sa->sin_addr), ntohs(srv_sa->sin_port));
173 return s;
174 }
175 }
177 } while(timeout > 0);
179 close(s);
180 return -1;
181 }
183 static int send_request(int s, struct message *msg, long timeout)
184 {
185 fd_set rdset;
186 struct timeval tv, tv0, tv_timeout;
187 struct message resp;
189 do {
190 if(send(s, msg, sizeof *msg, 0) == -1) {
191 perror("failed to send message");
192 return -1;
193 }
195 tv_timeout.tv_sec = timeout / 1000;
196 tv_timeout.tv_usec = (timeout % 1000) * 1000;
198 FD_ZERO(&rdset);
199 FD_SET(s, &rdset);
201 gettimeofday(&tv0, 0);
202 while(select(s + 1, &rdset, 0, 0, &tv_timeout) == -1 && errno == EINTR);
203 gettimeofday(&tv, 0);
205 if(FD_ISSET(s, &rdset)) {
206 if(recv(s, &resp, sizeof resp, 0) == -1) {
207 perror("failed to recieve message");
208 return -1;
209 }
210 if(resp.magic != MAGIC) {
211 fprintf(stderr, "got invalid response\n");
212 return -1;
213 }
214 memcpy(msg, &resp, sizeof resp);
215 return 0;
216 }
218 timeout -= (tv.tv_sec - tv0.tv_sec) * 1000 + (tv.tv_usec - tv0.tv_usec) / 1000;
219 } while(timeout > 0);
221 return -1;
222 }