09efe117fdfae5974d40951e4a768e4d8167fab8
[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         ssize_t n;
98
99         printf("before send\n");
100         n = send(sockfd, snd_buf, PACKET_SIZE, 0);
101         printf("after send\n");
102         if (n < 0)
103                 perror("send");
104
105         printf ("n = %ld, send\n", n);
106
107         return n;
108 }
109
110 static ssize_t receive_buffer(int sockfd)
111 {
112         ssize_t nbytes = 0;
113         ssize_t n;
114
115         while (nbytes < (ssize_t) PACKET_SIZE) {
116                 n = recv(sockfd, rcv_buf, PACKET_SIZE - nbytes, 0);
117                 if (n <= 0)
118                         break;
119                 nbytes += n;
120         }
121
122         return nbytes;
123 }
124
125 static void delay_packet(void)
126 {
127         struct timespec ts;
128         int rc;
129
130         ts.tv_sec = cmd_args.packet_delay / 1000;
131         ts.tv_nsec = (cmd_args.packet_delay % 1000) * 1000000;
132
133         rc = nanosleep(&ts, NULL);
134         DIE(rc < 0, "nanosleep");
135 }
136
137 static void usage(const char *argv0)
138 {
139         fprintf(stderr, "Usage: %s [-h | --help] [-b | --buffer-size <buffer-size>] [-d | --delay <packet-delay>] <server-host> <server-port>\n", argv0);
140 }
141
142 static void print_args(void)
143 {
144         printf("buffer_size: %lu\n", cmd_args.buffer_size);
145         printf("delay: %lu\n", cmd_args.packet_delay);
146         printf("server_host: %s\n", cmd_args.server_host);
147         printf("server_port: %hu\n", cmd_args.server_port);
148 }
149
150 static void parse_args(int argc, char **argv)
151 {
152         int c;
153
154         while (1) {
155                 int option_index = 0;
156                 static struct option long_options[] = {
157                         {"buffer-size", 1, NULL, 'b'},
158                         {"packet-delay", 1, NULL, 'd'},
159                         {"help", 0, NULL, 'h'},
160                         {0, 0, 0, 0}
161                 };
162
163                 c = getopt_long(argc, argv, "hb:d:",
164                                 long_options, &option_index);
165                 if (c == -1)
166                         break;
167
168                 switch (c) {
169                 case 0:
170                         printf("option %s", long_options[option_index].name);
171                         if (optarg)
172                                 printf(" with arg %s", optarg);
173                         printf("\n");
174                         break;
175
176                 case 'b':
177                         /* TODO: use strtoul */
178                         cmd_args.buffer_size = atoi(optarg);
179                         break;
180
181                 case 'd':
182                         /* TODO: use strtoul */
183                         cmd_args.packet_delay = atoi(optarg);
184                         break;
185
186                 case 'h':
187                         usage(argv[0]);
188                         exit(EXIT_SUCCESS);
189                         break;
190
191                 case '?':
192                         break;
193
194                 default:
195                         printf("?? getopt returned character code 0%o ??\n", c);
196                 }
197         }
198
199         if (optind + 2 != argc) {
200                 usage(argv[0]);
201                 exit(EXIT_FAILURE);
202         }
203
204         /* TODO: check argv[argc-2] size */
205         strcpy(cmd_args.server_host, argv[argc-2]);
206         /* TODO: use strtoul */
207         cmd_args.server_port = atoi(argv[argc-1]);
208
209         print_args();
210 }
211
212 int main(int argc, char **argv)
213 {
214         parse_args(argc, argv);
215
216         init();
217
218 try_connect:
219         sleep(1);
220
221         printf("ready to connect\n");
222
223         connectfd = tcp_connect_to_server(cmd_args.server_host,
224                         cmd_args.server_port);
225         if (connectfd < 0) {
226                 perror("tcp_connect_to_server");
227                 goto try_connect;
228         }
229
230         printf("connected\n");
231
232         while (1) {
233                 ssize_t nbytes;
234
235                 fill_send_buffer();
236                 nbytes = send_buffer(connectfd);
237                 printf("nbytes: %lu\n", nbytes);
238                 DIE(nbytes < 0, "send_buffer");
239                 if (nbytes == 0) {
240                         printf("Connection closed\n");
241                         close(connectfd);
242                         goto try_connect;
243                 }
244                 delay_packet();
245         }
246
247         close(connectfd);
248
249         cleanup();
250
251         return 0;
252 }