Exemplo n.º 1
0
void *FileTransferManager_tep(void *arg)
{
  CFileTransferManager *ftman = (CFileTransferManager *)arg;

  fd_set f_recv, f_send;
  struct timeval *tv;
  struct timeval tv_updates = { 2, 0 };
  int l, nSocketsAvailable, nCurrentSocket;

  if (!ftman->isReceiver())
  {
    if (!ftman->ConnectToFileServer(ftman->m_nPort))
    {
      ftman->PushFileTransferEvent(FT_ERRORxCONNECT);
      return NULL;
    }
  }
  else if (!ftman->isReceiver())
    return NULL;

  while (true)
  {
    f_recv = ftman->sockman.socketSet();
    l = ftman->sockman.LargestSocket() + 1;

    // Add the new socket pipe descriptor
    FD_SET(ftman->myThreadPipe.getReadFd(), &f_recv);
    if (ftman->myThreadPipe.getReadFd() >= l)
      l = ftman->myThreadPipe.getReadFd() + 1;

    // Set up the send descriptor
    FD_ZERO(&f_send);
    if (ftman->m_nState == FT_STATE_SENDINGxFILE)
    {
      FD_SET(ftman->ftSock.Descriptor(), &f_send);
      // No need to check "l" as ftSock is already in the read list
    }

    // Prepare max timeout if necessary
    if (ftman->m_nUpdatesEnabled &&
        (ftman->m_nState == FT_STATE_SENDINGxFILE ||
         ftman->m_nState == FT_STATE_RECEIVINGxFILE) )
    {
      tv_updates.tv_sec = ftman->m_nUpdatesEnabled;
      tv_updates.tv_usec = 0;
      tv = &tv_updates;
    }
    else
    {
      tv = NULL;
    }

    nSocketsAvailable = select(l, &f_recv, &f_send, NULL, tv);

    if (nSocketsAvailable == -1)
    {
      // Something is very wrong, most likely we've lost control of a file
      //   descriptor and select will continue to fail causing this thread to
      //   spin so better to just give up and exit.

      gLog.warning(tr("File Transfer: select failed, aborting thread: %s"), strerror(errno));
      pthread_exit(NULL);
    }

    // Check if we timed out
    if (tv != NULL && nSocketsAvailable == 0)
    {
      ftman->PushFileTransferEvent(FT_UPDATE);
      gettimeofday(&ftman->tv_lastupdate, NULL);
    }

    nCurrentSocket = 0;
    while (nSocketsAvailable > 0 && nCurrentSocket < l)
    {
      if (FD_ISSET(nCurrentSocket, &f_recv))
      {
        // New socket event ----------------------------------------------------
        if (nCurrentSocket == ftman->myThreadPipe.getReadFd())
        {
          char buf = ftman->myThreadPipe.getChar();
          if (buf == 'R')
          {
            DEBUG_THREADS("[FileTransferManager_tep] Reloading socket info.\n");
          }
          else if (buf == 'X')
          {
            DEBUG_THREADS("[FileTransferManager_tep] Exiting.\n");
            pthread_exit(NULL);
          }
        }

        // Connection on the server port ---------------------------------------
        else if (nCurrentSocket == ftman->ftServer.Descriptor())
        {
          if (ftman->ftSock.Descriptor() != -1)
          {
            gLog.warning(tr("File Transfer: Receiving repeat incoming connection."));

            // Dump the extra connection to clear the listen socket queue
            Licq::TCPSocket ts;
            if (ftman->ftServer.RecvConnection(ts))
              ts.CloseConnection();
          }
          else
          {
            if (ftman->ftServer.RecvConnection(ftman->ftSock))
            {
              ftman->sockman.AddSocket(&ftman->ftSock);
              ftman->sockman.DropSocket(&ftman->ftSock);

              ftman->m_nState = FT_STATE_HANDSHAKE;
              gLog.info(tr("File Transfer: Received connection."));
            }
            else
            {
              gLog.error(tr("File Transfer: Unable to receive new connection."));
            }
          }
        }

        // Message from connected socket----------------------------------------
        else if (nCurrentSocket == ftman->ftSock.Descriptor())
        {
          ftman->ftSock.Lock();
          bool ok = ftman->ProcessPacket();
          ftman->ftSock.Unlock();
          if (!ok)
          {
            ftman->CloseConnection();
            ftman->PushFileTransferEvent(ftman->m_nResult);
          }
        }

        else
        {
          gLog.warning(tr("File Transfer: No such socket."));
        }

        nSocketsAvailable--;
      }
      else if (FD_ISSET(nCurrentSocket, &f_send))
      {
        if (nCurrentSocket == ftman->ftSock.Descriptor())
        {
          ftman->ftSock.Lock();
          bool ok = ftman->SendFilePacket();
          ftman->ftSock.Unlock();
          if (!ok)
          {
            ftman->CloseConnection();
            ftman->PushFileTransferEvent(ftman->m_nResult);
          }
        }
        nSocketsAvailable--;
      }

      nCurrentSocket++;
    }
  }
  return NULL;
}
Exemplo n.º 2
0
void *FileTransferManager_tep(void *arg)
{
  CFileTransferManager *ftman = (CFileTransferManager *)arg;

  fd_set f_recv, f_send;
  struct timeval *tv;
  struct timeval tv_updates = { 2, 0 };
  int l, nSocketsAvailable, nCurrentSocket;
  char buf[2];

  if (ftman->m_nDirection == D_SENDER)
  {
    if (!ftman->ConnectToFileServer(ftman->m_nPort))
    {
      ftman->PushFileTransferEvent(FT_ERRORxCONNECT);
      return NULL;
    }
  }
  else if (ftman->m_nDirection != D_RECEIVER)
    return NULL;

  while (true)
  {
    f_recv = ftman->sockman.SocketSet();
    l = ftman->sockman.LargestSocket() + 1;

    // Add the new socket pipe descriptor
    FD_SET(ftman->pipe_thread[PIPE_READ], &f_recv);
    if (ftman->pipe_thread[PIPE_READ] >= l)
      l = ftman->pipe_thread[PIPE_READ] + 1;

    // Set up the send descriptor
    FD_ZERO(&f_send);
    if (ftman->m_nState == FT_STATE_SENDINGxFILE)
    {
      FD_SET(ftman->ftSock.Descriptor(), &f_send);
      // No need to check "l" as ftSock is already in the read list
    }

    // Prepare max timeout if necessary
    if (ftman->m_nUpdatesEnabled &&
        (ftman->m_nState == FT_STATE_SENDINGxFILE ||
         ftman->m_nState == FT_STATE_RECEIVINGxFILE) )
    {
      tv_updates.tv_sec = ftman->m_nUpdatesEnabled;
      tv_updates.tv_usec = 0;
      tv = &tv_updates;
    }
    else
    {
      tv = NULL;
    }

    nSocketsAvailable = select(l, &f_recv, &f_send, NULL, tv);

    // Check if we timed out
    if (tv != NULL && nSocketsAvailable == 0)
    {
      ftman->PushFileTransferEvent(FT_UPDATE);
      gettimeofday(&ftman->tv_lastupdate, NULL);
    }

    nCurrentSocket = 0;
    while (nSocketsAvailable > 0 && nCurrentSocket < l)
    {
      if (FD_ISSET(nCurrentSocket, &f_recv))
      {
        // New socket event ----------------------------------------------------
        if (nCurrentSocket == ftman->pipe_thread[PIPE_READ])
        {
          read(ftman->pipe_thread[PIPE_READ], buf, 1);
          if (buf[0] == 'R')
          {
            DEBUG_THREADS("[FileTransferManager_tep] Reloading socket info.\n");
          }
          else if (buf[0] == 'X')
          {
            DEBUG_THREADS("[FileTransferManager_tep] Exiting.\n");
            pthread_exit(NULL);
          }
        }

        // Connection on the server port ---------------------------------------
        else if (nCurrentSocket == ftman->ftServer.Descriptor())
        {
          if (ftman->ftSock.Descriptor() != -1)
          {
            gLog.Warn(tr("%sFile Transfer: Receiving repeat incoming connection.\n"), L_WARNxSTR);
          }
          else
          {
            ftman->ftServer.RecvConnection(ftman->ftSock);
            ftman->sockman.AddSocket(&ftman->ftSock);
            ftman->sockman.DropSocket(&ftman->ftSock);

            ftman->m_nState = FT_STATE_HANDSHAKE;
            gLog.Info(tr("%sFile Transfer: Received connection.\n"), L_TCPxSTR);
          }
        }

        // Message from connected socket----------------------------------------
        else if (nCurrentSocket == ftman->ftSock.Descriptor())
        {
          ftman->ftSock.Lock();
          bool ok = ftman->ProcessPacket();
          ftman->ftSock.Unlock();
          if (!ok)
          {
            ftman->CloseConnection();
            ftman->PushFileTransferEvent(ftman->m_nResult);
          }
        }

        else
        {
          gLog.Warn(tr("%sFile Transfer: No such socket.\n"), L_WARNxSTR);
        }

        nSocketsAvailable--;
      }
      else if (FD_ISSET(nCurrentSocket, &f_send))
      {
        if (nCurrentSocket == ftman->ftSock.Descriptor())
        {
          ftman->ftSock.Lock();
          bool ok = ftman->SendFilePacket();
          ftman->ftSock.Unlock();
          if (!ok)
          {
            ftman->CloseConnection();
            ftman->PushFileTransferEvent(ftman->m_nResult);
          }
        }
        nSocketsAvailable--;
      }

      nCurrentSocket++;
    }
  }
  return NULL;
}