예제 #1
0
        /// <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));
        }
예제 #2
0
        /// <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);
            }
        }
예제 #3
0
            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++;
            }
예제 #4
0
        /// <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);
        }
예제 #5
0
 /// <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);
     }
 }
예제 #6
0
            /// <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));
            }
예제 #7
0
            /// <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));
            }
예제 #8
0
            /// <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);
            }
예제 #9
0
            /// <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);
            }
예제 #10
0
        /// <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);
        }
예제 #11
0
            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);
            }
예제 #12
0
 public IPAddress ToIPAddress()
 {
     return(NetHelpers.GetIPAddress(NetHelpers.EndianSwap(IPAddress)));
 }
예제 #13
0
        /// <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);
        }