11using SteamQueryNet . Models ;
2- using SteamQueryNet . Attributes ;
2+ using SteamQueryNet . Utils ;
3+
34using System ;
45using System . Collections . Generic ;
5- using System . Globalization ;
66using System . Linq ;
77using System . Net ;
88using System . Net . NetworkInformation ;
99using System . Net . Sockets ;
10- using System . Reflection ;
11- using System . Runtime . InteropServices ;
1210using System . Text ;
13- using System . Threading ;
1411using System . Threading . Tasks ;
15- using SteamQueryNet . Utils ;
1612
13+ [ assembly: System . Runtime . CompilerServices . InternalsVisibleTo ( "SteamQueryNet.Tests" ) ]
1714namespace SteamQueryNet
1815{
1916 // This is not really required but imma be a good guy and create this for them people that wants to mock the ServerQuery.
@@ -39,6 +36,30 @@ public interface IServerQuery
3936 /// <returns>Connected instance of ServerQuery.</returns>
4037 IServerQuery Connect ( string serverAddress , ushort port ) ;
4138
39+ /// <summary>
40+ /// Configures and Connects the created instance of SteamQuery UDP socket for Steam Server Query Operations.
41+ /// </summary>
42+ /// <param name="serverAddressAndPort">IPAddress or HostName of the server and port separated by a colon(:) or a comma(,).</param>
43+ /// <returns>Connected instance of ServerQuery.</returns>
44+ IServerQuery Connect ( string serverAddressAndPort ) ;
45+
46+ /// <summary>
47+ /// Configures and Connects the created instance of SteamQuery UDP socket for Steam Server Query Operations.
48+ /// </summary>
49+ /// <param name="customLocalIPEndpoint">Desired local IPEndpoint to bound.</param>
50+ /// <param name="serverAddressAndPort">IPAddress or HostName of the server and port separated by a colon(:) or a comma(,).</param>
51+ /// <returns>Connected instance of ServerQuery.</returns>
52+ IServerQuery Connect ( IPEndPoint customLocalIPEndpoint , string serverAddressAndPort ) ;
53+
54+ /// <summary>
55+ /// Configures and Connects the created instance of SteamQuery UDP socket for Steam Server Query Operations.
56+ /// </summary>
57+ /// <param name="customLocalIPEndpoint">Desired local IPEndpoint to bound.</param>
58+ /// <param name="serverAddress">IPAddress or HostName of the server that queries will be sent.</param>
59+ /// <param name="port">Port of the server that queries will be sent.</param>
60+ /// <returns>Connected instance of ServerQuery.</returns>
61+ IServerQuery Connect ( IPEndPoint customLocalIPEndpoint , string serverAddress , ushort port ) ;
62+
4263 /// <summary>
4364 /// Requests and serializes the server information.
4465 /// </summary>
@@ -82,20 +103,21 @@ public interface IServerQuery
82103
83104 public class ServerQuery : IServerQuery , IDisposable
84105 {
85- private IPEndPoint _ipEndpoint ;
86- private readonly UdpClient _client = new UdpClient ( new IPEndPoint ( IPAddress . Any , 0 ) ) ;
106+ private IPEndPoint _remoteIpEndpoint ;
87107
88108 private ushort _port ;
89109 private int _currentChallenge ;
90110
111+ internal virtual UdpClient UdpClient { get ; private set ; }
112+
91113 /// <summary>
92114 /// Reflects the udp client connection state.
93115 /// </summary>
94116 public bool IsConnected
95117 {
96118 get
97119 {
98- return _client . Client . Connected ;
120+ return UdpClient . Client . Connected ;
99121 }
100122 }
101123
@@ -109,6 +131,17 @@ public bool IsConnected
109131 /// </summary>
110132 public int ReceiveTimeout { get ; set ; }
111133
134+ /// <summary>
135+ /// Creates a new instance of ServerQuery with given UDPClient and remote endpoint.
136+ /// </summary>
137+ /// <param name="udpClient">UdpClient to communicate.</param>
138+ /// <param name="remoteEndpoint">Remote server endpoint.</param>
139+ public ServerQuery ( UdpClient udpClient , IPEndPoint remoteEndpoint )
140+ {
141+ UdpClient = udpClient ;
142+ _remoteIpEndpoint = remoteEndpoint ;
143+ }
144+
112145 /// <summary>
113146 /// Creates a new instance of ServerQuery without UDP socket connection.
114147 /// </summary>
@@ -141,7 +174,7 @@ public ServerQuery(string serverAddressAndPort)
141174 /// <param name="serverAddressAndPort">IPAddress or HostName of the server and port separated by a colon(:) or a comma(,).</param>
142175 public ServerQuery ( IPEndPoint customLocalIPEndpoint , string serverAddressAndPort )
143176 {
144- _client = new UdpClient ( customLocalIPEndpoint ) ;
177+ UdpClient = new UdpClient ( customLocalIPEndpoint ) ;
145178 ( string serverAddress , ushort port ) = Helpers . ResolveIPAndPortFromString ( serverAddressAndPort ) ;
146179 PrepareAndConnect ( serverAddress , port ) ;
147180 }
@@ -154,7 +187,7 @@ public ServerQuery(IPEndPoint customLocalIPEndpoint, string serverAddressAndPort
154187 /// <param name="port">Port of the server that queries will be sent.</param>
155188 public ServerQuery ( IPEndPoint customLocalIPEndpoint , string serverAddress , ushort port )
156189 {
157- _client = new UdpClient ( customLocalIPEndpoint ) ;
190+ UdpClient = new UdpClient ( customLocalIPEndpoint ) ;
158191 PrepareAndConnect ( serverAddress , port ) ;
159192 }
160193
@@ -165,13 +198,38 @@ public IServerQuery Connect(string serverAddress, ushort port)
165198 return this ;
166199 }
167200
201+ /// <inheritdoc/>
202+ public IServerQuery Connect ( string serverAddressAndPort )
203+ {
204+ ( string serverAddress , ushort port ) = Helpers . ResolveIPAndPortFromString ( serverAddressAndPort ) ;
205+ PrepareAndConnect ( serverAddress , port ) ;
206+ return this ;
207+ }
208+
209+ /// <inheritdoc/>
210+ public IServerQuery Connect ( IPEndPoint customLocalIPEndpoint , string serverAddressAndPort )
211+ {
212+ UdpClient = new UdpClient ( customLocalIPEndpoint ) ;
213+ ( string serverAddress , ushort port ) = Helpers . ResolveIPAndPortFromString ( serverAddressAndPort ) ;
214+ PrepareAndConnect ( serverAddress , port ) ;
215+ return this ;
216+ }
217+
218+ /// <inheritdoc/>
219+ public IServerQuery Connect ( IPEndPoint customLocalIPEndpoint , string serverAddress , ushort port )
220+ {
221+ UdpClient = new UdpClient ( customLocalIPEndpoint ) ;
222+ PrepareAndConnect ( serverAddress , port ) ;
223+ return this ;
224+ }
225+
168226 /// <inheritdoc/>
169227 public async Task < ServerInfo > GetServerInfoAsync ( )
170228 {
171229 const string requestPayload = "Source Engine Query\0 " ;
172230 var sInfo = new ServerInfo
173231 {
174- Ping = new Ping ( ) . Send ( _ipEndpoint . Address ) . RoundtripTime
232+ Ping = new Ping ( ) . Send ( _remoteIpEndpoint . Address ) . RoundtripTime
175233 } ;
176234
177235 byte [ ] response = await SendRequestAsync ( RequestHeaders . A2S_INFO , Encoding . UTF8 . GetBytes ( requestPayload ) ) ;
@@ -262,8 +320,8 @@ public List<Rule> GetRules()
262320 /// </summary>
263321 public void Dispose ( )
264322 {
265- _client . Close ( ) ;
266- _client . Dispose ( ) ;
323+ UdpClient . Close ( ) ;
324+ UdpClient . Dispose ( ) ;
267325 }
268326
269327 private void PrepareAndConnect ( string serverAddress , ushort port )
@@ -274,7 +332,7 @@ private void PrepareAndConnect(string serverAddress, ushort port)
274332 if ( IPAddress . TryParse ( serverAddress , out IPAddress parsedIpAddress ) )
275333 {
276334 // Yep its an IP.
277- _ipEndpoint = new IPEndPoint ( parsedIpAddress , _port ) ;
335+ _remoteIpEndpoint = new IPEndPoint ( parsedIpAddress , _port ) ;
278336 }
279337 else
280338 {
@@ -285,7 +343,7 @@ private void PrepareAndConnect(string serverAddress, ushort port)
285343 if ( addresslist . Length > 0 )
286344 {
287345 // We get the first address.
288- _ipEndpoint = new IPEndPoint ( addresslist [ 0 ] , _port ) ;
346+ _remoteIpEndpoint = new IPEndPoint ( addresslist [ 0 ] , _port ) ;
289347 }
290348 else
291349 {
@@ -298,16 +356,17 @@ private void PrepareAndConnect(string serverAddress, ushort port)
298356 }
299357 }
300358
301- _client . Client . SendTimeout = SendTimeout ;
302- _client . Client . ReceiveTimeout = ReceiveTimeout ;
303- _client . Connect ( _ipEndpoint ) ;
359+ UdpClient = UdpClient ?? new UdpClient ( new IPEndPoint ( IPAddress . Any , 0 ) ) ;
360+ UdpClient . Client . SendTimeout = SendTimeout ;
361+ UdpClient . Client . ReceiveTimeout = ReceiveTimeout ;
362+ UdpClient . Connect ( _remoteIpEndpoint ) ;
304363 }
305364
306365 private async Task < byte [ ] > SendRequestAsync ( byte requestHeader , byte [ ] payload = null )
307366 {
308367 var request = BuildRequest ( requestHeader , payload ) ;
309- await _client . SendAsync ( request , request . Length ) ;
310- UdpReceiveResult result = await _client . ReceiveAsync ( ) ;
368+ await UdpClient . SendAsync ( request , request . Length ) ;
369+ UdpReceiveResult result = await UdpClient . ReceiveAsync ( ) ;
311370 return result . Buffer ;
312371 }
313372
0 commit comments