vrmodel

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