Implement netcat

This commit is contained in:
Jan Schär 2022-06-02 20:42:11 +02:00
parent e0272d15e8
commit dd10f575c9
11 changed files with 207 additions and 44 deletions

View File

@ -14,3 +14,4 @@ module /armv8/sbin/echoserver
module /armv8/sbin/shelly
module /armv8/sbin/filereader
module /armv8/sbin/block_driver_server
module /armv8/sbin/netcat

View File

@ -49,8 +49,6 @@ static void handle_response(void *arg, size_t header_size, void *header_buf, siz
if (state.current_request->type == SHELLY_MSG_GETCHAR) {
*state.buf = header->character;
} else if (state.current_request->type == SHELLY_MSG_PUTCHAR) {
//nothing to do
} else {
SHELLY_CLIENT_DEBUG("[handle_response] unexpected request type");
}
@ -60,34 +58,32 @@ static void handle_response(void *arg, size_t header_size, void *header_buf, siz
static void handle_send_completed(void *arg, struct ump_send_queue_entry *entry) {
SHELLY_CLIENT_DEBUG("[handle_send_completed]\n");
free((void *)entry->header);
free((void *)entry->payload);
free(entry);
bool *done = arg;
*done = true;
}
errval_t shelly_client_getchar(struct aos_rpc * rpc, char * ret) {
errval_t err;
SHELLY_CLIENT_DEBUG("[shelly_client_getchar]\n");
struct shelly_header * header = malloc(sizeof(struct shelly_header));
if (header == NULL) return LIB_ERR_MALLOC_FAIL;
struct ump_send_queue_entry *entry = malloc(sizeof(struct ump_send_queue_entry));
if (entry == NULL) return LIB_ERR_MALLOC_FAIL;
struct shelly_header header;
struct ump_send_queue_entry entry;
state.request_ongoing = true;
state.buf = ret;
state.current_request = header;
state.current_request = &header;
header->type = SHELLY_MSG_GETCHAR;
header->character = 0;
header.type = SHELLY_MSG_GETCHAR;
header.character = 0;
ump_send(state.send_chan, entry, sizeof(struct shelly_header), header, 0, NULL, handle_send_completed, NULL);
bool send_done = false;
ump_send(state.send_chan, &entry, sizeof(struct shelly_header), &header, 0, NULL, handle_send_completed, &send_done);
// register response handler
ump_recv_header(state.recv_chan, handle_response, NULL);
// wait for the response
while (state.request_ongoing) {
while (!send_done || state.request_ongoing) {
err = event_dispatch(&ws);
if (err_is_fail(err)) {
DEBUG_ERR(err, "in event_dispatch");
@ -103,25 +99,17 @@ errval_t shelly_client_putchar(struct aos_rpc * rpc, char input) {
errval_t err;
SHELLY_CLIENT_DEBUG("[shelly_client_putchar]\n");
struct shelly_header * header = malloc(sizeof(struct shelly_header));
if (header == NULL) return LIB_ERR_MALLOC_FAIL;
struct ump_send_queue_entry *entry = malloc(sizeof(struct ump_send_queue_entry));
if (entry == NULL) return LIB_ERR_MALLOC_FAIL;
struct shelly_header header;
struct ump_send_queue_entry entry;
state.request_ongoing = true;
state.current_request = header;
state.buf = NULL;
header.type = SHELLY_MSG_PUTCHAR;
header.character = input;
header->type = SHELLY_MSG_PUTCHAR;
header->character = input;
ump_send(state.send_chan, entry, sizeof(struct shelly_header), header, 0, NULL, handle_send_completed, NULL);
// register response handler
ump_recv_header(state.recv_chan, handle_response, NULL);
bool done = false;
ump_send(state.send_chan, &entry, sizeof(struct shelly_header), &header, 0, NULL, handle_send_completed, &done);
// wait for the response
while (state.request_ongoing) {
while (!done) {
err = event_dispatch(&ws);
if (err_is_fail(err)) {
DEBUG_ERR(err, "in event_dispatch");

View File

@ -12,7 +12,7 @@
let
-- Default list of modules to build/install
modules_common = [ "/sbin/" ++ f | f <- [ "init", "hello", "mallocator", "stackoverflow", "echoserver", "enet", "shelly", "filereader", "block_driver_server"
modules_common = [ "/sbin/" ++ f | f <- [ "init", "hello", "mallocator", "stackoverflow", "echoserver", "enet", "shelly", "filereader", "block_driver_server", "netcat"
] ]
in
[

View File

@ -6,7 +6,6 @@
-- If you do not find this file, copies can be found by writing to:
-- ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
--
-- Hakefile for /usr/init
--
--------------------------------------------------------------------------

View File

@ -6,7 +6,6 @@
-- If you do not find this file, copies can be found by writing to:
-- ETH Zurich D-INFK, Universitaetstr 6, CH-8092 Zurich. Attn: Systems Group.
--
-- Hakefile for /usr/init
--
--------------------------------------------------------------------------

View File

@ -6,12 +6,11 @@
-- If you do not find this file, copies can be found by writing to:
-- ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
--
-- Hakefile for /usr/init
--
--------------------------------------------------------------------------
[ build application
{
[ build application
{
target = "mallocator",
cFiles = [ "main.c" ]
}

View File

@ -6,12 +6,11 @@
-- If you do not find this file, copies can be found by writing to:
-- ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
--
-- Hakefile for /usr/init
--
--------------------------------------------------------------------------
[ build application
{
[ build application
{
target = "memeater",
cFiles = [ "main.c" ]
}

17
usr/netcat/Hakefile Normal file
View File

@ -0,0 +1,17 @@
--------------------------------------------------------------------------
-- Copyright (c) 2007-2010, ETH Zurich.
-- All rights reserved.
--
-- This file is distributed under the terms in the attached LICENSE file.
-- If you do not find this file, copies can be found by writing to:
-- ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
--
--
--------------------------------------------------------------------------
[ build application
{
target = "netcat",
cFiles = [ "main.c" ]
}
]

163
usr/netcat/main.c Normal file
View File

@ -0,0 +1,163 @@
#include <stdio.h>
#include <stdlib.h>
#include <aos/aos.h>
#include <aos/waitset_chan.h>
#include <aos/aos_rpc.h>
#include <aos/ump_binding.h>
#include <aos/ump_chan.h>
#include <aos/ump_net.h>
#include <aos/ump_net_client.h>
#include <netutil/ip.h>
#define BUF_SIZE (1500 - 20 - 8)
struct send_buf {
struct ump_net_call call;
uint8_t payload[BUF_SIZE];
size_t send_len;
struct waitset_chanstate chan;
};
static uint16_t local_port;
static uint16_t remote_port;
static uint32_t remote_ip;
static void udp_listen_callback (void *arg, errval_t err, uint16_t src_port) {
if (err_is_fail(err)) {
printf("Failed to listen on port %d:\n", local_port);
err_print_calltrace(err);
return;
}
local_port = src_port;
DEBUG_PRINTF("Listening on UDP port %d.\n", src_port);
}
static void net_recv_packet (void *arg, size_t payload_size, void *payload) {
printf("%.*s", payload_size, arg);
free(arg);
}
static void handle_udp_recv (void *arg, struct ump_net_ev_udp_recv *udp_recv, size_t payload_size) {
void *payload = malloc(payload_size);
if (payload == NULL) {
printf("ERROR: malloc failed\n");
ump_net_recv_payload(NULL, NULL, NULL);
} else {
if (remote_ip == 0) remote_ip = udp_recv->src_ip;
if (remote_port == 0) remote_port = udp_recv->src_port;
ump_net_recv_payload(payload, net_recv_packet, payload);
}
}
static void send_callback (void *arg, errval_t err) {
struct send_buf *send_buf = arg;
free(send_buf);
if (err_is_fail(err)) {
DEBUG_ERR(err, "failed to send packet");
}
}
static void udp_send(void *arg) {
struct send_buf *send_buf = arg;
ump_net_udp_send(
&send_buf->call,
remote_ip,
local_port, remote_port,
send_buf->send_len, &send_buf->payload,
send_callback, send_buf
);
}
static struct send_buf *create_send_buffer (void) {
struct send_buf *send_buf = malloc(sizeof(struct send_buf));
if (send_buf == NULL) {
printf("ERROR: malloc failed\n");
return NULL;
}
waitset_chanstate_init(&send_buf->chan, CHANTYPE_OTHER);
send_buf->send_len = 0;
return send_buf;
}
static struct waitset_chanstate exitchan;
static struct ump_net_call stopcall;
static void udp_stop_callback (void *arg, errval_t err) {
exit(0);
}
static void exit_process(void *arg) {
ump_net_udp_listen_stop(&stopcall, local_port, udp_stop_callback, NULL);
}
static int input_reader (void *arg) {
errval_t err;
struct aos_rpc *rpc = aos_rpc_get_serial_channel();
struct waitset *default_ws = get_default_waitset();
struct send_buf *send_buf = create_send_buffer();
if (send_buf == NULL) return 1;
while (true) {
char in;
err = aos_rpc_serial_getchar(rpc, &in);
if (err_is_fail(err)) {
DEBUG_ERR(err, "failed to read");
return 1;
}
if (in == '\x03') { // Ctrl+C
waitset_chan_trigger_closure(default_ws, &exitchan, MKCLOSURE(exit_process, NULL));
return 0;
}
if (in == '\0') in = '\n';
send_buf->payload[send_buf->send_len] = in;
send_buf->send_len++;
if (send_buf->send_len == sizeof(send_buf->payload) || in == '\n') {
if (remote_port == 0 || remote_ip == 0) {
printf("Error: Can't send, remote ip/port not provided and no packet received yet.\n");
send_buf->send_len = 0;
} else {
waitset_chan_trigger_closure(default_ws, &send_buf->chan, MKCLOSURE(udp_send, send_buf));
send_buf = create_send_buffer();
if (send_buf == NULL) return 1;
}
}
}
}
int main (int argc, char *argv[]) {
errval_t err;
struct waitset *default_ws = get_default_waitset();
if (argc < 2) {
printf("Usage: netcat local_port [remote_ip] [remote_port]\n");
return 1;
}
local_port = strtol(argv[1], NULL, 10);
if (argc > 2) {
int a1, a2, a3, a4;
int parsed = sscanf(argv[2], "%d.%d.%d.%d.", &a1, &a2, &a3, &a4);
if (parsed != 4) {
printf("Error: failed to parse IP address\n");
return 1;
}
remote_ip = MK_IP(a1, a2, a3, a4);
remote_port = local_port;
}
if (argc > 3) {
remote_port = strtol(argv[3], NULL, 10);
}
err = ump_net_init(default_ws);
if (err_is_fail(err)) USER_PANIC_ERR(err, "Failed to connect to net server");
struct ump_net_call call_udp_listen;
ump_net_udp_listen(&call_udp_listen, local_port, handle_udp_recv, NULL, udp_listen_callback, NULL);
thread_create(input_reader, NULL);
while (true) {
err = event_dispatch(default_ws);
if (err_is_fail(err)) {
DEBUG_ERR(err, "in event_dispatch");
abort();
}
}
}

View File

@ -87,7 +87,7 @@ static void handle_lpuart_interrupt(void * arg) {
if (err_is_fail(err)) USER_PANIC_ERR(err, "while trying to put character");
if (is_newline(input_char)) {
err = lpuart_putchar(global_state->uart_s, ASCII_CR);
err = lpuart_putchar(global_state->uart_s, ASCII_NL);
if (err_is_fail(err)) USER_PANIC_ERR(err, "while trying to put character");
}
@ -187,7 +187,6 @@ static void handle_client_request(void *arg, size_t header_size, void *header_bu
err = lpuart_putchar(global_state->uart_s, ASCII_CR);
if (err_is_fail(err)) USER_PANIC_ERR(err, "while trying to put character");
}
send_response(local_state, SYS_ERR_OK, '\0', 0, NULL);
}
// skip payload
@ -309,4 +308,4 @@ int main(int argc, char *argv[])
USER_PANIC_ERR(err, "in event_dispatch");
}
}
}
}

View File

@ -6,12 +6,11 @@
-- If you do not find this file, copies can be found by writing to:
-- ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
--
-- Hakefile for /usr/init
--
--------------------------------------------------------------------------
[ build application
{
[ build application
{
target = "stackoverflow",
cFiles = [ "main.c" ]
}