From f92d371a198a54f4bae5d67c93a30ce220e212cd Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Fri, 9 Aug 2024 11:07:54 +0300 Subject: [PATCH 1/2] Add test bed project --- Samples/999_TestBed/999_TestBed.csproj | 12 ++++++ Samples/999_TestBed/Program.cs | 58 ++++++++++++++++++++++++++ Samples/Samples.sln | 14 +++++++ 3 files changed, 84 insertions(+) create mode 100644 Samples/999_TestBed/999_TestBed.csproj create mode 100644 Samples/999_TestBed/Program.cs diff --git a/Samples/999_TestBed/999_TestBed.csproj b/Samples/999_TestBed/999_TestBed.csproj new file mode 100644 index 000000000..3985e06e7 --- /dev/null +++ b/Samples/999_TestBed/999_TestBed.csproj @@ -0,0 +1,12 @@ + + + + Exe + net8.0 + + + + + + + diff --git a/Samples/999_TestBed/Program.cs b/Samples/999_TestBed/Program.cs new file mode 100644 index 000000000..a550b34a8 --- /dev/null +++ b/Samples/999_TestBed/Program.cs @@ -0,0 +1,58 @@ +using System; +using System.Threading; +using SteamKit2; + +// This is just a test bed to nethook various packets to later be added in tests + +var steamClient = new SteamClient(); +var manager = new CallbackManager( steamClient ); +using var cts = new CancellationTokenSource(); + +steamClient.DebugNetworkListener = new NetHookNetworkListener(); + +var steamUser = steamClient.GetHandler(); +var steamApps = steamClient.GetHandler(); + +manager.Subscribe( OnConnected ); +manager.Subscribe( OnDisconnected ); +manager.Subscribe( OnLoggedOn ); + +Console.WriteLine( "Connecting to Steam..." ); + +steamClient.Connect(); + +while ( !cts.IsCancellationRequested ) +{ + await manager.RunWaitCallbackAsync( cts.Token ); +} + +void OnConnected( SteamClient.ConnectedCallback callback ) +{ + Console.WriteLine( "Connected to Steam! Logging in..." ); + + steamUser.LogOnAnonymous(); +} + +void OnDisconnected( SteamClient.DisconnectedCallback callback ) +{ + Console.WriteLine( "Disconnected from Steam" ); + + cts.Cancel(); +} + +async void OnLoggedOn( SteamUser.LoggedOnCallback callback ) +{ + if ( callback.Result != EResult.OK ) + { + Console.WriteLine( $"Unable to logon to Steam: {callback.Result}" ); + cts.Cancel(); + return; + } + + Console.WriteLine( "Successfully logged on!" ); + + await steamApps.PICSGetProductInfo( new SteamApps.PICSRequest( 480 ), null ); + await steamApps.PICSGetProductInfo( new SteamApps.PICSRequest( 480 ), null, true ); + + steamUser.LogOff(); +} diff --git a/Samples/Samples.sln b/Samples/Samples.sln index cb790089f..c7f54fbb6 100644 --- a/Samples/Samples.sln +++ b/Samples/Samples.sln @@ -31,6 +31,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "022_DotaMatchRequest", "022 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamKit2", "..\SteamKit2\SteamKit2\SteamKit2.csproj", "{4B2B0365-DE37-4B65-B614-3E4E7C05147D}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "999_TestBed", "999_TestBed\999_TestBed.csproj", "{A5DDFB34-6FFC-4CE5-8575-8D600DE9D547}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -209,6 +211,18 @@ Global {4B2B0365-DE37-4B65-B614-3E4E7C05147D}.Release|Mixed Platforms.Build.0 = Release|Any CPU {4B2B0365-DE37-4B65-B614-3E4E7C05147D}.Release|x86.ActiveCfg = Release|Any CPU {4B2B0365-DE37-4B65-B614-3E4E7C05147D}.Release|x86.Build.0 = Release|Any CPU + {A5DDFB34-6FFC-4CE5-8575-8D600DE9D547}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A5DDFB34-6FFC-4CE5-8575-8D600DE9D547}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A5DDFB34-6FFC-4CE5-8575-8D600DE9D547}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {A5DDFB34-6FFC-4CE5-8575-8D600DE9D547}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {A5DDFB34-6FFC-4CE5-8575-8D600DE9D547}.Debug|x86.ActiveCfg = Debug|Any CPU + {A5DDFB34-6FFC-4CE5-8575-8D600DE9D547}.Debug|x86.Build.0 = Debug|Any CPU + {A5DDFB34-6FFC-4CE5-8575-8D600DE9D547}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A5DDFB34-6FFC-4CE5-8575-8D600DE9D547}.Release|Any CPU.Build.0 = Release|Any CPU + {A5DDFB34-6FFC-4CE5-8575-8D600DE9D547}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {A5DDFB34-6FFC-4CE5-8575-8D600DE9D547}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {A5DDFB34-6FFC-4CE5-8575-8D600DE9D547}.Release|x86.ActiveCfg = Release|Any CPU + {A5DDFB34-6FFC-4CE5-8575-8D600DE9D547}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From d9cb1874c579dab2d5325c8e682e1055b2b0dcb4 Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Fri, 9 Aug 2024 11:36:52 +0300 Subject: [PATCH 2/2] Add pics info test packets --- SteamKit2/SteamKit2/Steam/CMClient.cs | 4 + SteamKit2/Tests/PacketFacts.cs | 81 ++++++++++++++++++ ...ICSProductInfoResponse_app480_metadata.bin | Bin 0 -> 120 bytes ...sgClientPICSProductInfoResponse_app480.bin | Bin 0 -> 3313 bytes ...EMsgClientPICSProductInfoResponse_sub0.bin | Bin 0 -> 9352 bytes SteamKit2/Tests/Tests.csproj | 3 + 6 files changed, 88 insertions(+) create mode 100644 SteamKit2/Tests/PacketFacts.cs create mode 100644 SteamKit2/Tests/Packets/001_in_8904_k_EMsgClientPICSProductInfoResponse_app480_metadata.bin create mode 100644 SteamKit2/Tests/Packets/002_in_8904_k_EMsgClientPICSProductInfoResponse_app480.bin create mode 100644 SteamKit2/Tests/Packets/003_in_8904_k_EMsgClientPICSProductInfoResponse_sub0.bin diff --git a/SteamKit2/SteamKit2/Steam/CMClient.cs b/SteamKit2/SteamKit2/Steam/CMClient.cs index d4c9e633f..09a16bbe3 100644 --- a/SteamKit2/SteamKit2/Steam/CMClient.cs +++ b/SteamKit2/SteamKit2/Steam/CMClient.cs @@ -430,6 +430,10 @@ void NetMsgReceived( object? sender, NetMsgEventArgs e ) OnClientMsgReceived( GetPacketMsg( e.Data, this ) ); } +#if DEBUG + internal void ReceiveTestPacketMsg( IPacketMsg packetMsg ) => OnClientMsgReceived( packetMsg ); +#endif + void Connected( object? sender, EventArgs e ) { DebugLog.Assert( connection != null, nameof( CMClient ), "No connection object after connecting." ); diff --git a/SteamKit2/Tests/PacketFacts.cs b/SteamKit2/Tests/PacketFacts.cs new file mode 100644 index 000000000..5712fd803 --- /dev/null +++ b/SteamKit2/Tests/PacketFacts.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using SteamKit2; +using SteamKit2.Internal; +using Xunit; + +#nullable enable +namespace Tests +{ + public class PacketFacts + { + internal record struct TestPacket( EMsg EMsg, byte[] Data ); + + private static Type? GetCallback( EMsg msg ) => msg switch + { + EMsg.ClientPICSProductInfoResponse => typeof( SteamApps.PICSProductInfoCallback ), + _ => null, + }; + + [Fact] + public async Task PostsExpectedCallbacks() + { + var steamClient = new SteamClient(); + + await foreach ( var (eMsg, data) in GetPackets( "in" ) ) + { + var expectedCallback = GetCallback( eMsg ); + Assert.NotNull( expectedCallback ); + + var packetMsg = CMClient.GetPacketMsg( data, steamClient ); + Assert.NotNull( packetMsg ); + Assert.IsAssignableFrom( packetMsg ); + + Assert.Null( steamClient.GetCallback() ); // There must be no callbacks queued + + steamClient.ReceiveTestPacketMsg( packetMsg ); + + var callback = steamClient.GetCallback(); + Assert.NotNull( callback ); + Assert.Equal( expectedCallback, callback.GetType() ); + } + } + + private static async IAsyncEnumerable GetPackets( string direction ) + { + var folder = Path.Join( AppDomain.CurrentDomain.BaseDirectory, "Packets" ); + var files = Directory.GetFiles( folder, "*.bin" ); + + foreach ( var filename in files ) + { + var packet = await GetPacket( filename, direction ); + + if ( packet.HasValue ) + { + yield return packet.Value; + } + } + } + + private static async Task GetPacket( string filename, string direction ) + { + var parts = Path.GetFileNameWithoutExtension( filename ).Split( '_' ); + + Assert.True( parts.Length > 3 ); + + if ( parts[ 1 ] != direction ) + { + return null; + } + + var emsg = ( EMsg )uint.Parse( parts[ 2 ] ); + + var data = await File.ReadAllBytesAsync( filename ); + + return new( emsg, data ); + } + } +} +#nullable disable diff --git a/SteamKit2/Tests/Packets/001_in_8904_k_EMsgClientPICSProductInfoResponse_app480_metadata.bin b/SteamKit2/Tests/Packets/001_in_8904_k_EMsgClientPICSProductInfoResponse_app480_metadata.bin new file mode 100644 index 0000000000000000000000000000000000000000..adee3a3321ecc8ddadad48939ea4622e5fb1be1f GIT binary patch literal 120 zcmX@1#Lytiz`(#M9BSmDSh|2wVDF(%t27#9heoPEpsvHlP1s1Qm#x231 zBvQy4zk1S5hQ6>pH*(T41d>i@L|-&uu$U{U!3d-pIGmJ|b23x&N|N*Q(lXQa60;L? W6EpRSOHvbai%SwqGL!X^^K$|D_$tu= literal 0 HcmV?d00001 diff --git a/SteamKit2/Tests/Packets/002_in_8904_k_EMsgClientPICSProductInfoResponse_app480.bin b/SteamKit2/Tests/Packets/002_in_8904_k_EMsgClientPICSProductInfoResponse_app480.bin new file mode 100644 index 0000000000000000000000000000000000000000..9dd7af9e5bb4c55c314b642b17394cce4627f08e GIT binary patch literal 3313 zcmb_e&2HpG5S|4gG2s#k4(tIb__RV%;@`2&Ey*Mxfw+WSgg96|c2B02w%h5pXELCb zcmfXGS3=?jJOUh%_R0mp4RPZg5KvWZdnTJK2Sk)8?ym0o`Rc2xe(H=qe`7QnjbDA} zzx!tU)xF&xe*f;zzy5}wdmrB$?fxeTKTCKR|#R0fIwBQCKcz8~(pj-Io zXnxfS&CTVkRIMQ#>7LW9Yg)a7=-QK#Gs8{88WLzu>w<)YMZORfgT!gI@QIud@qY zX@ZED<>Ua^h0<$u!LqU6$@~PPv56YaWkGP)ZWs=`WDSd;twgiVmcodc_vqdz;el!V965KiWI{5ClQb?_4)iEh(Mq1Pd_ji2 ziA5ZRHzmFs4A)397n1i@jcRqy1z>qlu*ROVkg7_qR|{T=3Y-C2ZLzu#2AwerR&cF3 za!phh8;myu0uXMq#zC^Hc_DMU;<>5o?}uUR1sDP*1n`@S3s_K-gW4?1E%+pBE2xEm zQnrZ^y)c(NZyUl2jGtql`UuHzdJPRr@&l0LO_23;uT*8XkXjwRDk!d|KVaeOaOend zBU=@e)e^b`*xFR#1`fzjemPgVtpQ?gW*okG7X|EGZ8+b_& zxk2K3k>>`k7x*^4Xi|J?`&a5t+=#FvFV(7&ic!;v(|8hC+EOy$R!^`yttCO?CvlJl z{=@~!2SFIyb6eJ8sDzj>eAXIpFZ4rufe^E>@haEry5Ys$v2XL-l6D9_Nsrt#oWxUb zBu&qf(<$&faZh~z$UjaeU0@sEg0tx4`1myPk`v#Jpcp16(P$LNsrp>y_v(*A7GrZnRJv{9!#8<6q7^TQfiL_41uB*1h zNp1&YKRM0XfJ=kg?m3Cz*wl1S!>wr!L!fT6QV?FDMZ(dnytzdlKi(O+qvXl`2k`G7 D77t)% literal 0 HcmV?d00001 diff --git a/SteamKit2/Tests/Packets/003_in_8904_k_EMsgClientPICSProductInfoResponse_sub0.bin b/SteamKit2/Tests/Packets/003_in_8904_k_EMsgClientPICSProductInfoResponse_sub0.bin new file mode 100644 index 0000000000000000000000000000000000000000..ed85f40a0ee55527810f134aa9124110f7bd8af9 GIT binary patch literal 9352 zcmXZidB9g=-Ujfi$5JFh(qt`Ol|~b;Q4L|j zOl66(@B3c7-f1jDcEgB4!(89*_5O8ze&?Lu@7d1xzVCB?pJzMboOS@V$d8)+Qiq8P zo3(!bxy3(kHnCXV-$Xqr5sY3zum5oleVwq>avA?tHD~$DwxL|<2PUvyIWsUt8GD9PxXNJC>IVO7+=z6Q2 zFVWXC;Fl%#y2A6fTSokYf0c%i@ZI;8HKuOcjDM>}oY~$oL$94JbM!dLvOwplmL-nA z$1>owwwo|3jPr~b@0qY?dplmE?@r9vh~@iPX6WACGDp?ZvcMspCEo63uLD~2v8?cy z0hSRA4o;?4HDMDJTH15Wg;@Zw$eI%2z(mI-@#))??0UuTVt zxcWIqh9}=}C*Mn{E*g@`M++SEQL;il~zHQLNDuv8vj;K;B> z$g%koex$(SXB;JVe$^2$^mRvtBx|`+02gQxPGpK zb-3J7;>necfS+D>ROtPtBVy|Ao7=k*+8*d&bw>lsXWmhc42y*vcM1i*o$9AbT=%#m z;LIl-6>d4axxGE&+fgkHEX%tcHSYY$z(N`^WD7%v*;z{iZ~ZQg0yhnDl<3@VD?1f% zd%ISK3dbDhi1=l`BjJ=$TidA`*WP7dN#(P)F=Y5|y(7oicCGD5f%p15N^~FS2zYd( zqe9>Nx3y~`TDRQJkkIuVM~!j68dzMLAGCuZ!zD`{IbMFgtsUY0wsSi}iHF~I1bp(H zqr%pCdpi};e%(%ngg0;4*-+!WTMaC;PhN6lxNf5($B6xRwNnMI@4uU&#HNRJFa&(p zyrZGQ0c-X!@NPa}Pea1wXF3^beDF$V4(cPC#+^3d{|9^y%sd5-pBx~;;gjPUHnrd= zXc54%lEsgf77<%nB($=qv9$&7;%z)La6IMf9NT&p*v_*A$5$Q?*uk?xThE9cJriuI zY{+W-#*+8$Zk`!-_sqd@na2xo9A=i-!!w|hXNAt55&L>3?B~e=)slBC$8BbY(lbZ! zERZ})bn^`8?pfhr&xk`j6AtyP@q0_&r#(C~^z_VeglB;xJxlcR3^>Y@RplAc$1|ay zXN^Bt^6os^Gs7{SIr@7R;QYYzB?fv14Dzfn*fV0NXTr&zHAY$To;<}f!)VVOV>}C- z>RDo}CkK4b3g>!8oadQvnP-i8mb??^duF)aGsi;D0?&Guc-}MMMb8Q^dq%wCneeJ- zjn^zW;J@ja;cd?x?|2qi=UL)!o&oQ9R(Rht;seiw4?S!A-I4?TN1hoz_RO)~lM}jU ziBCNPKJ%>bxo5-|o(bQ2*7&ET4fx*)88!$xIHlUD0zU{P{v`zbC{*}Ki1=AZ*eKNa zw}Ykfi;&@0A&0HPI2ROXCX{Fp0yYyWY%WB!5E6D0YH&{H+gUWb2pM)2a_lA)*j*^m zK?vw5RM|h}sDrESr zkYj*QV4zT9kPyJtGk;PJ_{RznLxhC?5o#RgU`ZV>WEd{w7%dc-A(S{<2slTmFjI(_ zB_y0Ha9DP*xXu?cTp;AQS}1UhP~uu4V2)7XIw4}NkT6fEG2g*5yFtjXRLJpwP~btK z#3~_RwZPS`5b>~(@TgGZF$W9oNg=~aLXP)^0vm)9-wPZYIUO`)TxV?|L~JP}v=nM= z&Q8hlsCaQPEyLc*Vf8cQ9l!OWkIxajKE!rsM2S5Kk95kiS0g@9fH7hOU`e<5LjP-CEj zH8@nrFjvTN;uiKLxab-olo%-loGes0Tj1lMkT6rIG0VXkymw3c94@*Rv~uLQNhol$ zP-3AFu!zeOUR+_R5OEL}Bs`L^hAR+)i`xzc*5Fcs4~KjC5!PTQM}fEYbCj5VfFs}} zj^2D%g^@zUb3(%NLX8(3ticxr)}X+JqEKKu7bp#RDltO{*q=)h9^rCMh&WK-vRSB+ zIaq_akl_I#$1YsS@QJs;-a?5^LO^Gs!oEU8CL|O>jnYuC2D=Cu4i|Ft5ef_zN(>hQ znuH1`2@xZOgj0nYr#V=IIisHsIW?iSS|3AoBWy@ z=Z`e71}_jYTqxwYNZ{{T;O|-B?^&oYTZp(!NVr0%aixPbc$JW0*va;_xa+V?D6m{8 zv0|#9;<|gfgF7t(?+qd0457w&L&+MPAY_;#2pI+nIR*&@ zc3JG#l-NxO=yt0gsnA`B=qDsRxWrG@Smj_1t`;&pB;1zoCoi? z(-ARqm4mBXp+>(a>|!q(aj!j)-NA4z9iguD%?s!FvU+z65^q z33f5(!DS~pN-P%wD%%7t>k3;PYA))cDj8Sc9Jl89oe}*p6`ET69I`C~=PvaIe7U!OBlX94;gr9sNj+^<50C!N1y$a^PBY zoseS-+d~eV2aoLQ;O2_J-4%h`D+2ddgoM5V?`H>V@HX3f4%`5obG#$RV<$KY3>)F# zT2u&F*5pSjEEghH2nqKHHKy3+bzlun6*5c{xMH;Z?7$7cNw$F2$&*N7;Ssn zfg6B>ZBsjNEqba@V~??Rgf;l%Bu9pygdFpy`w@;vGaMX|1dd2Tg~>w16d_@%z`5JO z8azwj+%0hK7C3hcoVx|i-9m*~0_PNgbBe$@#laf9K*(^BkmF*Zz$HS7OND^hLWRqO zh|2}eumWdTL&X}rO2}}vz&?vm;98-?93kL3p~74tVxEvNU#M}tgEe@Akl{ul#{z-d z&H~q>Lcl_y!XhDJv5@dbp~fu^*5Iu|h9yFd+XT+ALWw(sfIkU*P7xyR6cX+dYTWH$ z4gOik@E3vW4T0+of$I$+;2xpEy+Xu&Lc;w*jg=18-~&R22ZbD~gaWID5)TOh4+~u7 z3K5SA36BXi9(S+?pAgta5pp~w6nI)F@r)4gtWe=OA>w%<;RT__iw@S{OG1X1g&eO4 z1zr_Oye0&^E>w6!hJR|wp$w7yftP53UC zIx2J(BDx6)!-X0n9IU}6A;YCYj@d$i%LM)f1^xvE{sjf@tzKqdi`}na-L5L}8P>rX zi~<{ALXKJ}aFD>&mk`iZsL)MdTTMtfSg3J`A+iP!6}Vp~di;G!?ZI?RO1r!P_y3dcWjbMGb$UZ_Fp~4PA zL|Y+YZ=uFM4%T2NAwy>&$3W}rMb3kRgc5^=fD=~xsR~1dh+#s)i9(Ix4%Xm;$LwPE z6&`xr!PS?*)t6A>DeD+UJ`X-ERCq>+cveVwPT*dFgEjcFkl_^}$E!kt*94A8AK53f z5%#rE;U7Z8Hv%`dg&Iv?+QqEFlY|T-g&Zdf1*TXlGqT;Vz*?CxuwS#$!G?_xx#`WW zVq_!iN1?`5*4&J&!JDnQ8M!C3?=FrU&G&H>ct_w)p!Gc?Tg`0+-W%uok%(>PITD_* zPH5zw%vuL)u(`EFBOA{BpK|2*qxD83Yw#AK#H|ANz69=l2@#)LZ#1$IRc(6Kim;HEk1XaGsE3Vs|!e6MGYr1g>NRu4IG?Q-z3WLPBPZ-Nb%gll5~G zYw!;1)h4b*f3+5E;`89JoSoUk8XRrC+Qg>b7$IP+z^4i8-X^X^Z!X!iO>9PQuzHK$`X%QV>ht|x3PY1VsBz6>*pr! z$-HI#+{FLxSR?R$cCZFNwZ?AZT6C^8c2nT@Z2jECebLRVpPN{N8?2w3Sc3 + + PreserveNewest +