int main(int argc, const char** argv) { setvbuf(stdout, NULL, _IONBF, 0); int portnum = 9090; if (argc >= 2) { portnum = atoi(argv[1]); } printf("Serving on port %d\n", portnum); int listener_sockfd = listen_inet_socket(portnum); make_socket_non_blocking(listener_sockfd); int epollfd = epoll_create1(0); if (epollfd < 0) { perror_die("epoll_create1"); } struct epoll_event accept_event; accept_event.data.fd = listener_sockfd; accept_event.events = EPOLLIN; if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listener_sockfd, &accept_event) < 0) { perror_die("epoll_ctl EPOLL_CTL_ADD"); } struct epoll_event* events = calloc(MAXFDS, sizeof(struct epoll_event)); if (events == NULL) { die("Unable to allocate memory for epoll_events"); } while (1) { int nready = epoll_wait(epollfd, events, MAXFDS, -1); for (int i = 0; i < nready; i++) { if (events[i].events & EPOLLERR) { perror_die("epoll_wait returned EPOLLERR"); } if (events[i].data.fd == listener_sockfd) { // The listening socket is ready; this means a new peer is connecting. struct sockaddr_in peer_addr; socklen_t peer_addr_len = sizeof(peer_addr); int newsockfd = accept(listener_sockfd, (struct sockaddr*)&peer_addr, &peer_addr_len); if (newsockfd < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { // This can happen due to the nonblocking socket mode; in this // case don't do anything, but print a notice (since these events // are extremely rare and interesting to observe...) printf("accept returned EAGAIN or EWOULDBLOCK\n"); } else { perror_die("accept"); } } else { make_socket_non_blocking(newsockfd); if (newsockfd >= MAXFDS) { die("socket fd (%d) >= MAXFDS (%d)", newsockfd, MAXFDS); } fd_status_t status = on_peer_connected(newsockfd, &peer_addr, peer_addr_len); struct epoll_event event = {0}; event.data.fd = newsockfd; if (status.want_read) { event.events |= EPOLLIN; } if (status.want_write) { event.events |= EPOLLOUT; } if (epoll_ctl(epollfd, EPOLL_CTL_ADD, newsockfd, &event) < 0) { perror_die("epoll_ctl EPOLL_CTL_ADD"); } } } else { // A peer socket is ready. if (events[i].events & EPOLLIN) { // Ready for reading. int fd = events[i].data.fd; fd_status_t status = on_peer_ready_recv(fd); struct epoll_event event = {0}; event.data.fd = fd; if (status.want_read) { event.events |= EPOLLIN; } if (status.want_write) { event.events |= EPOLLOUT; } if (event.events == 0) { printf("socket %d closing\n", fd); if (epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, NULL) < 0) { perror_die("epoll_ctl EPOLL_CTL_DEL"); } close(fd); } else if (epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &event) < 0) { perror_die("epoll_ctl EPOLL_CTL_MOD"); } } else if (events[i].events & EPOLLOUT) { // Ready for writing. int fd = events[i].data.fd; fd_status_t status = on_peer_ready_send(fd); struct epoll_event event = {0}; event.data.fd = fd; if (status.want_read) { event.events |= EPOLLIN; } if (status.want_write) { event.events |= EPOLLOUT; } if (event.events == 0) { printf("socket %d closing\n", fd); if (epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, NULL) < 0) { perror_die("epoll_ctl EPOLL_CTL_DEL"); } close(fd); } else if (epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &event) < 0) { perror_die("epoll_ctl EPOLL_CTL_MOD"); } } } } } return 0; }
static void myHandshakeDoneCB (CcnetHandshake *handshake, CcnetPacketIO *io, int is_connected, const char *peer_id, void *vmanager) { CcnetConnManager *manager = vmanager; CcnetPeerManager *peerMgr = manager->session->peer_mgr; CcnetPeer *peer; if (!is_connected) { if (ccnet_packet_io_is_incoming (io)) { ccnet_warning ("[conn] incoming handshake fails.\n"); ccnet_packet_io_free (io); return; } /* temporally use peer, so don't need to increase the reference */ peer = handshake->peer; if (peer->num_fails == 0) { /* print error for the first time */ ccnet_message ("[Conn] peer %s(%.10s) connection fails\n", peer->name, peer->id); } else { ccnet_debug ("[Conn] peer %s(%.10s) connection fails\n", peer->name, peer->id); } if (peer->net_state == PEER_CONNECTED) { ccnet_debug ("[Conn] But Peer %s(%.10s) is already connected me.\n", peer->name, peer->id); } else if (peer->net_state == PEER_DOWN){ ccnet_peer_shutdown(peer); } ccnet_packet_io_free (io); peer->num_fails++; peer->in_connection = 0; return; } if (!ccnet_packet_io_is_incoming (io)) { peer = handshake->peer; peer->in_connection = 0; if (peer->to_resolve) { if (!peer_id_valid(peer_id)) { /* TODO: Remove the peer */ ccnet_warning ("[Conn] Resolving: Received invalid peer id\n"); return; } ccnet_debug ("[Conn] Resolving: Peer %.8s is resolved\n", peer_id); memcpy (peer->id, peer_id, 40); peer->id[40] = '\0'; on_resolve_peer_connected (peer, io); return; } /* ref for using the peer below */ g_object_ref (peer); } else { /* incoming */ if (peer_id == NULL) { ccnet_warning ("Unknown peer (no-id) connecting\n"); ccnet_packet_io_free (io); return; } peer = ccnet_peer_manager_get_peer (peerMgr, peer_id); if (!peer) { ccnet_message ("Unknown peer %s connecting\n", peer_id); peer = ccnet_peer_new (peer_id); ccnet_peer_manager_add_peer (peerMgr, peer); set_peer_address_from_socket(peer, io); peer->last_up = time(NULL); on_unauthed_peer_connected (peer, io); g_object_unref (peer); return; } set_peer_address_from_socket(peer, io); peer->last_up = time(NULL); } /* hold a reference on the peer */ if (peer->net_state == PEER_CONNECTED) { ccnet_message ("[Conn] Peer %s (%.10s) is already connected. " "Discarding this handshake.\n", peer->name, peer->id); ccnet_packet_io_free (io); g_object_unref (peer); return; } ccnet_message ("[Conn] Peer %s (%.10s) connected\n", peer->name, peer->id); peer->num_fails = 0; on_peer_connected (peer, io); g_object_unref (peer); }