Пример #1
0
int main(int argc, char const *argv[])
{
    char err[SOCKET_ERR_LEN];

    pool = buffer_pool_create(100);
    prev_recv = prev_send = 0;
    recv_total = send_total = 0;

    int sfd = tcp_server_serve(err, "localhost", 3456, SOMAXCONN);
    if (sfd < 0) {
        printf("%d %s\n", sfd, err);
        return 0;
    }

    if (set_nonblock(err, sfd) != 0) {
        printf("%s\n", err);
        return 0;
    }

    if (set_tcp_nodelay(err, sfd, 1) != 0) {
        printf("%s\n", err);
        return 0;
    }

    event_loop_t *loop = event_loop_create(100, 10);
    assert(loop != NULL);

    create_timer(loop, 1000, print_info, NULL);
    create_event(loop, sfd, EV_RDABLE, server_accept_cb, NULL);

    event_loop_start(loop);
}
Пример #2
0
void server_accept_cb(event_loop_t *loop, int fd, void *data)
{
    int  cfd;
    int  port;
    char ip[256];
    char err[SOCKET_ERR_LEN];

    while (1) {
        cfd = tcp_accept(err, fd, ip, 256, &port);
        if (cfd < 0) {
            if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) {
                break;
            } else {
                printf("accept: %s\n", err);
                break;
            }
        }

        printf("client %s:%d\n", ip, port);
        if (set_nonblock(err, cfd) != 0) {
            printf("%s\n", err);
            close(cfd);
        }

        if (set_tcp_nodelay(err, cfd, 1) != 0) {
            printf("%s\n", err);
            close(cfd);
        }

        buffer_chain_t *chain = malloc(sizeof(*chain));
        assert(chain != NULL);
        chain->pool = pool;
        chain->rbuf = chain->wbuf = buffer_pool_get(pool);
        chain->sent = chain->recv = 0;
        
        connection_t *conn = malloc(sizeof(*conn));
        assert(conn != NULL);
        conn->chain = chain;
        conn->total = 0;
        conn->eof = 0;
        conn->writing = 0;

        create_event(loop, cfd, EV_RDABLE, client_readcb, conn);
    }
}
Пример #3
0
//-----------------------------------------------------------------------------
CySocket* CySocket::accept() {
	init();
	SOCKET newSock = ::accept(sock, (sockaddr *) &addr, &addr_len);
	if (newSock == INVALID_SOCKET) {
		dperror("accept: invalid socket\n");
		return NULL;
	}
	CySocket *new_ySocket = new CySocket(newSock);
	if (new_ySocket != NULL) {
		new_ySocket->setAddr(addr);
#ifdef TCP_CORK
		new_ySocket->set_option(IPPROTO_TCP, TCP_CORK);
#else
		set_tcp_nodelay();
#endif
	}
	new_ySocket->isOpened = true;
	//	handling = true;
	return new_ySocket;
}
Пример #4
0
Файл: sock.c Проект: udhos/nepim
int nepim_socket_tcp_opt(FILE *err, int family, int sd, int nodelay, int mss)
{
  if (set_tcp_nodelay(err, sd, nodelay)) {
    /*
      Tolerate failure in setting NODELAY for PF_UNIX sockets
    */
    if (family != PF_UNIX)
      return NEPIM_SOCK_ERR_NODELAY;
  }

  if (nepim_socket_mss(err, sd, mss)) {
    /*
      Tolerate failure in setting TCP_MAXSEG for PF_UNIX sockets
    */
    if (family != PF_UNIX)
      return NEPIM_SOCK_ERR_MSS;
  }

  return NEPIM_SOCK_ERR_NONE;
}
Пример #5
0
/*
 * Fetches the resource denoted by |uri|.
 */
static void fetch_uri(const struct URI *uri)
{
  spdylay_session_callbacks callbacks;
  int fd;
  SSL_CTX *ssl_ctx;
  SSL *ssl;
  struct Request req;
  struct Connection connection;
  int rv;
  nfds_t npollfds = 1;
  struct pollfd pollfds[1];
  uint16_t spdy_proto_version;

  request_init(&req, uri);

  setup_spdylay_callbacks(&callbacks);

  /* Establish connection and setup SSL */
  fd = connect_to(req.host, req.port);
  ssl_ctx = SSL_CTX_new(SSLv23_client_method());
  if(ssl_ctx == NULL) {
    dief("SSL_CTX_new", ERR_error_string(ERR_get_error(), NULL));
  }
  init_ssl_ctx(ssl_ctx, &spdy_proto_version);
  ssl = SSL_new(ssl_ctx);
  if(ssl == NULL) {
    dief("SSL_new", ERR_error_string(ERR_get_error(), NULL));
  }
  /* To simplify the program, we perform SSL/TLS handshake in blocking
     I/O. */
  ssl_handshake(ssl, fd);

  connection.ssl = ssl;
  connection.want_io = IO_NONE;

  /* Here make file descriptor non-block */
  make_non_block(fd);
  set_tcp_nodelay(fd);

  printf("[INFO] SPDY protocol version = %d\n", spdy_proto_version);
  rv = spdylay_session_client_new(&connection.session, spdy_proto_version,
                                  &callbacks, &connection);
  if(rv != 0) {
    diec("spdylay_session_client_new", rv);
  }

  /* Submit the HTTP request to the outbound queue. */
  submit_request(&connection, &req);

  pollfds[0].fd = fd;
  ctl_poll(pollfds, &connection);

  /* Event loop */
  while(spdylay_session_want_read(connection.session) ||
        spdylay_session_want_write(connection.session)) {
    int nfds = poll(pollfds, npollfds, -1);
    if(nfds == -1) {
      dief("poll", strerror(errno));
    }
    if(pollfds[0].revents & (POLLIN | POLLOUT)) {
      exec_io(&connection);
    }
    if((pollfds[0].revents & POLLHUP) || (pollfds[0].revents & POLLERR)) {
      die("Connection error");
    }
    ctl_poll(pollfds, &connection);
  }

  /* Resource cleanup */
  spdylay_session_del(connection.session);
  SSL_shutdown(ssl);
  SSL_free(ssl);
  SSL_CTX_free(ssl_ctx);
  shutdown(fd, SHUT_WR);
  close(fd);
  request_free(&req);
}
Пример #6
0
int server_main(char *home, char *dev, char *port, int udp, int ipv4, int log)
{
	int lfd = -1, kdpfd, nfds, nfd, curfds, efd[2], refd[2], tunfd, i;
	unsigned int cpus = 0, threads, udp_cpu = 0;
	ssize_t ret;
	struct epoll_event *events;
	struct addrinfo hints, *ahead, *ai;

	auth_log = !!log;
	openlog("curvetun", LOG_PID | LOG_CONS | LOG_NDELAY, LOG_DAEMON);

	syslog(LOG_INFO, "curvetun server booting!\n");
	syslog_maybe(!auth_log, LOG_INFO, "curvetun user logging disabled!\n");

	parse_userfile_and_generate_user_store_or_die(home);

	memset(&hints, 0, sizeof(hints));
	hints.ai_family = PF_UNSPEC;
	hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM;
	hints.ai_protocol = udp ? IPPROTO_UDP : IPPROTO_TCP;
	hints.ai_flags = AI_PASSIVE;

	ret = getaddrinfo(NULL, port, &hints, &ahead);
	if (ret < 0)
		syslog_panic("Cannot get address info!\n");

	for (ai = ahead; ai != NULL && lfd < 0; ai = ai->ai_next) {
		lfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
		if (lfd < 0)
			continue;
		if (ai->ai_family == AF_INET6) {
#ifdef IPV6_V6ONLY
			ret = set_ipv6_only(lfd);
			if (ret < 0) {
				close(lfd);
				lfd = -1;
				continue;
			}
#else
			close(lfd);
			lfd = -1;
			continue;
#endif /* IPV6_V6ONLY */
		}

		set_reuseaddr(lfd);
		set_mtu_disc_dont(lfd);

		ret = bind(lfd, ai->ai_addr, ai->ai_addrlen);
		if (ret < 0) {
			close(lfd);
			lfd = -1;
			continue;
		}

		if (!udp) {
			ret = listen(lfd, 5);
			if (ret < 0) {
				close(lfd);
				lfd = -1;
				continue;
			}
		}

		if (ipv4 == -1) {
			ipv4 = (ai->ai_family == AF_INET6 ? 0 :
				(ai->ai_family == AF_INET ? 1 : -1));
		}

		syslog_maybe(auth_log, LOG_INFO, "curvetun on IPv%d via %s "
			     "on port %s!\n", ai->ai_family == AF_INET ? 4 : 6,
			     udp ? "UDP" : "TCP", port);
		syslog_maybe(auth_log, LOG_INFO, "Allowed overlay proto is "
			     "IPv%d!\n", ipv4 ? 4 : 6);
	}

	freeaddrinfo(ahead);

	if (lfd < 0 || ipv4 < 0)
		syslog_panic("Cannot create socket!\n");

	tunfd = tun_open_or_die(dev ? dev : DEVNAME_SERVER, IFF_TUN | IFF_NO_PI);

	pipe_or_die(efd, O_NONBLOCK);
	pipe_or_die(refd, O_NONBLOCK);

	set_nonblocking(lfd);

	events = xzmalloc(MAX_EPOLL_SIZE * sizeof(*events));
	for (i = 0; i < MAX_EPOLL_SIZE; ++i)
		events[i].data.fd = -1;

	kdpfd = epoll_create(MAX_EPOLL_SIZE);
	if (kdpfd < 0)
		syslog_panic("Cannot create socket!\n");

	set_epoll_descriptor(kdpfd, EPOLL_CTL_ADD, lfd,
			     udp ? EPOLLIN | EPOLLET | EPOLLONESHOT : EPOLLIN);
	set_epoll_descriptor(kdpfd, EPOLL_CTL_ADD, efd[0], EPOLLIN);
	set_epoll_descriptor(kdpfd, EPOLL_CTL_ADD, refd[0], EPOLLIN);
	set_epoll_descriptor(kdpfd, EPOLL_CTL_ADD, tunfd,
			     EPOLLIN | EPOLLET | EPOLLONESHOT);
	curfds = 4;

	trie_init();

	cpus = get_number_cpus_online();
	threads = cpus * THREADS_PER_CPU;
	if (!ispow2(threads))
		syslog_panic("Thread number not power of two!\n");

	threadpool = xzmalloc(sizeof(*threadpool) * threads);
	thread_spawn_or_panic(cpus, efd[1], refd[1], tunfd, ipv4, udp);

	init_cpusched(threads);

	register_socket(tunfd);
	register_socket(lfd);

	syslog(LOG_INFO, "curvetun up and running!\n");

	while (likely(!sigint)) {
		nfds = epoll_wait(kdpfd, events, curfds, -1);
		if (nfds < 0) {
			syslog(LOG_ERR, "epoll_wait error: %s\n",
			       strerror(errno));
			break;
		}

		for (i = 0; i < nfds; ++i) {
			if (unlikely(events[i].data.fd < 0))
				continue;

			if (events[i].data.fd == lfd && !udp) {
				int ncpu;
				char hbuff[256], sbuff[256];
				struct sockaddr_storage taddr;
				socklen_t tlen;

				tlen = sizeof(taddr);
				nfd = accept(lfd, (struct sockaddr *) &taddr,
					     &tlen);
				if (nfd < 0) {
					syslog(LOG_ERR, "accept error: %s\n",
					       strerror(errno));
					continue;
				}

				if (curfds + 1 > MAX_EPOLL_SIZE) {
					close(nfd);
					continue;
				}

				curfds++;

				ncpu = register_socket(nfd);

				memset(hbuff, 0, sizeof(hbuff));
				memset(sbuff, 0, sizeof(sbuff));
				getnameinfo((struct sockaddr *) &taddr, tlen,
					    hbuff, sizeof(hbuff),
					    sbuff, sizeof(sbuff),
					    NI_NUMERICHOST | NI_NUMERICSERV);

				syslog_maybe(auth_log, LOG_INFO, "New connection "
					     "from %s:%s (%d active client connections) -  id %d on CPU%d",
					     hbuff, sbuff, curfds-4, nfd, ncpu);

				set_nonblocking(nfd);
				set_socket_keepalive(nfd);
				set_tcp_nodelay(nfd);
				ret = set_epoll_descriptor2(kdpfd, EPOLL_CTL_ADD,
						nfd, EPOLLIN | EPOLLET | EPOLLONESHOT);
				if (ret < 0) {
					close(nfd);
					curfds--;
					continue;
				}
			} else if (events[i].data.fd == refd[0]) {
				int fd_one;

				ret = read_exact(refd[0], &fd_one,
						 sizeof(fd_one), 1);
				if (ret != sizeof(fd_one) || fd_one <= 0)
					continue;

				ret = set_epoll_descriptor2(kdpfd, EPOLL_CTL_MOD,
						fd_one, EPOLLIN | EPOLLET | EPOLLONESHOT);
				if (ret < 0) {
					close(fd_one);
					continue;
				}
			} else if (events[i].data.fd == efd[0]) {
				int fd_del, test;

				ret = read_exact(efd[0], &fd_del,
						 sizeof(fd_del), 1);
				if (ret != sizeof(fd_del) || fd_del <= 0)
					continue;

				ret = read(fd_del, &test, sizeof(test));
				if (ret < 0 && errno == EBADF)
					continue;

				ret = set_epoll_descriptor2(kdpfd, EPOLL_CTL_DEL,
						fd_del, 0);
				if (ret < 0) {
					close(fd_del);
					continue;
				}

				close(fd_del);
				curfds--;
				unregister_socket(fd_del);

				syslog_maybe(auth_log, LOG_INFO, "Closed connection "
					     "with id %d (%d active client connections remain)\n", fd_del,
					     curfds-4);
			} else {
				int cpu, fd_work = events[i].data.fd;

				if (!udp)
					cpu = socket_to_cpu(fd_work);
				else
					udp_cpu = (udp_cpu + 1) & (threads - 1);

				write_exact(threadpool[udp ? udp_cpu : cpu].efd[1],
					    &fd_work, sizeof(fd_work), 1);
			}
		}
	}

	syslog(LOG_INFO, "curvetun prepare shut down!\n");

	close(lfd);
	close(efd[0]);
	close(efd[1]);
	close(refd[0]);
	close(refd[1]);
	close(tunfd);

	thread_finish(cpus);

	xfree(threadpool);
	xfree(events);

	unregister_socket(lfd);
	unregister_socket(tunfd);

	destroy_cpusched();

	trie_cleanup();

	destroy_user_store();

	syslog(LOG_INFO, "curvetun shut down!\n");
	closelog();

	return 0;
}
Пример #7
0
int client_main(char *home, char *dev, char *host, char *port, int udp)
{
	int fd = -1, tunfd = 0, retry_server = 0;
	int ret, try = 1, i;
	struct addrinfo hints, *ahead, *ai;
	struct pollfd fds[2];
	struct curve25519_proto *p;
	struct curve25519_struct *c;
	char *buff;
	size_t blen = TUNBUFF_SIZ; //FIXME

retry:
	if (!retry_server) {
		openlog("curvetun", LOG_PID | LOG_CONS | LOG_NDELAY, LOG_DAEMON);
		syslog(LOG_INFO, "curvetun client booting!\n");
	}

	c = xmalloc(sizeof(struct curve25519_struct));

	ret = curve25519_alloc_or_maybe_die(c);
	if (ret < 0)
		syslog_panic("Cannot init curve!\n");

	p = get_serv_store_entry_proto_inf();
	if (!p)
		syslog_panic("Cannot proto!\n");

	memset(&hints, 0, sizeof(hints));
	hints.ai_family = PF_UNSPEC;
	hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM;
	hints.ai_protocol = udp ? IPPROTO_UDP : IPPROTO_TCP;
	hints.ai_flags = AI_NUMERICSERV;

	ret = getaddrinfo(host, port, &hints, &ahead);
	if (ret < 0) {
		syslog(LOG_ERR, "Cannot get address info! Retry!\n");
		curve25519_free(c);
		xfree(c);
		fd = -1;
		retry_server = 1;
		closed_by_server = 0;
		sleep(1);
		goto retry;
	}

	for (ai = ahead; ai != NULL && fd < 0; ai = ai->ai_next) {
		fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
		if (fd < 0)
			continue;
		ret = connect(fd, ai->ai_addr, ai->ai_addrlen);
		if (ret < 0) {
			syslog(LOG_ERR, "Cannot connect to remote, try %d: %s!\n",
			       try++, strerror(errno));
			close(fd);
			fd = -1;
			continue;
		}

		set_socket_keepalive(fd);
		set_mtu_disc_dont(fd);
		if (!udp)
			set_tcp_nodelay(fd);
	}
Пример #8
0
/*
 * Fetches the resource denoted by |uri|.
 */
static void fetch_uri(const struct URI *uri)
{
  spdylay_session_callbacks callbacks;
  int fd;
  struct Request req;
  struct Connection connection;
  int rv;
  nfds_t npollfds = 1;
  struct pollfd pollfds[1];
  uint16_t spdy_proto_version = 3;

  request_init(&req, uri);

  setup_spdylay_callbacks(&callbacks);

  /* Establish connection and setup SSL */
  fd = connect_to(req.host, req.port);
  if (-1 == fd)
    abort ();

  connection.fd = fd;
  connection.want_io = IO_NONE;

  /* Here make file descriptor non-block */
  make_non_block(fd);
  set_tcp_nodelay(fd);

  printf("[INFO] SPDY protocol version = %d\n", spdy_proto_version);
  rv = spdylay_session_client_new(&connection.session, spdy_proto_version,
                                  &callbacks, &connection);
  if(rv != 0) {
    diec("spdylay_session_client_new", rv);
  }

  /* Submit the HTTP request to the outbound queue. */
  submit_request(&connection, &req);

  pollfds[0].fd = fd;
  ctl_poll(pollfds, &connection);

  /* Event loop */
  while(spdylay_session_want_read(connection.session) ||
        spdylay_session_want_write(connection.session)) {
    int nfds = poll(pollfds, npollfds, -1);
    if(nfds == -1) {
      dief("poll", strerror(errno));
    }
    if(pollfds[0].revents & (POLLIN | POLLOUT)) {
      exec_io(&connection);
    }
    if((pollfds[0].revents & POLLHUP) || (pollfds[0].revents & POLLERR)) {
      die("Connection error");
    }
    ctl_poll(pollfds, &connection);
  }

  /* Resource cleanup */
  spdylay_session_del(connection.session);
  shutdown(fd, SHUT_WR);
  MHD_socket_close_(fd);
  request_free(&req);
}