--- /dev/null
+/*
+ * inet (BSD) socket receiver application
+ * starts a listener socket that receives data from requesting
+ * client
+ *
+ * 2010, Razvan Deaconescu
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <time.h>
+#include <getopt.h>
+
+#include "sock_util.h"
+#include "utils.h"
+
+
+#define DEFAULT_LISTEN_PORT 54321
+#define DEFAULT_SERVER_BACKLOG 5
+#define DEFAULT_BUFFER_SIZE 1024
+
+#define PACKET_INDEX_SIZE sizeof(unsigned long long)
+#define PACKET_TIMESPEC_SIZE sizeof(time_t)
+#define PACKET_PAYLOAD_SIZE (PACKET_SIZE - PACKET_INDEX_SIZE - PACKET_TIMESPEC_SIZE)
+#define PACKET_SIZE (cmd_args.buffer_size)
+
+/*
+ * TODO: fix nomenclature (TIMER_BASE_PERIOD, cmd_args.frequency)
+ * run the timer once each TIMER_BASE_PERIOD
+ * this is divided by cmd_args.frequency for a shorter period
+ */
+
+static struct {
+ unsigned short int listen_port;
+ size_t buffer_size;
+} cmd_args = {
+ .listen_port = DEFAULT_LISTEN_PORT,
+ .buffer_size = DEFAULT_BUFFER_SIZE,
+};
+
+static char *rcv_buf;
+static char *snd_buf;
+
+/* connection socket */
+static int connectfd;
+
+static void init_buffer_random(char *buf, size_t len)
+{
+ size_t i;
+
+ srand(time(NULL));
+
+ for (i = 0; i < len-2; i++)
+ buf[i] = (char) (rand() % 26) + 'a';
+ buf[i] = '\0';
+}
+
+static void init_buffers(void)
+{
+ init_buffer_random(rcv_buf, PACKET_SIZE);
+ init_buffer_random(snd_buf, PACKET_SIZE);
+}
+
+static void init(void)
+{
+ rcv_buf = malloc(PACKET_SIZE * sizeof(char));
+ snd_buf = malloc(PACKET_SIZE * sizeof(char));
+ DIE(snd_buf == NULL, "malloc");
+
+ init_buffers();
+}
+
+static void cleanup(void)
+{
+ free(rcv_buf);
+ free(snd_buf);
+}
+
+static void fill_send_buffer(void)
+{
+ static unsigned long long index = 0;
+ char *ptr;
+ time_t curr_time_secs;
+
+ curr_time_secs = time(NULL);
+
+ ptr = snd_buf + PACKET_PAYLOAD_SIZE;
+ * (unsigned long long *) ptr = index;
+ ptr += PACKET_INDEX_SIZE;
+ * (time_t *) ptr = curr_time_secs;
+
+ printf("[send] index: %llu curr_time_secs: %lu\n", index, curr_time_secs);
+ index++;
+}
+
+static ssize_t send_buffer(int sockfd)
+{
+ return send(sockfd, snd_buf, PACKET_SIZE, 0);
+}
+
+static ssize_t receive_buffer(int sockfd)
+{
+ ssize_t nbytes = 0;
+ ssize_t n;
+
+ while (nbytes < (ssize_t) PACKET_SIZE) {
+ n = recv(sockfd, rcv_buf, PACKET_SIZE - nbytes, 0);
+ if (n <= 0)
+ break;
+ nbytes += n;
+ }
+
+ return nbytes;
+}
+
+static void print_buffer_meta(const char *buf, size_t len)
+{
+ unsigned long long index;
+ time_t curr_time_secs;
+ time_t sender_time_secs;
+ const char *ptr;
+
+ curr_time_secs = time(NULL);
+
+ ptr = buf + len - PACKET_INDEX_SIZE - PACKET_TIMESPEC_SIZE;
+ index = * (unsigned long long *) ptr;
+ ptr += PACKET_INDEX_SIZE;
+ sender_time_secs = * (time_t *) ptr;
+
+ printf("[recv] index %llu, ", index);
+ if (sender_time_secs > curr_time_secs)
+ printf("negative latency (weird)\n");
+ else
+ printf("latency %lu seconds (curr_time = %lu, sender_time = %lu)\n",
+ curr_time_secs - sender_time_secs,
+ curr_time_secs,
+ sender_time_secs);
+}
+
+static void usage(const char *argv0)
+{
+ fprintf(stderr, "Usage: %s [-p | --port <listen-port>] [-b | --buffer-size <buffer-size>]\n", argv0);
+}
+
+static void print_args(void)
+{
+ printf("listen_port: %hu\n", cmd_args.listen_port);
+ printf("buffer_size: %lu\n", cmd_args.buffer_size);
+}
+
+static void parse_args(int argc, char **argv)
+{
+ int c;
+
+ while (1) {
+ int option_index = 0;
+ static struct option long_options[] = {
+ {"port", 1, NULL, 0},
+ {"buffer-size", 1, NULL, 0},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long(argc, argv, "p:b:",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 0:
+ printf("option %s", long_options[option_index].name);
+ if (optarg)
+ printf(" with arg %s", optarg);
+ printf("\n");
+ break;
+
+ case 'p':
+ /* TODO: use strtoul */
+ cmd_args.listen_port = atoi(optarg);
+ break;
+
+ case 'b':
+ /* TODO: use strtoul */
+ cmd_args.buffer_size = atoi(optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind != argc) {
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ print_args();
+}
+
+int main(int argc, char **argv)
+{
+ int listenfd;
+ int sockfd;
+ struct sockaddr_in addr;
+ socklen_t addrlen = 0;
+
+ parse_args(argc, argv);
+
+ listenfd = tcp_listen_connections(cmd_args.listen_port,
+ DEFAULT_SERVER_BACKLOG);
+ DIE(listenfd < 0, "tcp_listen_connections");
+
+ sockfd = accept(listenfd, (SSA *) &addr, &addrlen);
+ DIE(sockfd < 0, "accept");
+
+ while (1) {
+ ssize_t nbytes;
+
+ nbytes = receive_buffer(sockfd);
+ DIE(nbytes < 0, "receive_buffer");
+ if (nbytes == 0)
+ break;
+
+ print_buffer_meta(rcv_buf, PACKET_SIZE);
+ }
+
+ close(sockfd);
+ close(listenfd);
+
+ return 0;
+}