예제 #1
0
        private SimpleSocket CreateSocketContext()
        {
            var socketContext = new SimpleSocket();
            socketContext.Connected = (clientSocketContext) =>
            {
                Task.Run(async () =>
                {
                    try
                    {

                        // Register service server
                        await socketContext.WriteStream.WriteInt16Async((short)RouterMessage.ServiceProvideServer);
                        await socketContext.WriteStream.WriteStringAsync(serverUrl);
                        await socketContext.WriteStream.FlushAsync();

                        while (true)
                        {
                            var routerMessage = (RouterMessage)await socketContext.ReadStream.ReadInt16Async();

                            switch (routerMessage)
                            {
                                case RouterMessage.ServiceRequestServer:
                                {
                                    var requestedUrl = await clientSocketContext.ReadStream.ReadStringAsync();
                                    var guid = await clientSocketContext.ReadStream.ReadGuidAsync();

                                    // Spawn actual server
                                    var realServerSocketContext = new SimpleSocket();
                                    realServerSocketContext.Connected = async (clientSocketContext2) =>
                                    {
                                        // Write connection string
                                        await clientSocketContext2.WriteStream.WriteInt16Async((short)RouterMessage.ServerStarted);
                                        await clientSocketContext2.WriteStream.WriteGuidAsync(guid);

                                        // Delegate next steps to actual server
                                        HandleClient(clientSocketContext2, requestedUrl);
                                    };

                                    // Start connection
                                    await realServerSocketContext.StartClient(address, port);
                                    break;
                                }
                                default:
                                    Console.WriteLine("Router: Unknown message: {0}", routerMessage);
                                    throw new ArgumentOutOfRangeException();
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        // TODO: Ideally, separate socket-related error messages (disconnection) from real errors
                        // Unfortunately, it seems WinRT returns Exception, so it seems we can't filter with SocketException/IOException only?
                        Log.Info("Client {0}:{1} disconnected with exception: {2}", clientSocketContext.RemoteAddress, clientSocketContext.RemotePort, e.Message);
                        clientSocketContext.Dispose();
                    }
                });
            };

            return socketContext;
        }
예제 #2
0
        /// <summary>
        /// Initiates a connection to the router.
        /// </summary>
        /// <returns></returns>
        private static Task<SimpleSocket> InitiateConnectionToRouter()
        {
            // Let's make sure this run in a different thread (in case some operation are blocking)
            return Task.Factory.StartNew(() =>
            {
                var socketContextTCS = new TaskCompletionSource<SimpleSocket>();
                var socketContext = new SimpleSocket();
                socketContext.Connected = context =>
                {
                    socketContextTCS.TrySetResult(context);
                };

                try
                {
                    // If connecting as a client, try once, otherwise try to listen multiple time (in case port is shared)
                    switch (ConnectionMode)
                    {
                        case RouterConnectionMode.Connect:
                            socketContext.StartClient("127.0.0.1", DefaultPort).Wait();
                            break;
                        case RouterConnectionMode.Listen:
                            socketContext.StartServer(DefaultListenPort, true, 10).Wait();
                            break;
                        case RouterConnectionMode.ConnectThenListen:
                            bool clientException = false;
                            try
                            {
                                socketContext.StartClient("127.0.0.1", DefaultPort).Wait();
                            }
                            catch (Exception) // Ideally we should filter SocketException, but not available on some platforms (maybe it should be wrapped in a type available on all paltforms?)
                            {
                                clientException = true;
                            }
                            if (clientException)
                            {
                                socketContext.StartServer(DefaultListenPort, true, 10).Wait();
                            }
                            break;
                        default:
                            throw new ArgumentOutOfRangeException();
                    }

                    // Connection should happen within 5 seconds, otherwise consider there is no connection router trying to connect back to us
                    if (!socketContextTCS.Task.Wait(TimeSpan.FromSeconds(5)))
                        throw new InvalidOperationException("Connection router did not connect back to our listen socket");

                    return socketContextTCS.Task.Result;
                }
                catch (Exception e)
                {
                    Log.Error("Could not connect to connection router using mode {0}: {1}", ConnectionMode, e.Message);
                    throw;
                }
            },
                CancellationToken.None,
                TaskCreationOptions.LongRunning,
                TaskScheduler.Default);
        }
예제 #3
0
        /// <summary>
        /// Initiates a connection to the router.
        /// </summary>
        /// <returns></returns>
        private static Task <SimpleSocket> InitiateConnectionToRouter()
        {
            // Let's make sure this run in a different thread (in case some operation are blocking)
            return(Task.Factory.StartNew(() =>
            {
                var socketContextTCS = new TaskCompletionSource <SimpleSocket>();
                var socketContext = new SimpleSocket();
                socketContext.Connected = context =>
                {
                    socketContextTCS.TrySetResult(context);
                };

                try
                {
#if SILICONSTUDIO_PLATFORM_UWP
                    var serverAddress = "127.0.0.1";
#else
                    var serverAddress = Environment.GetEnvironmentVariable("XenkoConnectionRouterRemoteIP") ?? "127.0.0.1";
#endif

                    // If connecting as a client, try once, otherwise try to listen multiple time (in case port is shared)
                    switch (ConnectionMode)
                    {
                    case RouterConnectionMode.Connect:
                        socketContext.StartClient(serverAddress, DefaultPort).Wait();
                        break;

                    case RouterConnectionMode.Listen:
                        socketContext.StartServer(DefaultListenPort, true, 10).Wait();
                        break;

                    case RouterConnectionMode.ConnectThenListen:
                        bool clientException = false;
                        try
                        {
                            socketContext.StartClient(serverAddress, DefaultPort).Wait();
                        }
                        catch (Exception)     // Ideally we should filter SocketException, but not available on some platforms (maybe it should be wrapped in a type available on all paltforms?)
                        {
                            clientException = true;
                        }
                        if (clientException)
                        {
                            socketContext.StartServer(DefaultListenPort, true, 10).Wait();
                        }
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }

                    // Connection should happen within 10 seconds, otherwise consider there is no connection router trying to connect back to us
                    if (!socketContextTCS.Task.Wait(TimeSpan.FromSeconds(10)))
                    {
                        throw new SimpleSocketException("Connection router did not connect back to our listen socket");
                    }

                    return socketContextTCS.Task.Result;
                }
                catch (Exception e)
                {
                    Log.Error($"Could not connect to connection router using mode {ConnectionMode}", e);
                    throw;
                }
            },
                                         CancellationToken.None,
                                         TaskCreationOptions.LongRunning,
                                         TaskScheduler.Default));
        }
예제 #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;
            }
        }