Exemplo n.º 1
0
 /// <summary>Creates a new client. A client can manage one connection to a server.</summary>
 /// <param name="dispatcherType">The message processing method for incomming notifications.
 /// See <see cref="EventDispatchType"/> for further information about each type.</param>
 public TsFullClient(DedicatedTaskScheduler?scheduler = null)
 {
     status              = TsClientStatus.Disconnected;
     msgProc             = new AsyncMessageProcessor(MessageHelper.GetToClientNotificationType);
     this.scheduler      = scheduler ?? new DedicatedTaskScheduler(Id.Null);
     this.isOwnScheduler = scheduler is null;
 }
Exemplo n.º 2
0
 /// <summary>Creates a new client. A client can manage one connection to a server.</summary>
 /// <param name="dispatcherType">The message processing method for incomming notifications.
 /// See <see cref="EventDispatchType"/> for further information about each type.</param>
 public TsFullClient()
 {
     status  = TsClientStatus.Disconnected;
     msgProc = new AsyncMessageProcessor(MessageHelper.GetToClientNotificationType);
     context = new ConnectionContext {
         WasExit = true
     };
 }
Exemplo n.º 3
0
        partial void ProcessEachInitServer(InitServer initServer)
        {
            packetHandler.ClientId = initServer.ClientId;

            lock (statusLock)
                status = TsClientStatus.Connected;
            OnConnected?.Invoke(this, EventArgs.Empty);
        }
Exemplo n.º 4
0
        private void ChangeState(ConnectionContext ctx, TsClientStatus setStatus, CommandError?error = null)
        {
            scheduler.VerifyOwnThread();

            if (ctx != context)
            {
                Log.Debug("Stray disconnect from old packethandler");
            }

            Log.Debug("ChangeState {0} -> {1} (error:{2})", status, setStatus, error?.ErrorFormat() ?? "none");

            switch ((status, setStatus))
            {
            case (TsClientStatus.Disconnected, TsClientStatus.Disconnected):
                // Already disconnected, do nothing
                break;

            case (TsClientStatus.Disconnected, TsClientStatus.Connecting):
                status = TsClientStatus.Connecting;
                break;

            case (TsClientStatus.Connecting, TsClientStatus.Connected):
                status = TsClientStatus.Connected;
                ctx.ConnectEvent.SetResult(R.Ok);
                break;

            case (TsClientStatus.Connecting, TsClientStatus.Disconnected):
            case (TsClientStatus.Connected, TsClientStatus.Disconnected):
            case (TsClientStatus.Disconnecting, TsClientStatus.Disconnected):
                status = TsClientStatus.Disconnected;
                ctx.PacketHandler.Stop();
                msgProc.DropQueue();

                var statusBefore = status;
                context = null;
                if (statusBefore == TsClientStatus.Connecting)
                {
                    ctx.ConnectEvent.SetResult(error ?? CommandError.ConnectionClosed);                     // TODO: Set exception maybe ?
                }
                ctx.DisconnectEvent.SetResult(null);
                OnDisconnected?.Invoke(this, new DisconnectEventArgs(ctx.ExitReason ?? Reason.LeftServer, error));
                break;

            case (TsClientStatus.Connected, TsClientStatus.Disconnecting):
                status = TsClientStatus.Disconnecting;
                break;

            default:
                Trace.Fail($"Invalid transition change from {status} to {setStatus}");
                break;
            }
        }
Exemplo n.º 5
0
        private void DisconnectInternal(ConnectionContext ctx, CommandError error = null, TsClientStatus?setStatus = null)
        {
            bool triggerEventSafe = false;

            lock (statusLock)
            {
                Log.Debug("DisconnectInternal wasExit:{0} error:{1} oldStatus:{2} newStatus:{3}", ctx.WasExit, error?.ErrorFormat(), status, setStatus);

                if (setStatus.HasValue)
                {
                    status = setStatus.Value;
                }

                if (ctx.WasExit)
                {
                    return;
                }

                switch (status)
                {
                case TsClientStatus.Connecting:
                case TsClientStatus.Disconnected:
                    ctx.WasExit = true;
                    packetHandler.Stop();
                    msgProc.DropQueue();
                    dispatcher.Dispose();
                    dispatcher       = null;
                    triggerEventSafe = true;
                    break;

                case TsClientStatus.Disconnecting:
                    break;

                case TsClientStatus.Connected:
                    ClientDisconnect(Reason.LeftServer, QuitMessage);
                    status = TsClientStatus.Disconnecting;
                    break;

                default:
                    throw Tools.UnhandledDefault(status);
                }
            }

            if (triggerEventSafe)
            {
                OnDisconnected?.Invoke(this, new DisconnectEventArgs(ctx.ExitReason ?? Reason.LeftServer, error));
            }
        }
Exemplo n.º 6
0
        /// <summary>Tries to connect to a server.</summary>
        /// <param name="conData">Set the connection information properties as needed.
        /// For further details about each setting see the respective property documentation in <see cref="ConnectionData"/></param>
        /// <exception cref="ArgumentException">When some required values are not set or invalid.</exception>
        /// <exception cref="TsException">When the connection could not be established.</exception>
        public override void Connect(ConnectionData conData)
        {
            if (!(conData is ConnectionDataFull conDataFull))
            {
                throw new ArgumentException($"Use the {nameof(ConnectionDataFull)} derivative to connect with the full client.", nameof(conData));
            }
            if (conDataFull.Identity is null)
            {
                throw new ArgumentNullException(nameof(conDataFull.Identity));
            }
            if (conDataFull.VersionSign is null)
            {
                throw new ArgumentNullException(nameof(conDataFull.VersionSign));
            }
            connectionDataFull = conDataFull;
            ConnectionData     = conData;

            Disconnect();

            if (!TsDnsResolver.TryResolve(conData.Address, out remoteAddress))
            {
                throw new TsException("Could not read or resolve address.");
            }

            lock (statusLock)
            {
                returnCode = 0;
                status     = TsClientStatus.Connecting;

                VersionSign      = conDataFull.VersionSign;
                tsCrypt          = new TsCrypt();
                tsCrypt.Identity = conDataFull.Identity;

                var ctx = new ConnectionContext {
                    WasExit = false
                };
                context = ctx;

                packetHandler             = new PacketHandler <S2C, C2S>(tsCrypt, conData.LogId);
                packetHandler.PacketEvent = (ref Packet <S2C> packet) => { PacketEvent(ctx, ref packet); };
                packetHandler.StopEvent   = (closeReason) => { ctx.ExitReason = closeReason; DisconnectInternal(ctx, setStatus: TsClientStatus.Disconnected); };
                packetHandler.Connect(remoteAddress);
                dispatcher = new ExtraThreadEventDispatcher();
                dispatcher.Init(InvokeEvent, conData.LogId);
            }
        }