--- /dev/null
+/*
+ * inet (BSD) socket sender application
+ * starts a client socket that connects to server and sends data
+ *
+ * 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_BUFFER_SIZE 1024
+#define DEFAULT_PACKET_DELAY 1000
+
+#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)
+
+
+static struct {
+ size_t buffer_size;
+ size_t packet_delay; /* milliseconds */
+ char server_host[128];
+ unsigned short int server_port;
+} cmd_args = {
+ .buffer_size = DEFAULT_BUFFER_SIZE,
+ .packet_delay = DEFAULT_PACKET_DELAY,
+};
+
+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_PAYLOAD_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 delay_packet(void)
+{
+ struct timespec ts;
+ int rc;
+
+ ts.tv_sec = cmd_args.packet_delay / 1000;
+ ts.tv_nsec = (cmd_args.packet_delay % 1000) * 1000000;
+
+ rc = nanosleep(&ts, NULL);
+ DIE(rc < 0, "nanosleep");
+}
+
+static void usage(const char *argv0)
+{
+ fprintf(stderr, "Usage: %s [-b | --buffer-size <buffer-size>] [-d | --delay <packet-delay>] <server-host> <server-port>\n", argv0);
+}
+
+static void print_args(void)
+{
+ printf("buffer_size: %lu\n", cmd_args.buffer_size);
+ printf("delay: %lu\n", cmd_args.packet_delay);
+ printf("server_host: %s\n", cmd_args.server_host);
+ printf("server_port: %hu\n", cmd_args.server_port);
+}
+
+static void parse_args(int argc, char **argv)
+{
+ int c;
+
+ while (1) {
+ int option_index = 0;
+ static struct option long_options[] = {
+ {"buffer-size", 1, NULL, 0},
+ {"packet-delay", 1, NULL, 0},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long(argc, argv, "b:d:",
+ 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 'b':
+ /* TODO: use strtoul */
+ cmd_args.buffer_size = atoi(optarg);
+ break;
+
+ case 'd':
+ /* TODO: use strtoul */
+ cmd_args.packet_delay = atoi(optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind + 2 != argc) {
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ /* TODO: check argv[argc-2] size */
+ strcpy(cmd_args.server_host, argv[argc-2]);
+ /* TODO: use strtoul */
+ cmd_args.server_port = atoi(argv[argc-1]);
+
+ print_args();
+}
+
+int main(void)
+{
+ connectfd = tcp_connect_to_server(cmd_args.server_host,
+ cmd_args.server_port);
+ DIE(connectfd < 0, "tcp_connect_to_server");
+
+ init();
+
+ while (1) {
+ ssize_t nbytes;
+
+ fill_send_buffer();
+ nbytes = send_buffer(connectfd);
+ DIE(nbytes < 0, "send_buffer");
+ delay_packet();
+ }
+
+ close(connectfd);
+
+ cleanup();
+
+ return 0;
+}