Beispiel #1
0
int fdset_sweep(fdset_t* set, fdset_sweep_cb_t cb, void *data)
{
	if (set == NULL || cb == NULL) {
		return KNOT_EINVAL;
	}

	/* Get time threshold. */
	timev_t now;
	if (time_now(&now) < 0) {
		return KNOT_ERROR;
	}

	unsigned i = 0;
	while (i < set->n) {

		/* Check sweep state, remove if requested. */
		if (set->timeout[i] > 0 && set->timeout[i] <= now.tv_sec) {
			if (cb(set, i, data) == FDSET_SWEEP) {
				if (fdset_remove(set, i) == KNOT_EOK)
					continue; /* Stay on the index. */
			}
		}

		/* Next descriptor. */
		++i;
	}

	return KNOT_EOK;
}
Beispiel #2
0
static int tcp_wait_for_events(tcp_context_t *tcp)
{
	/* Wait for events. */
	fdset_t *set = &tcp->set;
	int nfds = poll(set->pfd, set->n, TCP_SWEEP_INTERVAL * 1000);

	/* Mark the time of last poll call. */
	time_now(&tcp->last_poll_time);

	/* Process events. */
	unsigned i = 0;
	while (nfds > 0 && i < set->n) {

		/* Terminate faulty connections. */
		int fd = set->pfd[i].fd;

		/* Active sockets. */
		if (set->pfd[i].revents & POLLIN) {
			--nfds; /* One less active event. */

			/* Indexes <0, client_threshold) are master sockets. */
			if (i < tcp->client_threshold) {
				/* Faulty master sockets shall be sorted later. */
				(void) tcp_event_accept(tcp, i);
			} else {
				if (tcp_event_serve(tcp, i) != KNOT_EOK) {
					fdset_remove(set, i);
					close(fd);
					continue; /* Stay on the same index. */
				}
			}

		}

		if (set->pfd[i].revents & (POLLERR|POLLHUP|POLLNVAL)) {
			--nfds; /* One less active event. */
			fdset_remove(set, i);
			close(fd);
			continue; /* Stay on the same index. */
		}

		/* Next socket. */
		++i;
	}

	return nfds;
}
Beispiel #3
0
void fdset_add(fdset *fds, vector *v, int fd, void *opaque, ev_callback_t callback) {
    select_event_t se;
    se.fd = fd;
    se.opaque = opaque;
    se.callback = callback;

    fdset_remove(fds, v, fd);
    vector_push_back(v, &se);
}
Beispiel #4
0
int server_restore_streams(Server *s, FDSet *fds) {
        _cleanup_closedir_ DIR *d = NULL;
        struct dirent *de;
        int r;

        d = opendir("/run/systemd/journal/streams");
        if (!d) {
                if (errno == ENOENT)
                        return 0;

                return log_warning_errno(errno, "Failed to enumerate /run/systemd/journal/streams: %m");
        }

        FOREACH_DIRENT(de, d, goto fail) {
                unsigned long st_dev, st_ino;
                bool found = false;
                Iterator i;
                int fd;

                if (sscanf(de->d_name, "%lu:%lu", &st_dev, &st_ino) != 2)
                        continue;

                FDSET_FOREACH(fd, fds, i) {
                        struct stat st;

                        if (fstat(fd, &st) < 0)
                                return log_error_errno(errno, "Failed to stat %s: %m", de->d_name);

                        if (S_ISSOCK(st.st_mode) && st.st_dev == st_dev && st.st_ino == st_ino) {
                                found = true;
                                break;
                        }
                }

                if (!found) {
                        /* No file descriptor? Then let's delete the state file */
                        log_debug("Cannot restore stream file %s", de->d_name);
                        if (unlinkat(dirfd(d), de->d_name, 0) < 0)
                                log_warning_errno(errno, "Failed to remove /run/systemd/journal/streams/%s: %m",
                                                  de->d_name);
                        continue;
                }

                fdset_remove(fds, fd);

                r = stdout_stream_restore(s, de->d_name, fd);
                if (r < 0)
                        safe_close(fd);
        }

        return 0;

fail:
        return log_error_errno(errno, "Failed to read streams directory: %m");
}
Beispiel #5
0
static int tcp_wait_for_events(tcp_context_t *tcp)
{
	/* Wait for events. */
	fdset_t *set = &tcp->set;
	int nfds = poll(set->pfd, set->n, TCP_SWEEP_INTERVAL * 1000);

	/* Mark the time of last poll call. */
	time_now(&tcp->last_poll_time);
	bool is_throttled = (tcp->last_poll_time.tv_sec < tcp->throttle_end.tv_sec);
	if (!is_throttled) {
		/* Configuration limit, infer maximal pool size. */
		rcu_read_lock();
		conf_val_t *val = &conf()->cache.srv_max_tcp_clients;
		unsigned max_per_set = MAX(conf_int(val) / conf_tcp_threads(conf()), 1);
		rcu_read_unlock();
		/* Subtract master sockets check limits. */
		is_throttled = (set->n - tcp->client_threshold) >= max_per_set;
	}

	/* Process events. */
	unsigned i = 0;
	while (nfds > 0 && i < set->n) {
		bool should_close = false;
		int fd = set->pfd[i].fd;
		if (set->pfd[i].revents & (POLLERR|POLLHUP|POLLNVAL)) {
			should_close = (i >= tcp->client_threshold);
			--nfds;
		} else if (set->pfd[i].revents & (POLLIN)) {
			/* Master sockets */
			if (i < tcp->client_threshold) {
				if (!is_throttled && tcp_event_accept(tcp, i) == KNOT_EBUSY) {
					time_now(&tcp->throttle_end);
					tcp->throttle_end.tv_sec += tcp_throttle();
				}
			/* Client sockets */
			} else {
				if (tcp_event_serve(tcp, i) != KNOT_EOK) {
					should_close = true;
				}
			}
			--nfds;
		}

		/* Evaluate */
		if (should_close) {
			fdset_remove(set, i);
			close(fd);
		} else {
			++i;
		}
	}

	return nfds;
}
static int busname_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
        BusName *n = BUSNAME(u);

        assert(n);
        assert(key);
        assert(value);

        if (streq(key, "state")) {
                BusNameState state;

                state = busname_state_from_string(value);
                if (state < 0)
                        log_unit_debug(u->id, "Failed to parse state value %s", value);
                else
                        n->deserialized_state = state;

        } else if (streq(key, "result")) {
                BusNameResult f;

                f = busname_result_from_string(value);
                if (f < 0)
                        log_unit_debug(u->id, "Failed to parse result value %s", value);
                else if (f != BUSNAME_SUCCESS)
                        n->result = f;

        } else if (streq(key, "control-pid")) {
                pid_t pid;

                if (parse_pid(value, &pid) < 0)
                        log_unit_debug(u->id, "Failed to parse control-pid value %s", value);
                else
                        n->control_pid = pid;
        } else if (streq(key, "starter-fd")) {
                int fd;

                if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
                        log_unit_debug(u->id, "Failed to parse starter fd value %s", value);
                else {
                        safe_close(n->starter_fd);
                        n->starter_fd = fdset_remove(fds, fd);
                }
        } else
                log_unit_debug(u->id, "Unknown serialization key '%s'", key);

        return 0;
}
Beispiel #7
0
static void test_fdset_remove(void) {
        _cleanup_close_ int fd = -1;
        FDSet *fdset = NULL;
        char name[] = "/tmp/test-fdset_remove.XXXXXX";

        fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
        assert_se(fd >= 0);

        fdset = fdset_new();
        assert_se(fdset);
        assert_se(fdset_put(fdset, fd) >= 0);
        assert_se(fdset_remove(fdset, fd) >= 0);
        assert_se(!fdset_contains(fdset, fd));
        fdset_free(fdset);

        assert_se(fcntl(fd, F_GETFD) >= 0);

        unlink(name);
}
Beispiel #8
0
static int automount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
        Automount *a = AUTOMOUNT(u);
        int r;

        assert(a);
        assert(fds);

        if (streq(key, "state")) {
                AutomountState state;

                state = automount_state_from_string(value);
                if (state < 0)
                        log_unit_debug(u, "Failed to parse state value: %s", value);
                else
                        a->deserialized_state = state;
        } else if (streq(key, "result")) {
                AutomountResult f;

                f = automount_result_from_string(value);
                if (f < 0)
                        log_unit_debug(u, "Failed to parse result value: %s", value);
                else if (f != AUTOMOUNT_SUCCESS)
                        a->result = f;

        } else if (streq(key, "dev-id")) {
                unsigned d;

                if (safe_atou(value, &d) < 0)
                        log_unit_debug(u, "Failed to parse dev-id value: %s", value);
                else
                        a->dev_id = (unsigned) d;
        } else if (streq(key, "token")) {
                unsigned token;

                if (safe_atou(value, &token) < 0)
                        log_unit_debug(u, "Failed to parse token value: %s", value);
                else {
                        r = set_ensure_allocated(&a->tokens, NULL);
                        if (r < 0) {
                                log_oom();
                                return 0;
                        }

                        r = set_put(a->tokens, UINT_TO_PTR(token));
                        if (r < 0)
                                log_unit_error_errno(u, r, "Failed to add token to set: %m");
                }
        } else if (streq(key, "expire-token")) {
                unsigned token;

                if (safe_atou(value, &token) < 0)
                        log_unit_debug(u, "Failed to parse token value: %s", value);
                else {
                        r = set_ensure_allocated(&a->expire_tokens, NULL);
                        if (r < 0) {
                                log_oom();
                                return 0;
                        }

                        r = set_put(a->expire_tokens, UINT_TO_PTR(token));
                        if (r < 0)
                                log_unit_error_errno(u, r, "Failed to add expire token to set: %m");
                }
        } else if (streq(key, "pipe-fd")) {
                int fd;

                if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
                        log_unit_debug(u, "Failed to parse pipe-fd value: %s", value);
                else {
                        safe_close(a->pipe_fd);
                        a->pipe_fd = fdset_remove(fds, fd);
                }
        } else
                log_unit_debug(u, "Unknown serialization key: %s", key);

        return 0;
}
Beispiel #9
0
void send_file(void *opaque) {
  int portno;
  struct sockaddr sa;
  struct sockaddr_in *si = (struct sockaddr_in *) &sa;
  socklen_t sa_sz = sizeof(sa);
  
  packet_t pkt;
  int r;
  r = perhaps_recvfrom(sockfd, (void*)&pkt, sizeof(pkt), 0, &sa, &sa_sz);

  if (r < 0) {
    if (errno == EINTR || errno == ECONNREFUSED) {
      // We return from this function in the hope that the next time
      // 'sockfd' is read ready, we will be invoked again.
      return;
    } else {
      perror("recvfrom");
      exit(1);
    }
  }
  packet_ntoh(&pkt, &pkt);

  pkt.data[pkt.datalen] = '\0';
  sscanf(pkt.data, "%d", &portno);
  const char *serverIP = sa_data_str(&sa);

  INFO("Server endpoints {1} [%s:%d] & {2} [%s:%d]\n", serverIP, ntohs(si->sin_port), serverIP, portno);

  /*
  // Disconnect port association.
  sa.sa_family = AF_UNSPEC;
  Connect(sockfd, &sa, sizeof(SA));

  // Bind to the port we were originally bound to, and connect this
  // socket to the new port number that the server sent us.
  struct sockaddr cli_sa;
  struct sockaddr_in *cli_si = (struct sockaddr_in*)&cli_sa;
  memset(&cli_sa, 0, sizeof(cli_sa));
  memcpy(&cli_sa, conn->cli_sa, sizeof(struct sockaddr));
  cli_si->sin_port = htons(cliport);
  Bind(sockfd, &cli_sa, (socklen_t)sizeof(struct sockaddr_in));
  */

  // We open a new socket and dup2() since nothing else seems to be
  // working on both Linux as well as Solaris.
  int new_sockfd = Socket(AF_INET, SOCK_DGRAM, 0);
  dup2(new_sockfd, sockfd);
  if (conn->is_local) {
    set_dontroute(sockfd);
  }

  // Bind to the port we were originally bound to, and connect this
  // socket to the new port number that the server sent us.
  struct sockaddr_in cli_si;
  memset(&cli_si, 0, sizeof(cli_si));
  memcpy(&cli_si, conn->cli_sa, sizeof(struct sockaddr));
  cli_si.sin_port = htons(cliport);
  Bind(sockfd, (struct sockaddr*)&cli_si, (socklen_t)sizeof(struct sockaddr_in));

  sa = *(conn->serv_sa);
  si->sin_port = htons(portno);
  Connect(sockfd, &sa, sizeof(SA));

  // Send an ACK to the server.
  pkt.flags = FLAG_ACK;
  pkt.ack   = 1;
  pkt.rwinsz = cargs->sw_size;
  ++pkt.seq;
  pkt.datalen = 0;
  memset(pkt.data, 0, sizeof(pkt.data));
  sprintf(pkt.data, "ACK:%d, RWINSZ: %d", pkt.ack, pkt.rwinsz);

  INFO("Sending %d bytes of data to the server\n", sizeof(pkt));
  send_packet(&pkt);

  // Receive data from the socket till a packet with the FLAG_FIN flag
  // is received.
 
  if (pthread_create(&tid, NULL, (void *) (&consume_packets), (void *) (&rwin)) < 0) {
      err_sys("Could not spawn the consumer thread to read packets");
  }

  while (1) {
      VERBOSE("Waiting on recv(2)...%s\n", "");
      int r = recv_packet(&pkt);
      if (r < 0) {
        // Handle EINTR.
        if (errno == EINTR) {
          // Go back to waiting for a packet.
          continue;
        } else {
          if (errno == ECONNREFUSED) {
            INFO("http://memegenerator.net/instance/29609574%s\n", "");
          }
          perror("recv");
          exit(1);
        }
      }
      INFO("Received packet with SEQ#: %u\n", pkt.seq);
      packet_t *ack_pkt = rwindow_received_packet(&rwin, &pkt);
      INFO("ACK Packet will be sent with ACK: %u, Window Size: %d\n", ack_pkt->ack, ack_pkt->rwinsz);

      send_packet(ack_pkt);
      
      if (rwindow_received_all(&rwin)) {
          fdset_remove(&fds, &fds.rev, sockfd);
          fds.timeout_cb = fin_timeout;
          fdset_add(&fds, &fds.rev, sockfd, &sockfd, resend_fin_pkt);
          fds.timeout.tv_sec = 60;
          fds.timeout.tv_usec = 0;
          
          time_av_ms = 60*1000;
          at_select_ms = current_time_in_ms();
          INFO("Entering the TIME_WAIT state%s\n", "");
          INFO("File Transfer completed in %d sec\n", current_time_in_ms() / 1000);
          return;
      } 

      free(ack_pkt);
      ack_pkt = NULL;
  } // while (1)
}
Beispiel #10
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;
}
Beispiel #11
0
static int automount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
        Automount *a = AUTOMOUNT(u);
        int r;

        assert(a);
        assert(fds);

        if (streq(key, "state")) {
                AutomountState state;

                state = automount_state_from_string(value);
                if (state < 0)
                        log_debug_unit(u->id, "Failed to parse state value %s", value);
                else
                        a->deserialized_state = state;
        } else if (streq(key, "result")) {
                AutomountResult f;

                f = automount_result_from_string(value);
                if (f < 0)
                        log_debug_unit(u->id, "Failed to parse result value %s", value);
                else if (f != AUTOMOUNT_SUCCESS)
                        a->result = f;

        } else if (streq(key, "dev-id")) {
                unsigned d;

                if (safe_atou(value, &d) < 0)
                        log_debug_unit(u->id, "Failed to parse dev-id value %s", value);
                else
                        a->dev_id = (unsigned) d;
        } else if (streq(key, "token")) {
                unsigned token;

                if (safe_atou(value, &token) < 0)
                        log_debug_unit(u->id, "Failed to parse token value %s", value);
                else {
                        if (!a->tokens)
                                if (!(a->tokens = set_new(trivial_hash_func, trivial_compare_func)))
                                        return -ENOMEM;

                        r = set_put(a->tokens, UINT_TO_PTR(token));
                        if (r < 0)
                                return r;
                }
        } else if (streq(key, "pipe-fd")) {
                int fd;

                if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
                        log_debug_unit(u->id, "Failed to parse pipe-fd value %s", value);
                else {
                        if (a->pipe_fd >= 0)
                                close_nointr_nofail(a->pipe_fd);

                        a->pipe_fd = fdset_remove(fds, fd);
                }
        } else
                log_debug_unit(u->id, "Unknown serialization key '%s'", key);

        return 0;
}