397 lines
11 KiB
C

#include "user.h"
#include "embfmt/embformat.h"
#include "lwip/apps/fs.h"
#include "lwip/apps/httpd.h"
#include "lwip/igmp.h"
#include "lwip/tcp.h"
#include "lwip/udp.h"
#include "netif/ethernet.h"
#include "standard_output/standard_output.h"
#include <string.h>
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
// -----------------------------------
#define RECV_BUF_LEN (511)
static char recv_buf[RECV_BUF_LEN + 1];
static char *msg = "Üdvözlet a H735-ös kártyáról!";
// ----------- Custom EtherType client
// TODO: 0x9000 fölött kb. bármit lehet választani
#define CUSTOM_RX_ETHERTYPE (0x88F7)
err_t hook_unknown_ethertype(struct pbuf *pbuf, struct netif *netif) {
// aquire ethertype
uint16_t etherType = 0;
memcpy(&etherType, ((uint8_t *)pbuf->payload) + 12, 2);
etherType = ntohs(etherType);
uint8_t *shwa = ((uint8_t *)pbuf->payload) + 6; // get source hardware address
uint16_t len = pbuf->len - 14; // get payload length
uint8_t *payload = ((uint8_t *)pbuf->payload) + 14; // actual payload
// check for match
if (etherType == CUSTOM_RX_ETHERTYPE) {
// copy payload
uint16_t copy_len = MIN(RECV_BUF_LEN, len);
recv_buf[copy_len] = '\0';
memcpy(recv_buf, payload, copy_len);
// print it
MSG("[%02X:%02X:%02X:%02X:%02X:%02X] %u\n%s\n", shwa[0], shwa[1], shwa[2], shwa[3], shwa[4], shwa[5], len, recv_buf);
}
pbuf_free(pbuf);
return ERR_OK;
}
#define CUSTOM_TX_ETHERTYPE (0x9101)
static struct eth_addr dest_hwa = {.addr = {0x00, 0x1b, 0x21, 0x91, 0x9E, 0x64}};
void send_frame() {
uint16_t len = strlen(msg);
struct pbuf *p = pbuf_alloc(PBUF_LINK, len, PBUF_RAM);
if (p == NULL) {
MSG("Nem sikerült pbuf-ot foglalni az Ethernet-keret küldéséhez!\n");
return;
}
memcpy(p->payload, msg, len);
if (ethernet_output(netif_default, p, (struct eth_addr *)netif_default->hwaddr, &dest_hwa, CUSTOM_TX_ETHERTYPE) != ERR_OK) {
MSG("Sikertelen volt az Ethernet-keret küldése!\n");
return;
}
pbuf_free(p);
}
// ----------- UDP client ------------
static struct udp_pcb *udpc;
static ip4_addr_t dest_addr;
static uint16_t dest_port;
void udp_client_init() {
// create new PCB
udpc = udp_new();
if (udpc == NULL) {
MSG("Hiba az UDP-kliens létrehozásánál!\n");
}
// set destination IP address and port
IP4_ADDR(&dest_addr, 10, 42, 0, 1);
dest_port = 4000;
// TODO: connect?
}
void udp_client_send() {
uint16_t len = strlen(msg);
// allocate pbuf and fill with contents
struct pbuf *buf = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
if (buf == NULL) {
MSG("Nem lehetett újabb pbuf-ot foglalni!\n");
return;
}
memcpy(buf->payload, msg, len);
// send UDP datagram to defined destination
if (udp_sendto(udpc, buf, &dest_addr, dest_port) != ERR_OK) {
MSG("Nem sikerült elküldeni az UDP datagramot!\n");
}
// decrease reference count of the buf
pbuf_free(buf);
}
// -----------------------------------
static struct udp_pcb *udps;
static uint16_t server_port;
static void udp_server_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) {
uint16_t copy_len = MIN(RECV_BUF_LEN, p->len);
recv_buf[copy_len] = '\0';
memcpy(recv_buf, p->payload, copy_len);
MSG("[%s:%u] %ub\n%s\n", ipaddr_ntoa(addr), port, p->len, recv_buf);
pbuf_free(p);
}
void udp_server_init() {
// create new PCB
udps = udp_new();
if (udps == NULL) {
MSG("Hiba az UDP-szerver létrehozásánál!\n");
}
// set server port
server_port = 3000;
// bind it to a local address
if (udp_bind(udps, IP4_ADDR_ANY, server_port) != ERR_OK) {
MSG("Nem sikerült az UDP-szervert felcsatolni a %u portra!\n", server_port);
udp_remove(udps);
}
// register receive callback
udp_recv(udps, udp_server_recv, NULL);
}
// -----------------------------------
static struct udp_pcb *udpmc;
static uint16_t mc_port;
static ip4_addr_t mc_group;
static void udp_mcast_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) {
uint16_t copy_len = MIN(RECV_BUF_LEN, p->len);
recv_buf[copy_len] = '\0';
memcpy(recv_buf, p->payload, copy_len);
MSG("[%s:%u] %ub\n%s\n", ipaddr_ntoa(addr), port, p->len, recv_buf);
pbuf_free(p);
}
void udp_mcast_init() {
// create new PCB
udpmc = udp_new();
if (udps == NULL) {
MSG("Hiba a multicast UDP szolgáltatás létrehozásánál!\n");
}
// set multicast group's address and port
IP4_ADDR(&mc_group, 224, 0, 2, 5);
mc_port = 2000;
// join the relevant multicast group
igmp_joingroup(&netif_default->ip_addr, &mc_group);
// bind it to a local address
if (udp_bind(udpmc, &mc_group, mc_port) != ERR_OK) {
MSG("Nem sikerült az UDP-szervert felcsatolni a %u portra!\n", mc_port);
goto cleanup;
}
// connect to the IGMP group
if (udp_connect(udpmc, &mc_group, mc_port) != ERR_OK) {
MSG("Nem sikerült az UDP multicast szolgáltatást becsatlakoztatni a multicast-csoportba!\n");
goto cleanup;
}
// register receive callback
udp_recv(udpmc, udp_mcast_recv, NULL);
return;
// ---
cleanup:
udp_remove(udpmc);
return;
}
void udp_mcast_send() {
uint16_t len = strlen(msg);
// allocate pbuf and fill with contents
struct pbuf *buf = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
if (buf == NULL) {
MSG("Nem lehetett újabb pbuf-ot foglalni!\n");
return;
}
memcpy(buf->payload, msg, len);
// send UDP datagram to defined destination
if (udp_send(udpmc, buf) != ERR_OK) {
MSG("Nem sikerült elküldeni az UDP datagramot!\n");
}
// decrease reference count of the buf
pbuf_free(buf);
}
// -----------------------------------
static struct tcp_pcb *tcps;
static uint16_t tcps_port;
static ip_addr_t tcps_addr;
static err_t tcp_server_conn_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {
if (p != NULL) {
uint16_t copy_len = MIN(RECV_BUF_LEN, p->len);
recv_buf[copy_len] = '\0';
memcpy(recv_buf, p->payload, copy_len);
MSG("[%s:%u] %ub\n%s\n", ipaddr_ntoa(&tpcb->remote_ip), tpcb->remote_port, p->len, recv_buf);
pbuf_free(p);
tcp_recved(tpcb, copy_len);
} else {
MSG("A kliens lekapcsolódott %s:%u\n", ipaddr_ntoa(&tpcb->remote_ip), tpcb->remote_port);
}
return ERR_OK;
}
static void tcp_server_conn_err(void *arg, err_t err) {
MSG("TCP-kapcsolat hiba! (%u)\n", err);
}
static err_t tcp_server_accept(void *arg, struct tcp_pcb *newpcb, err_t err) {
tcp_recv(newpcb, tcp_server_conn_recv);
tcp_err(newpcb, tcp_server_conn_err);
MSG("Bejövő TCP-kapcsolat érkezett %s:%u!\n", ipaddr_ntoa(&newpcb->remote_ip), newpcb->remote_port);
return ERR_OK;
}
static void tcp_server_error(void *arg, err_t err) {
MSG("TCP-szerver hiba! (%u)\n", err);
}
void tcp_server_init() {
// create new TCP service
tcps = tcp_new();
if (tcps == NULL) {
MSG("Nem sikerült létrehozni a TCP szerver szolgáltatást!\n");
return;
}
// set port
tcps_port = 6000;
IP4_ADDR(&tcps_addr, 10, 42, 0, 137);
// bind to local port
if (tcp_bind(tcps, &tcps_addr, tcps_port) != ERR_OK) {
MSG("Nem sikerült a TCP-szervert a %u portra csatolni!\n", tcps_port);
goto cleanup;
}
// enable server functions
tcps = tcp_listen(tcps);
// assign error handling function
tcp_err(tcps, tcp_server_error);
// register accept callback
tcp_accept(tcps, tcp_server_accept);
return;
// -----
cleanup:
tcp_close(tcps);
return;
}
static struct tcp_pcb *tcpc;
static ip4_addr_t tcpc_remote_addr;
static uint16_t tcpc_remote_port;
static void tcp_client_error(void *arg, err_t err) {
MSG("TCP-kliens hiba! (%u)\n", err);
}
static err_t tcp_client_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {
if (p != NULL) {
uint16_t copy_len = MIN(RECV_BUF_LEN, p->len);
recv_buf[copy_len] = '\0';
memcpy(recv_buf, p->payload, copy_len);
MSG("[%s:%u] %ub\n%s\n", ipaddr_ntoa(&tpcb->remote_ip), tpcb->remote_port, p->len, recv_buf);
pbuf_free(p);
tcp_recved(tpcb, copy_len);
} else {
MSG("A szerver bontotta a kapcsolatot %s:%u\n", ipaddr_ntoa(&tpcb->remote_ip), tpcb->remote_port);
}
return ERR_OK;
}
static err_t tcp_client_connected(void *arg, struct tcp_pcb *tpcb, err_t err) {
MSG("Sikeresen fölkapcsolódtunk a TCP-szerverre: %s:%u!\n", ipaddr_ntoa(&tpcb->remote_ip), tpcb->remote_port);
tcp_write(tcpc, msg, strlen(msg), 0);
tcp_close(tcpc);
return ERR_OK;
}
void tcp_client_init() {
// create new TCP service
tcpc = tcp_new();
if (tcpc == NULL) {
MSG("Nem sikerült létrehozni a TCP szerver szolgáltatást!\n");
return;
}
// set remote address and port
IP4_ADDR(&tcpc_remote_addr, 10, 42, 0, 1);
tcpc_remote_port = 9000;
// assign error handling function
tcp_err(tcpc, tcp_client_error);
// assign reception callback
tcp_recv(tcpc, tcp_client_recv);
// connect to remote host
tcp_connect(tcpc, &tcpc_remote_addr, tcpc_remote_port, tcp_client_connected);
}
// -----------------------------------
#define GENDATA_LEN (31)
static char generated_data[GENDATA_LEN + 1];
int fs_open_custom(struct fs_file *file, const char *name) {
/* this example only provides one file */
if (!strcmp(name, "/generated.html")) {
/* generate a random number */
uint32_t random = rand();
embfmt(generated_data, GENDATA_LEN, "%u is random!", random);
/* initialize fs_file correctly */
memset(file, 0, sizeof(struct fs_file));
uint32_t len = strlen(generated_data);
file->pextension = mem_malloc(len);
if (file->pextension != NULL) {
/* instead of doing memcpy, you would generate e.g. a JSON here */
memcpy(file->pextension, generated_data, len);
file->data = (const char *)file->pextension;
file->len = len; /* don't send the trailing 0 */
file->index = file->len;
/* allow persisting connections */
file->flags = FS_FILE_FLAGS_HEADER_PERSISTENT;
return 1;
}
}
return 0;
}
void fs_close_custom(struct fs_file *file) {
if (file && file->pextension) {
mem_free(file->pextension);
file->pextension = NULL;
}
}
// -----------------------------------
void btn_cb() {
MSG("Küldés!\n");
//udp_client_send();
// send_frame();
// udp_mcast_send();
tcp_client_init();
}
void user_init() {
udp_client_init();
// udp_server_init();
// udp_mcast_init();
tcp_server_init();
httpd_init();
}