예제 #1
0
        public void Run(string[] args)
        {
            var settingsReader = new CommandLineClientSettingsReader();

            if (!settingsReader.ParseArgs(args))
            {
                return;
            }

            var settings = settingsReader.ClientSettings;

            if (settings.Email == null)
            {
                Console.Error.WriteLine("No Email configured");
                return;
            }

            if (settings.Password == null)
            {
                Console.Error.WriteLine("No Password configured");
                return;
            }

            var credentials = new CredentialsProvider()
            {
                Email    = settings.Email,
                Password = settings.Password
            };

            var webClient = new RopuWebClient("asdf", credentials);


            var keysClient       = new KeysClient(webClient, false, encryptionKey => new CachedEncryptionKey(encryptionKey, key => new AesGcmWrapper(key)));
            var packetEncryption = new PacketEncryption(keysClient);

            var protocolSwitch    = new ProtocolSwitch(_controlPortStarting, new PortFinder(), packetEncryption, keysClient, settings);
            var servingNodeClient = new ServingNodeClient(protocolSwitch);

            var callManagementProtocol = new LoadBalancerProtocol(new PortFinder(), 5079, packetEncryption, keysClient);

            _mediaClient = BuildMediaClient(protocolSwitch, settings);

            //IPEndPoint loadBalancerEndpoint = new IPEndPoint(settings.LoadBalancerIPAddress, LoadBalancerPort);
            var beepPlayer = BuildBeepPlayer(settings);



            _ropuClient = new RopuClient(protocolSwitch, servingNodeClient, _mediaClient, callManagementProtocol, settings, beepPlayer, webClient, keysClient);
            var ropuClientTask = _ropuClient.Run();

            //var consoleTask = TaskCordinator.RunLong(HandleCommands);

            //TaskCordinator.WaitAll(ropuClientTask, consoleTask).Wait();
            ropuClientTask.Wait();
        }
예제 #2
0
        IMediaClient BuildMediaClient(ProtocolSwitch protocolSwitch, IClientSettings settings)
        {
            if (settings.FakeMedia)
            {
                //Console.WriteLine("Using FakeMediaClient");
                return(new FakeMediaClient());
            }
            var audioSource  = new AlsaAudioSource();
            var audioPlayer  = new AlsaAudioPlayer(true);
            var audioCodec   = new RawCodec();
            var jitterBuffer = new AdaptiveJitterBuffer(2, 50);

            return(new MediaClient(protocolSwitch, audioSource, audioPlayer, audioCodec, jitterBuffer, settings));
        }
예제 #3
0
 public MediaClient(
     ProtocolSwitch protocolSwitch,
     IAudioSource audioSource,
     IAudioPlayer audioPlayer,
     IAudioCodec audioCodec,
     IJitterBuffer jitterBuffer,
     IClientSettings clientSettings)
 {
     _protocolSwitch = protocolSwitch;
     _protocolSwitch.SetMediaPacketParser(this);
     _audioSource    = audioSource;
     _audioPlayer    = audioPlayer;
     _audioCodec     = audioCodec;
     _jitterBuffer   = jitterBuffer;
     _clientSettings = clientSettings;
 }
예제 #4
0
        public RopuClient(
            ProtocolSwitch protocolSwitch,
            ServingNodeClient servingNodeClient,
            IMediaClient mediaClient,
            LoadBalancerProtocol loadBalancerProtocol,
            IClientSettings clientSettings,
            IBeepPlayer beepPlayer,
            RopuWebClient webClient,
            KeysClient keysClient)
        {
            _webClient            = webClient;
            _beepPlayer           = beepPlayer;
            _clientSettings       = clientSettings;
            _loadBalancerProtocol = loadBalancerProtocol;
            _protocolSwitch       = protocolSwitch;
            _servingNodeClient    = servingNodeClient;
            _mediaClient          = mediaClient;
            _servingNodeClient.SetControllingFunctionHandler(this);
            _retryTimer = new Ropu.Shared.Timer();
            _keysClient = keysClient;

            var allEvents = (EventId[])Enum.GetValues(typeof(EventId));

            //start
            _start        = new RopuState(StateId.Start);
            _stateManager = new StateManager <StateId, EventId>(_start);
            _stateManager.AddState(_start);
            _start.AddTransitions(allEvents, () => _start);

            //registered
            _registered = new RopuState(StateId.Registered)
            {
                Entry = async token =>
                {
                    if (_clientSettings.UserId == null)
                    {
                        throw new InvalidOperationException("UserId is not set");
                    }
                    _callGroup        = IdleGroup;
                    _registeredUserId = _clientSettings.UserId.Value;
                    if (_heartbeatTask == null)
                    {
                        _heartbeatTask = Heartbeat(_heartbeatCancellationTokenSource.Token);
                    }
                    _heartbeatOnEvent.Set(); //allows the heartbeat to continue
                    await Task.Run(() => {});
                },
            };
            _stateManager.AddState(_registered);
            _registered.AddTransition(EventId.CallRequest, () => _startingCall !);
            _registered.AddTransition(EventId.PttDown, () => _startingCall !);
            _registered.AddTransition(EventId.RegistrationResponseReceived, () => _registered);
            _registered.AddTransition(EventId.CallStartFailed, () => _registered);
            _registered.AddTransition(EventId.PttUp, () => _registered);
            _registered.AddTransition(EventId.GroupSelected, () => _registered);

            //unregistered
            _noGroup      = new RopuState(StateId.NoGroup);
            _unregistered = new RopuState(StateId.Unregistered)
            {
                Entry = async token =>
                {
                    _heartbeatOnEvent.Reset(); //stops the heartbeat
                    await Register(token);
                }
            };
            _unregistered.AddTransition(EventId.RegistrationResponseReceived, () => IdleGroup == null ? _noGroup : _registered);
            _unregistered.AddTransition(EventId.FloorIdle, () => _unregistered);
            _unregistered.AddTransition(EventId.FloorTaken, () => _unregistered);
            _unregistered.AddTransition(EventId.CallEnded, () => _unregistered);
            _unregistered.AddTransition(EventId.CallRequest, () => _unregistered);
            _unregistered.AddTransition(EventId.CallStartFailed, () => _unregistered);
            _unregistered.AddTransition(EventId.HeartbeatFailed, () => _unregistered);
            _unregistered.AddTransition(EventId.PttUp, () => _unregistered);
            _unregistered.AddTransition(EventId.PttDown, () => _unregistered);
            _unregistered.AddTransition(EventId.GroupSelected, () => _unregistered);

            _stateManager.AddState(_unregistered);

            //no group
            _noGroup.AddTransition(EventId.PttUp, () => _noGroup);
            _noGroup.AddTransition(EventId.PttDown, () => _noGroup);
            _noGroup.AddTransition(EventId.GroupSelected, () => _registered);
            _noGroup.AddTransition(EventId.RegistrationResponseReceived, () => _noGroup);
            _noGroup.AddTransition(EventId.CallRequest, () => _noGroup);
            _noGroup.AddTransition(EventId.CallStartFailed, () => _noGroup);


            _stateManager.AddState(_noGroup);

            //deregistering
            _deregistering = new RopuState(StateId.Deregistering)
            {
                Entry = async token => await Deregister(token),
            };
            _deregistering.AddTransition(EventId.DeregistrationResponseReceived, () => _unregistered);
            _deregistering.AddTransitions(allEvents.Where(e => e != EventId.DeregistrationResponseReceived), () => _deregistering);
            _deregistering.AddTransition(EventId.GroupSelected, () => _deregistering);
            _stateManager.AddState(_deregistering);

            //starting call
            _startingCall = new RopuState(StateId.StartingCall)
            {
                Entry = async token => await StartCall(token),
                Exit  = newState =>
                {
                    if (newState != _inCallTransmitting && newState != _inCallRequestingFloor)
                    {
                        _mediaClient.StopSendingAudio();
                    }
                }
            };
            _startingCall.AddTransition(EventId.CallStartFailed, () => _registered);
            _startingCall.AddTransition(EventId.PttUp, () => _startingCall);
            _startingCall.AddTransition(EventId.PttDown, () => _startingCall);
            _startingCall.AddTransition(EventId.RegistrationResponseReceived, () => _startingCall);
            _startingCall.AddTransition(EventId.CallRequest, () => _startingCall);
            _startingCall.AddTransition(EventId.GroupSelected, () => _startingCall);

            _stateManager.AddState(_startingCall);

            //in call idle
            _inCallIdle = new RopuState(StateId.InCallIdle);
            _inCallIdle.AddTransition(EventId.PttDown, () => _inCallRequestingFloor !);
            _inCallIdle.AddTransition(EventId.PttUp, () => _inCallIdle);
            _inCallIdle.AddTransition(EventId.RegistrationResponseReceived, () => _inCallIdle);
            _inCallIdle.AddTransition(EventId.CallRequest, () => _inCallIdle);
            _inCallIdle.AddTransition(EventId.CallStartFailed, () => _registered);
            _inCallIdle.AddTransition(EventId.GroupSelected, () => _inCallIdle);
            _stateManager.AddState(_inCallIdle);

            //in call receiving
            _inCallReceiveing = new RopuState(StateId.InCallReceiving);
            _inCallReceiveing.AddTransition(EventId.PttDown, () => _inCallReceiveing);
            _inCallReceiveing.AddTransition(EventId.PttUp, () => _inCallReceiveing);
            _inCallReceiveing.AddTransition(EventId.RegistrationResponseReceived, () => _inCallReceiveing);
            _inCallReceiveing.AddTransition(EventId.CallRequest, () => _inCallReceiveing);
            _inCallReceiveing.AddTransition(EventId.CallStartFailed, () => _registered);
            _inCallReceiveing.AddTransition(EventId.GroupSelected, () => _inCallReceiveing);
            _stateManager.AddState(_inCallReceiveing);

            //in call transmitting
            _inCallTransmitting = new RopuState(StateId.InCallTransmitting)
            {
                Entry = async token =>
                {
                    _beepPlayer.PlayGoAhead();
                    await Task.Run(() => {});
                },
                Exit = newState =>
                {
                    if (newState != _inCallTransmitting && newState != _inCallRequestingFloor)
                    {
                        _mediaClient.StopSendingAudio();
                    }
                }
            };
            _inCallTransmitting.AddTransition(EventId.PttUp, () => _inCallReleasingFloor !);
            _inCallTransmitting.AddTransition(EventId.RegistrationResponseReceived, () => _inCallTransmitting);
            _inCallTransmitting.AddTransition(EventId.CallRequest, () => _inCallTransmitting);
            _inCallTransmitting.AddTransition(EventId.CallStartFailed, () => _inCallTransmitting);
            _inCallTransmitting.AddTransition(EventId.PttDown, () => _inCallTransmitting);
            _inCallTransmitting.AddTransition(EventId.GroupSelected, () => _inCallTransmitting);

            _stateManager.AddState(_inCallTransmitting);

            //in call requesting floor
            _inCallRequestingFloor = new RopuState(StateId.InCallRequestingFloor)
            {
                Entry = token =>
                {
                    if (_callGroup == null)
                    {
                        return(Task.CompletedTask);
                    }
                    if (_clientSettings.UserId == null)
                    {
                        throw new InvalidOperationException("UserId is not set");
                    }
                    _servingNodeClient.SendFloorRequest(_callGroup.Value, _clientSettings.UserId.Value);
                    StartSendingAudio();
                    return(Task.CompletedTask);
                },
                Exit = newState =>
                {
                    if (newState != _inCallTransmitting && newState != _inCallRequestingFloor)
                    {
                        _mediaClient.StopSendingAudio();
                        _beepPlayer.PlayDenied();
                    }
                }
            };
            _inCallRequestingFloor.AddTransition(EventId.RegistrationResponseReceived, () => _inCallReleasingFloor !);
            _inCallRequestingFloor.AddTransition(EventId.CallRequest, () => _inCallReleasingFloor !);
            _inCallRequestingFloor.AddTransition(EventId.CallStartFailed, () => _registered);
            _inCallRequestingFloor.AddTransition(EventId.PttDown, () => _inCallRequestingFloor);
            _inCallRequestingFloor.AddTransition(EventId.PttUp, () => _inCallIdle);
            _inCallRequestingFloor.AddTransition(EventId.GroupSelected, () => _inCallRequestingFloor);
            _stateManager.AddState(_inCallRequestingFloor);

            //in call releasing floor
            _inCallReleasingFloor = new RopuState(StateId.InCallReleasingFloor)
            {
                Entry = async token =>
                {
                    if (_callGroup == null)
                    {
                        throw new InvalidOperationException("No call group");
                    }
                    if (_clientSettings.UserId == null)
                    {
                        throw new InvalidOperationException("UserId is not set");
                    }
                    while (!token.IsCancellationRequested)
                    {
                        _servingNodeClient.SendFloorReleased(_callGroup.Value, _clientSettings.UserId.Value);
                        await Task.Run(() => token.WaitHandle.WaitOne(1000));
                    }
                }
            };
            _inCallReleasingFloor.AddTransition(EventId.FloorGranted, () => _inCallReleasingFloor);
            _inCallReleasingFloor.AddTransition(EventId.RegistrationResponseReceived, () => _inCallReleasingFloor);
            _inCallReleasingFloor.AddTransition(EventId.CallRequest, () => _inCallReleasingFloor);
            _inCallReleasingFloor.AddTransition(EventId.CallStartFailed, () => _registered);
            _inCallReleasingFloor.AddTransition(EventId.PttDown, () => _inCallRequestingFloor);
            _inCallReleasingFloor.AddTransition(EventId.PttUp, () => _inCallReleasingFloor);
            _inCallReleasingFloor.AddTransition(EventId.GroupSelected, () => _inCallReleasingFloor);

            _stateManager.AddState(_inCallReleasingFloor);


            _inCallReleasingFloor.AddTransition(EventId.FloorGranted, () => _inCallReleasingFloor);


            _stateManager.StateChanged += (sender, args) =>
            {
                Console.WriteLine($"State Changed {this._stateManager.CurrentState}");
                StateChanged?.Invoke(this, args);
            };

            _stateManager.AddTransitionToAll(EventId.HeartbeatFailed, () => _unregistered, stateId => true);
            _stateManager.AddTransitionToAll(EventId.NotRegistered, () => _unregistered, stateId => true);
            _stateManager.AddTransitionToAll(EventId.CallEnded, () => _registered, stateId => stateId != StateId.Unregistered && stateId != StateId.Start && stateId != StateId.Deregistering);
            _stateManager.AddTransitionToAll(EventId.FloorIdle, () => _inCallIdle, IsRegistered);
            _stateManager.AddTransitionToAll(EventId.FloorTaken, () => _inCallReceiveing, IsRegistered);
            _stateManager.AddTransitionToAll(EventId.FloorGranted, () => _inCallTransmitting, stateId => stateId != StateId.InCallReleasingFloor);
            _stateManager.AddTransitionToAll(EventId.DeregistrationResponseReceived, () => _unregistered, stateId => true);
            _stateManager.AddTransitionToAll(EventId.GroupDeselected, () => _noGroup, stateId => true);

            _stateManager.CheckEventsAreHandledByAll((EventId[])Enum.GetValues(typeof(EventId)));
        }
예제 #5
0
 public ServingNodeClient(ProtocolSwitch protocolSwitch)
 {
     _protocolSwitch = protocolSwitch;
     _protocolSwitch.SetControlPacketParser(this);
 }