1// SPDX-License-Identifier: MIT
2
3/**
4 * The MIT License (MIT)
5 *
6 * Copyright (c) 2014 Mathias Buus
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
26
27/* Modifications made by Data61 */
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <sys/types.h>
32#include <sys/socket.h>
33#include <netinet/in.h>
34#include <unistd.h>
35#include <buffer.h>
36
37#define on_error(...) { fprintf(stderr, __VA_ARGS__); fflush(stderr); exit(1); }
38
39
40/* XXX: CAmkES symbols that are linked in after this file is compiled.
41   They need to be marked as weak and this is the current hacky way it is done */
42extern void *camkes_buffer;
43void camkes_ev_emit(void);
44void camkes_ev1_wait(void);
45#pragma weak camkes_buffer
46#pragma weak camkes_ev_emit
47#pragma weak camkes_ev1_wait
48
49
50int main (int argc, char *argv[]) {
51  if (argc < 2) on_error("Usage: %s [port]\n", argv[0]);
52
53    char *buffer_str = (char*)camkes_buffer;
54
55    snprintf(buffer_str, REVERSE_STRING_MAX_LEN, "Hello, World!");
56
57    printf("Sending string: %s\n", buffer_str);
58
59    /* Signal the string reverse server and wait for response */
60    camkes_ev_emit();
61    camkes_ev1_wait();
62
63    printf("%s\n", buffer_str);
64
65
66  int port = atoi(argv[1]);
67
68  int server_fd, client_fd, err;
69  struct sockaddr_in server, client;
70  char buf[REVERSE_STRING_BUFSIZE];
71
72  server_fd = socket(AF_INET, SOCK_STREAM, 0);
73  if (server_fd < 0) on_error("Could not create socket\n");
74
75  server.sin_family = AF_INET;
76  server.sin_port = htons(port);
77  server.sin_addr.s_addr = htonl(INADDR_ANY);
78
79  int opt_val = 1;
80  setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof opt_val);
81
82  err = bind(server_fd, (struct sockaddr *) &server, sizeof(server));
83  if (err < 0) on_error("Could not bind socket\n");
84
85  err = listen(server_fd, 128);
86  if (err < 0) on_error("Could not listen on socket\n");
87
88  printf("Server is listening on %d\n", port);
89
90  /* In a loop we wait for connections from clients */
91  while (1) {
92    socklen_t client_len = sizeof(client);
93    client_fd = accept(server_fd, (struct sockaddr *) &client, &client_len);
94
95    if (client_fd < 0) on_error("Could not establish new connection\n");
96
97    /* In a loop we wait for messages from the client, reverse the string
98       and then respond to the client */
99    while (1) {
100      int read = recv(client_fd, buf, REVERSE_STRING_BUFSIZE, 0);
101      if (!read) break; // done reading
102      if (read < 0) on_error("Client read failed\n");
103      buf[read] = 0;
104      snprintf(buffer_str, read +1, buf);
105      camkes_ev_emit();
106      camkes_ev1_wait();
107
108      err = send(client_fd, buffer_str, read, 0);
109      if (err < 0) on_error("Client write failed\n");
110    }
111  }
112
113  return 0;
114}
115