/// <summary> /// Opens a storage session with the storage server. /// </summary> /// <param name="depotId">The depot id.</param> /// <param name="depotVersion">The depot version.</param> /// <param name="cellId">The cell id.</param> /// <param name="credentials">The credentials.</param> /// <returns>A new StorageSession object for the session.</returns> public StorageSession OpenStorage(uint depotId, uint depotVersion, uint cellId, Credentials credentials) { bool bRet = this.HandshakeServer(( ESteam2ServerType )7); if (!bRet) { throw new Steam2Exception("Storage handshake with content server failed"); } bRet = this.SendCommand( 0, // open storage cellId ); byte success = this.Socket.Reader.ReadByte(); if (success == 0) { throw new Steam2Exception(string.Format("Unable to open storage depot for cellid {0}", cellId)); } ushort bannerLen = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt16()); byte[] bannerData = this.Socket.Reader.ReadBytes(bannerLen); return(new StorageSession(this, depotId, depotVersion, credentials)); }
/// <summary> /// Requests the cell ID of the currently connected content server. /// </summary> /// <returns>The cell ID of the server.</returns> public uint GetCellID() { if (!this.HandshakeServer(( ESteam2ServerType )3)) { throw new Steam2Exception("Package handshake with content server failed"); } TcpPacket packet = new TcpPacket(); packet.Write(( uint )2); try { this.Socket.Send(packet); uint cellId = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); return(cellId); } catch (Exception ex) { throw new Steam2Exception("Unable to request cell id", ex); } }
internal StorageSession(ContentServerClient cli, uint depotId, uint depotVersion, Credentials credentials) { this.DepotID = depotId; this.DepotVersion = depotVersion; this.client = cli; bool bRet = false; if (credentials == null) { bRet = this.SendCommand( 9, // open storage ConnectionID, MessageID, depotId, depotVersion ); } else { byte[] serverTgt = credentials.Steam2Ticket.Entries[14].Data; // god help this never change bRet = this.SendCommand( 10, // open storage with login ConnectionID, MessageID, depotId, depotVersion, ( ushort )serverTgt.Length, serverTgt, NetHelpers.EndianSwap(credentials.SessionToken), ( byte )credentials.AppTicket.Length, credentials.AppTicket ); } // the server sends us back the connection and message ids // the client probably performs a sanity check? uint connId = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint msgId = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); byte hasDepot = this.Socket.Reader.ReadByte(); // the server gives us 0x1 if the depot doesn't exist or requires authentication if (hasDepot != 0) { throw new Steam2Exception("Content server does not have depot, or valid credentials were not given"); } StorageID = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint storageChecksum = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); this.ConnectionID++; }
/// <summary> /// Attempts to receive a tcp packet from the socket. /// </summary> /// <returns>The packet.</returns> public TcpPacket ReceivePacket() { TcpPacket pack = new TcpPacket(); uint size = NetHelpers.EndianSwap(this.Reader.ReadUInt32()); byte[] payload = Reader.ReadBytes(( int )size); pack.SetPayload(payload); return(pack); }
/// <summary> /// Performs a handshake with the server. /// </summary> /// <param name="type">The expected server type the client is handshaking with.</param> /// <returns>True if the handshake succeeded; otherwise false.</returns> protected bool HandshakeServer(ESteam2ServerType type) { try { Socket.Writer.Write(NetHelpers.EndianSwap(( uint )type)); return(Socket.Reader.ReadByte() == 1); } catch { return(false); } }
/// <summary> /// Downloads the <see cref="Steam2Manifest"/> which contains metadata representing the files within the depot. /// </summary> /// <returns></returns> public Steam2Manifest DownloadManifest() { bool bRet = this.SendCommand( 4, // download manifest this.StorageID, this.MessageID ); uint storId = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint msgId = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); // name is a guess byte hasManifest = this.Socket.Reader.ReadByte(); uint manifestLength = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); byte[] manifest = new byte[manifestLength]; uint manifestChunksToRead = manifestLength; do { uint chunkStorID = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint chunkMsgID = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint chunkLen = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); chunkLen = Math.Min(chunkLen, manifestChunksToRead); uint toRead = chunkLen; while (toRead > 0) { uint socketRead = ( uint )this.Socket.Reader.Read(manifest, ( int )((manifestLength - manifestChunksToRead) + (chunkLen - toRead)), ( int )toRead); toRead = toRead - socketRead; } manifestChunksToRead = manifestChunksToRead - chunkLen; } while (manifestChunksToRead > 0); this.MessageID++; return(new Steam2Manifest(manifest)); }
/// <summary> /// Downloads the <see cref="Steam2ChecksumData"/> for this depot. /// </summary> /// <returns></returns> public Steam2ChecksumData DownloadChecksums() { bool bRet = this.SendCommand( 6, // download checksums this.StorageID, this.MessageID ); uint storId = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint msgId = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); // name is a(n incorrect) guess byte hasChecksums = this.Socket.Reader.ReadByte(); uint checksumsLength = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); byte[] checksumData = new byte[checksumsLength]; uint checksumChunksToRead = checksumsLength; do { uint chunkStorID = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint chunkMsgID = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint chunkLen = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); chunkLen = Math.Min(chunkLen, checksumChunksToRead); uint toRead = chunkLen; while (toRead > 0) { uint socketRead = ( uint )this.Socket.Reader.Read(checksumData, ( int )((checksumsLength - checksumChunksToRead) + (chunkLen - toRead)), ( int )toRead); toRead = toRead - socketRead; } checksumChunksToRead = checksumChunksToRead - chunkLen; } while (checksumChunksToRead > 0); this.MessageID++; return(new Steam2ChecksumData(checksumData)); }
/// <summary> /// Downloads the specified package file. /// </summary> /// <param name="fileName">Name of the file.</param> /// <returns>A byte array representing the file.</returns> public byte[] DownloadPackage(string fileName) { TcpPacket packet = new TcpPacket(); packet.Write(( uint )0); // unknown, always 0? packet.Write(( uint )0); // unknown, always 0? packet.Write(( uint )fileName.Length); packet.Write(fileName); packet.Write(this.CellID); this.Socket.Send(packet); // length is sent twice, as two uints uint len1 = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint len2 = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); byte[] packageData = this.Socket.Reader.ReadBytes(( int )len1); return(packageData); }
/// <summary> /// Downloads a list of updated FileIDs since the given version. /// </summary> /// <param name="oldVersion">The old version to compare to.</param> /// <returns>A list of FileIDs that have been updated.</returns> public uint[] DownloadUpdates(uint oldVersion) { bool bRet = this.SendCommand( 5, // download updates this.StorageID, this.MessageID, oldVersion ); uint storId = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint msgId = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); byte updateState = this.Socket.Reader.ReadByte(); uint numUpdates = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); if (numUpdates == 0) { return(null); } uint storId2 = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint msgId2 = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); TcpPacket packet = this.Socket.ReceivePacket(); DataStream ds = new DataStream(packet.GetPayload()); uint[] fileIdList = new uint[numUpdates]; for (int x = 0; x < numUpdates; ++x) { fileIdList[x] = ds.ReadUInt32(); } this.MessageID++; return(fileIdList); }
/// <summary> /// Requests the network key from the config server. /// </summary> /// <returns>The network key.</returns> public byte[] GetNetworkKey() { if (!this.HandshakeServer(ESteam2ServerType.ConfigServer)) { return(null); } uint externalIp = this.Socket.Reader.ReadUInt32(); if (!this.SendCommand(4)) // command: get network key { return(null); } ushort keyLen = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt16()); byte[] key = this.Socket.Reader.ReadBytes(keyLen); ushort sigLen = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt16()); byte[] signature = this.Socket.Reader.ReadBytes(sigLen); return(key); }
byte[] DownloadFileParts(Steam2Manifest.Node file, uint filePart, uint numParts, DownloadPriority priority = DownloadPriority.Low, byte[] cryptKey = null) { this.SendCommand( 7, // download file this.StorageID, this.MessageID, file.FileID, filePart, numParts, ( byte )priority ); uint storId = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint msgId = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); byte hasFile = this.Socket.Reader.ReadByte(); uint numChunks = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint fileModeValue = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); FileMode fileMode = ( FileMode )fileModeValue; MemoryStream ms = new MemoryStream(); for (int x = 0; x < numChunks; ++x) { uint storId2 = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint msgId2 = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint chunkLen = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint storId3 = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint msgId3 = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint chunkLen2 = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); if (chunkLen == 0) { continue; } byte[] chunk = null; int len = 0; if (fileMode == FileMode.Compressed) { chunk = this.Socket.Reader.ReadBytes(( int )chunkLen); len = DecompressFileChunk(ref chunk, ( int )file.Parent.BlockSize); } else if (fileMode == FileMode.Encrypted) { len = DecryptFileChunk(out chunk, ( int )chunkLen, cryptKey); } else if (fileMode == FileMode.EncryptedAndCompressed) { // Account for 2 integers before the encrypted data chunkLen -= 8; // Skip first integer (length of the encrypted data) this.Socket.Reader.ReadInt32(); // Length of decrypted and decompressed data int plainLen = this.Socket.Reader.ReadInt32(); DecryptFileChunk(out chunk, ( int )chunkLen, cryptKey); len = DecompressFileChunk(ref chunk, plainLen); } else if (fileMode == FileMode.None) { chunk = this.Socket.Reader.ReadBytes(( int )chunkLen); len = chunk.Length; } ms.Write(chunk, 0, len); } byte[] data = ms.ToArray(); this.MessageID++; return(data); }
public IPAddress ToIPAddress() { return(NetHelpers.GetIPAddress(NetHelpers.EndianSwap(IPAddress))); }
/// <summary> /// Gets an auth server list for a specific username. /// </summary> /// <param name="userName">The username.</param> /// <returns>A list of servers on success; otherwise, <c>null</c>.</returns> public IPEndPoint[] GetAuthServerList(string userName) { userName = userName.ToLower(); byte[] userHash = CryptoHelper.JenkinsHash(Encoding.ASCII.GetBytes(userName)); uint userData = BitConverter.ToUInt32(userHash, 0) & 1; TcpPacket packet = base.GetRawServerList(ESteam2ServerType.ProxyASClientAuthentication, NetHelpers.EndianSwap(userData)); if (packet == null) { return(null); } DataStream ds = new DataStream(packet.GetPayload(), true); ushort numAddrs = ds.ReadUInt16(); IPEndPoint[] serverList = new IPEndPoint[numAddrs]; for (int x = 0; x < numAddrs; ++x) { IPAddrPort ipAddr = IPAddrPort.Deserialize(ds.ReadBytes(6)); serverList[x] = ipAddr; } return(serverList); }