Implement netcat
This commit is contained in:
parent
e0272d15e8
commit
dd10f575c9
@ -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
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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
|
||||
[
|
||||
|
||||
@ -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
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
|
||||
@ -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
|
||||
--
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
|
||||
@ -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" ]
|
||||
}
|
||||
|
||||
@ -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
17
usr/netcat/Hakefile
Normal 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
163
usr/netcat/main.c
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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" ]
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user