vrmodel

annotate 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
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 }