test-socket-signal: add help option; fix long option arguments
[p2p-testing-infrastructure.git] / Utils / test-socket-signal / sender.c
1 /*
2  * inet (BSD) socket sender application
3  *       starts a client socket that connects to server and sends data
4  *
5  * 2010, Razvan Deaconescu
6  */
7
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <time.h>
15 #include <getopt.h>
16
17 #include "sock_util.h"
18 #include "utils.h"
19
20
21 #define DEFAULT_BUFFER_SIZE             1024
22 #define DEFAULT_PACKET_DELAY            1000
23
24 #define PACKET_INDEX_SIZE               sizeof(unsigned long long)
25 #define PACKET_TIMESPEC_SIZE            sizeof(time_t)
26 #define PACKET_PAYLOAD_SIZE             (PACKET_SIZE - PACKET_INDEX_SIZE - PACKET_TIMESPEC_SIZE)
27 #define PACKET_SIZE                     (cmd_args.buffer_size)
28
29
30 static struct {
31         size_t buffer_size;
32         size_t packet_delay;    /* milliseconds */
33         char server_host[128];
34         unsigned short int server_port;
35 } cmd_args = {
36         .buffer_size = DEFAULT_BUFFER_SIZE,
37         .packet_delay = DEFAULT_PACKET_DELAY,
38 };
39
40 static char *rcv_buf;
41 static char *snd_buf;
42
43 /* connection socket */
44 static int connectfd;
45
46 static void init_buffer_random(char *buf, size_t len)
47 {
48         size_t i;
49
50         srand(time(NULL));
51
52         for (i = 0; i < len-2; i++)
53                 buf[i] = (char) (rand() % 26) + 'a';
54         buf[i] = '\0';
55 }
56
57 static void init_buffers(void)
58 {
59         init_buffer_random(rcv_buf, PACKET_SIZE);
60         init_buffer_random(snd_buf, PACKET_PAYLOAD_SIZE);
61 }
62
63 static void init(void)
64 {
65         rcv_buf = malloc(PACKET_SIZE * sizeof(char));
66         snd_buf = malloc(PACKET_SIZE * sizeof(char));
67         DIE(snd_buf == NULL, "malloc");
68
69         init_buffers();
70 }
71
72 static void cleanup(void)
73 {
74         free(rcv_buf);
75         free(snd_buf);
76 }
77
78 static void fill_send_buffer(void)
79 {
80         static unsigned long long index = 0;
81         char *ptr;
82         time_t curr_time_secs;
83
84         curr_time_secs = time(NULL);
85
86         ptr = snd_buf + PACKET_PAYLOAD_SIZE;
87         * (unsigned long long *) ptr = index;
88         ptr += PACKET_INDEX_SIZE;
89         * (time_t *) ptr = curr_time_secs;
90
91         printf("[send] index: %llu curr_time_secs: %lu\n", index, curr_time_secs);
92         index++;
93 }
94
95 static ssize_t send_buffer(int sockfd)
96 {
97         return send(sockfd, snd_buf, PACKET_SIZE, 0);
98 }
99
100 static ssize_t receive_buffer(int sockfd)
101 {
102         ssize_t nbytes = 0;
103         ssize_t n;
104
105         while (nbytes < (ssize_t) PACKET_SIZE) {
106                 n = recv(sockfd, rcv_buf, PACKET_SIZE - nbytes, 0);
107                 if (n <= 0)
108                         break;
109                 nbytes += n;
110         }
111
112         return nbytes;
113 }
114
115 static void delay_packet(void)
116 {
117         struct timespec ts;
118         int rc;
119
120         ts.tv_sec = cmd_args.packet_delay / 1000;
121         ts.tv_nsec = (cmd_args.packet_delay % 1000) * 1000000;
122
123         rc = nanosleep(&ts, NULL);
124         DIE(rc < 0, "nanosleep");
125 }
126
127 static void usage(const char *argv0)
128 {
129         fprintf(stderr, "Usage: %s [-h | --help] [-b | --buffer-size <buffer-size>] [-d | --delay <packet-delay>] <server-host> <server-port>\n", argv0);
130 }
131
132 static void print_args(void)
133 {
134         printf("buffer_size: %lu\n", cmd_args.buffer_size);
135         printf("delay: %lu\n", cmd_args.packet_delay);
136         printf("server_host: %s\n", cmd_args.server_host);
137         printf("server_port: %hu\n", cmd_args.server_port);
138 }
139
140 static void parse_args(int argc, char **argv)
141 {
142         int c;
143
144         while (1) {
145                 int option_index = 0;
146                 static struct option long_options[] = {
147                         {"buffer-size", 1, NULL, 'b'},
148                         {"packet-delay", 1, NULL, 'd'},
149                         {"help", 0, NULL, 'h'},
150                         {0, 0, 0, 0}
151                 };
152
153                 c = getopt_long(argc, argv, "hb:d:",
154                                 long_options, &option_index);
155                 if (c == -1)
156                         break;
157
158                 switch (c) {
159                 case 0:
160                         printf("option %s", long_options[option_index].name);
161                         if (optarg)
162                                 printf(" with arg %s", optarg);
163                         printf("\n");
164                         break;
165
166                 case 'b':
167                         /* TODO: use strtoul */
168                         cmd_args.buffer_size = atoi(optarg);
169                         break;
170
171                 case 'd':
172                         /* TODO: use strtoul */
173                         cmd_args.packet_delay = atoi(optarg);
174                         break;
175
176                 case 'h':
177                         usage(argv[0]);
178                         exit(EXIT_SUCCESS);
179                         break;
180
181                 case '?':
182                         break;
183
184                 default:
185                         printf("?? getopt returned character code 0%o ??\n", c);
186                 }
187         }
188
189         if (optind + 2 != argc) {
190                 usage(argv[0]);
191                 exit(EXIT_FAILURE);
192         }
193
194         /* TODO: check argv[argc-2] size */
195         strcpy(cmd_args.server_host, argv[argc-2]);
196         /* TODO: use strtoul */
197         cmd_args.server_port = atoi(argv[argc-1]);
198
199         print_args();
200 }
201
202 int main(int argc, char **argv)
203 {
204         parse_args(argc, argv);
205
206         connectfd = tcp_connect_to_server(cmd_args.server_host,
207                         cmd_args.server_port);
208         DIE(connectfd < 0, "tcp_connect_to_server");
209
210         init();
211
212         while (1) {
213                 ssize_t nbytes;
214
215                 fill_send_buffer();
216                 nbytes = send_buffer(connectfd);
217                 DIE(nbytes < 0, "send_buffer");
218                 delay_packet();
219         }
220
221         close(connectfd);
222
223         cleanup();
224
225         return 0;
226 }