virtual void Pulse(const PulseArgs & args) { AbstractReflectSession::Pulse(args); while(_pendingReplies.HasItems()) { const uint64 nextSendTime = *_pendingReplies.GetFirstValue(); if (args.GetCallbackTime() >= nextSendTime) { MessageRef msgToSend; if (_pendingReplies.RemoveFirst(msgToSend) == B_NO_ERROR) { IPAddressAndPort dest; (void) msgToSend()->FindFlat(PR_NAME_PACKET_REMOTE_LOCATION, dest); printf("Sending UDP reply to [%s]:\n", dest.ToString()()); ByteBufferRef msgData; (void) msgToSend()->FindFlat(PR_NAME_DATA_CHUNKS, msgData); PrintHexBytes(msgData); // Hand the Message off to the RawMessageDataGateway for immediate transmission (void) AddOutgoingMessage(msgToSend); } } else break; // nothing to do yet!? } }
virtual void MessageReceivedFromGateway(const MessageRef & msg, void * userData) { ByteBufferRef receivedData; if (msg()->FindFlat(PR_NAME_DATA_CHUNKS, receivedData) == B_NO_ERROR) { IPAddressAndPort sourceIAP; if (msg()->FindFlat(PR_NAME_PACKET_REMOTE_LOCATION, sourceIAP) == B_NO_ERROR) { printf("Received from [%s]:\n", sourceIAP.ToString()()); PrintHexBytes(receivedData); // If we wanted to reply immediately, we could just call AddOutgoingMessage(msg) right here // But example_2_udp_pingpong waits 100mS before sending back the reply, so let's do that // here as well. We'll use Pulse() and GetPulseTime() to implement without blocking the // server's event loop. if (_pendingReplies.Put(msg, GetRunTime64()+MillisToMicros(100)) == B_NO_ERROR) InvalidatePulseTime(); } else LogTime(MUSCLE_LOG_ERROR, "Error, gateway didn't provide the UDP packet's source location?!\n"); } }
int32 PacketTunnelIOGateway :: DoInputImplementation(AbstractGatewayMessageReceiver & receiver, uint32 maxBytes) { if (_inputPacketBuffer.SetNumBytes(_maxTransferUnit, false) != B_NO_ERROR) return -1; bool firstTime = true; uint32 totalBytesRead = 0; while((totalBytesRead < maxBytes)&&((firstTime)||(IsSuggestedTimeSliceExpired() == false))) { firstTime = false; int32 bytesRead = GetDataIO()()->Read(_inputPacketBuffer.GetBuffer(), _inputPacketBuffer.GetNumBytes()); //printf(" READ " INT32_FORMAT_SPEC "/" UINT32_FORMAT_SPEC " bytes\n", bytesRead, _inputPacketBuffer.GetNumBytes()); if (bytesRead > 0) { totalBytesRead += bytesRead; IPAddressAndPort fromIAP; const PacketDataIO * packetIO = dynamic_cast<PacketDataIO *>(GetDataIO()()); if (packetIO) fromIAP = packetIO->GetSourceOfLastReadPacket(); const uint8 * p = (const uint8 *) _inputPacketBuffer.GetBuffer(); if ((_allowMiscData)&&((bytesRead < (int32)FRAGMENT_HEADER_SIZE)||(((uint32)B_LENDIAN_TO_HOST_INT32(muscleCopyIn<uint32>(p))) != _magic))) { // If we're allowed to handle miscellaneous data, we'll just pass it on through verbatim ByteBuffer temp; temp.AdoptBuffer(bytesRead, const_cast<uint8 *>(p)); HandleIncomingMessage(receiver, ByteBufferRef(&temp, false), fromIAP); (void) temp.ReleaseBuffer(); } else { const uint8 * invalidByte = p+bytesRead; while(invalidByte-p >= (int32)FRAGMENT_HEADER_SIZE) { const uint32 magic = B_LENDIAN_TO_HOST_INT32(muscleCopyIn<uint32>(&p[0*sizeof(uint32)])); const uint32 sexID = B_LENDIAN_TO_HOST_INT32(muscleCopyIn<uint32>(&p[1*sizeof(uint32)])); const uint32 messageID = B_LENDIAN_TO_HOST_INT32(muscleCopyIn<uint32>(&p[2*sizeof(uint32)])); const uint32 offset = B_LENDIAN_TO_HOST_INT32(muscleCopyIn<uint32>(&p[3*sizeof(uint32)])); const uint32 chunkSize = B_LENDIAN_TO_HOST_INT32(muscleCopyIn<uint32>(&p[4*sizeof(uint32)])); const uint32 totalSize = B_LENDIAN_TO_HOST_INT32(muscleCopyIn<uint32>(&p[5*sizeof(uint32)])); //printf(" PARSE magic=" UINT32_FORMAT_SPEC "/" UINT32_FORMAT_SPEC " sex=" UINT32_FORMAT_SPEC "/" UINT32_FORMAT_SPEC " messageID=" UINT32_FORMAT_SPEC " offset=" UINT32_FORMAT_SPEC " chunkSize=" UINT32_FORMAT_SPEC " totalSize=" UINT32_FORMAT_SPEC "\n", magic, _magic, sexID, _sexID, messageID, offset, chunkSize, totalSize); p += FRAGMENT_HEADER_SIZE; if ((magic == _magic)&&((_sexID == 0)||(_sexID != sexID))&&((invalidByte-p >= (int32)chunkSize)&&(totalSize <= _maxIncomingMessageSize))) { ReceiveState * rs = _receiveStates.Get(fromIAP); if (rs == NULL) { if (offset == 0) rs = _receiveStates.PutAndGet(fromIAP, ReceiveState(messageID)); if (rs) { rs->_buf = GetByteBufferFromPool(totalSize); if (rs->_buf() == NULL) { _receiveStates.Remove(fromIAP); rs = NULL; } } } if (rs) { if ((offset == 0)||(messageID != rs->_messageID)) { // A new message... start receiving it (but only if we are starting at the beginning) rs->_messageID = messageID; rs->_offset = 0; rs->_buf()->SetNumBytes(totalSize, false); } uint32 rsSize = rs->_buf()->GetNumBytes(); //printf(" CHECK: offset=" UINT32_FORMAT_SPEC "/" UINT32_FORMAT_SPEC " %s\n", offset, rs->_offset, (offset==rs->_offset)?"":"DISCONTINUITY!!!"); if ((messageID == rs->_messageID)&&(totalSize == rsSize)&&(offset == rs->_offset)&&(offset+chunkSize <= rsSize)) { memcpy(rs->_buf()->GetBuffer()+offset, p, chunkSize); rs->_offset += chunkSize; if (rs->_offset == rsSize) { HandleIncomingMessage(receiver, rs->_buf, fromIAP); rs->_offset = 0; rs->_buf()->Clear(rsSize > MAX_CACHE_SIZE); } } else { LogTime(MUSCLE_LOG_DEBUG, "Unknown fragment (" UINT32_FORMAT_SPEC "/" UINT32_FORMAT_SPEC "/" UINT32_FORMAT_SPEC "/" UINT32_FORMAT_SPEC ") received from %s, ignoring it.\n", messageID, offset, chunkSize, totalSize, fromIAP.ToString()()); rs->_offset = 0; rs->_buf()->Clear(rsSize > MAX_CACHE_SIZE); } } p += chunkSize; } else break; } } } else if (bytesRead < 0) return -1; else break; } return totalBytesRead; }
int main(int argc, char ** argv) { CompleteSetupSystem css; PrintExampleDescription(); // Let's enable a bit of debug-output, just to see what the client is doing SetConsoleLogLevel(MUSCLE_LOG_DEBUG); MessageTransceiverThread mtt; if (mtt.StartInternalThread() != B_NO_ERROR) { LogTime(MUSCLE_LOG_CRITICALERROR, "Couldn't start the MessageTransceiverThread, aborting!\n"); return 10; } if (mtt.AddNewConnectSession(localhostIP, SMART_SERVER_TCP_PORT, SecondsToMicros(1)) != B_NO_ERROR) { LogTime(MUSCLE_LOG_CRITICALERROR, "mtt.AddNewConnectSession() failed, aborting!\n"); mtt.ShutdownInternalThread(); return 10; } LogTime(MUSCLE_LOG_INFO, "This program is designed to be run in conjunction with example_4_smart_server\n"); LogTime(MUSCLE_LOG_INFO, "You'll probably want to run multiple instances of this client at the same time, also.\n"); printf("\n"); PrintHelp(); printf("\n"); LogTime(MUSCLE_LOG_INFO, "Some example commands that you can enter:\n"); LogTime(MUSCLE_LOG_INFO, " subscribe /*/* -> will set up a subscription that always lets you know who is connected\n"); LogTime(MUSCLE_LOG_INFO, " subscribe /*/*/* -> will set up a subscription that always lets you know who set/deleted/updated a node\n"); LogTime(MUSCLE_LOG_INFO, " subscribe * -> is the same as the previous command (the initial wildcards can be implicit)\n"); LogTime(MUSCLE_LOG_INFO, " set frood = groovy -> create a node named 'frood' in your session-folder, with the word 'groovy' in its Message\n"); LogTime(MUSCLE_LOG_INFO, " delete frood -> delete the node named 'frood' in your session-folder\n"); LogTime(MUSCLE_LOG_INFO, " delete f* -> delete all nodes in your session-folder whose names start with f\n"); LogTime(MUSCLE_LOG_INFO, " delete * -> delete all nodes in your session-folder\n"); LogTime(MUSCLE_LOG_INFO, " msg /*/* hello -> say hello to everyone who is connected\n"); LogTime(MUSCLE_LOG_INFO, " msg /*/*/frood hello -> say hello to everyone who is connected and created a node named \'frood\' in their session-folder\n"); LogTime(MUSCLE_LOG_INFO, " die -> cause the client process to exit\n"); printf("\n"); // Run our own event loop to read from stdin and retrieve // feedback events from the MessageTransceiverThread. // (In other contexts this might be a QEventLoop or // a Win32 event loop or an SDL event loop or etc; anything // where the main thread needs to be doing some non-MUSCLE // event loop is a good use case for QMessageTransceiverThread) StdinDataIO stdinIO(false); SocketMultiplexer sm; while(true) { sm.RegisterSocketForReadReady(stdinIO.GetReadSelectSocket().GetFileDescriptor()); sm.RegisterSocketForReadReady(mtt.GetOwnerWakeupSocket().GetFileDescriptor()); sm.WaitForEvents(); if (sm.IsSocketReadyForRead(stdinIO.GetReadSelectSocket().GetFileDescriptor())) { // Handle stdin input, and send a Message to the MessageTransceiverThread // for it to send on to the server, if appropriate uint8 inputBuf[1024]; const int numBytesRead = stdinIO.Read(inputBuf, sizeof(inputBuf)-1); if (numBytesRead > 0) { String inputCmd((const char *) inputBuf, numBytesRead); inputCmd = inputCmd.Trim(); if (inputCmd == "die") break; MessageRef msgToSend = ParseStdinCommand(inputCmd); if (msgToSend()) { printf("Calling mtt.SendMessageToSessions() with the following Message:\n"); msgToSend()->PrintToStream(); (void) mtt.SendMessageToSessions(msgToSend); } } else if (numBytesRead < 0) break; } if (sm.IsSocketReadyForRead(mtt.GetOwnerWakeupSocket().GetFileDescriptor())) { // Handle any feedback events sent back to us from the MessageTransceiverThread uint32 code; MessageRef ref; String session; uint32 factoryID; IPAddressAndPort location; while(mtt.GetNextEventFromInternalThread(code, &ref, &session, &factoryID, &location) >= 0) { String codeStr; switch(code) { case MTT_EVENT_INCOMING_MESSAGE: codeStr = "IncomingMessage"; break; case MTT_EVENT_SESSION_ACCEPTED: codeStr = "SessionAccepted"; break; case MTT_EVENT_SESSION_ATTACHED: codeStr = "SessionAttached"; break; case MTT_EVENT_SESSION_CONNECTED: codeStr = "SessionConnected"; break; case MTT_EVENT_SESSION_DISCONNECTED: codeStr = "SessionDisconnected"; break; case MTT_EVENT_SESSION_DETACHED: codeStr = "SessionDetached"; break; case MTT_EVENT_FACTORY_ATTACHED: codeStr = "FactoryAttached"; break; case MTT_EVENT_FACTORY_DETACHED: codeStr = "FactoryDetached"; break; case MTT_EVENT_OUTPUT_QUEUES_DRAINED: codeStr = "OutputQueuesDrained"; break; case MTT_EVENT_SERVER_EXITED: codeStr = "ServerExited"; break; default: codeStr = String("\'%1\'").Arg(GetTypeCodeString(code)); break; } printf("Event from MTT: type=[%s], session=[%s] factoryID=[" UINT32_FORMAT_SPEC "] location=[%s]\n", codeStr(), session(), factoryID, location.ToString()()); if (ref()) ref()->PrintToStream(); } } } mtt.ShutdownInternalThread(); return 0; }
virtual ThreadWorkerSessionRef CreateThreadWorkerSession(const String & loc, const IPAddressAndPort & iap) { AdvancedThreadWorkerSession * ret = newnothrow AdvancedThreadWorkerSession(); if (ret) printf("AdvancedThreadWorkerSessionFactory created AdvancedThreadWorkerSession %p for client at loc=[%s] iap=[%s]\n", ret, loc(), iap.ToString()()); else WARN_OUT_OF_MEMORY; return ThreadWorkerSessionRef(ret); }
virtual AbstractReflectSessionRef CreateSession(const String & clientAddress, const IPAddressAndPort & factoryInfo) { printf("MyDumbReflectSessionFactory::CreateSession() called! (clientAddress=[%s] factoryInfo=[%s])\n", clientAddress(), factoryInfo.ToString()()); return AbstractReflectSessionRef(new MyDumbReflectSession); }