protected void ReadCommands() { // todo: more like Delphi code TCommands Command = TCommands.icEndSession; // define once byte[] FixedCommandPart = new byte[MagicBytes.Length + sizeof(Int32) + sizeof(Int32)]; // magic + command + payloadsize TByteBuffer Payload = new TByteBuffer(); byte[] PayloadCheck = new byte[sizeof(Int32)]; do { try { try { if (ReadCommand(ref Command, FixedCommandPart, Payload, PayloadCheck)) { HandleCommand(Command, Payload); } else if (Connected) { Debug.Print("## Dropped command (" + (int)Command + ") in ReadCommands loop"); } } catch (ThreadAbortException) { Thread.ResetAbort(); Command = TCommands.icEndSession; } } catch (Exception e) { if (Connected) { Debug.Print("## Exception in ReadCommands loop: " + e.Message); } } } while (Command != TCommands.icEndSession && Connected); }
// Debug: public Int64 ReadCommandsCount = 0; // function returns payload of command, fills found command and returns problems during read in aResult // commandmagic + command + payloadsize [ + payload + payloadmagic] protected bool ReadCommand(ref TCommands aCommand, byte[] aFixedCommandPart, TByteBuffer aPayload, byte[] aPayloadCheck) { // Debug: ReadCommandsCount++; int NumBytesRead = FNetStream.Read(aFixedCommandPart, 0, aFixedCommandPart.Length); if (NumBytesRead > 0) { while (NumBytesRead < aFixedCommandPart.Length) { NumBytesRead += FNetStream.Read(aFixedCommandPart, NumBytesRead, aFixedCommandPart.Length - NumBytesRead); } while (BitConverter.ToInt64(aFixedCommandPart, 0) != MagicBytesInt64) { Array.Copy(aFixedCommandPart, 1, aFixedCommandPart, 0, aFixedCommandPart.Length - 1); int rbr = FNetStream.ReadByte(); if (rbr != -1) { aFixedCommandPart[aFixedCommandPart.Length - 1] = (byte)rbr; // skipped bytes because of invalid magic in read command } else { return(false); // error, no valid connection } } // we found the magic in the stream aCommand = (TCommands)BitConverter.ToInt32(aFixedCommandPart, MagicBytes.Length); Int32 PayloadSize = BitConverter.ToInt32(aFixedCommandPart, MagicBytes.Length + sizeof(Int32)); if (PayloadSize <= MaxPayloadSize) { aPayload.Clear(PayloadSize); if (PayloadSize > 0) { int Len = ReadBytesFromNetStream(aPayload); if (Len == aPayload.Length) { NumBytesRead = 0; while (NumBytesRead < aPayloadCheck.Length) { NumBytesRead += FNetStream.Read(aPayloadCheck, NumBytesRead, aPayloadCheck.Length - NumBytesRead); } return((NumBytesRead == aPayloadCheck.Length) && (BitConverter.ToInt32(aPayloadCheck, 0) == CheckStringMagic)); } else { return(false); // error, payload size mismatch } } else { return(true); // ok, no payload } } else { return(false); // error, payload is over max size } } else { return(false); // error, no valid connection } }
protected bool ReadCommand(ref TCommands aCommand, byte[] aFixedCommandPart, TByteBuffer aPayload, byte[] aPayloadCheck) { int NumBytesRead = FNetStream.Read(aFixedCommandPart, 0, aFixedCommandPart.Length); if (NumBytesRead > 0) { while (BitConverter.ToInt64(aFixedCommandPart, 0) != MagicBytesInt64) { Array.Copy(aFixedCommandPart, 1, aFixedCommandPart, 0, aFixedCommandPart.Length - 1); int rbr = FNetStream.ReadByte(); if (rbr != -1) aFixedCommandPart[aFixedCommandPart.Length - 1] = (byte)rbr; // skipped bytes because of invalid magic in read command else return false; // error, no valid connection } // we found the magic in the stream aCommand = (TCommands)BitConverter.ToInt32(aFixedCommandPart, MagicBytes.Length); Int32 PayloadSize = BitConverter.ToInt32(aFixedCommandPart, MagicBytes.Length + sizeof(Int32)); if (PayloadSize <= MaxPayloadSize) { aPayload.Clear(PayloadSize); if (PayloadSize > 0) { int Len = ReadBytesFromNetStream(aPayload); if (Len == aPayload.Length) { NumBytesRead = FNetStream.Read(aPayloadCheck, 0, aPayloadCheck.Length); return NumBytesRead == aPayloadCheck.Length && BitConverter.ToInt32(aPayloadCheck, 0) == CheckStringMagic; } else return false; // error, payload size mismatch } else return true; // ok, no payload } else return false; // error, payload is over max size } else return false; // error, no valid connection }
protected virtual void HandleCommand(TCommands aCommand, TByteBuffer aPayload) { }
public static void SocketRead(ref Socket Socket, ref TCommands RcvCmds, ref ByteArray RecBuf, TDecodePacketProc DecodeProc, byte XorByte) { if (Socket == null) { return; } if (Socket.Connected == false) { return; } if (Socket != null && Socket.Available > 0) { //野汪修正 續傳Buf不夠問題 Array.Clear(mSocketTempBuf, 0, mSocketTempBuf.Length); int count = Socket.Receive(mSocketTempBuf); int size = Math.Min(mSocketTempBuf.GetUpperBound(0) + 1, count); if ((size > 0) && (size + RecBuf.Size <= RecBuf.Data.Length)) { if (XorByte > 0) { for (int i = 0; i < mSocketTempBuf.Length; i++) { mSocketTempBuf[i] = (byte)(mSocketTempBuf[i] ^ XorByte); } } Array.Copy(mSocketTempBuf, 0, RecBuf.Data, RecBuf.Size, size); RecBuf.Size += size; while (RecBuf.Size > 0) { if (DecodeProc(ref RcvCmds.Cmds[RcvCmds.CmdTail], ref RecBuf)) { RcvCmds.CmdTail++; if (RcvCmds.CmdTail == RcvCmds.CmdHead) { RcvCmds.CmdTail = 0; RcvCmds.CmdHead = 0; } if (RcvCmds.CmdTail > RcvCmds.Cmds.GetUpperBound(0)) { RcvCmds.CmdTail = 0; } if (RecBuf.Index > 0 && RecBuf.Index < RecBuf.Size) { Array.Copy(RecBuf.Data, RecBuf.Index, RecBuf.Data, 0, RecBuf.Size - RecBuf.Index); RecBuf.Size -= RecBuf.Index; } else { RecBuf.Size = 0; } RecBuf.Index = 0; } else { return; } } } } }
private void HandleCommandOther(TCommands aCommand, TByteBuffer aPayload) { // override to implement protocol extensions }
private void HandleSubAndPub(TCommands aCommand, TByteBuffer aPayload) { string eventName; TEventEntry ee; switch (aCommand) { case TCommands.icSubscribe: case TCommands.icPublish: Int32 eventID; aPayload.Read(out eventID); Int32 eventEntryType; aPayload.Read(out eventEntryType); aPayload.Read(out eventName); ee = FindEventL(eventName); if (ee == null) { var ep = FindEventParentL(eventName); if (ep != null) { ee = AddEventL(eventName); ee.FParent = ep; ee.CopyHandlersFrom(ep); } } else { if (OnSubAndPub != null && !ee.IsEmpty) OnSubAndPub(this, aCommand, eventName); } if (ee != null) ee.HandleOnSubAndPub(aCommand); break; case TCommands.icUnsubscribe: case TCommands.icUnpublish: aPayload.Read(out eventName); if (OnSubAndPub != null) OnSubAndPub(this, aCommand, eventName); ee = FindEventL(eventName); if (ee != null) ee.HandleOnSubAndPub(aCommand); break; } }
// command handlers protected override void HandleCommand(TCommands aCommand, TByteBuffer aPayload) { switch (aCommand) { case TCommands.icEvent: HandleCommandEvent(aPayload); break; case TCommands.icSetVariable: HandleCommandVariable(aPayload); break; case TCommands.icSetEventIDTranslation: FEventTranslation.SetEventTranslation( aPayload.PeekInt32(0, TEventTranslation.InvalidTranslatedEventID), aPayload.PeekInt32(sizeof (Int32), TEventTranslation.InvalidTranslatedEventID)); break; case TCommands.icUniqueClientID: aPayload.Read(out FUniqueClientID); aPayload.Read(out FClientHandle); break; case TCommands.icTimeStamp: // ignore for now, only when using and syncing local time (we trust hub time for now) aPayload.Read(out FBrokerAbsoluteTime); aPayload.Read(out FBrokerTick); aPayload.Read(out FBrokerTickDelta); break; case TCommands.icEventNames: HandleEventNames(aPayload); break; case TCommands.icEndSession: Close(); break; case TCommands.icSubscribe: case TCommands.icPublish: case TCommands.icUnsubscribe: case TCommands.icUnpublish: HandleSubAndPub(aCommand, aPayload); break; default: HandleCommandOther(aCommand, aPayload); break; } }
internal int WriteCommand(TCommands aCommand, byte[] aPayload) { lock (WriteCommandLock) { var Buffer = new TByteBuffer(); Buffer.Prepare(MagicBytes); Buffer.Prepare((Int32) aCommand); Buffer.Prepare((Int32) 0); // payload size if ((aPayload != null) && (aPayload.Length > 0)) { Buffer.Prepare(aPayload); Buffer.Prepare(CheckStringMagic); } Buffer.PrepareApply(); Buffer.QWrite(MagicBytes); Buffer.QWrite((Int32) aCommand); if ((aPayload != null) && (aPayload.Length > 0)) { Buffer.QWrite((Int32) aPayload.Length); Buffer.QWrite(aPayload); Buffer.QWrite(CheckStringMagic); } else Buffer.QWrite((Int32) 0); // send buffer over socket if (Connected) { try { WriteCommandLow(Buffer.Buffer, Buffer.Length); return Buffer.Length; } catch { Close(); return iceConnectionClosed; } } else return iceConnectionClosed; } }