1 /*
2 * This code is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This code is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13 #include <sys/types.h>
14 #include <sys/uio.h>
15
16 #include "config.h"
17 #include "spectool_net_client.h"
18
spectool_netcli_init(spectool_server * sr,char * url,char * errstr)19 int spectool_netcli_init(spectool_server *sr, char *url, char *errstr) {
20 int ret;
21
22 sr->sock = -1;
23 sr->hostname[0] = '\0';
24 sr->port = 0;
25 sr->url = NULL;
26
27 sr->host = NULL;
28
29 sr->bufferwrite = 1;
30
31 memset(sr->wbuf, 0, CLI_BUF_SZ);
32 memset(sr->rbuf, 0, CLI_BUF_SZ);
33
34 sr->write_pos = 0;
35 sr->read_pos = 0;
36 sr->write_fill = 0;
37 sr->read_fill = 0;
38
39 sr->devlist = NULL;
40
41 sr->state = SPECTOOL_NET_STATE_NONE;
42
43 if ((ret = sscanf(url, "tcp://%256[^:]:%hd", sr->hostname,
44 &(sr->port))) == 1) {
45 sr->port = SPECTOOL_NET_DEFAULT_PORT;
46 } else if (ret != 2) {
47 snprintf(errstr, SPECTOOL_ERROR_MAX, "Could not parse server URL, expected "
48 "tcp://host:port");
49 sr->state = SPECTOOL_NET_STATE_ERROR;
50 return -1;
51 }
52
53 sr->host = gethostbyname(sr->hostname);
54
55 if (sr->host == NULL) {
56 snprintf(errstr, SPECTOOL_ERROR_MAX, "Could not resolve host '%s'",
57 sr->hostname);
58 sr->state = SPECTOOL_NET_STATE_ERROR;
59 return -1;
60 }
61
62 memcpy((char *) &(sr->conaddr), sr->host->h_addr_list[0],
63 sizeof(unsigned int) < sr->host->h_length ?
64 sizeof(unsigned int) : sr->host->h_length);
65
66 sr->url = strdup(url);
67
68 return 1;
69 }
70
spectool_netcli_connect(spectool_server * sr,char * errstr)71 int spectool_netcli_connect(spectool_server *sr, char *errstr) {
72 int save_mode;
73
74 struct sockaddr_in servaddr, localaddr;
75
76 memset(&servaddr, 0, sizeof(struct sockaddr_in));
77 servaddr.sin_family = sr->host->h_addrtype;
78 memcpy((char *) &servaddr.sin_addr.s_addr,
79 sr->host->h_addr_list[0], sr->host->h_length);
80 servaddr.sin_port = htons(sr->port);
81
82 if ((sr->sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
83 snprintf(errstr, SPECTOOL_ERROR_MAX, "Failed to create socket to server: %s",
84 strerror(errno));
85 sr->state = SPECTOOL_NET_STATE_ERROR;
86 return -1;
87 }
88
89 memset(&localaddr, 0, sizeof(struct sockaddr_in));
90 localaddr.sin_family = AF_INET;
91 localaddr.sin_addr.s_addr = htonl(INADDR_ANY);
92 localaddr.sin_port = htons(0);
93
94 if (bind(sr->sock, (struct sockaddr *) &localaddr, sizeof(localaddr)) < 0) {
95 close(sr->sock);
96 snprintf(errstr, SPECTOOL_ERROR_MAX, "Failed to bind socket to server: %s",
97 strerror(errno));
98 sr->state = SPECTOOL_NET_STATE_ERROR;
99 return -1;
100 }
101
102 if (connect(sr->sock, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
103 close(sr->sock);
104 snprintf(errstr, SPECTOOL_ERROR_MAX, "Failed to connect socket to server: %s",
105 strerror(errno));
106 sr->state = SPECTOOL_NET_STATE_ERROR;
107 return -1;
108 }
109
110 save_mode = fcntl(sr->sock, F_GETFL, 0);
111 fcntl(sr->sock, F_SETFL, save_mode | O_NONBLOCK);
112
113 sr->state = SPECTOOL_NET_STATE_CONNECTED;
114
115 return 1;
116 }
117
spectool_netcli_close(spectool_server * sr)118 int spectool_netcli_close(spectool_server *sr) {
119 spectool_net_dev *di;
120
121 while (sr->devlist != NULL) {
122 di = sr->devlist->next;
123 free(sr->devlist);
124 sr->devlist = di;
125 }
126
127 if (sr->sock >= 0)
128 close(sr->sock);
129
130 if (sr->url != NULL)
131 free(sr->url);
132
133 return 1;
134 }
135
spectool_netcli_getstate(spectool_server * sr)136 int spectool_netcli_getstate(spectool_server *sr) {
137 return sr->state;
138 }
139
spectool_netcli_geturl(spectool_server * sr)140 char *spectool_netcli_geturl(spectool_server *sr) {
141 return sr->url;
142 }
143
spectool_netcli_getpollfd(spectool_server * sr)144 int spectool_netcli_getpollfd(spectool_server *sr) {
145 return sr->sock;
146 }
147
spectool_netcli_getwritefd(spectool_server * sr)148 int spectool_netcli_getwritefd(spectool_server *sr) {
149 return sr->sock;
150 }
151
spectool_netcli_getaddr(spectool_server * sr)152 unsigned int spectool_netcli_getaddr(spectool_server *sr) {
153 return sr->conaddr;
154 }
155
spectool_netcli_getport(spectool_server * sr)156 unsigned short int spectool_netcli_getport(spectool_server *sr) {
157 return sr->port;
158 }
159
spectool_netcli_setbufferwrite(spectool_server * sr,int buf)160 void spectool_netcli_setbufferwrite(spectool_server *sr, int buf) {
161 sr->bufferwrite = buf;
162 }
163
spectool_netcli_getwritepend(spectool_server * sr)164 int spectool_netcli_getwritepend(spectool_server *sr) {
165 return (sr->write_pos < sr->write_fill);
166 }
167
spectool_netcli_poll(spectool_server * sr,char * errstr)168 int spectool_netcli_poll(spectool_server *sr, char *errstr) {
169 spectool_fr_header *header;
170 int res;
171 int ret = 0;
172
173 if (sr->sock < 0)
174 return -1;
175
176 while (sr->read_fill - sr->read_pos >= spectool_fr_header_size()) {
177 header = (spectool_fr_header *) &(sr->rbuf[sr->read_pos]);
178
179 /* Nuke the buffer entirely and start over if we can't find a
180 * sentinel */
181 if (ntohl(header->sentinel) != SPECTOOL_NET_SENTINEL) {
182 sr->read_fill = 0;
183 sr->read_pos = 0;
184 return 0;
185 }
186
187 if (ntohs(header->frame_len) > (sr->read_fill - sr->read_pos)) {
188 return 0;
189 }
190
191 sr->read_pos += ntohs(header->frame_len);
192
193 /* If we've finished the packet reset the buffer to the beginning */
194 if (sr->read_pos >= sr->read_fill) {
195 sr->read_pos = 0;
196 sr->read_fill = 0;
197 }
198
199 /* We only care about device and sweeps, the rest get ignored (for now) */
200 if (header->block_type == SPECTOOL_NET_FRAME_DEVICE) {
201 if ((res = spectool_netcli_block_netdev(sr, header, errstr)) < 0) {
202 return -1;
203 }
204
205 if (res > 0) {
206 ret |= SPECTOOL_NETCLI_POLL_NEWDEVS;
207 }
208
209 } else if (header->block_type == SPECTOOL_NET_FRAME_SWEEP) {
210 if ((res = spectool_netcli_block_sweep(sr, header, errstr)) < 0) {
211 return -1;
212 }
213
214 if (res > 0) {
215 ret |= SPECTOOL_NETCLI_POLL_NEWSWEEPS;
216 }
217 }
218 }
219
220 /* Read as much as we can */
221 if ((res = read(sr->sock, &(sr->rbuf[sr->read_fill]),
222 CLI_BUF_SZ - sr->read_fill)) <= 0) {
223 if (errno == EAGAIN)
224 return ret;
225
226 snprintf(errstr, SPECTOOL_ERROR_MAX, "Failed to read from socket: %s",
227 strerror(errno));
228 sr->state == SPECTOOL_NET_STATE_ERROR;
229 return -1;
230 }
231
232 sr->read_fill += res;
233
234 if (res > 0) {
235 ret |= SPECTOOL_NETCLI_POLL_ADDITIONAL;
236 }
237
238 return ret;
239 }
240
spectool_netcli_writepoll(spectool_server * sr,char * errstr)241 int spectool_netcli_writepoll(spectool_server *sr, char *errstr) {
242 int res;
243
244 if ((res = write(sr->sock, &(sr->wbuf[sr->write_pos]),
245 sr->write_fill - sr->write_pos)) < 0) {
246 snprintf(errstr, SPECTOOL_ERROR_MAX, "write() failed on %s",
247 strerror(errno));
248 return -1;
249 }
250
251 sr->write_pos += res;
252
253 if (sr->write_pos >= sr->write_fill) {
254 sr->write_fill = 0;
255 sr->write_pos = 0;
256 }
257
258 return 1;
259 }
260
spectool_netcli_block_netdev(spectool_server * sr,spectool_fr_header * header,char * errstr)261 int spectool_netcli_block_netdev(spectool_server *sr, spectool_fr_header *header,
262 char *errstr) {
263 spectool_fr_device *dev;
264 spectool_net_dev *sni;
265 int bsize = ntohs(header->frame_len) - spectool_fr_header_size();
266
267 int num_devices;
268 int x;
269
270 num_devices = header->num_blocks;
271
272 for (x = 0; x < header->num_blocks; x++) {
273 /* If we can't fit, bail. In the future this will have to be
274 * rewritten to handle variable sized devices, maybe */
275 if (bsize < spectool_fr_device_size() * (x + 1)) {
276 return -1;
277 }
278
279 dev = (spectool_fr_device *) &(header->data[spectool_fr_device_size() * x]);
280
281 /* Is this the last device? */
282 if (dev->device_version == SPECTOOL_NET_DEVTYPE_LASTDEV) {
283 sr->state == SPECTOOL_NET_STATE_CONFIGURED;
284 return 1;
285 }
286
287 /* Does this device exist in the list? If it does, just update it,
288 * otherwise we need to make a new one */
289 sni = sr->devlist;
290 while (sni != NULL) {
291 if (ntohl(dev->device_id) == sni->device_id)
292 break;
293
294 sni = sni->next;
295 }
296
297 if (sni == NULL) {
298 sni = (spectool_net_dev *) malloc(sizeof(spectool_net_dev));
299 sni->phydev = NULL;
300 sni->next = sr->devlist;
301 sr->devlist = sni;
302 }
303
304 sni->device_version = dev->device_version;
305 sni->device_flags = ntohs(dev->device_flags);
306 sni->device_id = ntohl(dev->device_id);
307
308 snprintf(sni->device_name, 256, "%s", dev->device_name);
309 sni->device_name[dev->device_name_len] = '\0';
310
311 sni->amp_offset_mdbm = ntohl(dev->amp_offset_mdbm) * -1;
312 sni->amp_res_mdbm = ntohl(dev->amp_res_mdbm);
313 sni->rssi_max = ntohs(dev->rssi_max);
314
315 sni->def_start_khz = ntohl(dev->def_start_khz);
316 sni->def_res_hz = ntohl(dev->def_res_hz);
317 sni->def_num_samples = ntohs(dev->def_num_samples);
318
319 sni->start_khz = ntohl(dev->start_khz);
320 sni->res_hz = ntohl(dev->res_hz);
321 sni->num_samples = ntohs(dev->num_samples);
322 }
323
324 return 0;
325 }
326
spectool_netcli_block_sweep(spectool_server * sr,spectool_fr_header * header,char * errstr)327 int spectool_netcli_block_sweep(spectool_server *sr, spectool_fr_header *header,
328 char *errstr) {
329 spectool_fr_sweep *sweep;
330 int x, y;
331 int bsize = ntohs(header->frame_len) - spectool_fr_header_size();
332 int pos = 0;
333 spectool_net_dev *sni;
334 spectool_sample_sweep *auxsweep;
335
336 for (x = 0; x < header->num_blocks; x++) {
337 sweep = (spectool_fr_sweep *) &(header->data[pos]);
338
339 if (bsize - pos < 2) {
340 /* way too short, bail with error */
341 snprintf(errstr, SPECTOOL_ERROR_MAX, "Got runt sweep frame, bailing");
342 return -1;
343 }
344
345 if (ntohs(sweep->frame_len) < spectool_fr_sweep_size(0)) {
346 /* Again, too short */
347 snprintf(errstr, SPECTOOL_ERROR_MAX, "Got runt sweep frame, bailing");
348 return -1;
349 }
350
351 sni = sr->devlist;
352 while (sni != NULL) {
353 if (ntohl(sweep->device_id) == sni->device_id)
354 break;
355
356 sni = sni->next;
357 }
358
359 if (sni == NULL) {
360 snprintf(errstr, SPECTOOL_ERROR_MAX, "Got sweep frame for device which "
361 "was not advertised, discarding");
362 return -1;
363 }
364
365 if (ntohs(sweep->frame_len) <
366 spectool_fr_sweep_size(sni->num_samples)) {
367 snprintf(errstr, SPECTOOL_ERROR_MAX, "Got sweep frame too small to hold "
368 "indicated number of samples, bailing - %u samples %u < %u",
369 sni->num_samples,
370 ntohs(sweep->frame_len),
371 spectool_fr_sweep_size(sni->num_samples));
372 return -1;
373 }
374
375
376 pos += htons(sweep->frame_len);
377
378 /* For now we don't bother tracking data for devices which don't have a
379 * phydev linked to them -- we shouldn't get it, anyhow */
380 if (sni->phydev == NULL)
381 continue;
382
383 if ((auxsweep = ((spectool_net_dev_aux *) (sni->phydev->auxptr))->sweep) != NULL) {
384 free(auxsweep);
385 }
386
387 auxsweep =
388 (spectool_sample_sweep *) malloc(SPECTOOL_SWEEP_SIZE(sni->num_samples));
389
390 /* Copy data out of our device record (this will change later when the
391 * spectool internals change) */
392 auxsweep->start_khz = sni->start_khz;
393 auxsweep->res_hz = sni->res_hz;
394 auxsweep->num_samples = sni->num_samples;
395 auxsweep->end_khz =
396 ((auxsweep->res_hz / 1000) * auxsweep->num_samples) +
397 auxsweep->start_khz;
398
399 auxsweep->amp_offset_mdbm = sni->amp_offset_mdbm;
400 auxsweep->amp_res_mdbm = sni->amp_res_mdbm;
401 auxsweep->rssi_max = sni->rssi_max;
402
403 /* Lock start and end to the same */
404 auxsweep->tm_start.tv_sec =
405 auxsweep->tm_end.tv_sec =
406 ntohl(sweep->start_sec);
407 auxsweep->tm_start.tv_usec =
408 auxsweep->tm_end.tv_usec =
409 ntohl(sweep->start_usec);
410
411 /* Copy the RSSI data */
412 for (y = 0; y < sni->num_samples; y++) {
413 auxsweep->sample_data[y] = sweep->sample_data[y];
414
415 if (sni->phydev->min_rssi_seen > sweep->sample_data[y])
416 sni->phydev->min_rssi_seen = sweep->sample_data[y];
417 }
418
419 auxsweep->min_rssi_seen = sni->phydev->min_rssi_seen;
420
421 auxsweep->phydev = sni->phydev;
422
423 /* Flag that we got a new frame */
424 ((spectool_net_dev_aux *) (sni->phydev->auxptr))->new_sweep = 1;
425 ((spectool_net_dev_aux *) (sni->phydev->auxptr))->sweep = auxsweep;
426 write(((spectool_net_dev_aux *) (sni->phydev->auxptr))->spipe[1], "0", 1);
427 }
428
429 return 1;
430 }
431
spectool_netcli_append(spectool_server * sr,uint8_t * data,int len,char * errstr)432 int spectool_netcli_append(spectool_server *sr, uint8_t *data, int len, char *errstr) {
433 if (sr->bufferwrite == 0) {
434 if (write(sr->sock, data, len) < 0) {
435 snprintf(errstr, SPECTOOL_ERROR_MAX, "write() failed on %s",
436 strerror(errno));
437 return -1;
438 }
439
440 return 1;
441 }
442
443 if (sr->write_fill + len >= CLI_BUF_SZ) {
444 snprintf(errstr, SPECTOOL_ERROR_MAX, "Network client write buffer can't "
445 "fit %d bytes, %d of %d full", len, sr->write_fill, CLI_BUF_SZ);
446 return -1;
447 }
448
449 memcpy(&(sr->wbuf[sr->write_fill]), data, len);
450 sr->write_fill += len;
451
452 return 1;
453 }
454
spectool_netcli_enabledev(spectool_server * sr,unsigned int dev_id,char * errstr)455 spectool_phy *spectool_netcli_enabledev(spectool_server *sr, unsigned int dev_id,
456 char *errstr) {
457 spectool_phy *phyret;
458 spectool_net_dev_aux *aux;
459 spectool_net_dev *sni;
460 spectool_fr_header *header;
461 spectool_fr_command *cmd;
462 spectool_fr_command_enabledev *cmde;
463 int sz;
464
465 sni = sr->devlist;
466 while (sni != NULL) {
467 if (dev_id == sni->device_id)
468 break;
469
470 sni = sni->next;
471 }
472
473 if (sni == NULL) {
474 snprintf(errstr, SPECTOOL_ERROR_MAX, "Could not find device %u in list "
475 "from server.", dev_id);
476 return NULL;
477 }
478
479 if (sni->phydev != NULL)
480 return sni->phydev;
481
482 sz = spectool_fr_header_size() +
483 spectool_fr_command_size(spectool_fr_command_enabledev_size(0));
484
485 header = (spectool_fr_header *) malloc(sz);
486
487 cmd = (spectool_fr_command *) header->data;
488 cmde = (spectool_fr_command_enabledev *) cmd->command_data;
489
490 header->sentinel = htonl(SPECTOOL_NET_SENTINEL);
491 header->frame_len = htons(sz);
492 header->proto_version = SPECTOOL_NET_PROTO_VERSION;
493 header->block_type = SPECTOOL_NET_FRAME_COMMAND;
494 header->num_blocks = 1;
495
496 cmd->frame_len =
497 htons(spectool_fr_command_size(spectool_fr_command_enabledev_size(0)));
498 cmd->command_id = SPECTOOL_NET_COMMAND_ENABLEDEV;
499 cmd->command_len = htons(spectool_fr_command_enabledev_size(0));
500
501 cmde->device_id = htonl(dev_id);
502
503 if (spectool_netcli_append(sr, (uint8_t *) header, sz, errstr) < 0) {
504 free(header);
505 return NULL;
506 }
507
508 free(header);
509
510 phyret = (spectool_phy *) malloc(SPECTOOL_PHY_SIZE);
511 aux = (spectool_net_dev_aux *) malloc(sizeof(spectool_net_dev_aux));
512 phyret->auxptr = aux;
513
514 aux->sweep = NULL;
515 aux->new_sweep = 0;
516
517 pipe(aux->spipe);
518 fcntl(aux->spipe[0], F_SETFL, fcntl(aux->spipe[0], F_GETFL, 0) | O_NONBLOCK);
519
520 phyret->device_spec = (spectool_dev_spec *) malloc(sizeof(spectool_dev_spec));
521
522 phyret->state = SPECTOOL_STATE_CONFIGURING;
523 phyret->min_rssi_seen = -1;
524
525 phyret->device_spec->device_id = sni->device_id;
526 phyret->device_spec->device_version = sni->device_version;
527 phyret->device_spec->device_flags = sni->device_flags;
528
529 phyret->device_spec->num_sweep_ranges = 1;
530
531 phyret->device_spec->supported_ranges =
532 (spectool_sample_sweep *) malloc(SPECTOOL_SWEEP_SIZE(0));
533
534 phyret->device_spec->supported_ranges[0].num_samples = sni->def_num_samples;
535 phyret->device_spec->supported_ranges[0].amp_offset_mdbm = sni->amp_offset_mdbm;
536 phyret->device_spec->supported_ranges[0].amp_res_mdbm = sni->amp_res_mdbm;
537 phyret->device_spec->supported_ranges[0].rssi_max = sni->rssi_max;
538
539 phyret->device_spec->supported_ranges[0].start_khz = sni->start_khz;
540 phyret->device_spec->supported_ranges[0].end_khz =
541 ((sni->res_hz / 1000) * sni->num_samples) +
542 sni->start_khz;
543 phyret->device_spec->supported_ranges[0].res_hz = sni->res_hz;
544
545 phyret->device_spec->default_range = phyret->device_spec->supported_ranges;
546
547 phyret->device_spec->cur_profile = 0;
548
549 phyret->open_func = &spectool_net_open;
550 phyret->close_func = &spectool_net_close;
551 phyret->poll_func = &spectool_net_poll;
552 phyret->pollfd_func = &spectool_net_getpollfd;
553 phyret->setcalib_func = &spectool_net_setcalibration;
554 phyret->getsweep_func = &spectool_net_getsweep;
555 phyret->setposition_func = &spectool_net_setposition;
556
557 snprintf(phyret->device_spec->device_name, SPECTOOL_PHY_NAME_MAX,
558 "%s", sni->device_name);
559
560 sni->phydev = phyret;
561
562 return phyret;
563 }
564
spectool_netcli_disabledev(spectool_server * sr,spectool_phy * dev)565 int spectool_netcli_disabledev(spectool_server *sr, spectool_phy *dev) {
566 spectool_net_dev_aux *aux;
567 spectool_net_dev *sni;
568 spectool_fr_header *header;
569 spectool_fr_command *cmd;
570 spectool_fr_command_disabledev *cmdd;
571 char errstr[SPECTOOL_ERROR_MAX];
572 int sz;
573
574 sni = sr->devlist;
575 while (sni != NULL) {
576 if (dev == sni->phydev)
577 break;
578
579 sni = sni->next;
580 }
581
582 if (sni == NULL) {
583 return -1;
584 }
585
586 if (sni->phydev == NULL)
587 return -1;
588
589 sz = spectool_fr_header_size() +
590 spectool_fr_command_size(spectool_fr_command_disabledev_size(0));
591
592 header = (spectool_fr_header *) malloc(sz);
593
594 cmd = (spectool_fr_command *) header->data;
595 cmdd = (spectool_fr_command_disabledev *) cmd->command_data;
596
597 header->sentinel = htonl(SPECTOOL_NET_SENTINEL);
598 header->frame_len = htons(sz);
599 header->proto_version = SPECTOOL_NET_PROTO_VERSION;
600 header->block_type = SPECTOOL_NET_FRAME_COMMAND;
601 header->num_blocks = 1;
602
603 cmd->frame_len =
604 htons(spectool_fr_command_size(spectool_fr_command_disabledev_size(0)));
605 cmd->command_id = SPECTOOL_NET_COMMAND_DISABLEDEV;
606 cmd->command_len = htons(spectool_fr_command_disabledev_size(0));
607
608 cmdd->device_id = htonl(sni->device_id);
609
610 free(dev->auxptr);
611 free(dev);
612 sni->phydev = NULL;
613
614 if (spectool_netcli_append(sr, (uint8_t *) header, sz, errstr) < 0) {
615 free(header);
616 return -1;
617 }
618
619 free(header);
620
621 return 1;
622 }
623
spectool_net_setcalibration(spectool_phy * phydev,int in_calib)624 void spectool_net_setcalibration(spectool_phy *phydev, int in_calib) {
625 return;
626 }
627
spectool_net_poll(spectool_phy * phydev)628 int spectool_net_poll(spectool_phy *phydev) {
629 int ret = SPECTOOL_POLL_NONE;
630 char junk[8];
631
632 read(((spectool_net_dev_aux *) phydev->auxptr)->spipe[0], junk, 8);
633
634 if (phydev->state == SPECTOOL_STATE_CONFIGURING) {
635 ret |= SPECTOOL_POLL_CONFIGURED;
636 ret |= SPECTOOL_POLL_ADDITIONAL;
637 phydev->state = SPECTOOL_STATE_RUNNING;
638 return ret;
639 }
640
641 if (((spectool_net_dev_aux *) phydev->auxptr)->new_sweep) {
642 ((spectool_net_dev_aux *) phydev->auxptr)->new_sweep = 0;
643 ret |= SPECTOOL_POLL_SWEEPCOMPLETE;
644 }
645
646 return ret;
647 }
648
spectool_net_getpollfd(spectool_phy * phydev)649 int spectool_net_getpollfd(spectool_phy *phydev) {
650 return ((spectool_net_dev_aux *) phydev->auxptr)->spipe[0];
651 }
652
spectool_net_open(spectool_phy * phydev)653 int spectool_net_open(spectool_phy *phydev) {
654 return 1;
655 }
656
spectool_net_close(spectool_phy * phydev)657 int spectool_net_close(spectool_phy *phydev) {
658 /* TODO - fill this in w/a close */
659 close(((spectool_net_dev_aux *) phydev->auxptr)->spipe[0]);
660 close(((spectool_net_dev_aux *) phydev->auxptr)->spipe[1]);
661 return 1;
662 }
663
spectool_net_getsweep(spectool_phy * phydev)664 spectool_sample_sweep *spectool_net_getsweep(spectool_phy *phydev) {
665 return ((spectool_net_dev_aux *) phydev->auxptr)->sweep;
666 }
667
spectool_net_setposition(spectool_phy * phydev,int in_profile,int start_khz,int res_hz)668 int spectool_net_setposition(spectool_phy *phydev, int in_profile,
669 int start_khz, int res_hz) {
670 /* todo - fill this in */
671 return 1;
672 }
673
spectool_netcli_initbroadcast(short int port,char * errstr)674 int spectool_netcli_initbroadcast(short int port, char *errstr) {
675 struct sockaddr_in lsin;
676 int sock;
677 int x;
678
679 memset(&lsin, 0, sizeof(struct sockaddr_in));
680 lsin.sin_family = AF_INET;
681 lsin.sin_port = htons(port);
682 lsin.sin_addr.s_addr = INADDR_ANY;
683
684 if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
685 snprintf(errstr, SPECTOOL_ERROR_MAX,
686 "netcli broadcast listen socket failed: %s", strerror(errno));
687 return -1;
688 }
689
690 /* we don't seem to need this in listen mode?
691 x = 1;
692 if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &x, sizeof(x)) < 0) {
693 snprintf(errstr, SPECTOOL_ERROR_MAX,
694 "netcli broadcast listen socket bcast sockopt failed: %s",
695 strerror(errno));
696 close(sock);
697 return -1;
698 }
699 */
700
701 fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK);
702
703 if (bind(sock, (struct sockaddr *) &lsin, sizeof(lsin)) < 0) {
704 snprintf(errstr, SPECTOOL_ERROR_MAX,
705 "netcli broadcast listen socket bind failed: %s",
706 strerror(errno));
707 close(sock);
708 return -1;
709 }
710
711 return sock;
712 }
713
spectool_netcli_pollbroadcast(int sock,char * ret_url,char * errstr)714 int spectool_netcli_pollbroadcast(int sock, char *ret_url, char *errstr) {
715 struct msghdr rcv_msg;
716 struct iovec iov;
717 spectool_fr_broadcast buf;
718 struct sockaddr_in recv_addr;
719
720 iov.iov_base = &buf;
721 iov.iov_len = sizeof(spectool_fr_broadcast);
722
723 rcv_msg.msg_name = &recv_addr;
724 rcv_msg.msg_namelen = sizeof(recv_addr);
725 rcv_msg.msg_iov = &iov;
726 rcv_msg.msg_iovlen = 1;
727 rcv_msg.msg_control = NULL;
728 rcv_msg.msg_controllen = 0;
729
730 if (recvmsg(sock, &rcv_msg, 0) < 0) {
731 snprintf(errstr, SPECTOOL_ERROR_MAX,
732 "netcli broadcast recv failed: %s", strerror(errno));
733 return -1;
734 }
735
736 if (ntohl(buf.sentinel) == SPECTOOL_NET_SENTINEL) {
737 snprintf(ret_url, SPECTOOL_NETCLI_URL_MAX, "tcp://%s:%hu",
738 inet_ntoa(recv_addr.sin_addr), ntohs(buf.server_port));
739 return 1;
740 }
741
742 return 0;
743 }
744
745