Пример #1
0
// This is a text based test client for the muscled server.  It is useful for testing
// the server, and could possibly be useful for other things, I don't know.
int main(int argc, char ** argv)
{
   CompleteSetupSystem css;

   String hostName;
   uint16 port = 2960;
   if (argc > 1) ParseConnectArg(argv[1], hostName, port, false);
   ConstSocketRef sock = Connect(hostName(), port, "portablereflectclient", false);
   if (sock() == NULL) return 10;

   // We'll receive plain text over stdin
   StdinDataIO stdinIO(false);
   PlainTextMessageIOGateway stdinGateway; 
   stdinGateway.SetDataIO(DataIORef(&stdinIO, false));

   // And send and receive flattened Message objects over our TCP socket
   TCPSocketDataIO tcpIO(sock, false);
   MessageIOGateway tcpGateway;
   tcpGateway.SetDataIO(DataIORef(&tcpIO, false));

   DataIORef networkIORef(&tcpIO, false);
   AbstractMessageIOGatewayRef gatewayRef(&tcpGateway, false);

#ifdef MUSCLE_ENABLE_SSL
   for (int i=1; i<argc; i++)
   {
      const char * a = argv[i];
      if (strncmp(a, "publickey=", 10) == 0)
      { 
         a += 10;  // skip past the 'publickey=' part
         SSLSocketDataIO * sslIO = new SSLSocketDataIO(sock, false, false);
         DataIORef sslIORef(sslIO);
         if (sslIO->SetPublicKeyCertificate(a) == B_NO_ERROR) 
         {
            LogTime(MUSCLE_LOG_INFO, "Using public key certificate file [%s] to connect to server\n", a);
            networkIORef = sslIORef;
            gatewayRef.SetRef(new SSLSocketAdapterGateway(gatewayRef));
            gatewayRef()->SetDataIO(networkIORef);
         }
         else
         {
            LogTime(MUSCLE_LOG_CRITICALERROR, "Couldn't load public key certificate file [%s] (file not found?)\n", a);
            return 10;
         }
      }
   }
#endif

   SocketMultiplexer multiplexer;
   QueueGatewayMessageReceiver stdinInQueue, tcpInQueue;
   bool keepGoing = true;
   uint64 nextTimeoutTime = MUSCLE_TIME_NEVER;
   while(keepGoing)
   {
      const int stdinFD       = stdinIO.GetReadSelectSocket().GetFileDescriptor();
      const int socketReadFD  = networkIORef()->GetReadSelectSocket().GetFileDescriptor();
      const int socketWriteFD = networkIORef()->GetWriteSelectSocket().GetFileDescriptor();

      multiplexer.RegisterSocketForReadReady(stdinFD);
      multiplexer.RegisterSocketForReadReady(socketReadFD);
      if (gatewayRef()->HasBytesToOutput()) multiplexer.RegisterSocketForWriteReady(socketWriteFD);
      if (multiplexer.WaitForEvents(nextTimeoutTime) < 0) printf("portablereflectclient: WaitForEvents() failed!\n");

      const uint64 now = GetRunTime64();
      if (now >= nextTimeoutTime)
      {
         // For OpenSSL testing:  Generate some traffic to the server every 50mS
         printf("Uploading timed OpenSSL-tester update at time " UINT64_FORMAT_SPEC "\n", now);
         MessageRef stateMsg = GetMessageFromPool();
         stateMsg()->AddString("username", "portablereflectclient");
         stateMsg()->AddPoint("position", Point((rand()%100)/100.0f, (rand()%100)/100.0f));
         stateMsg()->AddInt32("color", -1);

         MessageRef uploadMsg = GetMessageFromPool(PR_COMMAND_SETDATA);
         uploadMsg()->AddMessage("qt_example/state", stateMsg);
         gatewayRef()->AddOutgoingMessage(uploadMsg);

         nextTimeoutTime = now + MillisToMicros(50);
      }

      // Receive data from stdin
      if (multiplexer.IsSocketReadyForRead(stdinFD))
      {
         while(1)
         {
            const int32 bytesRead = stdinGateway.DoInput(stdinInQueue);
            if (bytesRead < 0)
            {
               printf("Stdin closed, exiting!\n");
               keepGoing = false;
               break;
            }
            else if (bytesRead == 0) break;  // no more to read
         }
      }

      // Handle any input lines that were received from stdin
      MessageRef msgFromStdin;
      while(stdinInQueue.RemoveHead(msgFromStdin) == B_NO_ERROR)
      {
         const String * st;
         for (int32 i=0; msgFromStdin()->FindString(PR_NAME_TEXT_LINE, i, &st) == B_NO_ERROR; i++)
         {
            const char * text = st->Cstr();

            printf("You typed: [%s]\n", text);
            bool send = true;
            MessageRef ref = GetMessageFromPool();

            const char * arg1 = (st->Length()>2) ? &text[2] : NULL;
            switch(text[0])
            {
               case 'm':
                  ref()->what = MAKETYPE("umsg");
                  if (arg1) ref()->AddString(PR_NAME_KEYS, arg1);
                  ref()->AddString("info", "This is a user message");
               break;

               case 'i':
                  ref()->what = PR_COMMAND_PING;
                  ref()->AddString("Test ping", "yeah");
               break;

               case 's':
               {
                  ref()->what = PR_COMMAND_SETDATA;
                  MessageRef uploadMsg = GetMessageFromPool(MAKETYPE("HELO"));
                  uploadMsg()->AddString("This node was posted at: ", GetHumanReadableTimeString(GetRunTime64()));
                  if (arg1) ref()->AddMessage(arg1, uploadMsg);
               }
               break;

               case 'k':
                  ref()->what = PR_COMMAND_KICK;
                  if (arg1) ref()->AddString(PR_NAME_KEYS, arg1);
               break;

               case 'b':
                  ref()->what = PR_COMMAND_ADDBANS;
                  if (arg1) ref()->AddString(PR_NAME_KEYS, arg1);
               break;

               case 'B':
                  ref()->what = PR_COMMAND_REMOVEBANS;
                  if (arg1) ref()->AddString(PR_NAME_KEYS, arg1);
               break;

               case 'g':
                  ref()->what = PR_COMMAND_GETDATA;
                  if (arg1) ref()->AddString(PR_NAME_KEYS, arg1);
               break;

               case 'G':
                  ref()->what = PR_COMMAND_GETDATATREES;
                  if (arg1) ref()->AddString(PR_NAME_KEYS, arg1);
                  ref()->AddString(PR_NAME_TREE_REQUEST_ID, "Tree ID!");
               break;

               case 'q':
                  keepGoing = send = false;
               break;

               case 'p':
                  ref()->what = PR_COMMAND_SETPARAMETERS;
                  if (arg1) ref()->AddString(arg1, "");
               break;

               case 'P':
                  ref()->what = PR_COMMAND_GETPARAMETERS;
               break;

               case 'L':
               {
                  // simulate the behavior of qt_example, for testing OpenSSL problem
                  ref()->what = PR_COMMAND_SETPARAMETERS;
                  ref()->AddBool("SUBSCRIBE:qt_example/state", true);
                  printf("Starting OpenSSL problem test...\n");
                  nextTimeoutTime = 0;
               }
               break;
 
               case 'x':
               {
                  ref()->what = PR_COMMAND_SETPARAMETERS;
                  StringQueryFilter sqf("sc_tstr", StringQueryFilter::OP_SIMPLE_WILDCARD_MATCH, "*Output*");
                  ref()->AddArchiveMessage("SUBSCRIBE:/*/*/csproj/default/subcues/*", sqf);
               }
               break;

               case 'd':
                  ref()->what = PR_COMMAND_REMOVEDATA;
                  if (arg1) ref()->AddString(PR_NAME_KEYS, arg1);
               break;

               case 'D':
                  ref()->what = PR_COMMAND_REMOVEPARAMETERS;
                  if (arg1) ref()->AddString(PR_NAME_KEYS, arg1);
               break;

               case 't':
               {
                  // test all data types
                  ref()->what = 1234;
                  ref()->AddString("String", "this is a string");
                  ref()->AddInt8("Int8", 123);
                  ref()->AddInt8("-Int8", -123);
                  ref()->AddInt16("Int16", 1234);
                  ref()->AddInt16("-Int16", -1234);
                  ref()->AddInt32("Int32", 12345);
                  ref()->AddInt32("-Int32", -12345);
                  ref()->AddInt64("Int64", 123456789);
                  ref()->AddInt64("-Int64", -123456789);
                  ref()->AddBool("Bool", true);
                  ref()->AddBool("-Bool", false);
                  ref()->AddFloat("Float", 1234.56789f);
                  ref()->AddFloat("-Float", -1234.56789f);
                  ref()->AddDouble("Double", 1234.56789);
                  ref()->AddDouble("-Double", -1234.56789);
                  ref()->AddPointer("Pointer", ref());
                  ref()->AddFlat("Flat", *ref());
                  char data[] = "This is some data";
                  ref()->AddData("Flat", B_RAW_TYPE, data, sizeof(data));
               }
               break;

               default:
                  printf("Sorry, wot?\n");
                  send = false;
               break;
            }

            if (send) 
            {
               printf("Sending message...\n");
               ref()->PrintToStream();
               gatewayRef()->AddOutgoingMessage(ref);
            }
         }
      }

      // Handle input and output on the TCP socket
      const bool reading = multiplexer.IsSocketReadyForRead(socketReadFD);
      const bool writing = multiplexer.IsSocketReadyForWrite(socketWriteFD);
      const bool writeError = ((writing)&&(gatewayRef()->DoOutput() < 0));
      const bool readError  = ((reading)&&(gatewayRef()->DoInput(tcpInQueue) < 0));
      if ((readError)||(writeError))
      {
         printf("Connection closed (%s), exiting.\n", writeError?"Write Error":"Read Error");
         keepGoing = false;
      }

      MessageRef msgFromTCP;
      while(tcpInQueue.RemoveHead(msgFromTCP) == B_NO_ERROR)
      {
         printf("Heard message from server:-----------------------------------\n");
         msgFromTCP()->PrintToStream();
         printf("-------------------------------------------------------------\n");
      }
   }

   if (gatewayRef()->HasBytesToOutput())
   {
      printf("Waiting for all pending messages to be sent...\n");
      while((gatewayRef()->HasBytesToOutput())&&(gatewayRef()->DoOutput() >= 0)) {printf ("."); fflush(stdout);}
   }
   printf("\n\nBye!\n");

   return 0;
}
Пример #2
0
status_t
AbstractReflectSession ::
Reconnect()
{
   TCHECKPOINT;

#ifdef MUSCLE_ENABLE_SSL
   ConstByteBufferRef publicKey;  // If it's an SSL connection we'll grab its key into here so we can reuse it
#endif

   MASSERT(IsAttachedToServer(), "Can not call Reconnect() while not attached to the server");
   if (_gateway())
   {
#ifdef MUSCLE_ENABLE_SSL
      SSLSocketDataIO * sdio = dynamic_cast<SSLSocketDataIO *>(_gateway()->GetDataIO()());
      if (sdio) publicKey = sdio->GetPublicKeyCertificate();
#endif
      _gateway()->SetDataIO(DataIORef());  // get rid of any existing socket first
      _gateway()->Reset();                 // set gateway back to its virgin state
   }

   _isConnected = _wasConnected = false;
   SetConnectingAsync(false);

   bool doTCPConnect = ((_reconnectViaTCP)&&(_asyncConnectDest.GetIPAddress() != invalidIP));
   bool isReady = false;
   ConstSocketRef sock = doTCPConnect ? ConnectAsync(_asyncConnectDest.GetIPAddress(), _asyncConnectDest.GetPort(), isReady) : CreateDefaultSocket();

   // FogBugz #5256:  If ConnectAsync() fails, we want to act as if it succeeded, so that the calling
   //                 code still uses its normal asynchronous-connect-failure code path.  That way the
   //                 caller doesn't have to worry about synchronous failure as a separate case.
   if ((doTCPConnect)&&(sock() == NULL))
   {
      ConstSocketRef tempSockRef;  // tempSockRef represents the closed remote end of the failed connection and is intentionally closed ASAP
      if (CreateConnectedSocketPair(sock, tempSockRef) == B_NO_ERROR) doTCPConnect = false;
   }

   if (sock())
   {
      DataIORef io = CreateDataIO(sock);
      if (io())
      {
         if (_gateway() == NULL)
         {
            _gateway = CreateGateway();
            if (_gateway() == NULL) return B_ERROR;
         }

#ifdef MUSCLE_ENABLE_SSL
         // auto-wrap the user's gateway and socket in the necessary SSL adapters!
         if ((publicKey())&&(dynamic_cast<TCPSocketDataIO *>(io()) != NULL))
         {
            SSLSocketDataIO * ssio = newnothrow SSLSocketDataIO(sock, false, false);
            if (ssio == NULL) {WARN_OUT_OF_MEMORY; return B_ERROR;}
            io.SetRef(ssio);
            if (ssio->SetPublicKeyCertificate(publicKey) != B_NO_ERROR) return B_ERROR;

            if (dynamic_cast<SSLSocketAdapterGateway *>(_gateway()) == NULL) 
            {
               _gateway.SetRef(newnothrow SSLSocketAdapterGateway(_gateway));
               if (_gateway() == NULL) return B_ERROR;
            }
         }
#endif

         _gateway()->SetDataIO(io);
         if (isReady) 
         {
            _isConnected = _wasConnected = true;
            AsyncConnectCompleted();
         }
         else 
         {
            _isConnected = false;
            SetConnectingAsync(doTCPConnect);
         }
         _scratchReconnected = true;   // tells ReflectServer not to shut down our new IO!
         return B_NO_ERROR;
      }
   }
   return B_ERROR;
}