1321936Shselasky/* 2321936Shselasky * Copyright (c) 2011 Intel Corporation. All rights reserved. 3321936Shselasky * 4321936Shselasky * This software is available to you under the OpenIB.org BSD license 5321936Shselasky * below: 6321936Shselasky * 7321936Shselasky * Redistribution and use in source and binary forms, with or 8321936Shselasky * without modification, are permitted provided that the following 9321936Shselasky * conditions are met: 10321936Shselasky * 11321936Shselasky * - Redistributions of source code must retain the above 12321936Shselasky * copyright notice, this list of conditions and the following 13321936Shselasky * disclaimer. 14321936Shselasky * 15321936Shselasky * - Redistributions in binary form must reproduce the above 16321936Shselasky * copyright notice, this list of conditions and the following 17321936Shselasky * disclaimer in the documentation and/or other materials 18321936Shselasky * provided with the distribution. 19321936Shselasky * 20321936Shselasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21321936Shselasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22321936Shselasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV 23321936Shselasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 24321936Shselasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 25321936Shselasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 26321936Shselasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27321936Shselasky * SOFTWARE. 28321936Shselasky */ 29321936Shselasky 30321936Shselasky#include <stdio.h> 31321936Shselasky#include <stdlib.h> 32321936Shselasky#include <string.h> 33321936Shselasky#include <strings.h> 34321936Shselasky#include <errno.h> 35321936Shselasky#include <getopt.h> 36321936Shselasky#include <arpa/inet.h> 37321936Shselasky#include <sys/mman.h> 38321936Shselasky#include <sys/types.h> 39321936Shselasky#include <sys/socket.h> 40321936Shselasky#include <sys/time.h> 41321936Shselasky#include <sys/stat.h> 42321936Shselasky#include <fcntl.h> 43321936Shselasky#include <netdb.h> 44321936Shselasky#include <unistd.h> 45321936Shselasky 46321936Shselasky#include <rdma/rsocket.h> 47321936Shselasky 48321936Shselaskyunion rsocket_address { 49321936Shselasky struct sockaddr sa; 50321936Shselasky struct sockaddr_in sin; 51321936Shselasky struct sockaddr_in6 sin6; 52321936Shselasky struct sockaddr_storage storage; 53321936Shselasky}; 54321936Shselasky 55321936Shselaskystatic const char *port = "7427"; 56321936Shselaskystatic char *dst_addr; 57321936Shselaskystatic char *dst_file; 58321936Shselaskystatic char *src_file; 59321936Shselaskystatic struct timeval start, end; 60321936Shselasky//static void buf[1024 * 1024]; 61321936Shselaskystatic uint64_t bytes; 62321936Shselaskystatic int fd; 63321936Shselaskystatic void *file_addr; 64321936Shselasky 65321936Shselaskyenum { 66321936Shselasky CMD_NOOP, 67321936Shselasky CMD_OPEN, 68321936Shselasky CMD_CLOSE, 69321936Shselasky CMD_WRITE, 70321936Shselasky CMD_RESP = 0x80, 71321936Shselasky}; 72321936Shselasky 73321936Shselasky/* TODO: handle byte swapping */ 74321936Shselaskystruct msg_hdr { 75321936Shselasky uint8_t version; 76321936Shselasky uint8_t command; 77321936Shselasky uint16_t len; 78321936Shselasky uint32_t data; 79321936Shselasky uint64_t id; 80321936Shselasky}; 81321936Shselasky 82321936Shselaskystruct msg_open { 83321936Shselasky struct msg_hdr hdr; 84321936Shselasky char path[0]; 85321936Shselasky}; 86321936Shselasky 87321936Shselaskystruct msg_write { 88321936Shselasky struct msg_hdr hdr; 89321936Shselasky uint64_t size; 90321936Shselasky}; 91321936Shselasky 92321936Shselaskystatic void show_perf(void) 93321936Shselasky{ 94321936Shselasky float usec; 95321936Shselasky 96321936Shselasky usec = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec); 97321936Shselasky 98321936Shselasky printf("%lld bytes in %.2f seconds = %.2f Gb/sec\n", 99321936Shselasky (long long) bytes, usec / 1000000., (bytes * 8) / (1000. * usec)); 100321936Shselasky} 101321936Shselasky 102321936Shselaskystatic char *_ntop(union rsocket_address *rsa) 103321936Shselasky{ 104321936Shselasky static char addr[32]; 105321936Shselasky 106321936Shselasky switch (rsa->sa.sa_family) { 107321936Shselasky case AF_INET: 108321936Shselasky inet_ntop(AF_INET, &rsa->sin.sin_addr, addr, sizeof addr); 109321936Shselasky break; 110321936Shselasky case AF_INET6: 111321936Shselasky inet_ntop(AF_INET6, &rsa->sin6.sin6_addr, addr, sizeof addr); 112321936Shselasky break; 113321936Shselasky default: 114321936Shselasky addr[0] = '\0'; 115321936Shselasky break; 116321936Shselasky } 117321936Shselasky 118321936Shselasky return addr; 119321936Shselasky} 120321936Shselasky 121321936Shselaskystatic size_t _recv(int rs, char *msg, size_t len) 122321936Shselasky{ 123321936Shselasky size_t ret, offset; 124321936Shselasky 125321936Shselasky for (offset = 0; offset < len; offset += ret) { 126321936Shselasky ret = rrecv(rs, msg + offset, len - offset, 0); 127321936Shselasky if (ret <= 0) 128321936Shselasky return ret; 129321936Shselasky } 130321936Shselasky 131321936Shselasky return len; 132321936Shselasky} 133321936Shselasky 134321936Shselaskystatic int msg_recv_hdr(int rs, struct msg_hdr *hdr) 135321936Shselasky{ 136321936Shselasky int ret; 137321936Shselasky 138321936Shselasky ret = _recv(rs, (char *) hdr, sizeof *hdr); 139321936Shselasky if (ret != sizeof *hdr) 140321936Shselasky return -1; 141321936Shselasky 142321936Shselasky if (hdr->version || hdr->len < sizeof *hdr) { 143321936Shselasky printf("invalid version %d or length %d\n", 144321936Shselasky hdr->version, hdr->len); 145321936Shselasky return -1; 146321936Shselasky } 147321936Shselasky 148321936Shselasky return sizeof *hdr; 149321936Shselasky} 150321936Shselasky 151321936Shselaskystatic int msg_get_resp(int rs, struct msg_hdr *msg, uint8_t cmd) 152321936Shselasky{ 153321936Shselasky int ret; 154321936Shselasky 155321936Shselasky ret = msg_recv_hdr(rs, msg); 156321936Shselasky if (ret != sizeof *msg) 157321936Shselasky return ret; 158321936Shselasky 159321936Shselasky if ((msg->len != sizeof *msg) || (msg->command != (cmd | CMD_RESP))) { 160321936Shselasky printf("invalid length %d or bad command response %x:%x\n", 161321936Shselasky msg->len, msg->command, cmd | CMD_RESP); 162321936Shselasky return -1; 163321936Shselasky } 164321936Shselasky 165321936Shselasky return msg->data; 166321936Shselasky} 167321936Shselasky 168321936Shselaskystatic void msg_send_resp(int rs, struct msg_hdr *msg, uint32_t status) 169321936Shselasky{ 170321936Shselasky struct msg_hdr resp; 171321936Shselasky 172321936Shselasky resp.version = 0; 173321936Shselasky resp.command = msg->command | CMD_RESP; 174321936Shselasky resp.len = sizeof resp; 175321936Shselasky resp.data = status; 176321936Shselasky resp.id = msg->id; 177321936Shselasky rsend(rs, (char *) &resp, sizeof resp, 0); 178321936Shselasky} 179321936Shselasky 180321936Shselaskystatic int server_listen(void) 181321936Shselasky{ 182321936Shselasky struct addrinfo hints, *res; 183321936Shselasky int ret, rs; 184321936Shselasky 185321936Shselasky memset(&hints, 0, sizeof hints); 186321936Shselasky hints.ai_flags = RAI_PASSIVE; 187321936Shselasky ret = getaddrinfo(NULL, port, &hints, &res); 188321936Shselasky if (ret) { 189321936Shselasky printf("getaddrinfo failed: %s\n", gai_strerror(ret)); 190321936Shselasky return ret; 191321936Shselasky } 192321936Shselasky 193321936Shselasky rs = rsocket(res->ai_family, res->ai_socktype, res->ai_protocol); 194321936Shselasky if (rs < 0) { 195321936Shselasky perror("rsocket failed\n"); 196321936Shselasky ret = rs; 197321936Shselasky goto free; 198321936Shselasky } 199321936Shselasky 200321936Shselasky ret = 1; 201321936Shselasky ret = rsetsockopt(rs, SOL_SOCKET, SO_REUSEADDR, &ret, sizeof ret); 202321936Shselasky if (ret) { 203321936Shselasky perror("rsetsockopt failed"); 204321936Shselasky goto close; 205321936Shselasky } 206321936Shselasky 207321936Shselasky ret = rbind(rs, res->ai_addr, res->ai_addrlen); 208321936Shselasky if (ret) { 209321936Shselasky perror("rbind failed"); 210321936Shselasky goto close; 211321936Shselasky } 212321936Shselasky 213321936Shselasky ret = rlisten(rs, 1); 214321936Shselasky if (ret) { 215321936Shselasky perror("rlisten failed"); 216321936Shselasky goto close; 217321936Shselasky } 218321936Shselasky 219321936Shselasky ret = rs; 220321936Shselasky goto free; 221321936Shselasky 222321936Shselaskyclose: 223321936Shselasky rclose(rs); 224321936Shselaskyfree: 225321936Shselasky freeaddrinfo(res); 226321936Shselasky return ret; 227321936Shselasky} 228321936Shselasky 229321936Shselaskystatic int server_open(int rs, struct msg_hdr *msg) 230321936Shselasky{ 231321936Shselasky char *path = NULL; 232321936Shselasky int ret, len; 233321936Shselasky 234321936Shselasky printf("opening: "); 235321936Shselasky fflush(NULL); 236321936Shselasky if (file_addr || fd > 0) { 237321936Shselasky printf("cannot open another file\n"); 238321936Shselasky ret = EBUSY; 239321936Shselasky goto out; 240321936Shselasky } 241321936Shselasky 242321936Shselasky len = msg->len - sizeof *msg; 243321936Shselasky path = malloc(len); 244321936Shselasky if (!path) { 245321936Shselasky printf("cannot allocate path name\n"); 246321936Shselasky ret = ENOMEM; 247321936Shselasky goto out; 248321936Shselasky } 249321936Shselasky 250321936Shselasky ret = _recv(rs, path, len); 251321936Shselasky if (ret != len) { 252321936Shselasky printf("error receiving path\n"); 253321936Shselasky goto out; 254321936Shselasky } 255321936Shselasky 256321936Shselasky printf("%s, ", path); 257321936Shselasky fflush(NULL); 258321936Shselasky fd = open(path, O_RDWR | O_CREAT | O_TRUNC, msg->data); 259321936Shselasky if (fd < 0) { 260321936Shselasky printf("unable to open destination file\n"); 261321936Shselasky ret = errno; 262321936Shselasky } 263321936Shselasky 264321936Shselasky ret = 0; 265321936Shselaskyout: 266321936Shselasky if (path) 267321936Shselasky free(path); 268321936Shselasky 269321936Shselasky msg_send_resp(rs, msg, ret); 270321936Shselasky return ret; 271321936Shselasky} 272321936Shselasky 273321936Shselaskystatic void server_close(int rs, struct msg_hdr *msg) 274321936Shselasky{ 275321936Shselasky printf("closing..."); 276321936Shselasky fflush(NULL); 277321936Shselasky msg_send_resp(rs, msg, 0); 278321936Shselasky 279321936Shselasky if (file_addr) { 280321936Shselasky munmap(file_addr, bytes); 281321936Shselasky file_addr = NULL; 282321936Shselasky } 283321936Shselasky 284321936Shselasky if (fd > 0) { 285321936Shselasky close(fd); 286321936Shselasky fd = 0; 287321936Shselasky } 288321936Shselasky printf("done\n"); 289321936Shselasky} 290321936Shselasky 291321936Shselaskystatic int server_write(int rs, struct msg_hdr *msg) 292321936Shselasky{ 293321936Shselasky size_t len; 294321936Shselasky int ret; 295321936Shselasky 296321936Shselasky printf("transferring"); 297321936Shselasky fflush(NULL); 298321936Shselasky if (fd <= 0) { 299321936Shselasky printf("...file not opened\n"); 300321936Shselasky ret = EINVAL; 301321936Shselasky goto out; 302321936Shselasky } 303321936Shselasky 304321936Shselasky if (msg->len != sizeof(struct msg_write)) { 305321936Shselasky printf("...invalid message length %d\n", msg->len); 306321936Shselasky ret = EINVAL; 307321936Shselasky goto out; 308321936Shselasky } 309321936Shselasky 310321936Shselasky ret = _recv(rs, (char *) &bytes, sizeof bytes); 311321936Shselasky if (ret != sizeof bytes) 312321936Shselasky goto out; 313321936Shselasky 314321936Shselasky ret = ftruncate(fd, bytes); 315321936Shselasky if (ret) 316321936Shselasky goto out; 317321936Shselasky 318321936Shselasky file_addr = mmap(NULL, bytes, PROT_WRITE, MAP_SHARED, fd, 0); 319321936Shselasky if (file_addr == (void *) -1) { 320321936Shselasky printf("...error mapping file\n"); 321321936Shselasky ret = errno; 322321936Shselasky goto out; 323321936Shselasky } 324321936Shselasky 325321936Shselasky printf("...%lld bytes...", (long long) bytes); 326321936Shselasky fflush(NULL); 327321936Shselasky len = _recv(rs, file_addr, bytes); 328321936Shselasky if (len != bytes) { 329321936Shselasky printf("...error receiving data\n"); 330321936Shselasky ret = (int) len; 331321936Shselasky } 332321936Shselaskyout: 333321936Shselasky msg_send_resp(rs, msg, ret); 334321936Shselasky return ret; 335321936Shselasky} 336321936Shselasky 337321936Shselaskystatic void server_process(int rs) 338321936Shselasky{ 339321936Shselasky struct msg_hdr msg; 340321936Shselasky int ret; 341321936Shselasky 342321936Shselasky do { 343321936Shselasky ret = msg_recv_hdr(rs, &msg); 344321936Shselasky if (ret != sizeof msg) 345321936Shselasky break; 346321936Shselasky 347321936Shselasky switch (msg.command) { 348321936Shselasky case CMD_OPEN: 349321936Shselasky ret = server_open(rs, &msg); 350321936Shselasky break; 351321936Shselasky case CMD_CLOSE: 352321936Shselasky server_close(rs, &msg); 353321936Shselasky ret = 0; 354321936Shselasky break; 355321936Shselasky case CMD_WRITE: 356321936Shselasky ret = server_write(rs, &msg); 357321936Shselasky break; 358321936Shselasky default: 359321936Shselasky msg_send_resp(rs, &msg, EINVAL); 360321936Shselasky ret = -1; 361321936Shselasky break; 362321936Shselasky } 363321936Shselasky 364321936Shselasky } while (!ret); 365321936Shselasky} 366321936Shselasky 367321936Shselaskystatic int server_run(void) 368321936Shselasky{ 369321936Shselasky int lrs, rs; 370321936Shselasky union rsocket_address rsa; 371321936Shselasky socklen_t len; 372321936Shselasky 373321936Shselasky lrs = server_listen(); 374321936Shselasky if (lrs < 0) 375321936Shselasky return lrs; 376321936Shselasky 377321936Shselasky while (1) { 378321936Shselasky len = sizeof rsa; 379321936Shselasky printf("waiting for connection..."); 380321936Shselasky fflush(NULL); 381321936Shselasky rs = raccept(lrs, &rsa.sa, &len); 382321936Shselasky 383321936Shselasky printf("client: %s\n", _ntop(&rsa)); 384321936Shselasky server_process(rs); 385321936Shselasky 386321936Shselasky rshutdown(rs, SHUT_RDWR); 387321936Shselasky rclose(rs); 388321936Shselasky } 389321936Shselasky return 0; 390321936Shselasky} 391321936Shselasky 392321936Shselaskystatic int client_connect(void) 393321936Shselasky{ 394321936Shselasky struct addrinfo *res; 395321936Shselasky int ret, rs; 396321936Shselasky 397321936Shselasky ret = getaddrinfo(dst_addr, port, NULL, &res); 398321936Shselasky if (ret) { 399321936Shselasky printf("getaddrinfo failed: %s\n", gai_strerror(ret)); 400321936Shselasky return ret; 401321936Shselasky } 402321936Shselasky 403321936Shselasky rs = rsocket(res->ai_family, res->ai_socktype, res->ai_protocol); 404321936Shselasky if (rs < 0) { 405321936Shselasky perror("rsocket failed\n"); 406321936Shselasky goto free; 407321936Shselasky } 408321936Shselasky 409321936Shselasky ret = rconnect(rs, res->ai_addr, res->ai_addrlen); 410321936Shselasky if (ret) { 411321936Shselasky perror("rconnect failed\n"); 412321936Shselasky rclose(rs); 413321936Shselasky rs = ret; 414321936Shselasky } 415321936Shselasky 416321936Shselaskyfree: 417321936Shselasky freeaddrinfo(res); 418321936Shselasky return rs; 419321936Shselasky} 420321936Shselasky 421321936Shselaskystatic int client_open(int rs) 422321936Shselasky{ 423321936Shselasky struct msg_open *msg; 424321936Shselasky struct stat stats; 425321936Shselasky uint32_t len; 426321936Shselasky int ret; 427321936Shselasky 428321936Shselasky printf("opening..."); 429321936Shselasky fflush(NULL); 430321936Shselasky fd = open(src_file, O_RDONLY); 431321936Shselasky if (fd < 0) 432321936Shselasky return fd; 433321936Shselasky 434321936Shselasky ret = fstat(fd, &stats); 435321936Shselasky if (ret < 0) 436321936Shselasky goto err1; 437321936Shselasky 438321936Shselasky bytes = (uint64_t) stats.st_size; 439321936Shselasky file_addr = mmap(NULL, bytes, PROT_READ, MAP_SHARED, fd, 0); 440321936Shselasky if (file_addr == (void *) -1) { 441321936Shselasky ret = errno; 442321936Shselasky goto err1; 443321936Shselasky } 444321936Shselasky 445321936Shselasky len = (((uint32_t) strlen(dst_file)) + 8) & 0xFFFFFFF8; 446321936Shselasky msg = calloc(1, sizeof(*msg) + len); 447321936Shselasky if (!msg) { 448321936Shselasky ret = -1; 449321936Shselasky goto err2; 450321936Shselasky } 451321936Shselasky 452321936Shselasky msg->hdr.command = CMD_OPEN; 453321936Shselasky msg->hdr.len = sizeof(*msg) + len; 454321936Shselasky msg->hdr.data = (uint32_t) stats.st_mode; 455321936Shselasky strcpy(msg->path, dst_file); 456321936Shselasky ret = rsend(rs, msg, msg->hdr.len, 0); 457321936Shselasky if (ret != msg->hdr.len) 458321936Shselasky goto err3; 459321936Shselasky 460321936Shselasky ret = msg_get_resp(rs, &msg->hdr, CMD_OPEN); 461321936Shselasky if (ret) 462321936Shselasky goto err3; 463321936Shselasky 464321936Shselasky return 0; 465321936Shselasky 466321936Shselaskyerr3: 467321936Shselasky free(msg); 468321936Shselaskyerr2: 469321936Shselasky munmap(file_addr, bytes); 470321936Shselaskyerr1: 471321936Shselasky close(fd); 472321936Shselasky return ret; 473321936Shselasky} 474321936Shselasky 475321936Shselaskystatic int client_start_write(int rs) 476321936Shselasky{ 477321936Shselasky struct msg_write msg; 478321936Shselasky int ret; 479321936Shselasky 480321936Shselasky printf("transferring"); 481321936Shselasky fflush(NULL); 482321936Shselasky memset(&msg, 0, sizeof msg); 483321936Shselasky msg.hdr.command = CMD_WRITE; 484321936Shselasky msg.hdr.len = sizeof(msg); 485321936Shselasky msg.size = bytes; 486321936Shselasky 487321936Shselasky ret = rsend(rs, &msg, sizeof msg, 0); 488321936Shselasky if (ret != msg.hdr.len) 489321936Shselasky return ret; 490321936Shselasky 491321936Shselasky return 0; 492321936Shselasky} 493321936Shselasky 494321936Shselaskystatic int client_close(int rs) 495321936Shselasky{ 496321936Shselasky struct msg_hdr msg; 497321936Shselasky int ret; 498321936Shselasky 499321936Shselasky printf("closing..."); 500321936Shselasky fflush(NULL); 501321936Shselasky memset(&msg, 0, sizeof msg); 502321936Shselasky msg.command = CMD_CLOSE; 503321936Shselasky msg.len = sizeof msg; 504321936Shselasky ret = rsend(rs, (char *) &msg, msg.len, 0); 505321936Shselasky if (ret != msg.len) 506321936Shselasky goto out; 507321936Shselasky 508321936Shselasky ret = msg_get_resp(rs, &msg, CMD_CLOSE); 509321936Shselasky if (ret) 510321936Shselasky goto out; 511321936Shselasky 512321936Shselasky printf("done\n"); 513321936Shselaskyout: 514321936Shselasky munmap(file_addr, bytes); 515321936Shselasky close(fd); 516321936Shselasky return ret; 517321936Shselasky} 518321936Shselasky 519321936Shselaskystatic int client_run(void) 520321936Shselasky{ 521321936Shselasky struct msg_hdr ack; 522321936Shselasky int ret, rs; 523321936Shselasky size_t len; 524321936Shselasky 525321936Shselasky rs = client_connect(); 526321936Shselasky if (rs < 0) 527321936Shselasky return rs; 528321936Shselasky 529321936Shselasky ret = client_open(rs); 530321936Shselasky if (ret) 531321936Shselasky goto shutdown; 532321936Shselasky 533321936Shselasky ret = client_start_write(rs); 534321936Shselasky if (ret) 535321936Shselasky goto close; 536321936Shselasky 537321936Shselasky printf("..."); 538321936Shselasky fflush(NULL); 539321936Shselasky gettimeofday(&start, NULL); 540321936Shselasky len = rsend(rs, file_addr, bytes, 0); 541321936Shselasky if (len == bytes) 542321936Shselasky ret = msg_get_resp(rs, &ack, CMD_WRITE); 543321936Shselasky else 544321936Shselasky ret = (int) len; 545321936Shselasky 546321936Shselasky gettimeofday(&end, NULL); 547321936Shselasky 548321936Shselaskyclose: 549321936Shselasky client_close(rs); 550321936Shselaskyshutdown: 551321936Shselasky rshutdown(rs, SHUT_RDWR); 552321936Shselasky rclose(rs); 553321936Shselasky if (!ret) 554321936Shselasky show_perf(); 555321936Shselasky return ret; 556321936Shselasky} 557321936Shselasky 558321936Shselaskystatic void show_usage(char *program) 559321936Shselasky{ 560321936Shselasky printf("usage 1: %s [options]\n", program); 561321936Shselasky printf("\t starts the server application\n"); 562321936Shselasky printf("\t[-p port_number]\n"); 563321936Shselasky printf("usage 2: %s source server[:destination] [options]\n", program); 564321936Shselasky printf("\t source - file name and path\n"); 565321936Shselasky printf("\t server - name or address\n"); 566321936Shselasky printf("\t destination - file name and path\n"); 567321936Shselasky printf("\t[-p port_number]\n"); 568321936Shselasky exit(1); 569321936Shselasky} 570321936Shselasky 571321936Shselaskystatic void server_opts(int argc, char **argv) 572321936Shselasky{ 573321936Shselasky int op; 574321936Shselasky 575321936Shselasky while ((op = getopt(argc, argv, "p:")) != -1) { 576321936Shselasky switch (op) { 577321936Shselasky case 'p': 578321936Shselasky port = optarg; 579321936Shselasky break; 580321936Shselasky default: 581321936Shselasky show_usage(argv[0]); 582321936Shselasky } 583321936Shselasky } 584321936Shselasky} 585321936Shselasky 586321936Shselaskystatic void client_opts(int argc, char **argv) 587321936Shselasky{ 588321936Shselasky int op; 589321936Shselasky 590321936Shselasky if (argc < 3) 591321936Shselasky show_usage(argv[0]); 592321936Shselasky 593321936Shselasky src_file = argv[1]; 594321936Shselasky dst_addr = argv[2]; 595321936Shselasky dst_file = strchr(dst_addr, ':'); 596321936Shselasky if (dst_file) { 597321936Shselasky *dst_file = '\0'; 598321936Shselasky dst_file++; 599321936Shselasky } 600321936Shselasky if (!dst_file) 601321936Shselasky dst_file = src_file; 602321936Shselasky 603321936Shselasky while ((op = getopt(argc, argv, "p:")) != -1) { 604321936Shselasky switch (op) { 605321936Shselasky case 'p': 606321936Shselasky port = optarg; 607321936Shselasky break; 608321936Shselasky default: 609321936Shselasky show_usage(argv[0]); 610321936Shselasky } 611321936Shselasky } 612321936Shselasky 613321936Shselasky} 614321936Shselasky 615321936Shselaskyint main(int argc, char **argv) 616321936Shselasky{ 617321936Shselasky int ret; 618321936Shselasky 619321936Shselasky if (argc == 1 || argv[1][0] == '-') { 620321936Shselasky server_opts(argc, argv); 621321936Shselasky ret = server_run(); 622321936Shselasky } else { 623321936Shselasky client_opts(argc, argv); 624321936Shselasky ret = client_run(); 625321936Shselasky } 626321936Shselasky 627321936Shselasky return ret; 628321936Shselasky} 629