示例#1
0
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;
}
示例#2
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);
}