Tool Libs
UMIT-TIROL Institute of Automation and Control Engineering library collection
 
Loading...
Searching...
No Matches
comm.h
1#pragma once
2#include <utils/queue.h>
3#include <core/logger.h>
4
5#include <arpa/inet.h>
6#include <cerrno>
7#include <fcntl.h>
8#include <sys/socket.h>
9#include <unistd.h>
10
12struct TTY:
13 public Sink<Buffer<uint8_t>>,
14 public Source<Buffer<uint8_t>> {
15 int fd{};
16 static constexpr size_t BLEN = 512;
18 Buffer<uint8_t> wrk = BLEN;
20 TTY (const char *path) {
21 fd = open(path, O_RDWR | O_NONBLOCK);
22 }
23 ~TTY() {
24 close(fd);
25 }
26 bool full() override {
27 return tx.full();
28 }
29 using Sink::push;
30 void push(Buffer<uint8_t> &&b) override {
31 tx.push(std::move(b));
32 process();
33 }
34 bool empty() override {
35 int l = read(fd, wrk.buf, wrk.size);
36 if (l < 0) {
37 if (errno != EAGAIN) {
38 perror("reading on fd error");
39 }
40 return rx.empty();
41 }
42 wrk.len = l;
43 rx.push(std::move(wrk));
44 wrk = BLEN;
45 return false;
46 }
47 Buffer<uint8_t> pop() override {
48 return rx.pop();
49 }
50 void process() {
51 //transmit side
52 while (!tx.empty()) {
53 auto msg = tx.front();
54 int l = write(fd, msg.buf, msg.len);
55 if (l < 0) {
56 if (errno != EAGAIN) {
57 perror("writing to fd error");
58 }
59 break;
60 } else if ((size_t)l < msg.len) {
61 for (size_t i = 0; i < msg.len-l; i++){
62 msg.buf[i] = msg.buf[i+l];
63 }
64 msg.len -= l;
65 } else { //success
66 tx.pop();
67 }
68 }
69 }
70};
71
76struct UDP:
77 public Sink<Buffer<uint8_t>>,
78 public Source<Buffer<uint8_t>> {
79 int fd{};
80 struct {
81 struct sockaddr addr {};
82 socklen_t len {sizeof (struct sockaddr)};
83 } peer;
84 static constexpr size_t BLEN = 128;
86 Buffer<uint8_t> wrk = BLEN;
88 UDP (const char *ip, uint16_t port) {
89 struct sockaddr_in addr = {
90 .sin_family = AF_INET,
91 .sin_port = htons(port),
92 };
93 inet_pton(AF_INET, ip, &addr.sin_addr);
94
95 fd = socket(PF_INET, SOCK_DGRAM, 0);
96 if (bind(fd, (sockaddr*)&addr, sizeof addr) == -1 ) {
97 perror("cannot bind socket to address");
98 return;
99 }
100 if (fcntl(fd, F_SETFL,
101 fcntl(fd, F_GETFL, 0) | O_NONBLOCK) == -1) {
102 perror("cannot set O_NONBLOCK on socket");
103 return;
104 }
105 }
106 ~UDP() {
107 close(fd);
108 }
109 bool full() override {
110 return tx.full();
111 }
112 using Sink::push;
113 void push(Buffer<uint8_t> &&b) override {
114 tx.push(std::move(b));
115 process();
116 }
117 bool empty() override {
118 int l = recvfrom(fd, wrk.buf, wrk.size, 0,
119 &peer.addr, &peer.len);
120 if (l < 0) {
121 if (errno != EAGAIN) {
122 perror("reading on socket error");
123 }
124 return rx.empty();
125 }
126 wrk.len = l;
127 rx.push(std::move(wrk));
128 wrk = BLEN;
129 return false;
130 }
131 Buffer<uint8_t> pop() override {
132 return rx.pop();
133 }
134 void process() {
135 //transmit side
136 while (!tx.empty()) {
137 auto msg = tx.front();
138 int l = sendto(fd, msg.buf, msg.len, 0,
139 &peer.addr, peer.len);
140 if (l < 0) {
141 if (errno != EAGAIN) {
142 perror("writing to socket error");
143 }
144 break;
145 } else if ((size_t)l < msg.len) {
146 for (size_t i = 0; i < msg.len-l; i++){
147 msg.buf[i] = msg.buf[i+l];
148 }
149 msg.len -= l;
150 } else { //success
151 tx.pop();
152 }
153 }
154 }
155};
156
160struct IFACE: public TTY, public Logger {
161 IFACE(const char *path): TTY(path), Logger(*(TTY*)this) {}
162};
simple Buffer backed queue implementation
Definition queue.h:12
T pop() override
remove front of queue and return it
Definition queue.h:65
bool empty() override
check if queue is empty
Definition queue.h:83
bool full() override
return true if queue is full
Definition queue.h:87
void push(T &&val) override
move element into queue
Definition queue.h:49
T & front()
return reference to first element in queue
Definition queue.h:55
Copyright (c) 2023 IACE.
Copyright (c) 2023 IACE.
dynamically allocated, but fixed-size buffer template
Definition buffer.h:18
size_t size
total capacity of buffer
Definition buffer.h:23
size_t len
number of items stored in buffer
Definition buffer.h:21
simple wrapper around TTY & Logger useful for creating simple user interactions
Definition comm.h:160
simple printf-style logging infrastructure
Definition logger.h:21
generic object sink, i.e.
Definition streams.h:15
virtual void push(const T &t)
copy semantics does not check for space. guard by using 'if (!full) { ... }'
Definition streams.h:20
generic object source, i.e.
Definition streams.h:40
TTY communication backend.
Definition comm.h:14
Buffer< uint8_t > pop() override
pull object from source does not check for data. guard by using 'if (!empty) { ......
Definition comm.h:47
TTY(const char *path)
open given path
Definition comm.h:20
void push(Buffer< uint8_t > &&b) override
move semantics does not check for space. guard by using 'if (!full) { ... }'
Definition comm.h:30
bool empty() override
check if source is empty
Definition comm.h:34
bool full() override
check if sink is full
Definition comm.h:26
UDP Server communication backend.
Definition comm.h:78
bool empty() override
check if source is empty
Definition comm.h:117
UDP(const char *ip, uint16_t port)
create UDP Server listening on ip/port
Definition comm.h:88
void push(Buffer< uint8_t > &&b) override
move semantics does not check for space. guard by using 'if (!full) { ... }'
Definition comm.h:113
Buffer< uint8_t > pop() override
pull object from source does not check for data. guard by using 'if (!empty) { ......
Definition comm.h:131
bool full() override
check if sink is full
Definition comm.h:109