/* ** Copyright (C) 2004-2007 by Carnegie Mellon University. ** ** @OPENSOURCE_HEADER_START@ ** ** Use of the SILK system and related source code is subject to the terms ** of the following licenses: ** ** GNU Public License (GPL) Rights pursuant to Version 2, June 1991 ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.225-7013 ** ** NO WARRANTY ** ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE ** DELIVERABLES UNDER THIS LICENSE. ** ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie ** Mellon University, its trustees, officers, employees, and agents from ** all claims or demands made against them (and any related losses, ** expenses, or attorney's fees) arising out of, or relating to Licensee's ** and/or its sub licensees' negligent use or willful misuse of or ** negligent conduct or willful misconduct regarding the Software, ** facilities, or other rights or assistance granted by Carnegie Mellon ** University under this License, including, but not limited to, any ** claims of product liability, personal injury, death, damage to ** property, or violation of any laws or regulations. ** ** Carnegie Mellon University Software Engineering Institute authored ** documents are sponsored by the U.S. Department of Defense under ** Contract F19628-00-C-0003. Carnegie Mellon University retains ** copyrights in all material produced under this contract. The U.S. ** Government retains a non-exclusive, royalty-free license to publish or ** reproduce these documents, or allow others to do so, for U.S. ** Government purposes only pursuant to the copyright license under the ** contract clause at 252.227.7013. ** ** @OPENSOURCE_HEADER_END@ */ /* ** Implements sender and receiver clients ** */ #include "silk.h" RCSIDENT("$SiLK: skt-client.c 6070 2007-01-22 18:03:49Z mthomas $"); #include "skt-private.h" static sktErr_t client_connect(skTransfer_t transfer) { struct sockaddr_in addr; int s = -1; int waittime = 5; int rv; assert(transfer); assert(transfer->server); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = transfer->server->server; addr.sin_port = htons(transfer->server->port); rv = -1; while (!transfer->quit_control && rv == -1) { if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) { int saveerr = errno; if (transfer->logfn) { transfer->logfn("Could not allocate new socket for client"); } errno = saveerr; return SK_TRANSFER_ESYSTEM; } if ((rv = connect(s, (struct sockaddr *)&addr, sizeof(addr))) == -1) { struct timespec ts, nts; close(s); ts.tv_sec = waittime; ts.tv_nsec = 0; while (nanosleep(&ts, &nts)) { ts = nts; } if (waittime < 60) { waittime += 5; } } } if (rv == 0) { transfer->newsession = 1; transfer->newsession_sock = s; return SK_TRANSFER_ESUCCESS; } return SK_TRANSFER_EFAILED_CLOSE; } static void client_thread_callback(char *file, void *item, sktErr_t err, skTransfer_t transfer) { switch (err) { case SK_TRANSFER_ESUCCESS: case SK_TRANSFER_EFATAL: case SK_TRANSFER_ESHUTDOWN_EXTERNAL: /* Pass back to the user handler and continue */ if (transfer->subcallback) { transfer->subcallback(file, item, err, transfer); } return; case SK_TRANSFER_EFAILED: if (file && transfer->subcallback) { transfer->subcallback(file, item, err, transfer); } return; case SK_TRANSFER_EFATAL_CLOSE: /* Pass back to the user handler as non-closing and restart */ if (transfer->subcallback) { transfer->subcallback(file, item, SK_TRANSFER_EFATAL, transfer); } if (transfer->sock != -1) { close(transfer->sock); transfer->sock = -1; } if (client_connect(transfer) == SK_TRANSFER_ESYSTEM) { if (transfer->subcallback) { transfer->subcallback(NULL, NULL, SK_TRANSFER_ESYSTEM, transfer); } break; } return; case SK_TRANSFER_EFAILED_CLOSE: /* Pass back to the user handler as non-closing and stop */ if (transfer->subcallback) { transfer->subcallback(file, item, SK_TRANSFER_EFAILED, transfer); } if (transfer->sock != -1) { close(transfer->sock); transfer->sock = -1; } if (client_connect(transfer) == SK_TRANSFER_ESYSTEM) { if (transfer->subcallback) { transfer->subcallback(NULL, NULL, SK_TRANSFER_ESYSTEM, transfer); } break; } return; case SK_TRANSFER_ETIMEOUT: /* Pass back to the user handler and stop */ if (transfer->subcallback) { transfer->subcallback(file, item, err, transfer); } if (transfer->sock != -1) { close(transfer->sock); transfer->sock = -1; } if (client_connect(transfer) == SK_TRANSFER_ESYSTEM) { if (transfer->subcallback) { transfer->subcallback(NULL, NULL, SK_TRANSFER_ESYSTEM, transfer); } break; } return; case SK_TRANSFER_ESHUTDOWN: case SK_TRANSFER_EBADARG: /* Programming error */ assert(0); break; case SK_TRANSFER_ESYSTEM: case SK_TRANSFER_ESYSTEM_THREAD: /* Log and stop */ if (transfer->logfn) { transfer->logfn("System failure %s", strerror(errno)); } break; default: assert(0); } if (transfer->sock != -1) { close(transfer->sock); transfer->sock = -1; } transfer->quit_control = 1; } sktErr_t skCreateSenderClient( skTransfer_t *sender, /* returns sender handle */ int port, /* Port to connect to */ in_addr_t saddr /* server address */ ) { sktErr_t err = SK_TRANSFER_EBADARG; sk_transfer_server_t *server = (sk_transfer_server_t *)malloc(sizeof(sk_transfer_server_t)); if (server == NULL) { return SK_TRANSFER_ESYSTEM; } server->port = port; server->num_valid_clients = 0; server->valid_clients = NULL; server->server = saddr; server->maxclients = 0; err = skCreateTransfer(sender, sender_thread, -1, NULL, skt_filename_identity, NULL, SKT_DEFAULT_ACK, SKT_DEFAULT_BAUD, NULL, client_connect, client_thread_callback, NULL, server, NULL, NULL, NULL); if (err != SK_TRANSFER_ESUCCESS) { free(server); } return err; } sktErr_t skCreateReceiverClient( skTransfer_t *rcvr, /* returns rcvr handle */ int port, /* Port to connect to */ in_addr_t saddr, /* server address */ const char* where /* Where to place files */ ) { sktErr_t err = SK_TRANSFER_EBADARG; sk_transfer_server_t *server = (sk_transfer_server_t *)malloc(sizeof(sk_transfer_server_t)); if (server == NULL) { return SK_TRANSFER_ESYSTEM; } server->port = port; server->num_valid_clients = 0; server->valid_clients = NULL; server->server = saddr; server->maxclients = 0; err = skCreateTransfer(rcvr, receiver_thread, -1, NULL, NULL, skt_filename_xform_identity, SKT_DEFAULT_ACK, SKT_DEFAULT_BAUD, where, NULL, client_thread_callback, NULL, server, NULL, NULL, NULL); if (err != SK_TRANSFER_ESUCCESS) { free(server); } return err; } /* ** Local variables: ** mode:c ** indent-tabs-mode:nil ** c-basic-offset:4 ** End: */