KernelTcp.cc 2.41 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
// KernelTcp.cc

#include "lib.h"
#include "KernelTcp.h"

void kernelTcp_addNewPeer(fd_set * readable)
{
  if (global::peerAccept != -1
      && FD_ISSET(global::peerAccept, readable))
  {
    struct sockaddr_in remoteAddress;
    socklen_t addressSize = sizeof(remoteAddress);
    int fd = accept(global::peerAccept, &remoteAddress, &addressSize);
    if (fd != -1)
    {
      // Add the peer.
      int flags = fctl(fd, F_GETFL);
      if (flags != -1)
      {
        int error = fctl(fd, F_SETFL, flags | O_NONBLOCK);
        if (error != -1)
        {
          global::peers.push_back(
            make_pair(fd, ipToString(remoteAddress.sin_addr.s_addr)));
          addDescriptor(fd);
          logWrite(PEER_CYCLE,
                   "Peer connection %d from %s was accepted normally.",
                   global::peers.back().first, global::peers.back().second);
        }
        else
        {
          logWrite(EXCEPTION, "fctl(F_SETFL) failed: %s", strerror(errno));
          close(fd);
        }
      }
      else
      {
        logWrite(EXCEPTION, "fctl(F_GETFL) failed: %s", strerror(errno));
        close(fd);
      }
    }
    else
    {
      logWrite(EXCEPTION, "accept() called on a peer connection failed: %s",
               strerror(errno));
    }
  }
}

void kernelTcp_readFromPeers(fd_set * readable)
{
  list<int>::iterator pos = global::peers.begin();
  while (pos != peers.end())
  {
    if (FD_ISSET(pos->first, readable))
    {
      static const int bufferSize = 8096;
      static char buffer[bufferSize];
      int size = read(pos->first, buffer, bufferSize);
      if (size == 0)
      {
        logWrite(PEER_CYCLE,
                 "Peer connection %d from %s is closing normally.",
                 pos->first, pos->second);
        close(pos->first);
        list<int>::iterator temp = pos;
        ++pos;
        global::peers.erase(temp);
      }
      else if (size == -1 && errno != EAGAIN && errno != EINTR)
      {
        logWrite(EXCEPTION,
                 "Failed to read peer connection %d from %s so "
                 "I'm shutting it down: %s", pos->first, pos->second,
                 strerror(errno));
        close(pos->first);
        list<int>::iterator temp = pos;
        ++pos;
        global::peers.erase(temp);
      }
      else
      {
        ++pos;
      }
    }
    else
    {
      ++pos;
    }
  }
}