1*d6b92ffaSHans Petter Selasky /*
2*d6b92ffaSHans Petter Selasky * Copyright (c) 2011 Intel Corporation. All rights reserved.
3*d6b92ffaSHans Petter Selasky *
4*d6b92ffaSHans Petter Selasky * This software is available to you under the OpenIB.org BSD license
5*d6b92ffaSHans Petter Selasky * below:
6*d6b92ffaSHans Petter Selasky *
7*d6b92ffaSHans Petter Selasky * Redistribution and use in source and binary forms, with or
8*d6b92ffaSHans Petter Selasky * without modification, are permitted provided that the following
9*d6b92ffaSHans Petter Selasky * conditions are met:
10*d6b92ffaSHans Petter Selasky *
11*d6b92ffaSHans Petter Selasky * - Redistributions of source code must retain the above
12*d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following
13*d6b92ffaSHans Petter Selasky * disclaimer.
14*d6b92ffaSHans Petter Selasky *
15*d6b92ffaSHans Petter Selasky * - Redistributions in binary form must reproduce the above
16*d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following
17*d6b92ffaSHans Petter Selasky * disclaimer in the documentation and/or other materials
18*d6b92ffaSHans Petter Selasky * provided with the distribution.
19*d6b92ffaSHans Petter Selasky *
20*d6b92ffaSHans Petter Selasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21*d6b92ffaSHans Petter Selasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22*d6b92ffaSHans Petter Selasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV
23*d6b92ffaSHans Petter Selasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
24*d6b92ffaSHans Petter Selasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25*d6b92ffaSHans Petter Selasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26*d6b92ffaSHans Petter Selasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27*d6b92ffaSHans Petter Selasky * SOFTWARE.
28*d6b92ffaSHans Petter Selasky */
29*d6b92ffaSHans Petter Selasky
30*d6b92ffaSHans Petter Selasky #include <stdio.h>
31*d6b92ffaSHans Petter Selasky #include <stdlib.h>
32*d6b92ffaSHans Petter Selasky #include <string.h>
33*d6b92ffaSHans Petter Selasky #include <strings.h>
34*d6b92ffaSHans Petter Selasky #include <errno.h>
35*d6b92ffaSHans Petter Selasky #include <getopt.h>
36*d6b92ffaSHans Petter Selasky #include <arpa/inet.h>
37*d6b92ffaSHans Petter Selasky #include <sys/mman.h>
38*d6b92ffaSHans Petter Selasky #include <sys/types.h>
39*d6b92ffaSHans Petter Selasky #include <sys/socket.h>
40*d6b92ffaSHans Petter Selasky #include <sys/time.h>
41*d6b92ffaSHans Petter Selasky #include <sys/stat.h>
42*d6b92ffaSHans Petter Selasky #include <fcntl.h>
43*d6b92ffaSHans Petter Selasky #include <netdb.h>
44*d6b92ffaSHans Petter Selasky #include <unistd.h>
45*d6b92ffaSHans Petter Selasky
46*d6b92ffaSHans Petter Selasky #include <rdma/rsocket.h>
47*d6b92ffaSHans Petter Selasky
48*d6b92ffaSHans Petter Selasky union rsocket_address {
49*d6b92ffaSHans Petter Selasky struct sockaddr sa;
50*d6b92ffaSHans Petter Selasky struct sockaddr_in sin;
51*d6b92ffaSHans Petter Selasky struct sockaddr_in6 sin6;
52*d6b92ffaSHans Petter Selasky struct sockaddr_storage storage;
53*d6b92ffaSHans Petter Selasky };
54*d6b92ffaSHans Petter Selasky
55*d6b92ffaSHans Petter Selasky static const char *port = "7427";
56*d6b92ffaSHans Petter Selasky static char *dst_addr;
57*d6b92ffaSHans Petter Selasky static char *dst_file;
58*d6b92ffaSHans Petter Selasky static char *src_file;
59*d6b92ffaSHans Petter Selasky static struct timeval start, end;
60*d6b92ffaSHans Petter Selasky //static void buf[1024 * 1024];
61*d6b92ffaSHans Petter Selasky static uint64_t bytes;
62*d6b92ffaSHans Petter Selasky static int fd;
63*d6b92ffaSHans Petter Selasky static void *file_addr;
64*d6b92ffaSHans Petter Selasky
65*d6b92ffaSHans Petter Selasky enum {
66*d6b92ffaSHans Petter Selasky CMD_NOOP,
67*d6b92ffaSHans Petter Selasky CMD_OPEN,
68*d6b92ffaSHans Petter Selasky CMD_CLOSE,
69*d6b92ffaSHans Petter Selasky CMD_WRITE,
70*d6b92ffaSHans Petter Selasky CMD_RESP = 0x80,
71*d6b92ffaSHans Petter Selasky };
72*d6b92ffaSHans Petter Selasky
73*d6b92ffaSHans Petter Selasky /* TODO: handle byte swapping */
74*d6b92ffaSHans Petter Selasky struct msg_hdr {
75*d6b92ffaSHans Petter Selasky uint8_t version;
76*d6b92ffaSHans Petter Selasky uint8_t command;
77*d6b92ffaSHans Petter Selasky uint16_t len;
78*d6b92ffaSHans Petter Selasky uint32_t data;
79*d6b92ffaSHans Petter Selasky uint64_t id;
80*d6b92ffaSHans Petter Selasky };
81*d6b92ffaSHans Petter Selasky
82*d6b92ffaSHans Petter Selasky struct msg_open {
83*d6b92ffaSHans Petter Selasky struct msg_hdr hdr;
84*d6b92ffaSHans Petter Selasky char path[0];
85*d6b92ffaSHans Petter Selasky };
86*d6b92ffaSHans Petter Selasky
87*d6b92ffaSHans Petter Selasky struct msg_write {
88*d6b92ffaSHans Petter Selasky struct msg_hdr hdr;
89*d6b92ffaSHans Petter Selasky uint64_t size;
90*d6b92ffaSHans Petter Selasky };
91*d6b92ffaSHans Petter Selasky
show_perf(void)92*d6b92ffaSHans Petter Selasky static void show_perf(void)
93*d6b92ffaSHans Petter Selasky {
94*d6b92ffaSHans Petter Selasky float usec;
95*d6b92ffaSHans Petter Selasky
96*d6b92ffaSHans Petter Selasky usec = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
97*d6b92ffaSHans Petter Selasky
98*d6b92ffaSHans Petter Selasky printf("%lld bytes in %.2f seconds = %.2f Gb/sec\n",
99*d6b92ffaSHans Petter Selasky (long long) bytes, usec / 1000000., (bytes * 8) / (1000. * usec));
100*d6b92ffaSHans Petter Selasky }
101*d6b92ffaSHans Petter Selasky
_ntop(union rsocket_address * rsa)102*d6b92ffaSHans Petter Selasky static char *_ntop(union rsocket_address *rsa)
103*d6b92ffaSHans Petter Selasky {
104*d6b92ffaSHans Petter Selasky static char addr[32];
105*d6b92ffaSHans Petter Selasky
106*d6b92ffaSHans Petter Selasky switch (rsa->sa.sa_family) {
107*d6b92ffaSHans Petter Selasky case AF_INET:
108*d6b92ffaSHans Petter Selasky inet_ntop(AF_INET, &rsa->sin.sin_addr, addr, sizeof addr);
109*d6b92ffaSHans Petter Selasky break;
110*d6b92ffaSHans Petter Selasky case AF_INET6:
111*d6b92ffaSHans Petter Selasky inet_ntop(AF_INET6, &rsa->sin6.sin6_addr, addr, sizeof addr);
112*d6b92ffaSHans Petter Selasky break;
113*d6b92ffaSHans Petter Selasky default:
114*d6b92ffaSHans Petter Selasky addr[0] = '\0';
115*d6b92ffaSHans Petter Selasky break;
116*d6b92ffaSHans Petter Selasky }
117*d6b92ffaSHans Petter Selasky
118*d6b92ffaSHans Petter Selasky return addr;
119*d6b92ffaSHans Petter Selasky }
120*d6b92ffaSHans Petter Selasky
_recv(int rs,char * msg,size_t len)121*d6b92ffaSHans Petter Selasky static size_t _recv(int rs, char *msg, size_t len)
122*d6b92ffaSHans Petter Selasky {
123*d6b92ffaSHans Petter Selasky size_t ret, offset;
124*d6b92ffaSHans Petter Selasky
125*d6b92ffaSHans Petter Selasky for (offset = 0; offset < len; offset += ret) {
126*d6b92ffaSHans Petter Selasky ret = rrecv(rs, msg + offset, len - offset, 0);
127*d6b92ffaSHans Petter Selasky if (ret <= 0)
128*d6b92ffaSHans Petter Selasky return ret;
129*d6b92ffaSHans Petter Selasky }
130*d6b92ffaSHans Petter Selasky
131*d6b92ffaSHans Petter Selasky return len;
132*d6b92ffaSHans Petter Selasky }
133*d6b92ffaSHans Petter Selasky
msg_recv_hdr(int rs,struct msg_hdr * hdr)134*d6b92ffaSHans Petter Selasky static int msg_recv_hdr(int rs, struct msg_hdr *hdr)
135*d6b92ffaSHans Petter Selasky {
136*d6b92ffaSHans Petter Selasky int ret;
137*d6b92ffaSHans Petter Selasky
138*d6b92ffaSHans Petter Selasky ret = _recv(rs, (char *) hdr, sizeof *hdr);
139*d6b92ffaSHans Petter Selasky if (ret != sizeof *hdr)
140*d6b92ffaSHans Petter Selasky return -1;
141*d6b92ffaSHans Petter Selasky
142*d6b92ffaSHans Petter Selasky if (hdr->version || hdr->len < sizeof *hdr) {
143*d6b92ffaSHans Petter Selasky printf("invalid version %d or length %d\n",
144*d6b92ffaSHans Petter Selasky hdr->version, hdr->len);
145*d6b92ffaSHans Petter Selasky return -1;
146*d6b92ffaSHans Petter Selasky }
147*d6b92ffaSHans Petter Selasky
148*d6b92ffaSHans Petter Selasky return sizeof *hdr;
149*d6b92ffaSHans Petter Selasky }
150*d6b92ffaSHans Petter Selasky
msg_get_resp(int rs,struct msg_hdr * msg,uint8_t cmd)151*d6b92ffaSHans Petter Selasky static int msg_get_resp(int rs, struct msg_hdr *msg, uint8_t cmd)
152*d6b92ffaSHans Petter Selasky {
153*d6b92ffaSHans Petter Selasky int ret;
154*d6b92ffaSHans Petter Selasky
155*d6b92ffaSHans Petter Selasky ret = msg_recv_hdr(rs, msg);
156*d6b92ffaSHans Petter Selasky if (ret != sizeof *msg)
157*d6b92ffaSHans Petter Selasky return ret;
158*d6b92ffaSHans Petter Selasky
159*d6b92ffaSHans Petter Selasky if ((msg->len != sizeof *msg) || (msg->command != (cmd | CMD_RESP))) {
160*d6b92ffaSHans Petter Selasky printf("invalid length %d or bad command response %x:%x\n",
161*d6b92ffaSHans Petter Selasky msg->len, msg->command, cmd | CMD_RESP);
162*d6b92ffaSHans Petter Selasky return -1;
163*d6b92ffaSHans Petter Selasky }
164*d6b92ffaSHans Petter Selasky
165*d6b92ffaSHans Petter Selasky return msg->data;
166*d6b92ffaSHans Petter Selasky }
167*d6b92ffaSHans Petter Selasky
msg_send_resp(int rs,struct msg_hdr * msg,uint32_t status)168*d6b92ffaSHans Petter Selasky static void msg_send_resp(int rs, struct msg_hdr *msg, uint32_t status)
169*d6b92ffaSHans Petter Selasky {
170*d6b92ffaSHans Petter Selasky struct msg_hdr resp;
171*d6b92ffaSHans Petter Selasky
172*d6b92ffaSHans Petter Selasky resp.version = 0;
173*d6b92ffaSHans Petter Selasky resp.command = msg->command | CMD_RESP;
174*d6b92ffaSHans Petter Selasky resp.len = sizeof resp;
175*d6b92ffaSHans Petter Selasky resp.data = status;
176*d6b92ffaSHans Petter Selasky resp.id = msg->id;
177*d6b92ffaSHans Petter Selasky rsend(rs, (char *) &resp, sizeof resp, 0);
178*d6b92ffaSHans Petter Selasky }
179*d6b92ffaSHans Petter Selasky
server_listen(void)180*d6b92ffaSHans Petter Selasky static int server_listen(void)
181*d6b92ffaSHans Petter Selasky {
182*d6b92ffaSHans Petter Selasky struct addrinfo hints, *res;
183*d6b92ffaSHans Petter Selasky int ret, rs;
184*d6b92ffaSHans Petter Selasky
185*d6b92ffaSHans Petter Selasky memset(&hints, 0, sizeof hints);
186*d6b92ffaSHans Petter Selasky hints.ai_flags = RAI_PASSIVE;
187*d6b92ffaSHans Petter Selasky ret = getaddrinfo(NULL, port, &hints, &res);
188*d6b92ffaSHans Petter Selasky if (ret) {
189*d6b92ffaSHans Petter Selasky printf("getaddrinfo failed: %s\n", gai_strerror(ret));
190*d6b92ffaSHans Petter Selasky return ret;
191*d6b92ffaSHans Petter Selasky }
192*d6b92ffaSHans Petter Selasky
193*d6b92ffaSHans Petter Selasky rs = rsocket(res->ai_family, res->ai_socktype, res->ai_protocol);
194*d6b92ffaSHans Petter Selasky if (rs < 0) {
195*d6b92ffaSHans Petter Selasky perror("rsocket failed\n");
196*d6b92ffaSHans Petter Selasky ret = rs;
197*d6b92ffaSHans Petter Selasky goto free;
198*d6b92ffaSHans Petter Selasky }
199*d6b92ffaSHans Petter Selasky
200*d6b92ffaSHans Petter Selasky ret = 1;
201*d6b92ffaSHans Petter Selasky ret = rsetsockopt(rs, SOL_SOCKET, SO_REUSEADDR, &ret, sizeof ret);
202*d6b92ffaSHans Petter Selasky if (ret) {
203*d6b92ffaSHans Petter Selasky perror("rsetsockopt failed");
204*d6b92ffaSHans Petter Selasky goto close;
205*d6b92ffaSHans Petter Selasky }
206*d6b92ffaSHans Petter Selasky
207*d6b92ffaSHans Petter Selasky ret = rbind(rs, res->ai_addr, res->ai_addrlen);
208*d6b92ffaSHans Petter Selasky if (ret) {
209*d6b92ffaSHans Petter Selasky perror("rbind failed");
210*d6b92ffaSHans Petter Selasky goto close;
211*d6b92ffaSHans Petter Selasky }
212*d6b92ffaSHans Petter Selasky
213*d6b92ffaSHans Petter Selasky ret = rlisten(rs, 1);
214*d6b92ffaSHans Petter Selasky if (ret) {
215*d6b92ffaSHans Petter Selasky perror("rlisten failed");
216*d6b92ffaSHans Petter Selasky goto close;
217*d6b92ffaSHans Petter Selasky }
218*d6b92ffaSHans Petter Selasky
219*d6b92ffaSHans Petter Selasky ret = rs;
220*d6b92ffaSHans Petter Selasky goto free;
221*d6b92ffaSHans Petter Selasky
222*d6b92ffaSHans Petter Selasky close:
223*d6b92ffaSHans Petter Selasky rclose(rs);
224*d6b92ffaSHans Petter Selasky free:
225*d6b92ffaSHans Petter Selasky freeaddrinfo(res);
226*d6b92ffaSHans Petter Selasky return ret;
227*d6b92ffaSHans Petter Selasky }
228*d6b92ffaSHans Petter Selasky
server_open(int rs,struct msg_hdr * msg)229*d6b92ffaSHans Petter Selasky static int server_open(int rs, struct msg_hdr *msg)
230*d6b92ffaSHans Petter Selasky {
231*d6b92ffaSHans Petter Selasky char *path = NULL;
232*d6b92ffaSHans Petter Selasky int ret, len;
233*d6b92ffaSHans Petter Selasky
234*d6b92ffaSHans Petter Selasky printf("opening: ");
235*d6b92ffaSHans Petter Selasky fflush(NULL);
236*d6b92ffaSHans Petter Selasky if (file_addr || fd > 0) {
237*d6b92ffaSHans Petter Selasky printf("cannot open another file\n");
238*d6b92ffaSHans Petter Selasky ret = EBUSY;
239*d6b92ffaSHans Petter Selasky goto out;
240*d6b92ffaSHans Petter Selasky }
241*d6b92ffaSHans Petter Selasky
242*d6b92ffaSHans Petter Selasky len = msg->len - sizeof *msg;
243*d6b92ffaSHans Petter Selasky path = malloc(len);
244*d6b92ffaSHans Petter Selasky if (!path) {
245*d6b92ffaSHans Petter Selasky printf("cannot allocate path name\n");
246*d6b92ffaSHans Petter Selasky ret = ENOMEM;
247*d6b92ffaSHans Petter Selasky goto out;
248*d6b92ffaSHans Petter Selasky }
249*d6b92ffaSHans Petter Selasky
250*d6b92ffaSHans Petter Selasky ret = _recv(rs, path, len);
251*d6b92ffaSHans Petter Selasky if (ret != len) {
252*d6b92ffaSHans Petter Selasky printf("error receiving path\n");
253*d6b92ffaSHans Petter Selasky goto out;
254*d6b92ffaSHans Petter Selasky }
255*d6b92ffaSHans Petter Selasky
256*d6b92ffaSHans Petter Selasky printf("%s, ", path);
257*d6b92ffaSHans Petter Selasky fflush(NULL);
258*d6b92ffaSHans Petter Selasky fd = open(path, O_RDWR | O_CREAT | O_TRUNC, msg->data);
259*d6b92ffaSHans Petter Selasky if (fd < 0) {
260*d6b92ffaSHans Petter Selasky printf("unable to open destination file\n");
261*d6b92ffaSHans Petter Selasky ret = errno;
262*d6b92ffaSHans Petter Selasky }
263*d6b92ffaSHans Petter Selasky
264*d6b92ffaSHans Petter Selasky ret = 0;
265*d6b92ffaSHans Petter Selasky out:
266*d6b92ffaSHans Petter Selasky if (path)
267*d6b92ffaSHans Petter Selasky free(path);
268*d6b92ffaSHans Petter Selasky
269*d6b92ffaSHans Petter Selasky msg_send_resp(rs, msg, ret);
270*d6b92ffaSHans Petter Selasky return ret;
271*d6b92ffaSHans Petter Selasky }
272*d6b92ffaSHans Petter Selasky
server_close(int rs,struct msg_hdr * msg)273*d6b92ffaSHans Petter Selasky static void server_close(int rs, struct msg_hdr *msg)
274*d6b92ffaSHans Petter Selasky {
275*d6b92ffaSHans Petter Selasky printf("closing...");
276*d6b92ffaSHans Petter Selasky fflush(NULL);
277*d6b92ffaSHans Petter Selasky msg_send_resp(rs, msg, 0);
278*d6b92ffaSHans Petter Selasky
279*d6b92ffaSHans Petter Selasky if (file_addr) {
280*d6b92ffaSHans Petter Selasky munmap(file_addr, bytes);
281*d6b92ffaSHans Petter Selasky file_addr = NULL;
282*d6b92ffaSHans Petter Selasky }
283*d6b92ffaSHans Petter Selasky
284*d6b92ffaSHans Petter Selasky if (fd > 0) {
285*d6b92ffaSHans Petter Selasky close(fd);
286*d6b92ffaSHans Petter Selasky fd = 0;
287*d6b92ffaSHans Petter Selasky }
288*d6b92ffaSHans Petter Selasky printf("done\n");
289*d6b92ffaSHans Petter Selasky }
290*d6b92ffaSHans Petter Selasky
server_write(int rs,struct msg_hdr * msg)291*d6b92ffaSHans Petter Selasky static int server_write(int rs, struct msg_hdr *msg)
292*d6b92ffaSHans Petter Selasky {
293*d6b92ffaSHans Petter Selasky size_t len;
294*d6b92ffaSHans Petter Selasky int ret;
295*d6b92ffaSHans Petter Selasky
296*d6b92ffaSHans Petter Selasky printf("transferring");
297*d6b92ffaSHans Petter Selasky fflush(NULL);
298*d6b92ffaSHans Petter Selasky if (fd <= 0) {
299*d6b92ffaSHans Petter Selasky printf("...file not opened\n");
300*d6b92ffaSHans Petter Selasky ret = EINVAL;
301*d6b92ffaSHans Petter Selasky goto out;
302*d6b92ffaSHans Petter Selasky }
303*d6b92ffaSHans Petter Selasky
304*d6b92ffaSHans Petter Selasky if (msg->len != sizeof(struct msg_write)) {
305*d6b92ffaSHans Petter Selasky printf("...invalid message length %d\n", msg->len);
306*d6b92ffaSHans Petter Selasky ret = EINVAL;
307*d6b92ffaSHans Petter Selasky goto out;
308*d6b92ffaSHans Petter Selasky }
309*d6b92ffaSHans Petter Selasky
310*d6b92ffaSHans Petter Selasky ret = _recv(rs, (char *) &bytes, sizeof bytes);
311*d6b92ffaSHans Petter Selasky if (ret != sizeof bytes)
312*d6b92ffaSHans Petter Selasky goto out;
313*d6b92ffaSHans Petter Selasky
314*d6b92ffaSHans Petter Selasky ret = ftruncate(fd, bytes);
315*d6b92ffaSHans Petter Selasky if (ret)
316*d6b92ffaSHans Petter Selasky goto out;
317*d6b92ffaSHans Petter Selasky
318*d6b92ffaSHans Petter Selasky file_addr = mmap(NULL, bytes, PROT_WRITE, MAP_SHARED, fd, 0);
319*d6b92ffaSHans Petter Selasky if (file_addr == (void *) -1) {
320*d6b92ffaSHans Petter Selasky printf("...error mapping file\n");
321*d6b92ffaSHans Petter Selasky ret = errno;
322*d6b92ffaSHans Petter Selasky goto out;
323*d6b92ffaSHans Petter Selasky }
324*d6b92ffaSHans Petter Selasky
325*d6b92ffaSHans Petter Selasky printf("...%lld bytes...", (long long) bytes);
326*d6b92ffaSHans Petter Selasky fflush(NULL);
327*d6b92ffaSHans Petter Selasky len = _recv(rs, file_addr, bytes);
328*d6b92ffaSHans Petter Selasky if (len != bytes) {
329*d6b92ffaSHans Petter Selasky printf("...error receiving data\n");
330*d6b92ffaSHans Petter Selasky ret = (int) len;
331*d6b92ffaSHans Petter Selasky }
332*d6b92ffaSHans Petter Selasky out:
333*d6b92ffaSHans Petter Selasky msg_send_resp(rs, msg, ret);
334*d6b92ffaSHans Petter Selasky return ret;
335*d6b92ffaSHans Petter Selasky }
336*d6b92ffaSHans Petter Selasky
server_process(int rs)337*d6b92ffaSHans Petter Selasky static void server_process(int rs)
338*d6b92ffaSHans Petter Selasky {
339*d6b92ffaSHans Petter Selasky struct msg_hdr msg;
340*d6b92ffaSHans Petter Selasky int ret;
341*d6b92ffaSHans Petter Selasky
342*d6b92ffaSHans Petter Selasky do {
343*d6b92ffaSHans Petter Selasky ret = msg_recv_hdr(rs, &msg);
344*d6b92ffaSHans Petter Selasky if (ret != sizeof msg)
345*d6b92ffaSHans Petter Selasky break;
346*d6b92ffaSHans Petter Selasky
347*d6b92ffaSHans Petter Selasky switch (msg.command) {
348*d6b92ffaSHans Petter Selasky case CMD_OPEN:
349*d6b92ffaSHans Petter Selasky ret = server_open(rs, &msg);
350*d6b92ffaSHans Petter Selasky break;
351*d6b92ffaSHans Petter Selasky case CMD_CLOSE:
352*d6b92ffaSHans Petter Selasky server_close(rs, &msg);
353*d6b92ffaSHans Petter Selasky ret = 0;
354*d6b92ffaSHans Petter Selasky break;
355*d6b92ffaSHans Petter Selasky case CMD_WRITE:
356*d6b92ffaSHans Petter Selasky ret = server_write(rs, &msg);
357*d6b92ffaSHans Petter Selasky break;
358*d6b92ffaSHans Petter Selasky default:
359*d6b92ffaSHans Petter Selasky msg_send_resp(rs, &msg, EINVAL);
360*d6b92ffaSHans Petter Selasky ret = -1;
361*d6b92ffaSHans Petter Selasky break;
362*d6b92ffaSHans Petter Selasky }
363*d6b92ffaSHans Petter Selasky
364*d6b92ffaSHans Petter Selasky } while (!ret);
365*d6b92ffaSHans Petter Selasky }
366*d6b92ffaSHans Petter Selasky
server_run(void)367*d6b92ffaSHans Petter Selasky static int server_run(void)
368*d6b92ffaSHans Petter Selasky {
369*d6b92ffaSHans Petter Selasky int lrs, rs;
370*d6b92ffaSHans Petter Selasky union rsocket_address rsa;
371*d6b92ffaSHans Petter Selasky socklen_t len;
372*d6b92ffaSHans Petter Selasky
373*d6b92ffaSHans Petter Selasky lrs = server_listen();
374*d6b92ffaSHans Petter Selasky if (lrs < 0)
375*d6b92ffaSHans Petter Selasky return lrs;
376*d6b92ffaSHans Petter Selasky
377*d6b92ffaSHans Petter Selasky while (1) {
378*d6b92ffaSHans Petter Selasky len = sizeof rsa;
379*d6b92ffaSHans Petter Selasky printf("waiting for connection...");
380*d6b92ffaSHans Petter Selasky fflush(NULL);
381*d6b92ffaSHans Petter Selasky rs = raccept(lrs, &rsa.sa, &len);
382*d6b92ffaSHans Petter Selasky
383*d6b92ffaSHans Petter Selasky printf("client: %s\n", _ntop(&rsa));
384*d6b92ffaSHans Petter Selasky server_process(rs);
385*d6b92ffaSHans Petter Selasky
386*d6b92ffaSHans Petter Selasky rshutdown(rs, SHUT_RDWR);
387*d6b92ffaSHans Petter Selasky rclose(rs);
388*d6b92ffaSHans Petter Selasky }
389*d6b92ffaSHans Petter Selasky return 0;
390*d6b92ffaSHans Petter Selasky }
391*d6b92ffaSHans Petter Selasky
client_connect(void)392*d6b92ffaSHans Petter Selasky static int client_connect(void)
393*d6b92ffaSHans Petter Selasky {
394*d6b92ffaSHans Petter Selasky struct addrinfo *res;
395*d6b92ffaSHans Petter Selasky int ret, rs;
396*d6b92ffaSHans Petter Selasky
397*d6b92ffaSHans Petter Selasky ret = getaddrinfo(dst_addr, port, NULL, &res);
398*d6b92ffaSHans Petter Selasky if (ret) {
399*d6b92ffaSHans Petter Selasky printf("getaddrinfo failed: %s\n", gai_strerror(ret));
400*d6b92ffaSHans Petter Selasky return ret;
401*d6b92ffaSHans Petter Selasky }
402*d6b92ffaSHans Petter Selasky
403*d6b92ffaSHans Petter Selasky rs = rsocket(res->ai_family, res->ai_socktype, res->ai_protocol);
404*d6b92ffaSHans Petter Selasky if (rs < 0) {
405*d6b92ffaSHans Petter Selasky perror("rsocket failed\n");
406*d6b92ffaSHans Petter Selasky goto free;
407*d6b92ffaSHans Petter Selasky }
408*d6b92ffaSHans Petter Selasky
409*d6b92ffaSHans Petter Selasky ret = rconnect(rs, res->ai_addr, res->ai_addrlen);
410*d6b92ffaSHans Petter Selasky if (ret) {
411*d6b92ffaSHans Petter Selasky perror("rconnect failed\n");
412*d6b92ffaSHans Petter Selasky rclose(rs);
413*d6b92ffaSHans Petter Selasky rs = ret;
414*d6b92ffaSHans Petter Selasky }
415*d6b92ffaSHans Petter Selasky
416*d6b92ffaSHans Petter Selasky free:
417*d6b92ffaSHans Petter Selasky freeaddrinfo(res);
418*d6b92ffaSHans Petter Selasky return rs;
419*d6b92ffaSHans Petter Selasky }
420*d6b92ffaSHans Petter Selasky
client_open(int rs)421*d6b92ffaSHans Petter Selasky static int client_open(int rs)
422*d6b92ffaSHans Petter Selasky {
423*d6b92ffaSHans Petter Selasky struct msg_open *msg;
424*d6b92ffaSHans Petter Selasky struct stat stats;
425*d6b92ffaSHans Petter Selasky uint32_t len;
426*d6b92ffaSHans Petter Selasky int ret;
427*d6b92ffaSHans Petter Selasky
428*d6b92ffaSHans Petter Selasky printf("opening...");
429*d6b92ffaSHans Petter Selasky fflush(NULL);
430*d6b92ffaSHans Petter Selasky fd = open(src_file, O_RDONLY);
431*d6b92ffaSHans Petter Selasky if (fd < 0)
432*d6b92ffaSHans Petter Selasky return fd;
433*d6b92ffaSHans Petter Selasky
434*d6b92ffaSHans Petter Selasky ret = fstat(fd, &stats);
435*d6b92ffaSHans Petter Selasky if (ret < 0)
436*d6b92ffaSHans Petter Selasky goto err1;
437*d6b92ffaSHans Petter Selasky
438*d6b92ffaSHans Petter Selasky bytes = (uint64_t) stats.st_size;
439*d6b92ffaSHans Petter Selasky file_addr = mmap(NULL, bytes, PROT_READ, MAP_SHARED, fd, 0);
440*d6b92ffaSHans Petter Selasky if (file_addr == (void *) -1) {
441*d6b92ffaSHans Petter Selasky ret = errno;
442*d6b92ffaSHans Petter Selasky goto err1;
443*d6b92ffaSHans Petter Selasky }
444*d6b92ffaSHans Petter Selasky
445*d6b92ffaSHans Petter Selasky len = (((uint32_t) strlen(dst_file)) + 8) & 0xFFFFFFF8;
446*d6b92ffaSHans Petter Selasky msg = calloc(1, sizeof(*msg) + len);
447*d6b92ffaSHans Petter Selasky if (!msg) {
448*d6b92ffaSHans Petter Selasky ret = -1;
449*d6b92ffaSHans Petter Selasky goto err2;
450*d6b92ffaSHans Petter Selasky }
451*d6b92ffaSHans Petter Selasky
452*d6b92ffaSHans Petter Selasky msg->hdr.command = CMD_OPEN;
453*d6b92ffaSHans Petter Selasky msg->hdr.len = sizeof(*msg) + len;
454*d6b92ffaSHans Petter Selasky msg->hdr.data = (uint32_t) stats.st_mode;
455*d6b92ffaSHans Petter Selasky strcpy(msg->path, dst_file);
456*d6b92ffaSHans Petter Selasky ret = rsend(rs, msg, msg->hdr.len, 0);
457*d6b92ffaSHans Petter Selasky if (ret != msg->hdr.len)
458*d6b92ffaSHans Petter Selasky goto err3;
459*d6b92ffaSHans Petter Selasky
460*d6b92ffaSHans Petter Selasky ret = msg_get_resp(rs, &msg->hdr, CMD_OPEN);
461*d6b92ffaSHans Petter Selasky if (ret)
462*d6b92ffaSHans Petter Selasky goto err3;
463*d6b92ffaSHans Petter Selasky
464*d6b92ffaSHans Petter Selasky return 0;
465*d6b92ffaSHans Petter Selasky
466*d6b92ffaSHans Petter Selasky err3:
467*d6b92ffaSHans Petter Selasky free(msg);
468*d6b92ffaSHans Petter Selasky err2:
469*d6b92ffaSHans Petter Selasky munmap(file_addr, bytes);
470*d6b92ffaSHans Petter Selasky err1:
471*d6b92ffaSHans Petter Selasky close(fd);
472*d6b92ffaSHans Petter Selasky return ret;
473*d6b92ffaSHans Petter Selasky }
474*d6b92ffaSHans Petter Selasky
client_start_write(int rs)475*d6b92ffaSHans Petter Selasky static int client_start_write(int rs)
476*d6b92ffaSHans Petter Selasky {
477*d6b92ffaSHans Petter Selasky struct msg_write msg;
478*d6b92ffaSHans Petter Selasky int ret;
479*d6b92ffaSHans Petter Selasky
480*d6b92ffaSHans Petter Selasky printf("transferring");
481*d6b92ffaSHans Petter Selasky fflush(NULL);
482*d6b92ffaSHans Petter Selasky memset(&msg, 0, sizeof msg);
483*d6b92ffaSHans Petter Selasky msg.hdr.command = CMD_WRITE;
484*d6b92ffaSHans Petter Selasky msg.hdr.len = sizeof(msg);
485*d6b92ffaSHans Petter Selasky msg.size = bytes;
486*d6b92ffaSHans Petter Selasky
487*d6b92ffaSHans Petter Selasky ret = rsend(rs, &msg, sizeof msg, 0);
488*d6b92ffaSHans Petter Selasky if (ret != msg.hdr.len)
489*d6b92ffaSHans Petter Selasky return ret;
490*d6b92ffaSHans Petter Selasky
491*d6b92ffaSHans Petter Selasky return 0;
492*d6b92ffaSHans Petter Selasky }
493*d6b92ffaSHans Petter Selasky
client_close(int rs)494*d6b92ffaSHans Petter Selasky static int client_close(int rs)
495*d6b92ffaSHans Petter Selasky {
496*d6b92ffaSHans Petter Selasky struct msg_hdr msg;
497*d6b92ffaSHans Petter Selasky int ret;
498*d6b92ffaSHans Petter Selasky
499*d6b92ffaSHans Petter Selasky printf("closing...");
500*d6b92ffaSHans Petter Selasky fflush(NULL);
501*d6b92ffaSHans Petter Selasky memset(&msg, 0, sizeof msg);
502*d6b92ffaSHans Petter Selasky msg.command = CMD_CLOSE;
503*d6b92ffaSHans Petter Selasky msg.len = sizeof msg;
504*d6b92ffaSHans Petter Selasky ret = rsend(rs, (char *) &msg, msg.len, 0);
505*d6b92ffaSHans Petter Selasky if (ret != msg.len)
506*d6b92ffaSHans Petter Selasky goto out;
507*d6b92ffaSHans Petter Selasky
508*d6b92ffaSHans Petter Selasky ret = msg_get_resp(rs, &msg, CMD_CLOSE);
509*d6b92ffaSHans Petter Selasky if (ret)
510*d6b92ffaSHans Petter Selasky goto out;
511*d6b92ffaSHans Petter Selasky
512*d6b92ffaSHans Petter Selasky printf("done\n");
513*d6b92ffaSHans Petter Selasky out:
514*d6b92ffaSHans Petter Selasky munmap(file_addr, bytes);
515*d6b92ffaSHans Petter Selasky close(fd);
516*d6b92ffaSHans Petter Selasky return ret;
517*d6b92ffaSHans Petter Selasky }
518*d6b92ffaSHans Petter Selasky
client_run(void)519*d6b92ffaSHans Petter Selasky static int client_run(void)
520*d6b92ffaSHans Petter Selasky {
521*d6b92ffaSHans Petter Selasky struct msg_hdr ack;
522*d6b92ffaSHans Petter Selasky int ret, rs;
523*d6b92ffaSHans Petter Selasky size_t len;
524*d6b92ffaSHans Petter Selasky
525*d6b92ffaSHans Petter Selasky rs = client_connect();
526*d6b92ffaSHans Petter Selasky if (rs < 0)
527*d6b92ffaSHans Petter Selasky return rs;
528*d6b92ffaSHans Petter Selasky
529*d6b92ffaSHans Petter Selasky ret = client_open(rs);
530*d6b92ffaSHans Petter Selasky if (ret)
531*d6b92ffaSHans Petter Selasky goto shutdown;
532*d6b92ffaSHans Petter Selasky
533*d6b92ffaSHans Petter Selasky ret = client_start_write(rs);
534*d6b92ffaSHans Petter Selasky if (ret)
535*d6b92ffaSHans Petter Selasky goto close;
536*d6b92ffaSHans Petter Selasky
537*d6b92ffaSHans Petter Selasky printf("...");
538*d6b92ffaSHans Petter Selasky fflush(NULL);
539*d6b92ffaSHans Petter Selasky gettimeofday(&start, NULL);
540*d6b92ffaSHans Petter Selasky len = rsend(rs, file_addr, bytes, 0);
541*d6b92ffaSHans Petter Selasky if (len == bytes)
542*d6b92ffaSHans Petter Selasky ret = msg_get_resp(rs, &ack, CMD_WRITE);
543*d6b92ffaSHans Petter Selasky else
544*d6b92ffaSHans Petter Selasky ret = (int) len;
545*d6b92ffaSHans Petter Selasky
546*d6b92ffaSHans Petter Selasky gettimeofday(&end, NULL);
547*d6b92ffaSHans Petter Selasky
548*d6b92ffaSHans Petter Selasky close:
549*d6b92ffaSHans Petter Selasky client_close(rs);
550*d6b92ffaSHans Petter Selasky shutdown:
551*d6b92ffaSHans Petter Selasky rshutdown(rs, SHUT_RDWR);
552*d6b92ffaSHans Petter Selasky rclose(rs);
553*d6b92ffaSHans Petter Selasky if (!ret)
554*d6b92ffaSHans Petter Selasky show_perf();
555*d6b92ffaSHans Petter Selasky return ret;
556*d6b92ffaSHans Petter Selasky }
557*d6b92ffaSHans Petter Selasky
show_usage(char * program)558*d6b92ffaSHans Petter Selasky static void show_usage(char *program)
559*d6b92ffaSHans Petter Selasky {
560*d6b92ffaSHans Petter Selasky printf("usage 1: %s [options]\n", program);
561*d6b92ffaSHans Petter Selasky printf("\t starts the server application\n");
562*d6b92ffaSHans Petter Selasky printf("\t[-p port_number]\n");
563*d6b92ffaSHans Petter Selasky printf("usage 2: %s source server[:destination] [options]\n", program);
564*d6b92ffaSHans Petter Selasky printf("\t source - file name and path\n");
565*d6b92ffaSHans Petter Selasky printf("\t server - name or address\n");
566*d6b92ffaSHans Petter Selasky printf("\t destination - file name and path\n");
567*d6b92ffaSHans Petter Selasky printf("\t[-p port_number]\n");
568*d6b92ffaSHans Petter Selasky exit(1);
569*d6b92ffaSHans Petter Selasky }
570*d6b92ffaSHans Petter Selasky
server_opts(int argc,char ** argv)571*d6b92ffaSHans Petter Selasky static void server_opts(int argc, char **argv)
572*d6b92ffaSHans Petter Selasky {
573*d6b92ffaSHans Petter Selasky int op;
574*d6b92ffaSHans Petter Selasky
575*d6b92ffaSHans Petter Selasky while ((op = getopt(argc, argv, "p:")) != -1) {
576*d6b92ffaSHans Petter Selasky switch (op) {
577*d6b92ffaSHans Petter Selasky case 'p':
578*d6b92ffaSHans Petter Selasky port = optarg;
579*d6b92ffaSHans Petter Selasky break;
580*d6b92ffaSHans Petter Selasky default:
581*d6b92ffaSHans Petter Selasky show_usage(argv[0]);
582*d6b92ffaSHans Petter Selasky }
583*d6b92ffaSHans Petter Selasky }
584*d6b92ffaSHans Petter Selasky }
585*d6b92ffaSHans Petter Selasky
client_opts(int argc,char ** argv)586*d6b92ffaSHans Petter Selasky static void client_opts(int argc, char **argv)
587*d6b92ffaSHans Petter Selasky {
588*d6b92ffaSHans Petter Selasky int op;
589*d6b92ffaSHans Petter Selasky
590*d6b92ffaSHans Petter Selasky if (argc < 3)
591*d6b92ffaSHans Petter Selasky show_usage(argv[0]);
592*d6b92ffaSHans Petter Selasky
593*d6b92ffaSHans Petter Selasky src_file = argv[1];
594*d6b92ffaSHans Petter Selasky dst_addr = argv[2];
595*d6b92ffaSHans Petter Selasky dst_file = strchr(dst_addr, ':');
596*d6b92ffaSHans Petter Selasky if (dst_file) {
597*d6b92ffaSHans Petter Selasky *dst_file = '\0';
598*d6b92ffaSHans Petter Selasky dst_file++;
599*d6b92ffaSHans Petter Selasky }
600*d6b92ffaSHans Petter Selasky if (!dst_file)
601*d6b92ffaSHans Petter Selasky dst_file = src_file;
602*d6b92ffaSHans Petter Selasky
603*d6b92ffaSHans Petter Selasky while ((op = getopt(argc, argv, "p:")) != -1) {
604*d6b92ffaSHans Petter Selasky switch (op) {
605*d6b92ffaSHans Petter Selasky case 'p':
606*d6b92ffaSHans Petter Selasky port = optarg;
607*d6b92ffaSHans Petter Selasky break;
608*d6b92ffaSHans Petter Selasky default:
609*d6b92ffaSHans Petter Selasky show_usage(argv[0]);
610*d6b92ffaSHans Petter Selasky }
611*d6b92ffaSHans Petter Selasky }
612*d6b92ffaSHans Petter Selasky
613*d6b92ffaSHans Petter Selasky }
614*d6b92ffaSHans Petter Selasky
main(int argc,char ** argv)615*d6b92ffaSHans Petter Selasky int main(int argc, char **argv)
616*d6b92ffaSHans Petter Selasky {
617*d6b92ffaSHans Petter Selasky int ret;
618*d6b92ffaSHans Petter Selasky
619*d6b92ffaSHans Petter Selasky if (argc == 1 || argv[1][0] == '-') {
620*d6b92ffaSHans Petter Selasky server_opts(argc, argv);
621*d6b92ffaSHans Petter Selasky ret = server_run();
622*d6b92ffaSHans Petter Selasky } else {
623*d6b92ffaSHans Petter Selasky client_opts(argc, argv);
624*d6b92ffaSHans Petter Selasky ret = client_run();
625*d6b92ffaSHans Petter Selasky }
626*d6b92ffaSHans Petter Selasky
627*d6b92ffaSHans Petter Selasky return ret;
628*d6b92ffaSHans Petter Selasky }
629