/// <summary>/// Just for showing pub/sub over the custom protocol.../// Your controller will probably have custom methods with strongly typed parameters./// </summary>[XSocketMetadata("sample")]public class SampleController : XSocketController{ public override void OnMessage(IMessage message) { this.PublishToAll(message); }}
public class SampleProtocol : XSocketProtocol{ public SampleProtocol() { this.ProtocolProxy = new SampleProtocolProxy(); } /// <summary> /// You can return false here since we implement a custom heartbeat for this sample... /// </summary> /// <returns></returns> public override bool CanDoHeartbeat() { return false; }
/// <summary> /// The message passed back on connection... /// </summary> public override string HostResponse { get { return "Welcome to SampleProtocol"; } }
/// <summary> /// Just adding crlf to get a new row since this protocol is for Putty or similar /// </summary> /// <returns></returns> public override byte[] GetHostResponse() { return Encoding.UTF8.GetBytes(string.Format("{0}\r\n", HostResponse)); }
public override bool Match(IList<byte> handshake) { //Check if the handshake matches the expected protocol... Do something more clever then this ;) return Encoding.UTF8.GetString(handshake.ToArray()).StartsWith("SampleProtocol"); }
/// <summary> /// Handle logic for reading frames... In this case I only look for \r\n... you probably have a more complex scenario /// </summary> /// <param name="segment"></param> /// <param name="readState"></param> /// <param name="processFrame"></param> public override void ReceiveData(ArraySegment<byte> segment, IReadState readState, Action<FrameType, IEnumerable<byte>> processFrame) { lock (_locker) { for (int i = 0; i < segment.Count; i++) { readState.Data.Add(segment.Array[i]); //if the frame is completed we will find \r\n at the end if (readState.Data.Count >= 2 && readState.Data[readState.Data.Count - 1] == 10 && readState.Data[readState.Data.Count - 2] == 13) { processFrame(FrameType.Text, readState.Data.Take(readState.Data.Count - 2)); readState.Clear(); } } } }
/// <summary> /// Convert the incoming frame to a IMessage... /// </summary> /// <param name="payload"></param> /// <param name="messageType"></param> /// <returns></returns> public override IMessage OnIncomingFrame(IEnumerable<byte> payload, MessageType messageType) { return this.ProtocolProxy.In(payload, messageType); }
/// <summary> /// Convert the outgoing IMessage to what ever your custom protocol and the client expects... /// </summary> /// <param name="message"></param> /// <returns></returns> public override byte[] OnOutgoingFrame(IMessage message) { return this.ProtocolProxy.Out(message); }
public override IXSocketProtocol NewInstance() { return new SampleProtocol(); }}
public class SampleProtocolProxy : IProtocolProxy{ private IXSocketJsonSerializer JsonSerializer { get; set; }
public SampleProtocolProxy() { JsonSerializer = Composable.GetExport<IXSocketJsonSerializer>(); }
/// <summary> /// I expect the stupid sample message to look like "controller|topic|data" /// You do not have to have controller and topic in here.. you might wanna send messages to a predefined controller for this protocol... /// I have no clue ;) /// </summary> /// <param name="payload"></param> /// <param name="messageType"></param> /// <returns></returns> public IMessage In(IEnumerable<byte> payload, MessageType messageType) { var data = Encoding.UTF8.GetString(payload.ToArray()); if (data.Length == 0) return null; var d = data.Split('|'); switch (d[1]) { //Special case for subscribe... case "subscribe": return new Message(new XSubscription { Topic = d[2] }, Constants.Events.PubSub.Subscribe, d[0], JsonSerializer); //Special case for unsubscribe... case "unsubscribe": return new Message(new XSubscription { Topic = d[2] }, Constants.Events.PubSub.Unsubscribe, d[0], JsonSerializer); default: return new Message(d[2], d[1], d[0], JsonSerializer);
} }
/// <summary> /// Just convert back to the format "controller|topic|data" /// </summary> /// <param name="message"></param> /// <returns></returns> public byte[] Out(IMessage message) { return Encoding.UTF8.GetBytes(string.Format("{0}|{1}|{2}\r\n", message.Controller, message.Topic, message.Data)); }}
sample|subscribe|foo
sample|foo|hello over my custom protocol