sources/Google.Solutions.IapDesktop.Core/ClientModel/Protocol/AppProtocol.cs (79 lines of code) (raw):
//
// Copyright 2023 Google LLC
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
using Google.Solutions.Common.Linq;
using Google.Solutions.Common.Util;
using Google.Solutions.IapDesktop.Core.ClientModel.Traits;
using System.Collections.Generic;
using System.Linq;
using System.Net;
namespace Google.Solutions.IapDesktop.Core.ClientModel.Protocol
{
/// <summary>
/// Custom protocol, to be used with a locally installed app.
/// </summary>
public class AppProtocol : IProtocol
{
public AppProtocol(
string name,
IEnumerable<ITrait> requiredTraits,
ushort remotePort,
IPEndPoint? localEndpoint,
IAppProtocolClient? client)
{
this.Name = name.ExpectNotNull(nameof(name));
this.RequiredTraits = requiredTraits.ExpectNotNull(nameof(requiredTraits));
this.RemotePort = remotePort;
this.LocalEndpoint = localEndpoint;
this.Client = client;
}
//---------------------------------------------------------------------
// Properties.
//---------------------------------------------------------------------
/// <summary>
/// Traits that a target has to have to use this protocol.
/// </summary>
public IEnumerable<ITrait> RequiredTraits { get; }
/// <summary>
/// Port to connect transport to.
/// </summary>
public ushort RemotePort { get; }
/// <summary>
/// Local (loopback) address and port to bind to. If null, a port is
/// selected dynamically.
/// </summary>
public IPEndPoint? LocalEndpoint { get; }
/// <summary>
/// Optional: Client app to launch after connecting transport.
/// </summary>
public IAppProtocolClient? Client { get; }
//---------------------------------------------------------------------
// IProtocol.
//---------------------------------------------------------------------
public string Name { get; }
public bool IsAvailable(IProtocolTarget target)
{
if (this.Client != null && !this.Client.IsAvailable)
{
return false;
}
else
{
return this.RequiredTraits
.EnsureNotNull()
.All(target.Traits.EnsureNotNull().Contains);
}
}
//---------------------------------------------------------------------
// Equality.
//---------------------------------------------------------------------
public override int GetHashCode()
{
return
this.Name.GetHashCode() ^
this.RemotePort ^
(this.LocalEndpoint?.GetHashCode() ?? 0);
}
public override bool Equals(object obj)
{
return Equals(obj as AppProtocol);
}
public bool Equals(IProtocol? other)
{
//
// NB. Ignore if the client is the same or not as the client
// doesn't "define" the protocol, and different clients
// should share the same transport if their protocol is
// equivalent otherwise.
//
return other is AppProtocol protocol &&
Equals(protocol.Name, this.Name) &&
Enumerable.SequenceEqual(protocol.RequiredTraits, this.RequiredTraits) &&
Equals(protocol.RemotePort, this.RemotePort) &&
Equals(protocol.LocalEndpoint, this.LocalEndpoint);
}
public static bool operator ==(AppProtocol obj1, AppProtocol obj2)
{
if (obj1 is null)
{
return obj2 is null;
}
return obj1.Equals(obj2);
}
public static bool operator !=(AppProtocol obj1, AppProtocol obj2)
{
return !(obj1 == obj2);
}
//---------------------------------------------------------------------
// Overrides.
//---------------------------------------------------------------------
public override string ToString()
{
return this.Name;
}
}
}