constexpr friend IP4Address operator & (IP4Address l, IP4Address r) { return IP4Address({ static_cast<uint8_t>(l._addr[0] & r._addr[0]), static_cast<uint8_t>(l._addr[1] & r._addr[1]), static_cast<uint8_t>(l._addr[2] & r._addr[2]), static_cast<uint8_t>(l._addr[3] & r._addr[3]), }); }
static void connect_client(int listen_fd) { struct sockaddr_in client_address; socklen_t len = sizeof(client_address); int fd = accept(listen_fd, reinterpret_cast<struct sockaddr *>(&client_address), &len); if (fd == -1) { perror("accept"); return; } if (fd >= SOFT_LIMIT) { FPRINTF(stderr, "softlimit reached, disconnecting : %d\n", fd); shutdown(fd, SHUT_RDWR); close(fd); return; } if (fd_max <= fd) { fd_max = fd + 1; } const int yes = 1; /// Allow to bind() again after the server restarts. // Since the socket is still in the TIME_WAIT, there's a possibility // that formerly lost packets might be delivered and confuse the server. setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes); /// Send packets as soon as possible /// even if the kernel thinks there is too little for it to be worth it! /// Testing shows this is indeed a good idea. setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof yes); // Linux-ism: Set socket options to optimize for thin streams // See http://lwn.net/Articles/308919/ and // Documentation/networking/tcp-thin.txt .. Kernel 3.2+ #ifdef TCP_THIN_LINEAR_TIMEOUTS setsockopt(fd, IPPROTO_TCP, TCP_THIN_LINEAR_TIMEOUTS, &yes, sizeof yes); #endif #ifdef TCP_THIN_DUPACK setsockopt(fd, IPPROTO_TCP, TCP_THIN_DUPACK, &yes, sizeof yes); #endif #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wold-style-cast" FD_SET(fd, &readfds); #pragma GCC diagnostic pop fcntl(fd, F_SETFL, O_NONBLOCK); session[fd] = make_unique<socket_data>(); session[fd]->rdata.new_(RFIFO_SIZE); session[fd]->wdata.new_(WFIFO_SIZE); session[fd]->max_rdata = RFIFO_SIZE; session[fd]->max_wdata = WFIFO_SIZE; session[fd]->func_recv = recv_to_fifo; session[fd]->func_send = send_from_fifo; session[fd]->func_parse = default_func_parse; session[fd]->client_ip = IP4Address(client_address.sin_addr); session[fd]->created = TimeT::now(); session[fd]->connected = 0; }
explicit IP4Address(struct in_addr addr) { static_assert(sizeof(addr) == sizeof(_addr), "4 bytes"); *this = IP4Address(reinterpret_cast<const uint8_t (&)[4]>(addr)); }