Exemple #1
0
        public async Task MessageLoop()
        {
            try
            {
                while (true)
                {
                    // Get next packet size
                    var bufferSize = await context.ReadStream.ReadInt32Async();

                    // Get next packet data (until complete)
                    var buffer = new byte[bufferSize];
                    await context.ReadStream.ReadAllAsync(buffer, 0, bufferSize);

                    // Deserialize as an object
                    var    binaryReader = new BinarySerializationReader(new MemoryStream(buffer));
                    object obj          = null;
                    binaryReader.Context.SerializerSelector = SerializerSelector.AssetWithReuse;
                    binaryReader.SerializeExtended <object>(ref obj, ArchiveMode.Deserialize, null);

                    // If it's a message, process it separately (StreamId)
                    if (obj is SocketMessage)
                    {
                        var socketMessage = (SocketMessage)obj;
                        ProcessMessage(socketMessage);
                    }

                    // Check if there is a specific handler for this packet type
                    bool handlerFound;
                    Tuple <Action <object>, bool> handler;
                    lock (packetHandlers)
                    {
                        handlerFound = packetHandlers.TryGetValue(obj.GetType(), out handler);

                        // one-time handler
                        if (handlerFound && handler.Item2)
                        {
                            packetHandlers.Remove(obj.GetType());
                        }
                    }

                    if (handlerFound)
                    {
                        handler.Item1(obj);
                    }
                }
            }
            catch (Exception)
            {
                context.Dispose();
                throw;
            }
        }
Exemple #2
0
        /// <summary>
        /// Handles ServerStarted messages. It happens when service opened a new "server" connection back to us.
        /// </summary>
        /// <param name="clientSocket">The client socket context.</param>
        /// <returns></returns>
        private async Task HandleMessageServerStarted(SimpleSocket clientSocket)
        {
            var guid = await clientSocket.ReadStream.ReadGuidAsync();
            var errorCode = await clientSocket.ReadStream.ReadInt32Async();
            var errorMessage = (errorCode != 0) ? await clientSocket.ReadStream.ReadStringAsync() : null;

            // Notify any waiter that a server with given GUID is available
            TaskCompletionSource<SimpleSocket> serverSocketTCS;
            lock (pendingServers)
            {
                if (!pendingServers.TryGetValue(guid, out serverSocketTCS))
                {
                    Log.Error("Could not find a matching server Guid");
                    clientSocket.Dispose();
                    return;
                }

                pendingServers.Remove(guid);
            }

            if (errorCode != 0)
                serverSocketTCS.TrySetException(new Exception(errorMessage));
            else
                serverSocketTCS.TrySetResult(clientSocket);
        }
Exemple #3
0
        public async Task MessageLoop()
        {
            try
            {
                while (true)
                {
                    // Get next packet size
                    var bufferSize = await context.ReadStream.ReadInt32Async();

                    // Get next packet data (until complete)
                    var buffer = new byte[bufferSize];
                    await context.ReadStream.ReadAllAsync(buffer, 0, bufferSize);

                    // Deserialize as an object
                    var    binaryReader = new BinarySerializationReader(new MemoryStream(buffer));
                    object obj          = null;
                    binaryReader.Context.SerializerSelector = SerializerSelector.AssetWithReuse;
                    binaryReader.SerializeExtended <object>(ref obj, ArchiveMode.Deserialize, null);

                    // If it's a message, process it separately (StreamId)
                    var message = obj as SocketMessage;
                    if (message != null)
                    {
                        var socketMessage = message;
                        ProcessMessage(socketMessage);
                    }

                    // Check if there is a specific handler for this packet type
                    bool handlerFound;
                    Tuple <Action <object>, bool> handler;
                    lock (packetHandlers)
                    {
                        handlerFound = packetHandlers.TryGetValue(obj.GetType(), out handler);

                        // one-time handler
                        if (handlerFound && handler.Item2)
                        {
                            packetHandlers.Remove(obj.GetType());
                        }
                    }

                    if (handlerFound)
                    {
                        try
                        {
                            handler.Item1(obj);
                        }
                        catch (Exception ex)
                        {
                            if (message != null && message.StreamId != 0)
                            {
                                var exceptionMessage = new ExceptionMessage
                                {
                                    ExceptionInfo = new ExceptionInfo(ex),
                                    StreamId      = message.StreamId
                                };

                                await Send(exceptionMessage);
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                context.Dispose();

                lock (packetCompletionTasks)
                {
                    // Cancel all pending packets
                    foreach (var packetCompletionTask in packetCompletionTasks)
                    {
                        packetCompletionTask.Value.TrySetException(e);
                    }
                    packetCompletionTasks.Clear();
                }

                throw;
            }
        }
Exemple #4
0
        /// <summary>
        /// Handles ClientRequestServer messages.
        /// It will try to find a matching service (spawn it if not started yet), and ask it to establish a new "server" connection back to us.
        /// </summary>
        /// <param name="clientSocket">The client socket context.</param>
        /// <returns></returns>
        private async Task HandleMessageClientRequestServer(SimpleSocket clientSocket)
        {
            // Check for an existing server
            // TODO: Proper Url parsing (query string)
            var url = await clientSocket.ReadStream.ReadStringAsync();

            Log.Info("Client {0}:{1} sent message ClientRequestServer with URL {2}", clientSocket.RemoteAddress, clientSocket.RemotePort, url);

            string[] urlSegments;
            string urlParameters;
            RouterHelper.ParseUrl(url, out urlSegments, out urlParameters);
            if (urlSegments.Length == 0)
                throw new InvalidOperationException("No URL Segments");

            SimpleSocket serverSocket = null;
            ExceptionDispatchInfo serverSocketCapturedException = null;

            try
            {
                // For now, we handle only "service" URL
                switch (urlSegments[0])
                {
                    case "service":
                    {
                        // From the URL, start service (if not started yet) and ask it to provide a server
                        serverSocket = await SpawnServerFromService(url, false);
                        break;
                    }
                    case "task":
                    {
                        // From the URL, start service (if not started yet) and ask it to provide a server
                        serverSocket = await SpawnServerFromService(url, true);
                    }
                        break;
                    case "redirect":
                    {
                        // Redirect to a IP/port
                        serverSocket = new SimpleSocket();
                        var host = urlSegments[1];
                        var port = int.Parse(urlSegments[2]);

                        // Note: for security reasons, we currently use a whitelist
                        if (host == "XenkoBuild.siliconstudio.co.jp" && port == 1832)
                            await serverSocket.StartClient(host, port, false);
                        else
                            throw new InvalidOperationException("Trying to redirect to a non-whitelisted host/port");
                            break;
                    }
                    default:
                        throw new InvalidOperationException("This type of URL is not supported");
                }
            }
            catch (Exception e)
            {
                serverSocketCapturedException = ExceptionDispatchInfo.Capture(e);
            }


            if (serverSocketCapturedException != null)
            {
                try
                {
                    // Notify client that there was an error
                    await clientSocket.WriteStream.WriteInt16Async((short)RouterMessage.ClientServerStarted);
                    await clientSocket.WriteStream.WriteInt32Async(1); // error code Failure
                    await clientSocket.WriteStream.WriteStringAsync(serverSocketCapturedException.SourceException.Message);
                    await clientSocket.WriteStream.FlushAsync();
                }
                finally
                {
                    serverSocketCapturedException.Throw();
                }
            }

            try
            {
                // Notify client that we've found a server for it
                await clientSocket.WriteStream.WriteInt16Async((short)RouterMessage.ClientServerStarted);
                await clientSocket.WriteStream.WriteInt32Async(0); // error code OK
                await clientSocket.WriteStream.FlushAsync();

                // Let's forward clientSocketContext and serverSocketContext
                await await Task.WhenAny(
                    ForwardSocket(clientSocket, serverSocket),
                    ForwardSocket(serverSocket, clientSocket));
            }
            catch
            {
                serverSocket.Dispose();
                throw;
            }
        }