/// <summary> /// Connects this client to a UFS server. /// This begins the process of connecting and encrypting the data channel between the client and the UFS server. /// Results are returned asynchronously in a <see cref="ConnectedCallback"/>. /// If the UFS server that this client attempts to connect to is down, a <see cref="DisconnectedCallback"/> will be posted instead. /// <see cref="UFSClient"/> will not attempt to reconnect to Steam, you must handle this callback and call <see cref="Connect"/> again, preferrably after a short delay. /// In order to connect to the UFS server, the parent <see cref="SteamClient"/> must be connected to the CM server. /// </summary> /// <param name="ufsServer"> /// The <see cref="System.Net.IPEndPoint"/> of the UFS server to connect to. /// If <c>null</c>, <see cref="UFSClient"/> will randomly select a UFS server from the <see cref="SteamClient"/>'s list of servers. /// </param> public void Connect(IPEndPoint ufsServer = null) { DebugLog.Assert(steamClient.IsConnected, nameof(UFSClient), "CMClient is not connected!"); Disconnect(); Debug.Assert(connection == null); if (ufsServer == null) { var serverList = steamClient.GetServersOfType(EServerType.UFS); if (serverList.Count == 0) { DebugLog.WriteLine(nameof(UFSClient), "No UFS server addresses were provided yet."); Disconnected(this, new DisconnectedEventArgs(userInitiated: false)); return; } var random = new Random(); ufsServer = serverList[random.Next(serverList.Count)]; } // steamclient has the connection type hardcoded as TCP // todo: determine if UFS supports UDP and if we want to support it connection = new EnvelopeEncryptedConnection(new TcpConnection(), steamClient.Universe); connection.NetMsgReceived += NetMsgReceived; connection.Connected += Connected; connection.Disconnected += Disconnected; connection.Connect(ufsServer, ( int )ConnectionTimeout.TotalMilliseconds); }
/// <summary> /// Connects this client to a UFS server. /// This begins the process of connecting and encrypting the data channel between the client and the UFS server. /// Results are returned asynchronously in a <see cref="ConnectedCallback"/>. /// If the UFS server that this client attempts to connect to is down, a <see cref="DisconnectedCallback"/> will be posted instead. /// <see cref="UFSClient"/> will not attempt to reconnect to Steam, you must handle this callback and call <see cref="Connect"/> again, preferrably after a short delay. /// In order to connect to the UFS server, the parent <see cref="SteamClient"/> must be connected to the CM server. /// </summary> /// <param name="ufsServer"> /// The <see cref="System.Net.IPEndPoint"/> of the UFS server to connect to. /// If <c>null</c>, <see cref="UFSClient"/> will randomly select a UFS server from the <see cref="SteamClient"/>'s list of servers. /// </param> public void Connect(IPEndPoint ufsServer = null) { DebugLog.Assert(steamClient.IsConnected, "UFSClient", "CMClient is not connected!"); Disconnect(); if (ufsServer == null) { var serverList = steamClient.GetServersOfType(EServerType.UFS); Random random = new Random(); ufsServer = serverList[random.Next(serverList.Count)]; } connection.Connect(ufsServer, ( int )ConnectionTimeout.TotalMilliseconds); }
/// <summary> /// Connects this client to a UFS server. /// This begins the process of connecting and encrypting the data channel between the client and the UFS server. /// Results are returned asynchronously in a <see cref="ConnectedCallback"/>. /// If the UFS server that this client attempts to connect to is down, a <see cref="DisconnectedCallback"/> will be posted instead. /// <see cref="UFSClient"/> will not attempt to reconnect to Steam, you must handle this callback and call <see cref="Connect"/> again, preferrably after a short delay. /// In order to connect to the UFS server, the parent <see cref="SteamClient"/> must be connected to the CM server. /// </summary> /// <param name="ufsServer"> /// The <see cref="System.Net.IPEndPoint"/> of the UFS server to connect to. /// If <c>null</c>, <see cref="UFSClient"/> will randomly select a UFS server from the <see cref="SteamClient"/>'s list of servers. /// </param> public void Connect(IPEndPoint ufsServer = null) { DebugLog.Assert(steamClient.IsConnected, "UFSClient", "CMClient is not connected!"); this.Disconnect(); pendingNetFilterEncryption = null; if (ufsServer == null) { var serverList = steamClient.GetServersOfType(EServerType.UFS); Random random = new Random(); ufsServer = serverList[random.Next(serverList.Count)]; } connection.Connect(Task.FromResult(ufsServer), ( int )ConnectionTimeout.TotalMilliseconds); }
/// <summary> /// Connects this client to a UFS server. /// This begins the process of connecting and encrypting the data channel between the client and the UFS server. /// Results are returned asynchronously in a <see cref="ConnectedCallback"/>. /// If the UFS server that this client attempts to connect to is down, a <see cref="DisconnectedCallback"/> will be posted instead. /// <see cref="UFSClient"/> will not attempt to reconnect to Steam, you must handle this callback and call <see cref="Connect"/> again, preferrably after a short delay. /// In order to connect to the UFS server, the parent <see cref="SteamClient"/> must be connected to the CM server. /// </summary> /// <param name="ufsServer"> /// The <see cref="System.Net.IPEndPoint"/> of the UFS server to connect to. /// If <c>null</c>, <see cref="UFSClient"/> will randomly select a UFS server from the <see cref="SteamClient"/>'s list of servers. /// </param> public void Connect(IPEndPoint ufsServer = null) { DebugLog.Assert(steamClient.IsConnected, nameof(UFSClient), "CMClient is not connected!"); Disconnect(); if (ufsServer == null) { var serverList = steamClient.GetServersOfType(EServerType.UFS); if (serverList.Count == 0) { DebugLog.WriteLine(nameof(UFSClient), "No UFS server addresses were provided yet."); Disconnected(this, new DisconnectedEventArgs(userInitiated: false)); return; } var random = new Random(); ufsServer = serverList[random.Next(serverList.Count)]; } connection.Connect(ufsServer, ( int )ConnectionTimeout.TotalMilliseconds); }
/// <summary> /// Fetches a list of content servers. /// </summary> /// <param name="csServer"> /// The optional Steam3 content server to fetch the list from. /// If this parameter is not specified, a random CS server will be selected. /// </param> /// <param name="cellId"> /// The optional CellID used to specify which regional servers should be returned in the list. /// If this parameter is not specified, Steam's GeoIP suggested CellID will be used instead. /// </param> /// <param name="maxServers">The maximum amount of servers to request.</param> /// <returns>A list of servers.</returns> /// <exception cref="System.InvalidOperationException"> /// No Steam CS servers available, or the suggested CellID is unavailable. /// Check that the <see cref="SteamClient"/> associated with this <see cref="CDNClient"/> instance is logged onto Steam. /// </exception> public List <Server> FetchServerList(IPEndPoint csServer = null, uint?cellId = null, int maxServers = 20) { DebugLog.Assert(steamClient.IsConnected, "CDNClient", "CMClient is not connected!"); DebugLog.Assert(steamClient.CellID != null, "CDNClient", "CMClient is not logged on!"); if (csServer == null) { // if we're not specifying what CS server we want to fetch a server list from, randomly select a cached CS server var csServers = steamClient.GetServersOfType(EServerType.CS); if (csServers.Count == 0) { // steamclient doesn't know about any CS servers yet throw new InvalidOperationException("No CS servers available!"); } Random random = new Random(); csServer = csServers[random.Next(csServers.Count)]; } if (cellId == null) { if (steamClient.CellID == null) { throw new InvalidOperationException("Recommended CellID is not available. CMClient not logged on?"); } // fallback to recommended cellid cellId = steamClient.CellID.Value; } KeyValue serverKv = DoCommand(csServer, "serverlist", args: string.Format("{0}/{1}/", cellId, maxServers)); var serverList = new List <Server>(maxServers); if (serverKv["deferred"].AsBoolean()) { return(serverList); } foreach (var server in serverKv.Children) { string type = server["type"].AsString(); string host = server["host"].AsString(); string[] hostSplits = host.Split(':'); int port = 80; if (hostSplits.Length > 1) { int parsedPort; if (int.TryParse(hostSplits[1], out parsedPort)) { port = parsedPort; } } uint serverCell = ( uint )server["cell"].AsInteger(); int load = server["load"].AsInteger(); int weightedLoad = server["weightedload"].AsInteger(); serverList.Add(new Server { Host = host, Port = port, Type = type, CellID = serverCell, Load = load, WeightedLoad = weightedLoad, }); } return(serverList); }
/// <summary> /// Fetches a list of content servers. /// </summary> /// <param name="csServer"> /// The optional Steam3 content server to fetch the list from. /// If this parameter is not specified, a random CS server will be selected. /// </param> /// <param name="cellId"> /// The optional CellID used to specify which regional servers should be returned in the list. /// If this parameter is not specified, Steam's GeoIP suggested CellID will be used instead. /// </param> /// <param name="maxServers">The maximum amount of servers to request.</param> /// <returns>A list of servers.</returns> /// <exception cref="System.InvalidOperationException"> /// No Steam CS servers available, or the suggested CellID is unavailable. /// Check that the <see cref="SteamClient"/> associated with this <see cref="CDNClient"/> instance is logged onto Steam. /// </exception> /// <exception cref="HttpRequestException">An network error occurred when performing the request.</exception> /// <exception cref="SteamKitWebRequestException">A network error occurred when performing the request.</exception> public async Task <IList <Server> > FetchServerListAsync(IPEndPoint csServer = null, uint?cellId = null, int maxServers = 20) { DebugLog.Assert(steamClient.IsConnected, "CDNClient", "CMClient is not connected!"); DebugLog.Assert(steamClient.CellID != null, "CDNClient", "CMClient is not logged on!"); if (csServer == null) { // if we're not specifying what CS server we want to fetch a server list from, randomly select a cached CS server var csServers = steamClient.GetServersOfType(EServerType.CS); if (csServers.Count == 0) { // steamclient doesn't know about any CS servers yet throw new InvalidOperationException("No CS servers available!"); } Random random = new Random(); csServer = csServers[random.Next(csServers.Count)]; } if (cellId == null) { if (steamClient.CellID == null) { throw new InvalidOperationException("Recommended CellID is not available. CMClient not logged on?"); } // fallback to recommended cellid cellId = steamClient.CellID.Value; } var serverKv = await DoCommandAsync(csServer, HttpMethod.Get, "serverlist", args : string.Format("{0}/{1}/", cellId, maxServers)).ConfigureAwait(false); var serverList = new List <Server>(maxServers); if (serverKv["deferred"].AsBoolean()) { return(serverList); } foreach (var server in serverKv.Children) { string type = server["type"].AsString(); string host = server["host"].AsString(); string vhost = server["vhost"].AsString(); string[] hostSplits = host.Split(':'); int port = 80; if (hostSplits.Length > 1) { int parsedPort; if (int.TryParse(hostSplits[1], out parsedPort)) { port = parsedPort; } } uint serverCell = ( uint )server["cell"].AsInteger(); int load = server["load"].AsInteger(); int weightedLoad = server["weightedload"].AsInteger(); int entries = server["NumEntriesInClientList"].AsInteger(1); int useTokenAuth = server["usetokenauth"].AsInteger(); string httpsSupport = server["https_support"].AsString(); // If usetokenauth is specified, we can treat this server as a CDN and request tokens if (useTokenAuth > 0) { type = "CDN"; } Server.ConnectionProtocol protocol = (httpsSupport == "optional" || httpsSupport == "mandatory") ? Server.ConnectionProtocol.HTTPS : Server.ConnectionProtocol.HTTP; serverList.Add(new Server { Protocol = protocol, Host = host, VHost = vhost, Port = protocol == Server.ConnectionProtocol.HTTPS ? 443 : port, Type = type, CellID = serverCell, Load = load, WeightedLoad = weightedLoad, NumEntries = entries }); } return(serverList); }