static void Main(string[] args)
        {
            string     filePath = "E:/test.zip";
            FileStream stream   = new FileStream(filePath, FileMode.Open, FileAccess.Read);

            DynamicListener listener = new DynamicListener(/*IPAddress.Any*/ IPAddress.Parse("192.168.1.73"), 54321);

            // netsh http add urlacl url=http://+:54322/ws user=everyone
            //WsListener listener = new WsListener("http://+:54322/ws/");
            listener.Start();

            //TCPRemoteClient client = new TCPRemoteClient();
            //WsRemoteClient client = new WsRemoteClient();

            ProtocolTree tree = new ProtocolTree();
            LeafProtocolHandler <Data> leaf = new LeafProtocolHandler <Data>();
            LeafProtocolHandler <Rec>  rec  = new LeafProtocolHandler <Rec>();
            LeafProtocolHandler <Done> done = new LeafProtocolHandler <Done>();

            tree.Register(leaf);
            tree.Register(rec);
            tree.Register(done);
            tree.EntryToLeaf(leaf);
            tree.EntryToLeaf(rec);
            tree.EntryToLeaf(done);

            ApplicationConnectionManager app = null;

            //TcpClient cl = null;
            //WebSocket cl = null;

            bool finish = false;
            Task task   = null;

            bool connected = false;

            void clean()
            {
                Console.WriteLine("conn lost + ");
                connected = false;
                Console.WriteLine("connection is down");
                reconn();
            }

            void rd(Rec data)
            {
                task = new Task(() =>
                {
                    Console.WriteLine("sen task started");
                    long p = data.seq;
                    while (p < stream.Length)
                    {
                        if (!connected)
                        {
                            Console.WriteLine("sen task ended"); return;
                        }
                        long blockSize = Math.Min(65536, stream.Length - p);
                        stream.Seek(p, SeekOrigin.Begin);
                        byte[] b = new byte[blockSize];
                        stream.Read(b, 0, (int)blockSize);
                        p     += blockSize;
                        Data d = new Data(b);
                        Console.WriteLine("sen task send");
                        leaf.Send(d);
                        Console.WriteLine("sen task send, done");
                        Console.WriteLine($"{blockSize} bytes sent, total {p} sent");
                        Thread.Sleep(15);
                    }
                    Console.WriteLine("sen task fined");
                    done.Send(new Done());
                });
                task.Start();
            }

            void fin(Done d) => finish = true;

            // client.ConnectionLost += clean;
            rec.NewData  += rd;
            done.NewData += fin;

            void reconn()
            {
                while (true)
                {
                    if (connected)
                    {
                        return;
                    }
                    try
                    {
                        Console.WriteLine("waiting...");
                        DynamicRemoteClient cl = listener.Accept();
                        if (app != null)
                        {
                            app.Dispose();
                        }
                        app = new ApplicationConnectionManager(cl, tree, 1000, 4000);
                        app.ConnectionLost += clean;
                        cl.Activate();
                        //cl = listener.AcceptWsClient();
                        connected = true;
                        Console.WriteLine("accepted! " /* + cl.Client.RemoteEndPoint.ToString()*/);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("network error");
                        Thread.Sleep(1000);
                        continue;
                    }
                }
            }

            reconn();

            while (true)
            {
                if (finish)
                {
                    Console.WriteLine("finished!!");
                    break;
                }
                else
                {
                    Thread.Sleep(500);
                }
            }
        }
Пример #2
0
        private void ListenerTask()
        {
            while (true)
            {
                Log("trying to accept a new client ...");

                DynamicRemoteClient remoteClient = null;
                try
                {
                    remoteClient = listener.Accept();
                }
                catch
                {
                    Log("unable to accept client", LogType.ERROR);
                    Thread.Sleep(2000);
                    continue;
                }

                ProtocolTree tree = new ProtocolTree();
                DummyHandler <DummyProtocol> treeRoot = new DummyHandler <DummyProtocol>();
                LeafProtocolHandler <AuthenticationProtocol> authHandler
                    = new LeafProtocolHandler <AuthenticationProtocol>();
                tree.Register(treeRoot);
                tree.Register(authHandler);
                tree.Entry(treeRoot);
                tree.ConnectToLeaf(treeRoot, authHandler);

                ApplicationConnectionManager app =
                    new ApplicationConnectionManager(remoteClient, tree, new DummyProvider(), 3000, 6000);

                applicationConnections.Add(app, -1);

                authHandler.NewData += data =>
                {
                    if (data.statusCode != AuthenticationProtocol.StatusCode.Ack)
                    {
                        Log("invalid auth status code: ACK", LogType.ERROR);
                        return;
                    }
                    void accept()
                    {
                        long resumeToken = 0;

                        if (!resumeTokens.ContainsKey(data.interfaceId))
                        {
                            resumeToken = Rnd64();
                            resumeTokens.Add(data.interfaceId, resumeToken);
                        }
                        else
                        {
                            resumeTokens[data.interfaceId] = resumeTokens[data.interfaceId];
                        }
                        Log($"accept the client {data.interfaceId}, token = {resumeToken}");

                        authHandler.Send(new AuthenticationProtocol
                        {
                            statusCode  = AuthenticationProtocol.StatusCode.Accept,
                            resumeToken = resumeToken
                        });
                    }

                    void reject(string reason)
                    {
                        authHandler.Send(new AuthenticationProtocol
                        {
                            statusCode = AuthenticationProtocol.StatusCode.Reject,
                            reason     = reason
                        });
                    }

                    if (data.interfaceId < 0 || data.interfaceId >= logic.MaxConnection)
                    {
                        Log($"reject the client since the interface {data.interfaceId} is not valie", LogType.WARNING);
                        reject("invalid interface id");
                        return;
                    }

                    lock (interfaceLock)
                    {
                        bool IsExistingUser = connectionInterruptTimers.ContainsKey(data.interfaceId);
                        if (IsExistingUser && data.resumeToken != resumeTokens[data.interfaceId])
                        {
                            Log($"reject the client since the resume token {data.resumeToken} is not correct", LogType.WARNING);
                            reject("wrong resume token");
                            return;
                        }
                        if (!serviceBackupData.connectionInterfaces[data.interfaceId].Enabled && !IsExistingUser)
                        {
                            Log($"reject the client since the interface {data.interfaceId} is not available", LogType.WARNING);
                            reject("interface is not available");
                            return;
                        }
                        if (serviceBackupData.connectionInterfaces[data.interfaceId].Ticket != data.ticket)
                        {
                            Log($"reject the client since the ticket {data.ticket} is not correct", LogType.WARNING);
                            reject("invalid ticket");
                            return;
                        }

                        Log("auth is valid, accept the client");
                        accept();

                        tree.Connect(treeRoot, logic.GetProtocolTree(data.interfaceId));
                        applicationConnections[app] = data.interfaceId;

                        if (IsExistingUser)
                        {
                            Log($"client with id {data.interfaceId} comes back", LogType.WARNING);
                            RemoveTimer(data.interfaceId);
                            logic.OnClientResume(data.interfaceId);
                        }
                        else
                        {
                            Log($"calling logic OnClientEnter and close interface {data.interfaceId}");
                            CloseInterface(data.interfaceId);
                            logic.OnClientEnter(data.interfaceId);
                        }
                    }
                };

                app.ConnectionLost += () =>
                {
                    app.Dispose();
                    int id = applicationConnections[app];
                    applicationConnections.Remove(app);

                    Log($"client {id} is leaving", LogType.WARNING);

                    if (id >= 0)
                    {
                        logic.GetProtocolTree(id).Detach();

                        if (logic.CanResume(id))
                        {
                            System.Timers.Timer timer = new System.Timers.Timer(20000)
                            {
                                AutoReset = false
                            };
                            timer.Elapsed += (s, e) =>
                            {
                                lock (interfaceLock)
                                {
                                    Log($"client {id} leave permanently", LogType.WARNING);
                                    timer.Dispose();
                                    connectionInterruptTimers.Remove(id);
                                    resumeTokens.Remove(id);
                                    logic.OnClientLeave(id);
                                }
                            };
                            timer.Start();
                            connectionInterruptTimers.Add(id, timer);
                            logic.OnClientDisconnect(id);
                            Log($"start timer to wait for client {id} to come back", LogType.WARNING);
                        }
                        else
                        {
                            logic.OnClientLeave(id);
                            Log($"client {id} leave permanently since logic cannot resume now", LogType.WARNING);
                        }
                    }
                };

                remoteClient.Activate();

                Logger.Log("sending auth data ...", "ServiceHost");
                authHandler.Send(new AuthenticationProtocol {
                    statusCode = AuthenticationProtocol.StatusCode.Request
                });
            }
        }