Ejemplo n.º 1
0
void ServerSocketThread::run (void)
{
    while (true) {
        Socket *pSocket = _pServerSocket->accept();
        if (pSocket) {
            printf ("ServerSocket: got a connection\n");
            ConnHandler *pHandler = new ConnHandler (pSocket);
            pHandler->start();
        }
    }
}
Ejemplo n.º 2
0
int main (int argc, char *argv[])
{
    #if defined (WIN32) && defined (_DEBUG)
        //getchar();    // Useful if you need to attach to the process before the break alloc happens
        _CrtSetReportMode (_CRT_ERROR, _CRTDBG_MODE_FILE);
        _CrtSetReportFile (_CRT_ERROR, _CRTDBG_FILE_STDERR);
        _CrtSetReportMode (_CRT_WARN, _CRTDBG_MODE_FILE);
        _CrtSetReportFile (_CRT_WARN, _CRTDBG_FILE_STDERR);
        //_CrtSetBreakAlloc (58);
    #endif

    if (argc < 2) {
        fprintf (stderr, "usage: %s <receiver | sender <filetosend> <server-hostname> <client-hostname> >\n", argv[0]);
        return -1;
    }
        
    pLogger = new Logger();
    pLogger->initLogFile ("filesend.log", false);
    pLogger->enableFileOutput();
    pLogger->disableScreenOutput();
    pLogger->setDebugLevel (Logger::L_MediumDetailDebug);
    
    Mocket *pMocket = new Mocket();
    pMocket->registerPeerUnreachableWarningCallback (unreachablePeerCallback, NULL);
    
    if (0 == stricmp (argv[1], "sender")) {
        if (argc != 5) {
            fprintf (stderr, "usage: %s <receiver | sender <filetosend> <server-hostname> <client-hostname> >\n", argv[0]);
            return -1;
        }
        
        pMocket->setIdentifier ("FileSend-Client");
        
        FILE *file = fopen (argv[2], "rb");
        if (file == NULL) {
            fprintf (stderr, "failed to open file %s\n", argv[2]);
            return -2;
        }

        // With this method we debug state capture by setting in mockets that only even packets can be sent.
        // Odd packets will remain in the queues and migrated to the new node along with the status of the mocket.
        pMocket->debugStateCapture();

        int rc;
        // Exchange security keys at connection time with parameter bSupportConnectivity = true
        // Or exchange keys as part of suspend/resume process with parameter bSupportConnectivity = false
        bool bSupportConnectivity = true;
        if (0 != (rc = pMocket->connect (argv[3], REM_PORT, bSupportConnectivity))) {
            fprintf (stderr, "failed to connect to host %s; rc = %d\n", argv[3], rc);
            delete pMocket;
            return -3;
        }

        char * buf = NULL;
        int n;
        int buffsize = 512;

        MessageSender sender = pMocket->getSender (true, true);
        while (true) {
            if (buffsize > 2048) {
                buffsize /= 5;
            }
            buf = (char*) malloc(buffsize);

            if ((n = fread (buf, 1, buffsize, file)) <= 0) {
                printf ("%s: EOF reached\n", argv[0]);
                free (buf);
                break;
            }
            else {
                printf("using buffer of size %d. Sending %d bytes\n", buffsize, n);
                sender.send (buf, n);
            }

            free(buf);
            // Increase the buffer size so we test with different packet dimensions
            buffsize *= 1.25;
        }
        fclose (file);
        // Suspend
        uint64 ui64StartSuspend = getTimeInMilliseconds();
        printf ("Mocket suspend finished with status %d\n", pMocket->suspend(0, 5000));
        printf ("TIME FOR SUSPENSION **  %llu  **\n", (getTimeInMilliseconds() - ui64StartSuspend));

        // Open a socket to transfer the data to the new client node
        String strNextNodeHost = argv[4];
        int iNextNodePort = 4444;
        TCPSocket *pSocketToNextNode;
        pSocketToNextNode = new TCPSocket();
        while (true) {
            printf ("trying to connect to %s:%d...\n", (const char*) strNextNodeHost, iNextNodePort);
            fflush (stdout);
            if (0 != (rc = pSocketToNextNode->connect (strNextNodeHost, iNextNodePort))) {
                printf ("failed - will try again in 2 seconds\n");
                sleepForMilliseconds (2000);
            }
            else {
                printf ("Connected\n");
                break;
            }
        }

        SocketWriter sw (pSocketToNextNode);
        BufferedWriter bw (&sw, 2048);
        
        // Freeze
        int result;
        uint64 ui64StartFreeze = getTimeInMilliseconds();
        result = pMocket->getState (&bw);
        printf ("TIME FOR GETSTATE **  %llu  **\n", (getTimeInMilliseconds() - ui64StartFreeze));
        printf ("getState ended with status %d\n", result);
        if (0 != result) {
            delete pMocket;
            return -3;
        }
    }

    else if (0 == stricmp (argv[1], "receiver")) {
        // Create the Server Socket
        int rc;
        TCPSocket *pServerSocket;
        pServerSocket = new TCPSocket();
        int iLocalPortNum = 4444;
        if (0 != (rc = pServerSocket->setupToReceive (iLocalPortNum))) {
            return -3;
        }
        printf ("listening on port %d\n", iLocalPortNum);
        
        Socket *pSocketFromPreviousNode;
        // Wait for connection from previous node
        printf ("Waiting for connection from previous node...\n");
        fflush (stdout);
        pSocketFromPreviousNode = pServerSocket->accept();
        if (pSocketFromPreviousNode == NULL) {
            printf ("Failed\n");
            return -4;
        }
        printf ("Connected\n");
        pSocketFromPreviousNode->bufferingMode(0);
        
        SocketReader sr (pSocketFromPreviousNode);
        BufferedReader br (&sr);
        
        // Resume
        int result;
        uint64 ui64StartResumeAndRestoreState = getTimeInMilliseconds();
        result = pMocket->resumeAndRestoreState (&br);
        printf ("TIME FOR RESUMEANDRESTORESTATE **  %llu  **\n", (getTimeInMilliseconds() - ui64StartResumeAndRestoreState));
        printf ("resumeFromSuspension ended with status %d\n", result);
        
        if (0 != result) {
            printf ("ERROR\n");
            delete pMocket;
            return -5;
        }

        /*
         * The connection has been restored successfully.
         * We do not set to skip odd packets with the method debugStateCapture().
         * Odd packets that were in the queues and have migrated to the new node will be sent now.
         * Sleep for a little bit before closing the connection so that the queues can be emptied.
         */
        sleepForMilliseconds (5000);

        delete (pServerSocket);
        pServerSocket = NULL;
        delete (pSocketFromPreviousNode);
        pSocketFromPreviousNode = NULL;
        pMocket->close();
    }
    else {
        printf ("ERROR\n");
        return 0;
    }
    
    printf ("Mocket statistics:\n");
    printf ("    Packets sent: %d\n", pMocket->getStatistics()->getSentPacketCount());
    printf ("    Bytes sent: %d\n", pMocket->getStatistics()->getSentByteCount());
    printf ("    Packets received: %d\n", pMocket->getStatistics()->getReceivedPacketCount());
    printf ("    Bytes received: %d\n", pMocket->getStatistics()->getReceivedByteCount());
    printf ("    Retransmits: %d\n", pMocket->getStatistics()->getRetransmitCount());

    delete pMocket;

    delete pLogger;
    pLogger = NULL;

    #if defined (WIN32) && defined (_DEBUG)
        _CrtDumpMemoryLeaks();
    #endif
    return 0;
}
Packet*
PacketReceiver::receiveAndCreatePacket(int32 micros,
                                       TCPSocket** tcpReceiverSock) 
{
   // Variables that must be set before creating the packet
   byte* buffer = NULL;
   /*ssize_t*/uint32 bufferLength = 0;
   int packetLength = 0;
   
   // Used to get the correct socket to read from
   TCPSocket* tcpSock;
   DatagramReceiver* datagramSock;

   // Reset tcpReceiverSock
   if ( tcpReceiverSock != NULL ) {
      *tcpReceiverSock = NULL;
   }
   
   if ( m_receiver.select( micros, tcpSock, datagramSock ) ) {
      if ( tcpSock != NULL ) {
         // Set the socket to read from depending on the state
         TCPSocket* readSocket = tcpSock;
         bool deleteReadSocket = false;
         bool keepSocket = false; // Override on deleteReadSocket

         if (tcpSock->getState() == TCPSocket::LISTEN) {
            uint32 acceptStartTime = TimeUtility::getCurrentTime();
            readSocket = tcpSock->accept();
            uint32 acceptTime = TimeUtility::getCurrentTime() - acceptStartTime;
            if ( acceptTime > 1000 ) {
               mc2dbg << "[PR]: Took " << acceptTime
                      << " to accept which is unacceptable" << endl;
            }
            // Check if the socket should be permanently added.
            if ( isPermanent( tcpSock ) ) {
               mc2dbg8 << "[PR]: Socket is permanent" << endl;
               // Yes - add the child socket too.
               addPermanentTCPSocket( readSocket );
            } else {
               PacketReceiveSocket* prs =  
                  dynamic_cast< PacketReceiveSocket* > ( readSocket );
               if ( prs == NULL ) {
                  mc2dbg8 << "[PR]: New socket is not PacketReceiveSocket"
                          << endl;
                  // No - disconnect after reading a packet.
                  deleteReadSocket = true;
               } else {
                  // Continue reading next time.
                  mc2dbg8 << "[PR]: I will read during the next round"
                          << endl;
                  // Add the socket, but don't restart the selector.
                  m_receiver.addTCPSocket( readSocket, true );
                  readSocket = NULL;
                  keepSocket = true;
               }
            }            
         }
            
         if (readSocket != NULL) {
            if ( dynamic_cast< PacketReceiveSocket* > ( readSocket ) ) {
               PacketReceiveSocket* prs =  
                  static_cast< PacketReceiveSocket* > ( readSocket );
               prs->readBytes();
               if ( prs->getReadState() == PacketReceiveSocket::done ) {
                  buffer = prs->getBuffer( true );
                  bufferLength = prs->getSize();
                  packetLength = prs->getSize();
                  if ( !isPermanent( readSocket ) ) {
                     deleteReadSocket = true;
                     removeTCPSocket ( readSocket );
                  }
               } else if ( prs->getReadState() == 
                           PacketReceiveSocket::reading_size ||
                           prs->getReadState() == 
                           PacketReceiveSocket::reading_packet )
               {
                  // This shouldn't happen anymore since it has been
                  // done above.
                  if ( readSocket != tcpSock && !isPermanent( tcpSock ) ) {
                     // Add new socket
                     MC2_ASSERT( false );
                     m_receiver.addTCPSocket( readSocket );
                  }
                  keepSocket = true;
               } else {
                  // Else error
                  if ( !isPermanent( readSocket ) ) {
                     deleteReadSocket = true;
                  }
               }
            } else if ( ! isPermanent( readSocket ) ) {
               // Should not hang forever if someone connects without
               // sending
               buffer = readPacket( readSocket, bufferLength, packetLength,
                                    10*1000*1000);
            } else {
               // Maybe timeout here too?
               buffer = readPacket( readSocket, bufferLength, packetLength);
            }
            if ( buffer == NULL && !keepSocket ) {
               if ( isPermanent(readSocket) ) {
                  // We do not want to receive more stuff on this one.
                  removeTCPSocket ( readSocket );
                  mc2dbg << "[PacketReceiver] Permanent socket closed"
                     " no need to crash" << endl;
               } else {
                  mc2log << warn << "PacketReceiver::receiveAndCreatePacket "
                         << "failed to read packet from socket." << endl;
                  if ( readSocket == tcpSock &&
                       tcpSock->getState() == TCPSocket::LISTEN ) {
                     mc2log << "PacketReceiver::receiveAndCreatePacket "
                            << "Failed to read from main socket: " 
                            << "Error: exiting with exit(2) instead of "
                            << "trying to fix the situation." << endl;
                     exit( 2 );
                  }
               } 
            }
         }
         // Check if the read-socket should be deleted or not.
         if ( keepSocket ) {
            // Keep it to read more later
         } else if (deleteReadSocket) {
            delete readSocket;
         } else if ( tcpReceiverSock != NULL ) {
            *tcpReceiverSock = readSocket;
         }
         
      } else if ( datagramSock != NULL ) {
         // Create buffer.
         bufferLength = Packet::MAX_UDP_PACKET_SIZE;
         buffer = new byte[bufferLength];
         packetLength = datagramSock->receive(buffer, bufferLength);
         if (packetLength < 0) {
            delete [] buffer;
            buffer = NULL;
         }
      }
   }

   // Return
   if (buffer != NULL) {
      Packet* returnPacket = Packet::makePacket(buffer, 
                                                bufferLength);
      returnPacket->setLength(packetLength);
      return returnPacket;
   } else {
      return NULL;
   }
}