示例#1
0
        async Task RunAsync(string[] args)
        {
            // FIBS test user
            string user = "******";
            string pw   = "dotnetcli1";

            using (fibs = new FibsSession()) {
                // catch Ctrl+C
                Console.CancelKeyPress += (sender, e) => {
                    SendAsync("bye").GetAwaiter().GetResult();
                    Process(fibs.ReceiveAsync().GetAwaiter().GetResult()).GetAwaiter().GetResult();
                };

                // login, set the right properties and watch someone play
                await Process(await fibs.LoginAsync(user, pw));
                await SendAsync("set boardstyle 3");

                // pick the player provided on the command line or the one least idle
                if (args.Length != 0)
                {
                    player = players.Find(p => string.Compare(p.Name, args[0], true) == 0);
                    if (player == null || player.Opponent == null)
                    {
                        Log($"{args[0]} not playing"); return;
                    }
                }
                else
                {
                    player = players.Where(p => p.Opponent != null).OrderBy(p => p.Idle).First();
                }

                Log($"{player.Name}: idle {player.Idle} seconds");
                await SendAsync($"watch {player.Name}");

                while (processing)
                {
                    await Process(await fibs.ReceiveAsync());
                }
            }
        }
        async Task FibsLoop(WebSocket socket)
        {
            using (var fibs = new FibsSession()) {
                var cancel        = CancellationToken.None;
                var socketSegment = new ArraySegment <byte>(new byte[4096]);

                // wait for login
                Task <WebSocketReceiveResult> socketReceiveTask = socket.ReceiveAsync(socketSegment, cancel);
                var socketInput = await socketReceiveTask;
                if (socketInput.MessageType != WebSocketMessageType.Text)
                {
                    await socket.CloseAsync(WebSocketCloseStatus.InvalidMessageType, "text messages only", cancel);

                    return;
                }

                // check for login
                var s     = Encoding.UTF8.GetString(socketSegment.Array, 0, socketInput.Count);
                var re    = new Regex(@"login (?<user>[^ ]+) (?<password>[^ ]+)");
                var match = re.Match(s);
                if (!match.Success)
                {
                    await socket.CloseAsync(WebSocketCloseStatus.ProtocolError, "must login first", cancel);

                    return;
                }

                // login to FIBS
                // TODO: support creating new users
                // TODO: support other servers besides fibs.com
                // TODO: support message queueing while there awaiting a response, otherwise FIBS drops requests
                // (and remember to take the hack out of the client...)
                var user     = match.Groups["user"].Value;
                var password = match.Groups["password"].Value;
                Task <CookieMessage[]> fibsReadTask = fibs.LoginAsync(user, password);
                Debug.WriteLine($"FibsLoop: logging into FIBS for {user}");

                // get more socket input
                socketReceiveTask = socket.ReceiveAsync(socketSegment, cancel);

                while (socket.State == WebSocketState.Open)
                {
                    var task = await Task.WhenAny(socketReceiveTask, fibsReadTask);

                    //if (task.IsCanceled) { break; }

                    if (task.Equals(socketReceiveTask))
                    {
                        socketInput = await socketReceiveTask;

                        if (socketInput.MessageType == WebSocketMessageType.Close)
                        {
                            await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "", cancel);

                            continue;
                        }

                        if (socketInput.MessageType != WebSocketMessageType.Text)
                        {
                            await socket.CloseAsync(WebSocketCloseStatus.InvalidMessageType, "text messages only", cancel);

                            continue;
                        }

                        if (!socketInput.EndOfMessage)
                        {
                            await socket.CloseAsync(WebSocketCloseStatus.MessageTooBig, "message too big", cancel);

                            continue;
                        }

                        s = Encoding.UTF8.GetString(socketSegment.Array, 0, socketInput.Count);
                        if (string.IsNullOrWhiteSpace(s))
                        {
                            await socket.CloseAsync(WebSocketCloseStatus.ProtocolError, "no empty messages", cancel);

                            continue;
                        }

                        // write socket input to FIBS and wait for more socket input
                        await fibs.SendAsync(s);

                        socketReceiveTask = socket.ReceiveAsync(socketSegment, cancel);
                    }
                    else if (task.Equals(fibsReadTask))
                    {
                        // read messages from FIBS
                        var messages = (await fibsReadTask).Where(cm => !MessagesToSkip.Contains(cm.Cookie)).ToArray();

                        if (messages.Length > 0)
                        {
                            // write messages to socket
                            var jsonBytes = Encoding.UTF8.GetBytes(messages.ToJson());
                            await socket.SendAsync(new ArraySegment <byte>(jsonBytes, 0, jsonBytes.Length), WebSocketMessageType.Text, true, cancel);

                            if (messages.Any(cm => cm.Cookie == FibsCookie.FIBS_Goodbye))
                            {
                                await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "", cancel);

                                break;
                            }
                        }

                        // wait for more FIBS input
                        fibsReadTask = fibs.ReceiveAsync();
                    }
                    else
                    {
                        Debug.Assert(false, "Unknown task");
                    }
                }
                Debug.WriteLine($"FibsLoop: socket closed for {user}");
            }
        }