#include "sock_util.h"
#include "utils.h"
-#define DEFAULT_LEADER_LISTEN_PORT 43210
-#define DEFAULT_LEADER_HOSTNAME "localhost"
-#define DEFAULT_FOLLOWER_LISTEN_PORT 54321
-#define DEFAULT_FOLLOWER_HOSTNAME "localhost"
+#define DEFAULT_LISTEN_PORT 54321
#define DEFAULT_SERVER_BACKLOG 5
+#define DEFAULT_BUFFER_SIZE 1024
+#define DEFAULT_FREQUENCY 1
+
-#define PACKET_PAYLOAD_SIZE 120
#define PACKET_INDEX_SIZE sizeof(unsigned long long)
#define PACKET_TIMESPEC_SIZE sizeof(time_t)
-#define PACKET_SIZE (PACKET_PAYLOAD_SIZE + PACKET_INDEX_SIZE + PACKET_TIMESPEC_SIZE)
+#define PACKET_PAYLOAD_SIZE (PACKET_SIZE - PACKET_INDEX_SIZE - PACKET_TIMESPEC_SIZE)
+#define PACKET_SIZE (cmd_args.buffer_size)
+
+#define RECEIVE_BUFFER_SIZE 65536
#define TIMER_FREQUENCY_SECS 1
#define CLOCKID CLOCK_REALTIME
#define SIG SIGRTMIN
-static enum {
- TYPE_LEADER = 1,
- TYPE_FOLLOWER,
- TYPE_OLD_LEADER
-} client_type;
-
-static char rcv_buf[PACKET_SIZE];
-static char snd_buf[PACKET_SIZE];
+static struct {
+ enum {
+ TYPE_LEADER = 1,
+ TYPE_FOLLOWER,
+ } client_type;
+ unsigned short int listen_port;
+ size_t buffer_size;
+ size_t peer_buffer_size;
+ size_t frequency;
+ char remote_host[128];
+ unsigned short int remote_port;
+} cmd_args = {
+ .client_type = TYPE_FOLLOWER,
+ .listen_port = DEFAULT_LISTEN_PORT,
+ .buffer_size = DEFAULT_BUFFER_SIZE,
+ .peer_buffer_size = DEFAULT_BUFFER_SIZE,
+ .frequency = DEFAULT_FREQUENCY
+};
+
+static char rcv_buf[RECEIVE_BUFFER_SIZE];
+static char *snd_buf;
/* connection socket */
static int connectfd;
static void init_buffers(void)
{
- init_buffer_random(rcv_buf, PACKET_PAYLOAD_SIZE);
+ init_buffer_random(rcv_buf, RECEIVE_BUFFER_SIZE);
init_buffer_random(snd_buf, PACKET_PAYLOAD_SIZE);
}
+static void init(void)
+{
+ snd_buf = malloc(PACKET_SIZE * sizeof(char));
+ DIE(snd_buf == NULL, "malloc");
+
+ init_buffers();
+}
+
+static void cleanup(void)
+{
+ free(snd_buf);
+}
+
static void fill_send_buffer(void)
{
static unsigned long long index = 0;
static ssize_t receive_buffer(int sockfd)
{
- return recv(sockfd, rcv_buf, PACKET_SIZE, 0);
+ ssize_t nbytes = 0;
+ ssize_t n;
+
+ while (nbytes < (ssize_t) cmd_args.peer_buffer_size) {
+ n = recv(sockfd, rcv_buf, RECEIVE_BUFFER_SIZE, 0);
+ if (n <= 0)
+ break;
+ nbytes += n;
+ }
+
+ return nbytes;
}
static void timer_handler(int sig, siginfo_t *si, void *uc)
DIE(rc < 0, "sigprocmask");
}
-static void print_buffer_meta(void)
+static void print_buffer_meta(const char *buf, size_t len)
{
unsigned long long index;
time_t curr_time_secs;
curr_time_secs = time(NULL);
- ptr = rcv_buf + PACKET_PAYLOAD_SIZE;
+ ptr = rcv_buf + len - PACKET_INDEX_SIZE - PACKET_TIMESPEC_SIZE;
index = * (unsigned long long *) ptr;
ptr += PACKET_INDEX_SIZE;
sender_time_secs = * (time_t *) ptr;
sender_time_secs);
}
+/* TODO: fill usage */
+
static void usage(const char *argv0)
{
- fprintf(stderr, "Usage: %s [-l | --leader] [-p | --port <listen-port>] [-b | --buffer-size <buffer-size>] [-f | --frequency <frequency>] <peer-host> <peer-port>\n", argv0);
+ fprintf(stderr, "Usage: %s [-l | --leader] [-p | --port <listen-port>] [-b | --buffer-size <buffer-size>] [-e | --peer_buffer_size <buffer-size>] [-f | --frequency <frequency>] <peer-host> <peer-port>\n", argv0);
+}
+
+static void print_args(void)
+{
+ printf("client_type: ");
+ switch (cmd_args.client_type) {
+ case TYPE_LEADER:
+ printf("leader");
+ break;
+ case TYPE_FOLLOWER:
+ printf("follower");
+ break;
+ default:
+ printf("unknown");
+ }
+ printf("\n");
+
+ printf("listen_port: %hu\n", cmd_args.listen_port);
+ printf("buffer_size: %lu\n", cmd_args.buffer_size);
+ printf("peer_buffer_size: %lu\n", cmd_args.peer_buffer_size);
+ printf("frequency: %lu\n", cmd_args.frequency);
+ printf("remote_host: %s\n", cmd_args.remote_host);
+ printf("remote_port: %hu\n", cmd_args.remote_port);
}
static void parse_args(int argc, char **argv)
{
int c;
- int digit_optind = 0;
while (1) {
- int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] = {
{"leader", 0, NULL, 0},
{"port", 1, NULL, 0},
{"buffer-size", 1, NULL, 0},
+ {"peer-buffer-size", 1, NULL, 0},
{"frequency", 1, NULL, 0},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, "lp:b:f:",
+ c = getopt_long(argc, argv, "lp:b:e:f:",
long_options, &option_index);
if (c == -1)
break;
break;
case 'l':
- printf("option l\n");
+ cmd_args.client_type = TYPE_LEADER;
break;
case 'p':
- printf("option l with value '%s'\n", optarg);
+ /* TODO: use strtoul */
+ cmd_args.listen_port = atoi(optarg);
break;
case 'b':
- printf("option b with value '%s'\n", optarg);
+ /* TODO: use strtoul */
+ cmd_args.buffer_size = atoi(optarg);
+ break;
+
+ case 'e':
+ /* TODO: use strtoul */
+ cmd_args.peer_buffer_size = atoi(optarg);
break;
case 'f':
- printf("option f with value '%s'\n", optarg);
+ /* TODO: use strtoul */
+ cmd_args.frequency = atoi(optarg);
break;
case '?':
}
}
- if (optind < argc) {
- printf("non-option ARGV-elements: ");
- while (optind < argc)
- printf("%s ", argv[optind++]);
- printf("\n");
+ if (optind + 2 != argc) {
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
}
+
+ /* TODO: check argv[argc-2] size */
+ strcpy(cmd_args.remote_host, argv[argc-2]);
+ /* TODO: use strtoul */
+ cmd_args.remote_port = atoi(argv[argc-1]);
+
+ print_args();
}
int main(int argc, char **argv)
parse_args(argc, argv);
-#if 0
- if (client_type == TYPE_LEADER) {
- listenfd = tcp_listen_connections(DEFAULT_LEADER_LISTEN_PORT,
+ switch (cmd_args.client_type) {
+ case TYPE_LEADER:
+ 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");
- connectfd = tcp_connect_to_server(DEFAULT_FOLLOWER_HOSTNAME,
- DEFAULT_FOLLOWER_LISTEN_PORT);
- DIE(connectfd < 0, "tcp_connect_to_server");
- }
- else if (client_type == TYPE_FOLLOWER) {
- listenfd = tcp_listen_connections(DEFAULT_FOLLOWER_LISTEN_PORT,
- DEFAULT_SERVER_BACKLOG);
- DIE(listenfd < 0, "tcp_listen_connections");
-
- connectfd = tcp_connect_to_server(DEFAULT_LEADER_HOSTNAME,
- DEFAULT_LEADER_LISTEN_PORT);
+ connectfd = tcp_connect_to_server(cmd_args.remote_host,
+ cmd_args.remote_port);
DIE(connectfd < 0, "tcp_connect_to_server");
+ break;
- sockfd = accept(listenfd, (SSA *) &addr, &addrlen);
- DIE(sockfd < 0, "accept");
- }
- else if (client_type == TYPE_OLD_LEADER) {
- listenfd = tcp_listen_connections(DEFAULT_LEADER_LISTEN_PORT,
+ case TYPE_FOLLOWER:
+ listenfd = tcp_listen_connections(cmd_args.listen_port,
DEFAULT_SERVER_BACKLOG);
DIE(listenfd < 0, "tcp_listen_connections");
- connectfd = tcp_connect_to_server(DEFAULT_FOLLOWER_HOSTNAME,
- DEFAULT_FOLLOWER_LISTEN_PORT);
+ connectfd = tcp_connect_to_server(cmd_args.remote_host,
+ cmd_args.remote_port);
DIE(connectfd < 0, "tcp_connect_to_server");
sockfd = accept(listenfd, (SSA *) &addr, &addrlen);
DIE(sockfd < 0, "accept");
- }
- else {
+ break;
+
+ default:
usage(argv[0]);
exit(EXIT_FAILURE);
}
- init_buffers();
+ init();
schedule_timer();
while (1) {
sockfd = accept(listenfd, (SSA *) &addr, &addrlen);
DIE(sockfd < 0, "accept");
+ connectfd = tcp_connect_to_server(cmd_args.remote_host, cmd_args.remote_port);
+ DIE(connectfd < 0, "tcp_connect_to_server");
- if (client_type == TYPE_FOLLOWER) {
- connectfd = tcp_connect_to_server(DEFAULT_LEADER_HOSTNAME, DEFAULT_LEADER_LISTEN_PORT);
- DIE(connectfd < 0, "tcp_connect_to_server");
- }
- if (client_type == TYPE_LEADER || client_type == TYPE_OLD_LEADER) {
- connectfd = tcp_connect_to_server(DEFAULT_FOLLOWER_HOSTNAME, DEFAULT_FOLLOWER_LISTEN_PORT);
- DIE(connectfd < 0, "tcp_connect_to_server");
- }
schedule_timer();
}
- print_buffer_meta();
+ print_buffer_meta(rcv_buf, nbytes);
}
close(sockfd);
close(connectfd);
-#endif
+ cleanup();
return 0;
}