263 lines
5.6 KiB
C
263 lines
5.6 KiB
C
#include <arpa/inet.h>
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/epoll.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/timerfd.h>
|
|
#include <unistd.h>
|
|
|
|
#include "bufsize.h"
|
|
#include "serial.h"
|
|
#include "timer.h"
|
|
#include "parse_serial.h"
|
|
|
|
#define PORT 4321
|
|
//#define SERIALPORT "/dev/ttyS0"
|
|
#define SERIALPORT "/dev/ttyUSB0"
|
|
|
|
int handle_sock(int sock)
|
|
{
|
|
struct sockaddr_in src_addr;
|
|
socklen_t addrlen = (sizeof (struct sockaddr_in));
|
|
|
|
char buf[BUFSIZE];
|
|
|
|
while (true) {
|
|
ssize_t recv_len = recvfrom(sock, buf, BUFSIZE, 0, (struct sockaddr *)&src_addr, &addrlen);
|
|
if (recv_len == -1) {
|
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
|
perror("sock eagain");
|
|
return 0;
|
|
} else {
|
|
perror("recvfrom sock");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
printf("got %ld data\n", recv_len);
|
|
printf("Received packet from %s:%d\n", inet_ntoa(src_addr.sin_addr), ntohs(src_addr.sin_port));
|
|
buf[recv_len] = 0;
|
|
printf("Data: %s\n", buf);
|
|
}
|
|
}
|
|
|
|
int rearm_timer(int timerfd)
|
|
{
|
|
struct itimerspec value;
|
|
value.it_value.tv_sec = 1;
|
|
value.it_value.tv_nsec = 0;
|
|
value.it_interval.tv_sec = 0;
|
|
value.it_interval.tv_nsec = 0;
|
|
|
|
int ret = timerfd_settime(timerfd, 0, &value, NULL);
|
|
if (ret == -1) {
|
|
perror("timerfd_settime");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int handle_timerfd(int timerfd)
|
|
{
|
|
uint64_t expired_count = 0;
|
|
while (true) {
|
|
ssize_t len = read(timerfd, &expired_count, (sizeof (expired_count)));
|
|
if (len == -1) {
|
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
|
fprintf(stderr, "timerfd eagain\n");
|
|
break;
|
|
} else {
|
|
perror("read timerfd");
|
|
return -1;
|
|
}
|
|
}
|
|
assert(len == (sizeof (expired_count)));
|
|
printf("len %ld\n", len);
|
|
}
|
|
|
|
rearm_timer(timerfd);
|
|
printf("do timer stuff\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct receiver_state {
|
|
uint64_t seq;
|
|
uint64_t ack_seq;
|
|
};
|
|
|
|
int handle_serialfd(int timerfd,
|
|
struct parser_state * parser_state,
|
|
struct timer_state * timer_state)
|
|
{
|
|
uint8_t buf[BUFSIZE];
|
|
|
|
while (true) {
|
|
ssize_t len = read(timerfd, buf, (sizeof (buf)));
|
|
if (len == -1) {
|
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
|
fprintf(stderr, "serialfd eagain\n");
|
|
break;
|
|
} else {
|
|
perror("read serialfd");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/*
|
|
for (int i = 0; i < len; i++) {
|
|
fprintf(stderr, "%x ", buf[i]);
|
|
}
|
|
fprintf(stderr, "\n");
|
|
*/
|
|
bool have_state_change = handle_parse(buf, len,
|
|
parser_state,
|
|
timer_state);
|
|
printf("have_state_change: %d\n", have_state_change);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
int ret;
|
|
|
|
int sock = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
|
|
if (sock == -1) {
|
|
perror("socket");
|
|
return -1;
|
|
}
|
|
|
|
struct sockaddr_in sockaddr = {0};
|
|
sockaddr.sin_family = AF_INET;
|
|
sockaddr.sin_port = htons(PORT);
|
|
sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
|
|
ret = bind(sock, (struct sockaddr *)&sockaddr, (sizeof (struct sockaddr_in)));
|
|
if (ret == -1) {
|
|
perror("bind");
|
|
return -1;
|
|
}
|
|
|
|
#define MAX_EVENTS 5
|
|
struct epoll_event events[MAX_EVENTS];
|
|
|
|
int epollfd = epoll_create1(0);
|
|
if (epollfd == -1) {
|
|
perror("epoll_create1");
|
|
return -1;
|
|
}
|
|
|
|
{
|
|
struct epoll_event ev;
|
|
ev.events = EPOLLIN | EPOLLET;
|
|
ev.data.fd = sock;
|
|
ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, sock, &ev);
|
|
if (ret == -1) {
|
|
perror("epoll_ctl: sock");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
|
|
if (timerfd == -1) {
|
|
perror("timerfd_create");
|
|
return -1;
|
|
}
|
|
|
|
ret = rearm_timer(timerfd);
|
|
if (ret == -1) {
|
|
return -1;
|
|
}
|
|
|
|
if (0) {
|
|
struct epoll_event ev;
|
|
ev.events = EPOLLIN | EPOLLET;
|
|
ev.data.fd = timerfd;
|
|
ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, timerfd, &ev);
|
|
if (ret == -1) {
|
|
perror("epoll_ctl: timerfd");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int serialfd = open(SERIALPORT, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
|
if (serialfd == -1) {
|
|
perror("open: serialport");
|
|
return -1;
|
|
}
|
|
ret = set_terminal_attributes(serialfd);
|
|
if (ret == -1) {
|
|
return -1;
|
|
}
|
|
|
|
{
|
|
struct epoll_event ev;
|
|
ev.events = EPOLLIN | EPOLLET;
|
|
ev.data.fd = serialfd;
|
|
ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, serialfd, &ev);
|
|
if (ret == -1) {
|
|
perror("epoll_ctl: timerfd");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
struct parser_state parser_state = {0};
|
|
struct timer_state timer_state = {0};
|
|
|
|
while (1) {
|
|
printf("Wait for datagram\n");
|
|
|
|
int nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
|
|
if (nfds == -1) {
|
|
perror("epoll_wait");
|
|
return -1;
|
|
}
|
|
|
|
for (int n = 0; n < nfds; ++n) {
|
|
if (events[n].data.fd == sock) {
|
|
ret = handle_sock(sock);
|
|
if (ret == -1)
|
|
return -1;
|
|
} else if (events[n].data.fd == timerfd) {
|
|
ret = handle_timerfd(timerfd);
|
|
if (ret == -1)
|
|
return -1;
|
|
} else if (events[n].data.fd == serialfd) {
|
|
fprintf(stderr, "handle_serialfd\n");
|
|
ret = handle_serialfd(serialfd,
|
|
&parser_state,
|
|
&timer_state);
|
|
if (ret == -1)
|
|
return -1;
|
|
} else {
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
/*
|
|
struct sockaddr_in dest_addr;
|
|
dest_addr.sin_family = AF_INET;
|
|
dest_addr.sin_port = htons(1234);
|
|
dest_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
|
|
|
ret = sendto(sock, buf, 3, 0, (struct sockaddr *)&dest_addr, (sizeof (struct sockaddr_in)));
|
|
if (ret == -1) {
|
|
perror("sendto()");
|
|
}
|
|
*/
|
|
|
|
//sleep(2);
|
|
}
|
|
|
|
close(sock);
|
|
|
|
return 0;
|
|
}
|