private void GenerateUniqueName(RemoteXTMF ourRemoteClient) { int uniqueID = Interlocked.Increment(ref this.UniqueID); ourRemoteClient.UniqueID = String.Format("Client:{0}", uniqueID); }
private bool ProcessMessage(bool done, RemoteXTMF ourRemoteClient, BinaryWriter writer, BinaryFormatter converter, Message message) { if (message != null) { //If we have a message to process, process it switch (message.Type) { case MessageType.Quit: { done = true; } break; case MessageType.RequestProgress: { writer.Write((Int32)MessageType.RequestProgress); writer.Flush(); } break; case MessageType.RequestResource: { var name = message.Data as string; object data; writer.Write((Int32)MessageType.ReturningResource); writer.Write(name); if (this.Resources.TryGetValue(name, out data)) { writer.Write(true); converter.Serialize(writer.BaseStream, data); } else { writer.Write(false); } writer.Flush(); } break; case MessageType.PostComplete: { this.CompletedTask(ourRemoteClient, 0, String.Empty); } break; case MessageType.PostCancel: { writer.Write((Int32)MessageType.PostCancel); writer.Flush(); } break; case MessageType.PostProgess: { var progress = (float)message.Data; ourRemoteClient.Progress = progress; // we need to lock here since other clients could also // be trying to update the host with their progress lock (this) { try { if (this.ProgressUpdated != null) { this.ProgressUpdated(ourRemoteClient, progress); } } catch { } } } break; case MessageType.PostResource: { var data = (ResourcePost)message.Data; this.Resources[data.Name] = data.Data; } break; case MessageType.SendModelSystem: { writer.Write((Int32)MessageType.SendModelSystem); var mss = message.Data as IModelSystemStructure; try { byte[] data = null; using (MemoryStream memStream = new MemoryStream()) { mss.Save(memStream); memStream.Position = 0; data = memStream.ToArray(); } writer.Write(data.Length); writer.Write(data, 0, data.Length); } catch (Exception e) { Console.WriteLine(e.ToString()); } writer.Flush(); } break; case MessageType.SendCustomMessage: { var msg = message.Data as SendCustomMessageMessage; int msgNumber = msg.CustomMessageNumber; int length = 0; var failed = false; byte[] buffer = null; Action <object, IRemoteXTMF, Stream> customConverter; if (this.CustomSenders.TryGetValue(msgNumber, out customConverter)) { using (MemoryStream mem = new MemoryStream(0x100)) { try { customConverter(msg.Data, ourRemoteClient, mem); mem.Position = 0; buffer = mem.ToArray(); length = buffer.Length; } catch { failed = true; } } } writer.Write((int)MessageType.SendCustomMessage); writer.Write((int)msg.CustomMessageNumber); writer.Write((Int32)length); if (!failed) { writer.Write(buffer, 0, length); buffer = null; } } break; case MessageType.ReceiveCustomMessage: { var msg = message.Data as ReceiveCustomMessageMessage; var customNumber = msg.CustomMessageNumber; Func <Stream, IRemoteXTMF, object> customConverter; if (this.CustomReceivers.TryGetValue(customNumber, out customConverter)) { using (var stream = msg.Stream) { try { object output = customConverter(stream, ourRemoteClient); List <Action <object, IRemoteXTMF> > handlers; if (this.CustomHandlers.TryGetValue(msg.CustomMessageNumber, out handlers)) { foreach (var handler in handlers) { try { handler(output, ourRemoteClient); } catch { } } } } catch { } } } } break; default: { done = true; } break; } } return(done); }
private void ClientMain(object clientObject) { var client = clientObject as TcpClient; if (client == null) { return; } bool done = false; RemoteXTMF ourRemoteClient = new RemoteXTMF(); try { // Step 1) Accept the Client var clientStream = client.GetStream(); GenerateUniqueName(ourRemoteClient); this.AvailableClients.Add(ourRemoteClient); lock (this) { try { this.ConnectedClients.Add(ourRemoteClient); if (this.NewClientConnected != null) { this.NewClientConnected(ourRemoteClient); } } catch { } } // Start up the thread to process the messages coming from the remote xtmf new Thread(delegate() { while (!done && !this.Exit) { // cycle every 500ms ~ 1/2 second try { clientStream.ReadTimeout = Timeout.Infinite; BinaryReader reader = new BinaryReader(clientStream); BinaryFormatter readingConverter = new BinaryFormatter(); while (!done && !this.Exit) { var messageType = (MessageType)reader.ReadInt32(); var clientMessage = new Message(messageType); switch (messageType) { case MessageType.Quit: { done = true; return; } case MessageType.RequestResource: { var name = reader.ReadString(); clientMessage.Data = name; ourRemoteClient.Messages.Add(clientMessage); } break; case MessageType.PostProgess: { var progress = reader.ReadSingle(); clientMessage.Data = progress; ourRemoteClient.Messages.Add(clientMessage); } break; case MessageType.PostComplete: { ourRemoteClient.Messages.Add(clientMessage); } break; case MessageType.PostResource: { var data = readingConverter.Deserialize(reader.BaseStream); clientMessage.Data = data; ourRemoteClient.Messages.Add(clientMessage); } break; case MessageType.SendCustomMessage: { // Time to recieve a new custom message var number = reader.ReadInt32(); var length = reader.ReadInt32(); var buff = new byte[length]; MemoryStream buffer = new MemoryStream(buff); int soFar = 0; while (soFar < length) { soFar += reader.Read(buff, soFar, length - soFar); } ourRemoteClient.Messages.Add(new Message(MessageType.ReceiveCustomMessage, new ReceiveCustomMessageMessage() { CustomMessageNumber = number, Stream = buffer })); } break; default: { done = true; client.Close(); } break; } } } catch { // we will get here if the connection is closed try { if (client.Connected) { continue; } } catch (ObjectDisposedException) { done = true; } } done = true; } // don't close the reader/writer since this will also close the client stream }).Start(); BinaryWriter writer = new BinaryWriter(clientStream); BinaryFormatter converter = new BinaryFormatter(); clientStream.WriteTimeout = 10000; while (!done && !this.Exit) { Message message = ourRemoteClient.Messages.GetMessageOrTimeout(200); if (message == null) { message = new Message(MessageType.RequestProgress); } var nowDone = ProcessMessage(done, ourRemoteClient, writer, converter, message); Thread.MemoryBarrier(); done = done | nowDone; } done = true; } catch { } finally { done = true; lock (this) { try { client.Close(); } catch { } try { lock ( ourRemoteClient ) { ourRemoteClient.Connected = false; ourRemoteClient.Messages.Dispose(); ourRemoteClient.Messages = null; } lock (this) { this.ConnectedClients.Remove(ourRemoteClient); if (this.ClientDisconnected != null) { this.ClientDisconnected(ourRemoteClient); } } } catch { } } } }