Commit | Line | Data |
---|---|---|
d8525fbd JA |
1 | /* |
2 | * Splice stdin to net | |
3 | */ | |
4 | #include <stdio.h> | |
5 | #include <stdlib.h> | |
6 | #include <unistd.h> | |
7 | #include <netdb.h> | |
8 | #include <unistd.h> | |
9 | #include <fcntl.h> | |
10 | #include <signal.h> | |
11 | #include <netinet/in.h> | |
12 | #include <arpa/inet.h> | |
13 | #include <string.h> | |
14 | #include <sys/time.h> | |
15 | ||
16 | #include "splice.h" | |
17 | ||
18 | static struct timeval start_time; | |
19 | static unsigned long long kb_sent; | |
20 | static unsigned long iters; | |
21 | ||
22 | static unsigned long mtime_since(struct timeval *s, struct timeval *e) | |
23 | { | |
24 | double sec, usec; | |
25 | ||
26 | sec = e->tv_sec - s->tv_sec; | |
27 | usec = e->tv_usec - s->tv_usec; | |
28 | if (sec > 0 && usec < 0) { | |
29 | sec--; | |
30 | usec += 1000000; | |
31 | } | |
32 | ||
33 | sec *= (double) 1000; | |
34 | usec /= (double) 1000; | |
35 | ||
36 | return sec + usec; | |
37 | } | |
38 | ||
39 | static unsigned long mtime_since_now(struct timeval *s) | |
40 | { | |
41 | struct timeval t; | |
42 | ||
43 | gettimeofday(&t, NULL); | |
44 | return mtime_since(s, &t); | |
45 | } | |
46 | ||
47 | void show_rate(int sig) | |
48 | { | |
49 | unsigned long msecs = mtime_since_now(&start_time); | |
50 | ||
51 | printf("Throughput: %LuMiB/sec (%Lu MiB in %lu msecs)\n", kb_sent / msecs, kb_sent, msecs); | |
52 | printf("avg put: %Lu\n", kb_sent / iters); | |
53 | } | |
54 | ||
55 | int main(int argc, char *argv[]) | |
56 | { | |
57 | struct sockaddr_in addr; | |
58 | unsigned short port; | |
59 | int fd, pfd[2], ffd, ret; | |
60 | unsigned long long b_sent = 0; | |
61 | int bla = 1; | |
62 | ||
63 | if (argc < 4) { | |
64 | printf("%s: file target port\n", argv[0]); | |
65 | return 1; | |
66 | } | |
67 | ||
68 | port = atoi(argv[3]); | |
69 | ||
70 | memset(&addr, 0, sizeof(addr)); | |
71 | addr.sin_family = AF_INET; | |
72 | addr.sin_port = htons(port); | |
73 | ||
74 | if (inet_aton(argv[2], &addr.sin_addr) != 1) { | |
75 | struct hostent *hent = gethostbyname(argv[2]); | |
76 | ||
77 | if (!hent) { | |
78 | perror("gethostbyname"); | |
79 | return 1; | |
80 | } | |
81 | ||
82 | memcpy(&addr.sin_addr, hent->h_addr, 4); | |
83 | } | |
84 | ||
85 | printf("Connecting to %s/%d\n", argv[2], port); | |
86 | ||
87 | fd = socket(AF_INET, SOCK_STREAM, 0); | |
88 | if (fd < 0) { | |
89 | perror("socket"); | |
90 | return 1; | |
91 | } | |
92 | ||
93 | if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { | |
94 | perror("connect"); | |
95 | return 1; | |
96 | } | |
97 | ||
98 | if (pipe(pfd) < 0) { | |
99 | perror("pipe"); | |
100 | return 1; | |
101 | } | |
102 | ||
103 | ffd = open(argv[1], O_RDWR); | |
104 | if (ffd < 0) { | |
105 | perror("open input"); | |
106 | return 1; | |
107 | } | |
108 | ||
109 | signal(SIGINT, show_rate); | |
110 | gettimeofday(&start_time, NULL); | |
111 | ||
112 | do { | |
113 | if (kb_sent >= 128*1024) { | |
114 | b_sent += 40000; | |
115 | ret = ftruncate(ffd, b_sent); | |
116 | printf("trunc file a little %d\n", ret); | |
117 | bla = 0; | |
118 | } | |
119 | ||
120 | ret = splice(ffd, NULL, pfd[1], NULL, SPLICE_SIZE, 0x02); | |
121 | ||
122 | if (!bla) | |
123 | printf("spliced %d\n", ret); | |
124 | ||
125 | if (ret < 0) { | |
126 | perror("splice"); | |
127 | break; | |
128 | } else if (!ret) { | |
129 | break; | |
130 | } | |
131 | b_sent += ret; | |
132 | kb_sent += ret >> 10; | |
133 | iters++; | |
134 | while (ret > 0) { | |
135 | int flags = 0; | |
136 | int written = splice(pfd[0], NULL, fd, NULL, ret, flags); | |
137 | if (written < 0) { | |
138 | perror("splice-out"); | |
139 | break; | |
140 | } else if (!written) | |
141 | break; | |
142 | ret -= written; | |
143 | } | |
144 | } while (kb_sent < 512 * 1024 && bla); | |
145 | ||
146 | show_rate(0); | |
147 | close(fd); | |
148 | return 0; | |
149 | } |