Exemple #1
0
/*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;
}
Exemple #2
0
/*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);
  }
}
Exemple #3
0
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;
}
Exemple #4
0
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;
}
Exemple #6
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;
}
Exemple #8
0
/***********************************************
 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;
}
Exemple #9
0
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);
}
Exemple #10
0
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;
}
Exemple #11
0
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;
}
Exemple #12
0
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;
}
Exemple #13
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
}
Exemple #14
0
/******************************************************************************
	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;
}
Exemple #16
0
/***********************************************
 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 );
}
Exemple #17
0
/*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);
}