Example #1
0
// Connect to the server, and send the first datagram
void initiate_tx(void) {
  sockfd = Socket(AF_INET, SOCK_DGRAM, 0);
  if (conn->is_local) {
    set_dontroute(sockfd);	
  }

  // Bind to port 0
  Bind(sockfd, conn->cli_sa, (socklen_t)sizeof(SA));

  struct sockaddr_in sin;
  UINT addrlen = sizeof(SA);

  // Fetch port number at which kernel bound this socket.
  Getsockname(sockfd, (SA *)&sin, &addrlen);
  cliport = ntohs(sin.sin_port);
  INFO("Client's ephemeral Port Number: %d\n", cliport);

  // Connect to the server.
  Connect(sockfd, conn->serv_sa, sizeof(SA));

  // TODO
  // Do we need getpeername here?
  
  // Start a timer here to re-send the file name till we receive an
  // ACK.

  struct timeval timeout;
  timeout.tv_sec = 3;
  timeout.tv_usec = 0;

  fdset_init(&fds, timeout, ack_timeout);

  fdset_add(&fds, &fds.rev, sockfd, &sockfd, send_file);
  fdset_add(&fds, &fds.exev, sockfd, &sockfd, handle_tx_error);

  // Send the packet to the server
  INFO("Trying to send the SYN packet to the Server with the file name%s\n", "");
  send_filename_pkt();

  int r = fdset_poll2(&fds);
  if (r < 0) {
    perror("select");
    ASSERT(errno != EINTR);
    exit(1);
  }
}
Example #2
0
void
server_loop(void) {
  struct timeval timeout;
  int r;

  VERBOSE("server_loop()%s\n", "");

  timeout.tv_sec = 10; // FIXME when we know better
  timeout.tv_usec = 0;

  fdset_init(&fds, timeout, NULL);

  fdset_add(&fds, &fds.rev,  s.sockfd, &s.sockfd, on_recv);
  fdset_add(&fds, &fds.exev, s.sockfd, &s.sockfd, on_error);

  r = fdset_poll(&fds, &timeout, on_recv_timedout);
  if (r < 0) {
    perror("select");
    ASSERT(errno != EINTR);
    exit(1);
  }
}
Example #3
0
int tcp_master(dthread_t *thread)
{
	if (!thread || !thread->data) {
		return KNOT_EINVAL;
	}

	iohandler_t *handler = (iohandler_t *)thread->data;
	unsigned *iostate = &handler->thread_state[dt_get_id(thread)];

	int ret = KNOT_EOK;
	ref_t *ref = NULL;
	tcp_context_t tcp;
	memset(&tcp, 0, sizeof(tcp_context_t));

	/* Create big enough memory cushion. */
	knot_mm_t mm;
	mm_ctx_mempool(&mm, 16 * MM_DEFAULT_BLKSIZE);

	/* Create TCP answering context. */
	tcp.server = handler->server;
	tcp.thread_id = handler->thread_id[dt_get_id(thread)];
	tcp.overlay.mm = &mm;

	/* Prepare structures for bound sockets. */
	conf_val_t val = conf_get(conf(), C_SRV, C_LISTEN);
	fdset_init(&tcp.set, conf_val_count(&val) + CONF_XFERS);

	/* Create iovec abstraction. */
	for (unsigned i = 0; i < 2; ++i) {
		tcp.iov[i].iov_len = KNOT_WIRE_MAX_PKTSIZE;
		tcp.iov[i].iov_base = malloc(tcp.iov[i].iov_len);
		if (tcp.iov[i].iov_base == NULL) {
			ret = KNOT_ENOMEM;
			goto finish;
		}
	}

	/* Initialize sweep interval. */
	timev_t next_sweep = {0};
	time_now(&next_sweep);
	next_sweep.tv_sec += TCP_SWEEP_INTERVAL;

	for(;;) {

		/* Check handler state. */
		if (unlikely(*iostate & ServerReload)) {
			*iostate &= ~ServerReload;

			/* Cancel client connections. */
			for (unsigned i = tcp.client_threshold; i < tcp.set.n; ++i) {
				close(tcp.set.pfd[i].fd);
			}

			ref_release(ref);
			ref = server_set_ifaces(handler->server, &tcp.set, IO_TCP, tcp.thread_id);
			if (tcp.set.n == 0) {
				break; /* Terminate on zero interfaces. */
			}

			tcp.client_threshold = tcp.set.n;
		}

		/* Check for cancellation. */
		if (dt_is_cancelled(thread)) {
			break;
		}

		/* Serve client requests. */
		tcp_wait_for_events(&tcp);

		/* Sweep inactive clients. */
		if (tcp.last_poll_time.tv_sec >= next_sweep.tv_sec) {
			fdset_sweep(&tcp.set, &tcp_sweep, NULL);
			time_now(&next_sweep);
			next_sweep.tv_sec += TCP_SWEEP_INTERVAL;
		}
	}

finish:
	free(tcp.iov[0].iov_base);
	free(tcp.iov[1].iov_base);
	mp_delete(mm.ctx);
	fdset_clear(&tcp.set);
	ref_release(ref);

	return ret;
}
Example #4
0
int main(int argc, char *argv[])
{
	plan(12);

	/* 1. Create fdset. */
	fdset_t set;
	int ret = fdset_init(&set, 32);
	is_int(0, ret, "fdset: init");

	/* 2. Create pipe. */
	int fds[2], tmpfds[2];
	ret = pipe(fds);
	ok(ret >= 0, "fdset: pipe() works");
	ret = pipe(tmpfds);
	ok(ret >= 0, "fdset: 2nd pipe() works");

	/* 3. Add fd to set. */
	ret = fdset_add(&set, fds[0], POLLIN, NULL);
	is_int(0, ret, "fdset: add to set works");
	fdset_add(&set, tmpfds[0], POLLIN, NULL);

	/* Schedule write. */
	struct timeval ts, te;
	gettimeofday(&ts, 0);
	pthread_t t;
	pthread_create(&t, 0, thr_action, &fds[1]);

	/* 4. Watch fdset. */
	int nfds = poll(set.pfd, set.n, 60 * 1000);
	gettimeofday(&te, 0);
	size_t diff = timeval_diff(&ts, &te);

	ok(nfds > 0, "fdset: poll returned %d events in %zu ms", nfds, diff);

	/* 5. Prepare event set. */
	ok(set.pfd[0].revents & POLLIN, "fdset: pipe is active");

	/* 6. Receive data. */
	char buf = 0x00;
	ret = read(set.pfd[0].fd, &buf, WRITE_PATTERN_LEN);
	ok(ret >= 0 && buf == WRITE_PATTERN, "fdset: contains valid data");

	/* 7-9. Remove from event set. */
	ret = fdset_remove(&set, 0);
	is_int(0, ret, "fdset: remove from fdset works");
	close(fds[0]);
	close(fds[1]);
	ret = fdset_remove(&set, 0);
	close(tmpfds[1]);
	close(tmpfds[1]);
	is_int(0, ret, "fdset: remove from fdset works (2)");
	ret = fdset_remove(&set, 0);
	ok(ret != 0, "fdset: removing nonexistent item");

	/* 10. Crash test. */
	fdset_init(0, 0);
	fdset_add(0, 1, 1, 0);
	fdset_add(0, 0, 1, 0);
	fdset_remove(0, 1);
	fdset_remove(0, 0);
	ok(1, "fdset: crash test successful");

	/* 11. Destroy fdset. */
	ret = fdset_clear(&set);
	is_int(0, ret, "fdset: destroyed");

	/* Cleanup. */
	pthread_join(t, 0);

	return 0;
}