vrmodel

view src/inpclient.cc @ 3:a1784a4290c2

client-side networking
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 01 Sep 2014 05:59:31 +0300
parents be91b72ce3f9
children a32b151fb3c6
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 return send_request(sock, &msg, opt_timeout);
44 }
46 int netinp_stop()
47 {
48 struct message msg;
50 if(sock == -1) {
51 return -1;
52 }
54 memset(&msg, 0, sizeof msg);
55 msg.magic = MAGIC;
56 msg.type = REQ_STOP;
57 return send_request(sock, &msg, opt_timeout);
58 }
60 int netinp_read(float *pos)
61 {
62 struct message msg;
64 if(sock == -1) {
65 return -1;
66 }
68 if(recv(sock, &msg, sizeof msg, 0) == -1) {
69 perror("netinp_read failed");
70 return -1;
71 }
73 pos[0] = ((float*)msg.data)[0];
74 pos[1] = ((float*)msg.data)[1];
75 pos[2] = ((float*)msg.data)[3];
76 return 0;
77 }
79 int netinp_reset()
80 {
81 return -1; // TODO
82 }
84 static int discover(struct sockaddr_in *srv_sa)
85 {
86 int s, true_val = 1;
87 struct sockaddr_in sa;
88 long timeout = opt_timeout;
89 struct message msg;
90 struct timeval tv0, tv, tv_timeout;
92 if((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
93 perror("failed to create discover datagram socket");
94 return -1;
95 }
96 setsockopt(s, SOL_SOCKET, SO_BROADCAST, &true_val, sizeof true_val);
98 memset(&sa, 0, sizeof sa);
99 sa.sin_family = AF_INET;
100 sa.sin_port = htons(opt_dport);
101 sa.sin_addr.s_addr = htonl(INADDR_ANY);
103 if(bind(s, (struct sockaddr*)&sa, sizeof sa) == -1) {
104 perror("failed to bind datagram socket");
105 close(s);
106 return -1;
107 }
109 do {
110 fd_set rdset;
112 msg.magic = MAGIC;
113 msg.type = REQ_DISCOVER;
115 memset(&sa, 0, sizeof sa);
116 sa.sin_family = AF_INET;
117 sa.sin_port = htons(opt_dport);
118 sa.sin_addr.s_addr = 0xffffffff;
120 if(sendto(s, &msg, sizeof msg, 0, (struct sockaddr*)&sa, sizeof sa) == -1) {
121 perror("failed to send discovery bcast dgram");
122 close(s);
123 return -1;
124 }
126 tv_timeout.tv_sec = timeout / 1000;
127 tv_timeout.tv_usec = (timeout % 1000) * 1000;
129 FD_ZERO(&rdset);
130 FD_SET(s, &rdset);
132 gettimeofday(&tv0, 0);
134 while(select(s + 1, &rdset, 0, 0, &tv_timeout) == -1 && errno == EINTR);
136 gettimeofday(&tv, 0);
137 timeout -= (tv.tv_sec - tv0.tv_sec) * 1000 + (tv.tv_usec - tv0.tv_usec) / 1000;
139 if(FD_ISSET(s, &rdset)) {
140 socklen_t sa_size = sizeof *srv_sa;
141 if(recvfrom(s, &msg, sizeof msg, 0, (struct sockaddr*)srv_sa, &sa_size) == -1) {
142 perror("failed to receive datagram\n");
143 }
144 if(msg.magic == MAGIC && msg.type == RSP_OK) {
145 printf("found input server \"%s\" at: %s:%d\n", msg.data,
146 inet_ntoa(srv_sa->sin_addr), ntohs(srv_sa->sin_port));
147 return s;
148 }
149 }
151 } while(timeout > 0);
153 close(s);
154 return -1;
155 }
157 static int send_request(int s, struct message *msg, long timeout)
158 {
159 fd_set rdset;
160 struct timeval tv, tv0, tv_timeout;
161 struct message resp;
163 do {
164 if(send(s, msg, sizeof *msg, 0) == -1) {
165 perror("failed to send message");
166 return -1;
167 }
169 tv_timeout.tv_sec = timeout / 1000;
170 tv_timeout.tv_usec = (timeout % 1000) * 1000;
172 FD_ZERO(&rdset);
173 FD_SET(s, &rdset);
175 gettimeofday(&tv0, 0);
176 while(select(s + 1, &rdset, 0, 0, &tv_timeout) == -1 && errno == EINTR);
177 gettimeofday(&tv, 0);
179 if(FD_ISSET(s, &rdset)) {
180 if(recv(s, &resp, sizeof resp, 0) == -1) {
181 perror("failed to recieve message");
182 return -1;
183 }
184 if(resp.magic != MAGIC) {
185 fprintf(stderr, "got invalid response\n");
186 return -1;
187 }
188 memcpy(msg, &resp, sizeof resp);
189 return 0;
190 }
192 timeout -= (tv.tv_sec - tv0.tv_sec) * 1000 + (tv.tv_usec - tv0.tv_usec) / 1000;
193 } while(timeout > 0);
195 return -1;
196 }