/*PAGE * * data_socket * * Create data socket for session. * * Input parameters: * info - corresponding SessionInfo structure * * Output parameters: * returns socket descriptor, or -1 if failure * */ static int data_socket(FTPD_SessionInfo_t *info) { int s = info->pasv_socket; if(0 > s) { int on = 1; s = socket(PF_INET, SOCK_STREAM, 0); if(0 > s) send_reply(info, 425, "Can't create data socket."); else if(0 > setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) { close_socket(s); s = -1; } else { struct sockaddr_in data_source; int tries; /* anchor socket to avoid multi-homing problems */ data_source = info->ctrl_addr; data_source.sin_port = htons(20); /* ftp-data port */ for(tries = 1; tries < 10; ++tries) { errno = 0; if(bind(s, (struct sockaddr *)&data_source, sizeof(data_source)) >= 0) break; if (errno != EADDRINUSE) tries = 10; else rtems_task_wake_after(tries * 10); } if(tries >= 10) { send_reply(info, 425, "Can't bind data socket."); close_socket(s); s = -1; } else { struct sockaddr_in *data_dest = (info->use_default) ? &info->def_addr : &info->data_addr; if(0 > connect(s, (struct sockaddr *)data_dest, sizeof(*data_dest))) { send_reply(info, 425, "Can't connect data socket."); close_socket(s); s = -1; } } } } info->data_socket = s; info->use_default = 1; if(s >= 0) set_socket_timeout(s, info->idle); return s; }
/*PAGE * * command_pasv * * Handle FTP PASV command. * Open socket, listen for and accept connection on it. * * Input parameters: * info - corresponding SessionInfo structure * * Output parameters: * info->pasv_socket is set to the descriptor of the data socket */ static void command_pasv(FTPD_SessionInfo_t *info) { int s = -1; int err = 1; close_data_socket(info); s = socket(PF_INET, SOCK_STREAM, 0); if (s < 0) syslog(LOG_ERR, "ftpd: Error creating PASV socket: %s", serr()); else { struct sockaddr_in addr; socklen_t addrLen = sizeof(addr); addr = info->ctrl_addr; addr.sin_port = htons(0); if (0 > bind(s, (struct sockaddr *)&addr, addrLen)) syslog(LOG_ERR, "ftpd: Error binding PASV socket: %s", serr()); else if (0 > listen(s, 1)) syslog(LOG_ERR, "ftpd: Error listening on PASV socket: %s", serr()); else if(set_socket_timeout(s, info->idle)) { char buf[FTPD_BUFSIZE]; unsigned char const *ip, *p; getsockname(s, (struct sockaddr *)&addr, &addrLen); ip = (unsigned char const*)&(addr.sin_addr); p = (unsigned char const*)&(addr.sin_port); snprintf(buf, FTPD_BUFSIZE, "Entering passive mode (%u,%u,%u,%u,%u,%u).", ip[0], ip[1], ip[2], ip[3], p[0], p[1]); send_reply(info, 227, buf); info->pasv_socket = accept(s, (struct sockaddr *)&addr, &addrLen); if (0 > info->pasv_socket) syslog(LOG_ERR, "ftpd: Error accepting PASV connection: %s", serr()); else { close_socket(s); s = -1; err = 0; } } } if(err) { /* (OSV) The note is from FreeBSD FTPD. * Note: a response of 425 is not mentioned as a possible response to * the PASV command in RFC959. However, it has been blessed as a * legitimate response by Jon Postel in a telephone conversation * with Rick Adams on 25 Jan 89. */ send_reply(info, 425, "Can't open passive connection."); close_socket(s); } }
static int network_set_timeout(struct iio_context *ctx, unsigned int timeout) { int ret = set_socket_timeout(ctx->pdata->fd, timeout); if (!ret) { timeout = calculate_remote_timeout(timeout); ret = set_remote_timeout(ctx, timeout); } if (ret < 0) { char buf[1024]; iio_strerror(-ret, buf, sizeof(buf)); WARNING("Unable to set R/W timeout: %s\n", buf); } else { ctx->rw_timeout_ms = timeout; } return ret; }
static int create_socket(const struct addrinfo *addrinfo) { struct timeval timeout; int fd, yes = 1; timeout.tv_sec = DEFAULT_TIMEOUT_MS / 1000; timeout.tv_usec = (DEFAULT_TIMEOUT_MS % 1000) * 1000; fd = do_connect(addrinfo, &timeout); if (fd < 0) return fd; set_socket_timeout(fd, DEFAULT_TIMEOUT_MS); setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char *) &yes, sizeof(yes)); return fd; }
int main(int argc, char **argv) { if (argc < 5) { printf("\n\tUsage: %s <filepath> <host> <port> <tcp|udp>\n\n", argv[0]); return 0; } char *filepath = argv[1]; char *host = argv[2]; char *port = argv[3]; char *protocol = argv[4]; int (*send_file_routine) (char *, int); if (!strcmp(protocol, "tcp")) send_file_routine = send_file_tcp; else if (!strcmp(protocol, "udp")) send_file_routine = send_file_udp; else { fprintf(stderr, "Invalid protocol specified.\n"); return 0; } int socket_descriptor = create_socket(protocol); if (socket_descriptor == -1) { perror("create_socket() error"); return 0; } if (connect_socket(socket_descriptor, host, atoi(port)) == -1) { perror("connect_socket() error"); close(socket_descriptor); return 0; } set_socket_timeout(socket_descriptor, 15); if (send_file_routine(filepath, socket_descriptor) == -1) perror("send_file() error"); close(socket_descriptor); return 0; }
static rtems_task osc_task(rtems_task_argument argument) { int r; socklen_t slen; char buf[1024]; lop_server server; server = lop_server_new(error_handler, send_handler, NULL); assert(server != NULL); lop_server_add_method(server, "/midi", "m", midi_method, NULL); lop_server_add_method(server, "/patch", "i", patch_method, NULL); lop_server_add_method(server, "/variable", "if", variable_method, NULL); lop_server_add_method(server, "/osd", "s", osd_method, NULL); udpsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if(udpsocket == -1) { printf("Unable to create socket for OSC server\n"); return; } memset((char *)&local, 0, sizeof(struct sockaddr_in)); local.sin_family = AF_INET; local.sin_port = htons(4444); local.sin_addr.s_addr = htonl(INADDR_ANY); r = bind(udpsocket, (struct sockaddr *)&local, sizeof(struct sockaddr_in)); if(r == -1) { printf("Unable to bind socket for OSC server\n"); close(udpsocket); return; } while(1) { set_socket_timeout(udpsocket, ((double)1000000.0)*lop_server_next_event_delay(server)); slen = sizeof(struct sockaddr_in); r = recvfrom(udpsocket, buf, 1024, 0, (struct sockaddr *)&remote, &slen); if(r > 0) lop_server_dispatch_data(server, buf, r); else lop_server_dispatch_data(server, NULL, 0); } }
int main(int argc, char *argv[]) { void *context = NULL; void *sender = NULL; FILE *fp = NULL; char line[1024]; if (argc <= 1) { printf("provide a file\n"); return ERROR; } if (access(argv[1], F_OK) == -1 ) { printf("%s file does not exist\n", argv[1]); return ERROR; } fp = fopen(argv[1], "r"); if (fp == NULL) { printf("unable to open %s\n", argv[1]); return ERROR; } context = zmq_ctx_new(); sender = zmq_socket(context, ZMQ_PUSH); set_socket_timeout(sender); zmq_bind(sender, VENTBIND); while(fgets(line, sizeof(line), fp)) { if (line[0] == '#') continue; if (s_send(sender, line) < 0) perror("s_send"); } fclose(fp); zmq_close(sender); zmq_ctx_destroy(context); return OK; }
/*********************************************** Method: udp_rdt_send_pkt Description: Send packet across the socket ***********************************************/ int udp_rdt_send_pkt ( int sock_fd, /* Socket descriptor */ udp_rdt_pkt_t * pkt, /* Packet to tx */ void * to, /* Sockaddr info */ socklen_t to_len, /* to length */ int timeout_us /* Timeout */ ) { int ret_val; /*---------------------------------------- Validate input params ----------------------------------------*/ if( pkt == NULL || to == NULL ) return -1; set_socket_timeout(sock_fd, timeout_us, 1); /*---------------------------------------- Send the packet over the socket ----------------------------------------*/ ret_val = sendto ( sock_fd, pkt, sizeof( udp_rdt_pkt_t ), 0, (struct sockaddr *) to, to_len ); /*---------------------------------------- Return to caller that there was a timeout ----------------------------------------*/ if( ( ret_val < 0 ) && ( errno == EAGAIN || errno == EWOULDBLOCK ) ) { ret_val = UDP_RDT_ERR_TIMEOUT; } return ret_val; }
void send_stats_from_thread(struct stats stats) { unsigned int sock_len; struct sockaddr_un ipc_socket; int s; // Create the socket to send the details back on s = socket( AF_UNIX, SOCK_DGRAM, 0); if ( s == INVALID_SOCKET ) { fprintf(stderr, "%s:%d socket() error (%d) %s\n", __FILE__, __LINE__, ERRNO, strerror(ERRNO) ); return; } if ( set_socket_timeout(s, IPC_TIMEOUT) ) { fprintf(stderr, "%s:%d set_socket_timeout() error (%d) %s\n", __FILE__, __LINE__, ERRNO, strerror(ERRNO) ); goto cleanup; } ipc_socket.sun_family = AF_UNIX; //strcpy(ipc_socket.sun_path, IPC_SOCK_NAME); sprintf(ipc_socket.sun_path , "%s", ipc_sock_name); sock_len = strlen(ipc_socket.sun_path) + sizeof(ipc_socket.sun_family); // Bind the IPC SOCKET if ( connect( s,(struct sockaddr *) &ipc_socket, sock_len) == SOCKET_ERROR) { fprintf(stderr, "%s:%d connect() error (%d) %s\n", __FILE__, __LINE__, ERRNO, strerror(ERRNO)); goto cleanup; } if ( send_results(s, &stats) ) { fprintf(stderr, "%s:%d send_results() error (%d) %s\n", __FILE__, __LINE__, ERRNO, strerror(ERRNO) ); goto cleanup; } cleanup: closesocket(s); }
static int create_socket(const struct addrinfo *addrinfo) { struct timeval timeout; int ret, fd, yes = 1; #ifdef _WIN32 SOCKET s = socket(addrinfo->ai_family, addrinfo->ai_socktype, 0); fd = (s == INVALID_SOCKET) ? -1 : (int) s; if (fd < 0) return -WSAGetLastError(); #else fd = socket(addrinfo->ai_family, addrinfo->ai_socktype, 0); if (fd < 0) return -errno; #endif timeout.tv_sec = DEFAULT_TIMEOUT_MS / 1000; timeout.tv_usec = (DEFAULT_TIMEOUT_MS % 1000) * 1000; #ifndef _WIN32 ret = do_connect(fd, addrinfo->ai_addr, addrinfo->ai_addrlen, &timeout); if (ret < 0) ret = -errno; #else ret = connect(fd, addrinfo->ai_addr, (int) addrinfo->ai_addrlen); if (ret == SOCKET_ERROR) ret = -WSAGetLastError(); #endif if (ret < 0) { close(fd); return ret; } set_socket_timeout(fd, DEFAULT_TIMEOUT_MS); setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char *) &yes, sizeof(yes)); return fd; }
SOCKET create_stats_socket() { struct sockaddr_un ipc_socket; int sock_len; // Create the socket to receive the stats data SOCKET s = socket( AF_UNIX, SOCK_DGRAM, 0); if ( s == INVALID_SOCKET ) { fprintf(stderr, "%s:%d socket() error (%d) %s\n", __FILE__, __LINE__, ERRNO, strerror(ERRNO) ); return SOCKET_ERROR; } if ( set_socket_timeout(s, IPC_TIMEOUT) ) { fprintf(stderr, "%s:%d set_socket_timeout() error (%d) %s\n", __FILE__, __LINE__, ERRNO, strerror(ERRNO) ); goto cleanup; } ipc_socket.sun_family = AF_UNIX; ipc_sock_name = tempnam(NULL, "threadnetperf"); sprintf(ipc_socket.sun_path, "%s", ipc_sock_name); sock_len = strlen(ipc_socket.sun_path) + sizeof(ipc_socket.sun_family); unlink(ipc_socket.sun_path); // Bind the IPC SOCKET if ( bind( s, &ipc_socket, sock_len) == SOCKET_ERROR) { fprintf(stderr, "%s:%d bind() error (%d) %s\n", __FILE__, __LINE__, ERRNO, strerror(ERRNO) ); goto cleanup; } return s; cleanup: unlink(ipc_sock_name); closesocket(s); return SOCKET_ERROR; }
int connect_connections(const struct settings *settings, const struct client_request * req, SOCKET *client, unsigned int *clients) { const struct client_request_details * details = req->details; // Loop all the client requests for this thread while (details != NULL) { unsigned int i = details->n; if (settings->verbose) { char addr[NI_MAXHOST + NI_MAXSERV + 1]; // Print the host/port addr_to_ipstr((const struct sockaddr *)&details->addr, details->addr_len, addr, sizeof(addr)); printf(" Core %d: Connecting %d client%s to %s\n", req->cores, details->n, details->n > 1 ? "s" : "", addr); } // Connect all the clients while (i > 0) { int send_socket_size, recv_socket_size; SOCKET s = socket( AF_INET, settings->type, settings->protocol); if (s == INVALID_SOCKET) { fprintf(stderr, "%s:%d socket() error (%d) %s\n", __FILE__, __LINE__, ERRNO, strerror(ERRNO)); return -1; } #ifndef WIN32 #ifndef USE_EPOLL // In GNU world, a socket can't be >= FD_SETSIZE, otherwise it can't be placed into a set if ( s >= FD_SETSIZE ) { fprintf(stderr, "%s:%d socket() value too large for fd_set (%d >= %d)\n", __FILE__, __LINE__, s, FD_SETSIZE ); return -1; } #endif #endif send_socket_size = set_socket_send_buffer(s, settings->socket_size); if (send_socket_size < 0) { fprintf(stderr, "%s:%d set_socket_send_buffer() error (%d) %s\n", __FILE__, __LINE__, ERRNO, strerror(ERRNO)); goto cleanup; } recv_socket_size = set_socket_recv_buffer(s, settings->socket_size); if (recv_socket_size < 0) { fprintf(stderr, "%s:%d set_socket_recv_buffer() error (%d) %s\n", __FILE__, __LINE__, ERRNO, strerror(ERRNO)); goto cleanup; } if (settings->verbose) { // TODO tidy this printf("client socket size: %d/%d\n", send_socket_size, recv_socket_size); } if (settings->disable_nagles) { if (disable_nagle(s) == SOCKET_ERROR) { fprintf(stderr, "%s:%d disable_nagle() error (%d) %s\n", __FILE__, __LINE__, ERRNO, strerror(ERRNO)); goto cleanup; } // This works around a big where disabling Nagle's does not actually stop packets being grouped // I don't think its a bug, more that stack notices there are multiple packets queued that // haven't been sent yet, so optimistically groups them. if ( enable_maxseq ( s , settings->message_size ) == SOCKET_ERROR ) { fprintf(stderr, "%s:%d enable_maxseq() error (%d) %s\n", __FILE__, __LINE__, ERRNO, strerror(ERRNO)); goto cleanup; } } if (set_socket_timeout(s, CONTROL_TIMEOUT) ) { fprintf(stderr, "%s:%d set_socket_timeout() error (%d) %s\n", __FILE__, __LINE__, ERRNO, strerror(ERRNO)); goto cleanup; } if (connect_ign_signal(s, (const struct sockaddr *)&details->addr, (int)details->addr_len ) == SOCKET_ERROR) { fprintf(stderr, "%s:%d connect() error (%d) %s\n", __FILE__, __LINE__, ERRNO, strerror(ERRNO)); goto cleanup; } // Always disable blocking (to work around linux bug) if (disable_blocking(s) == SOCKET_ERROR) { fprintf(stderr, "%s:%d disable_blocking() error (%d) %s\n", __FILE__, __LINE__, ERRNO, strerror(ERRNO)); goto cleanup; } assert ( s != INVALID_SOCKET ); assert ( *client == INVALID_SOCKET ); *client++ = s; // Add socket s to the end of the array and move along (*clients)++; // Increment the count of clients i--; continue; cleanup: // This cleanup section is within the loop so we can cleanup s closesocket(s); return -1; } // move onto the next client request details = details->next; } return 0; }
/****************************************************************************** Zjisteni pritomnosti rozsireni, pripadne zpracovani parametru *******************************************************************************/ int Client::opt_extension(char *message, int numbytes, Opt *options, File *f) { int zero_count = 0; int pos = 0; int opt_num = 0; int opt_len = 0; string option; string value; for(int i=2; i<numbytes; i++) {// spocitat vsechny oddelovace if(message[i] == '\0') { zero_count++; if(zero_count == 2) pos = i; } } if(zero_count > 2) {// i s options opt_num = (zero_count-2)/2; for(int i=0; i<opt_num; i++) { // ulozeni nazvu option do stringu option = message + pos + 1; opt_len = option.length(); // ulozim si jeho delku pos = pos + opt_len + 1; // nastavim novou pozici nuly // ulozeni hodnoty option do stringu value = message + pos + 1; pos = pos + value.length() + 1; // zmenit vsechny pismena na male for(int i=0; i<opt_len; i++) if(isupper(option[i])) option[i] = tolower(option[i]); if(!(option.compare("blksize"))) { // prevod ze stringu na int block_size.value = stoi(value); if(options->block_size() == 0) {// nebyla zadana velikost bloku pri spusteni, nastavi se max. velikost dle MTU if(block_size.value > (mtu_size - HEADERS)) block_size.value = mtu_size - HEADERS; else if(block_size.value < MIN_BLOCK_SIZE) block_size.value = MIN_BLOCK_SIZE; } else {// Byla zadana velikost bloku pri spusteni, musi se porovnat s ni if(block_size.value > options->block_size()) block_size.value = options->block_size(); else if(block_size.value < MIN_BLOCK_SIZE) block_size.value = MIN_BLOCK_SIZE; } block_size.used = true; extension = true; } else if(!(option.compare("timeout"))) { client_timeout.value = stoi(value); if(options->max_timeout() > 0) {// Byl zadan max. timeout pri spusteni if(client_timeout.value <= options->max_timeout()) {// Pozadovana hodnota je mensi nebo rovna nastavenemu limitu set_socket_timeout(options, client_timeout.value); client_timeout.used = true; extension = true; } } else {// Nebyl zadan if(client_timeout.value <= IMPLICIT_TIMEOUT) {// Pozadovana hodnota je mensi nebo rovna implicitnimu limitu set_socket_timeout(options, client_timeout.value); client_timeout.used = true; extension = true; } } } else if(!(option.compare("tsize"))) { transport_size.value = stoi(value); if(transport_size.value == 0) {// je to RRQ paket, oznami se velikost souboru transport_size.value = f->get_file_size(); } else {// WRQ paket, server by mel zkontrolovat volne misto a pripadne prerusit prenos transport_size.value = stoi(value); } transport_size.used = true; extension = true; } } if(extension == true) return EXTENSION; // aspon jeden option byl rozpoznan else return STANDARD; // options byly, ale server je nezna, takze je nebude uvazovat } else return STANDARD; // bez options }
/****************************************************************************** Start obsluhy klienta Inspirace (vytvoreni socketu, bind): http://beej.us/guide/bgnet/output/html/multipage/clientserver.html#datagram *******************************************************************************/ int Client::start(Opt *options, struct sockaddr_storage client_addr, int index, char *buf, int numbytes, int mtu) { // Generovani nahodneho cisla pro port, na kterem bude klient obsluhovan srand (getpid()); int port = rand() % MAX_PORT + MIN_PORT; client_port = to_string(port); service_ip = options->address_at(index); int sockfd; struct addrinfo hints, *servinfo, *p; int rv; socklen_t addr_len; char s[INET6_ADDRSTRLEN]; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; signal(SIGINT, client_signal_reaction); // Registrace funkce pro odchyt signalu if ((rv = getaddrinfo(service_ip.c_str(), client_port.c_str(), &hints, &servinfo)) != 0) { cerr << "Error - Service " << service_ip << ", " << client_port << gai_strerror(rv) << endl; return EXIT_FAILURE; } for(p = servinfo; p != NULL; p = p->ai_next) { if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { continue; } if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { close(sockfd); continue; } break; } if (p == NULL) { cerr << "Error - Service " << service_ip << ", " << client_port << " - failed to bind socket" << endl; return EXIT_FAILURE; } freeaddrinfo(servinfo); client_socket = sockfd; // Ulozim si deskr. socketu // Nastavi se vychozi timeout socketu if((set_socket_timeout(options, IMPLICIT_TIMEOUT)) == SET_FAILED) return EXIT_FAILURE; // ulozim si klientovu IP pro potreby vypisu informacnich hlasek string client_ip = inet_ntop(client_addr.ss_family, get_in_addr((struct sockaddr *)&client_addr), s, sizeof s); mtu_size = mtu; // Ulozim si MTU // Cinnost obsluhy serveru string err_msg; unsigned int data_counter = 0; // Pocitadlo dat unsigned int block_counter = 0; // Pocitadlo bloku int data_len; // Pocet odeslanych B int mode; // Mod prenosu int tryouts = 0; // Pocet pokusu o znovu navazani komunikace bool reading_data = false; // Flag cteni dat bool writing_data = false; // Flag zapisu dat int ack; // Cislo potvrzeneho bloku int type; // Typ paketu int file_status; // Info o uspesnosti operace se souborem int bytes_write; // Pocet zapsanych bajtu int block_num; // Cislo bloku int recv_status; // Pocet prijatych B pri volani funkce recvfrom() char *file_buf; // Buffer pro nacitani dat ze souboru int file_buf_size;// Velikost bufferu File *f = new File(); // Nova instance objektu pro praci se soubory while(1) {// Smycka obsluhy klienta if(writing_data == true) type = packet_type(file_buf); // buffer na heapu else type = packet_type(buf); // buffer na zasobniku switch(type) {// Podle typu paketu se provadi dana operace case RRQ: {// Zadost o cteni get_filename(buf); // ukladani jmena souboru // Zjisti se mod prenosu mode = transfer_mode(buf); if(mode == UNKNOWN_MODE) {// neznamy mod err_msg = "Unknown mode"; send_error(sockfd, client_addr, err_msg, ERROR_IL); cout << current_time() << client_ip << " Unknown mode, operation aborted" << endl; clean_sources(f, sockfd); return 1; } else if(mode == NETASCII) { cout << current_time() + client_ip + " Requested READ of " << filename << " [netascii]"<< endl; } else if(mode == OCTET) { cout << current_time() + client_ip + " Requested READ of " << filename << " [octet]"<< endl; } // Otevre se soubor pro cteni file_status = f->open(filename, options->working_path(), FILE_IN, mode_tr); if(file_status == NOT_FOUND) {// Soubor nebyl nalezen err_msg = "File not found"; send_error(sockfd, client_addr, err_msg, ERROR_NF); cout << current_time() + client_ip + " File " << filename << " not found, operation aborted" << endl; clean_sources(f, sockfd); return 1; } else if(file_status == PERM_DEN) {// Nedostatecne opravneni err_msg = "Permission denided"; send_error(sockfd, client_addr, err_msg, ERROR_AV); cout << current_time() << client_ip << " Permission denided, operation aborted" << endl; clean_sources(f, sockfd); return EXIT_FAILURE; } // Zjisti se pritomnost rozsireni if(opt_extension(buf, numbytes, options, f) == EXTENSION) {// request obsahuje options send_oack(sockfd, client_addr); reading_data = true; // Alokace bufferu pro nacitani souboru if(block_size.used == true) {// byla specifikovana velikost bloku file_buf = new char[block_size.value + 1]; file_buf_size = block_size.value + 1; if(f->get_file_size() > MAX_BLOCK_COUNT * block_size.value) {// Soubor je prilis velky na prenos pres tftp err_msg = "File is too large to send"; send_error(sockfd, client_addr, err_msg, ERROR_DF); cout << current_time() + client_ip + " File is too large to send. Operation aborted\n"; clean_sources(f, sockfd); return EXIT_FAILURE; } } else {// mezi parametry nebyla velikost bloku, uvazuje se standardni file_buf = new char[STANDARD_BLOCK + 1]; file_buf_size = STANDARD_BLOCK + 1; } } else {// bez parametru, posilani prvnich dat if(f->get_file_size() > MAX_BLOCK_COUNT * STANDARD_BLOCK) {// Soubor je prilis velky na prenos pres tftp err_msg = "File is too large to send"; send_error(sockfd, client_addr, err_msg, ERROR_IL); cout << current_time() + client_ip + " File is too large to send. Operation aborted\n"; clean_sources(f, sockfd); return 1; } // Alokace bufferu pro nacitani souboru - standardni velikost file_buf = new char[STANDARD_BLOCK + 1]; reading_data = true; cout << current_time() + client_ip + " Sending DATA\n"; // poslou se prvni data data_len = send_data(sockfd, client_addr, 1, STANDARD_BLOCK, f, file_buf); data_counter += data_len; if(data_len < STANDARD_BLOCK) {// Prvni blok je zaroven i posledni, tim konci cinnost reading_data = false; } } break; } case WRQ: {// Zadost o zapis get_filename(buf); // ulozim jmeno souboru // Zjistim mod prenosu mode = transfer_mode(buf); if(mode == UNKNOWN_MODE) {// neznamy mod err_msg = "Unknown transfer mode"; send_error(sockfd, client_addr, err_msg, ERROR_IL); break; } else if(mode == NETASCII) { cout << current_time() << client_ip << " Requested WRITE of " << filename << " [netascii]" << endl; } else if(mode == OCTET) { cout << current_time() << client_ip << " Requested WRITE of " << filename << " [octet]" << endl; } // Otevre se soubor pro zapis if(mode == OCTET) { file_status = f->open(filename, options->working_path(), FILE_OUT, OCTET); } else if(mode == NETASCII) { file_status = f->open(filename, options->working_path(), FILE_OUT, NETASCII); } if(file_status == FILE_EXISTS) {// Soubor j*z existuje err_msg = "File already exists"; send_error(sockfd, client_addr, err_msg, ERROR_AE); cout << current_time() << client_ip << " File " << filename << " already exists, operation aborted" << endl; clean_sources(f, sockfd); return 1; } else if(file_status == CANNOT_OPEN) {// Nelze otevrit err_msg = "Cannot open file for writing"; send_error(sockfd, client_addr, err_msg, ERROR_IL); cout << current_time() << client_ip << " Cannot opet file " << filename << " for writing, operation aborted" << endl; clean_sources(f, sockfd); return 1; } // Zjisti se rozsireni if(opt_extension(buf, numbytes, options, f) == EXTENSION) {// request obsahuje options send_oack(sockfd, client_addr); // Alokace bufferu pro nacitani souboru if(block_size.used == true) {// byla specifikovana velikost bloku file_buf = new char[block_size.value + 10]; file_buf_size = block_size.value + 10; } else {// mezi parametry nebyla velikost bloku, uvazuje se standardni file_buf = new char[STANDARD_BLOCK + 10]; file_buf_size = STANDARD_BLOCK + 10; } writing_data = true; cout << current_time() + client_ip + " Receiving DATA\n"; } else {// Bez rozsireni, zasle se ack 0 send_ack(sockfd, client_addr, 0); // Alokace bufferu pro zapis souboru - standardni velikost file_buf = new char[STANDARD_BLOCK + 10]; file_buf_size = STANDARD_BLOCK + 10; writing_data = true; cout << current_time() + client_ip + " Receiving DATA\n"; } break; } case DATA: {// Datovy paket od klienta if(writing_data == true) {// Probiha prenos block_num = ack_number(file_buf); // zjisti se cislo bloku if((block_counter + 1) != block_num) {// Prisel blok, ktery nenavazuje na predchozi err_msg = "Error while file transfer"; send_error(sockfd, client_addr, err_msg, ERROR_IL); break; } int actual_block; if(block_size.used == true) {// Pouziva se nestandardni velikost bloku actual_block = block_size.value; bytes_write = recv_data(file_buf, numbytes, actual_block, f); // zapisou se data } else {// Standardni velikost bloku actual_block = STANDARD_BLOCK; bytes_write = recv_data(file_buf, numbytes, actual_block, f); // zapisou se data } if(bytes_write >= 0) {// Zapis byl uspesny, potvrdi se klientovi send_ack(sockfd, client_addr, block_num); block_counter++; // zvetsi se pocitadlo ulozenych bloku data_counter += bytes_write; // pricte se pocet ulozenych dat k pocitadlu if((numbytes - 4) < actual_block) {// dat bylo min nez je velikost bloku writing_data = false; f->close_file(FILE_OUT); // uzavre se soubor pro zapis cout << current_time() << client_ip << " File " << filename << " has been stored [" << data_counter << " B, " << block_counter << " blocks]" << endl; clean_sources(f, sockfd); return EXIT_FAILURE; } } else if(bytes_write == READ_ERR) {// Zapis nebyl uspesny err_msg = "Error while writing to file"; send_error(sockfd, client_addr, err_msg, ERROR_IL); clean_sources(f, sockfd); return EXIT_FAILURE; } } break; } case ACK: {// Potvrzeni od klienta, ze obdrzel konkretni datovy paket ack = ack_number(buf); if(ack == 0) cout << current_time() + client_ip + " Sending DATA\n"; if(reading_data == true) {// prenos jeste nebyl dokoncen if(block_size.used == true) {// Pouziva se nestandardni velikost bloku data_len = send_data(sockfd, client_addr, ack + 1, block_size.value, f, file_buf); if(data_len == SEND_FAIL) {// Chyba pri odesilani cerr << current_time() << client_ip << " Error in sendto, operation aborted" << endl; clean_sources(f, sockfd); return EXIT_FAILURE; } else if(data_len < block_size.value) reading_data = false; } else {// Standardni velikost bloku data_len = send_data(sockfd, client_addr, ack + 1, STANDARD_BLOCK, f, file_buf); if(data_len == SEND_FAIL) {// Chyba pri odesilani cerr << current_time() << client_ip << " Error in sendto, operation aborted" << endl; clean_sources(f, sockfd); return EXIT_FAILURE; } else if(data_len < STANDARD_BLOCK) reading_data = false; } data_counter += data_len; } else {// Prenos byl dokoncen cout << current_time() << client_ip << " File " << filename << " has been sent [" << data_counter << " B, " << ack << " blocks]\n"; clean_sources(f, sockfd); return EXIT_SUCCESS; } break; } case ERR: {// Error paket int err; if(reading_data == true) {// Klient poslal error pri cteni dat err = recv_error(buf); switch(err) { case ERROR_UN: {// Unknown transfer ID f->close_file(FILE_IN); cout << current_time() << client_ip << " Client aborted file read (transport error)" << endl; return EXIT_FAILURE; } case ERROR_DF: {// Disk full f->close_file(FILE_IN); cout << current_time() << client_ip << " Client aborted file read (too large)" << endl; return EXIT_FAILURE; } case ERROR_ND: {// Nedefinovana chyba f->close_file(FILE_IN); cout << current_time() << client_ip << " Client aborted file read (undefined error)" << endl; return EXIT_FAILURE; } } } else if(writing_data == true) {// Klient poslal error pri zapisu dat err = recv_error(buf); switch(err) { case ERROR_UN: {// Unknown transfer ID f->close_file(FILE_OUT); cout << current_time() << client_ip << " Client aborted file write" << endl; return EXIT_FAILURE; } case ERROR_ND: {// Nedefinovana chyba f->close_file(FILE_OUT); cout << current_time() << client_ip << " Client aborted file read (undefined error)" << endl; return EXIT_FAILURE; } } } break; } case UNKNOWN_OPCODE: {// Neznamy opcode err_msg = "Unknown request"; send_error(sockfd, client_addr, err_msg, ERROR_IL); clean_sources(f, sockfd); return EXIT_FAILURE; } }// konec switch(type) if(writing_data == true) {// Pokud probiha zapis, pouziva se vetsi buffer alokovany na halde recv_status = recv_packet(sockfd, client_addr, file_buf, file_buf_size); } else {// Pri cteni staci mensi velikost na zasobniku recv_status = recv_packet(sockfd, client_addr, buf, BUFSIZE); } if(recv_status == TIMEOUT_ELAPSED) {// Vyprsel cas cekani, probehne 3x pokus o znovu navazani komunikace tryouts++; if(tryouts == 3) {// Probehly tri pokusy o znovu navazani komunikace cout << current_time() << client_ip << " Timeout elapsed, operation aborted" << endl; clean_sources(f, sockfd); return 1; } else {// Probehne pokus cout << current_time() << client_ip << " Timeout elapsed, retrying..." << endl; } } else {// Byl normalne prijat paket numbytes = recv_status; tryouts = 0; // Vynuluje se pocitadlo neuspesnych pokusu } } }
static int start_server(char *interface) { struct sockaddr_in client_addr; socklen_t client_len; int client_fd; char *client_ip_addr; struct hostent *client_host; FILE *fp; char *buffer; char *uri; char *method; int continue_proc = TRUE; if (init_tcp(interface) < 0) { fprintf(stderr, "init TCP failed\n"); return STATUS_ERROR; } if (!interface) strcpy(local_ip_addr, "localhost"); client_len = sizeof(client_addr); while (continue_proc) { client_fd = accept(server_fd, (struct sockaddr *) &client_addr, &client_len); if (client_fd < 0) { perror("errorn in accept"); continue; } client_host = gethostbyaddr( (const char *) &client_addr.sin_addr.s_addr, sizeof(client_addr.sin_addr.s_addr), AF_INET); if (client_host == NULL) { perror("error in gethostbyaddr"); /* No need to bail out */ } client_ip_addr = inet_ntoa(client_addr.sin_addr); if (client_ip_addr == NULL) { perror("Can't get client IP\n"); close(client_fd); continue; } set_socket_timeout(client_fd); fprintf(stdout, "Received Request from %s\n", client_ip_addr); fp = fdopen(client_fd, "r+"); if (fp == NULL) { perror("error in fdopen"); close(client_fd); continue; } buffer = malloc(MAX_BUFFER_SIZE); if (!buffer) { perror("error in malloc"); fclose(fp); close(client_fd); continue; } if (fgets(buffer, MAX_BUFFER_SIZE, fp) == NULL) goto continue_loop; uri = NULL; method = NULL; method = strtok(buffer, " "); if (!method) { flush_request_buffer(fp); send_error(fp, "none", "400", "Bad request", "unknown method"); goto continue_loop; } if (strncasecmp(method, "GET", 3)) { flush_request_buffer(fp); send_error(fp, method, "501", "Not Implemented", "Only GET is supported"); goto continue_loop; } uri = strtok(NULL, " "); if (!uri) { flush_request_buffer(fp); send_error(fp, method, "400", "Bad request", "Bad request"); goto continue_loop; } flush_request_buffer(fp); if (!process_cmd(fp, uri, MAX_BUFFER_SIZE, buffer)) continue_proc = FALSE; fprintf(stdout, "processing done\n"); continue_loop: free(buffer); fclose(fp); close(client_fd); } return STATUS_SUCCESS; }
/*********************************************** Method: udp_rdt_recv Description: Receive a packet with possible timeout ***********************************************/ int udp_rdt_recv_pkt ( int sock_fd, /* Socket descriptor */ udp_rdt_pkt_t * pkt, /* Packet to rx */ void * from, /* Who sent this? */ uint32_t from_sz, /* Size of address */ int timeout_us, /* Timeout value */ int * time_elapsed /* total time elapsed in ms */ ) { struct sockaddr_in rx_from; int rx_len; struct timeval begin; struct timeval end; int ret_val; int expected_pkt; /*---------------------------------------- Validate parameters ----------------------------------------*/ if( pkt == NULL || from == NULL ) return -1; expected_pkt = 0; /*---------------------------------------- Will return -1 on timeout or other error ----------------------------------------*/ while( !expected_pkt ) { set_socket_timeout( sock_fd, timeout_us, 0 ); rx_len = sizeof(rx_from); gettimeofday(&begin, NULL); ret_val = recvfrom ( sock_fd, (udp_rdt_pkt_t *)pkt, sizeof( udp_rdt_pkt_t ), 0, (struct sockaddr *)&rx_from, &rx_len ); gettimeofday(&end, NULL); /*---------------------------------------- In the event of a timeout, we want the caller to be able to properly adjust state. Any other negative values should be treated as an unrecoverable error. ----------------------------------------*/ if( ( ret_val < 0 ) && ( errno == EAGAIN || errno == EWOULDBLOCK ) ) { ret_val = UDP_RDT_ERR_TIMEOUT; expected_pkt = 1; } /*---------------------------------------- We could receive a packet from someone other than server. We should ignore it ----------------------------------------*/ else if( ((struct sockaddr_in *)from)->sin_addr.s_addr != rx_from.sin_addr.s_addr ) { printf("UDP_RDT: Unexpected packet received. Resetting timeout.\n"); expected_pkt = 0; } /*---------------------------------------- Expected packet :) ----------------------------------------*/ else { ret_val = UDP_RDT_ERR_OK; expected_pkt = 1; } } *time_elapsed = get_time_diff_in_us( &begin, &end ); return( ret_val ); }
/*PAGE * * daemon * * This task runs forever. It waits for service requests on the FTP port * (port 21 by default). When a request is received, it opens a new session * to handle those requests until the connection is closed. * * Input parameters: * NONE * * Output parameters: * NONE */ static void daemon(rtems_task_argument args __attribute__((unused))) { int s; socklen_t addrLen; struct sockaddr_in addr; FTPD_SessionInfo_t *info = NULL; s = socket(PF_INET, SOCK_STREAM, 0); if (s < 0) syslog(LOG_ERR, "ftpd: Error creating socket: %s", serr()); addr.sin_family = AF_INET; addr.sin_port = htons(rtems_ftpd_configuration.port); addr.sin_addr.s_addr = htonl(INADDR_ANY); memset(addr.sin_zero, 0, sizeof(addr.sin_zero)); if (0 > bind(s, (struct sockaddr *)&addr, sizeof(addr))) syslog(LOG_ERR, "ftpd: Error binding control socket: %s", serr()); else if (0 > listen(s, 1)) syslog(LOG_ERR, "ftpd: Error listening on control socket: %s", serr()); else while (1) { int ss; addrLen = sizeof(addr); ss = accept(s, (struct sockaddr *)&addr, &addrLen); if (0 > ss) syslog(LOG_ERR, "ftpd: Error accepting control connection: %s", serr()); else if(!set_socket_timeout(ss, ftpd_timeout)) close_socket(ss); else { info = task_pool_obtain(); if (NULL == info) { close_socket(ss); } else { info->ctrl_socket = ss; if ((info->ctrl_fp = fdopen(info->ctrl_socket, "r+")) == NULL) { syslog(LOG_ERR, "ftpd: fdopen() on socket failed: %s", serr()); close_stream(info); task_pool_release(info); } else { /* Initialize corresponding SessionInfo structure */ info->def_addr = addr; if(0 > getsockname(ss, (struct sockaddr *)&addr, &addrLen)) { syslog(LOG_ERR, "ftpd: getsockname(): %s", serr()); close_stream(info); task_pool_release(info); } else { info->use_default = 1; info->ctrl_addr = addr; info->pasv_socket = -1; info->data_socket = -1; info->xfer_mode = TYPE_A; info->data_addr.sin_port = htons(ntohs(info->ctrl_addr.sin_port) - 1); info->idle = ftpd_timeout; /* Wakeup the session task. The task will call task_pool_release after it closes connection. */ rtems_event_send(info->tid, FTPD_RTEMS_EVENT); } } } } } rtems_task_delete(RTEMS_SELF); }