1/*
2 * Copyright 2019, Data61, CSIRO (ABN 41 687 119 230)
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <camkes.h>
8#include <autoconf.h>
9#include <stdio.h>
10#include <string.h>
11#include <picoserver.h>
12#include <assert.h>
13#include <echo_listener_common.h>
14
15extern void *echo_send_buf;
16extern void *echo_recv_buf;
17
18int listener_socket = 0;
19
20seL4_CPtr echo_control_notification();
21
22void handle_picoserver_notification(void)
23{
24    picoserver_event_t server_event = echo_control_event_poll();
25    int ret = 0;
26    int socket = 0;
27    uint16_t events = 0;
28    char ip_string[16] = {0};
29
30    while (server_event.num_events_left > 0 || server_event.events) {
31        socket = server_event.socket_fd;
32        events = server_event.events;
33        if (events & PICOSERVER_CONN) {
34            if (socket != listener_socket) {
35                picoserver_peer_t peer = echo_control_accept(socket);
36                if (peer.result == -1) {
37                    assert(!"Failed to accept a peer");
38                }
39                pico_ipv4_to_string(ip_string, peer.peer_addr);
40                printf("%s: Connection established with %s on socket %d\n", get_instance_name(), ip_string, socket);
41            }
42        }
43        if (events & PICOSERVER_READ) {
44            printf("%s: Received a message on socket %d, going to echo to Listener\n", get_instance_name(), socket);
45            ret = echo_recv_recv(socket, 4096, 0);
46            strncpy(echo_send_buf, echo_recv_buf, ret);
47            ret = echo_send_send(listener_socket, strlen(echo_send_buf), 0);
48            memset(echo_recv_buf, 0, 4096);
49            memset(echo_send_buf, 0, 4096);
50        }
51        if (events & PICOSERVER_CLOSE) {
52            ret = echo_control_shutdown(socket, PICOSERVER_SHUT_RDWR);
53            printf("%s: Connection closing on socket %d\n", get_instance_name(), socket);
54        }
55        if (events & PICOSERVER_FIN) {
56            printf("%s: Connection closed on socket %d\n", get_instance_name(), socket);
57        }
58        if (events & PICOSERVER_ERR) {
59            printf("%s: Error with socket %d, going to die\n", get_instance_name(), socket);
60            assert(0);
61        }
62        server_event = echo_control_event_poll();
63    }
64}
65
66int run(void)
67{
68    printf("%s instance starting up, going to be listening on %s:%d\n",
69           get_instance_name(), ip_addr, ECHO_PORT);
70
71    int socket_in = echo_control_open(false);
72    if (socket_in == -1) {
73        assert(!"Failed to open a socket for listening!");
74    }
75
76    listener_socket = echo_control_open(false);
77    if (listener_socket == -1) {
78        assert(!"Failed to open a socket for echoing!");
79    }
80
81    int ret = echo_control_bind(socket_in, PICOSERVER_ANY_ADDR_IPV4, ECHO_PORT);
82    if (ret) {
83        assert(!"Failed to bind a socket for listening!");
84    }
85
86    ret = echo_control_listen(socket_in, 1);
87    if (ret) {
88        assert(!"Failed to listen for incoming connections!");
89    }
90
91    uint32_t ip = 0;
92    pico_string_to_ipv4(ip_addr, &ip);
93    ret = echo_control_connect(listener_socket, ip, LISTENER_PORT);
94    if (ret) {
95        assert(!"Failed to connect to the listener!");
96    }
97
98    /* Now poll for events and handle them */
99    seL4_Word badge;
100
101    while (1) {
102        seL4_Wait(echo_control_notification(), &badge);
103        handle_picoserver_notification();
104    }
105}
106