11using System ;
22using System . Collections . Generic ;
33using System . IO ;
4+ using System . IO . Compression ;
45using System . Net ;
56using System . Net . Http ;
67using System . Net . Sockets ;
@@ -587,7 +588,16 @@ private void BeginGetContextCallback(IAsyncResult ar)
587588
588589 _client . Logger . Debug ( $ "Client POST: { clientRequest } ") ;
589590
590- var response = PostAsync ( clientRequest ) . Result ;
591+ var data = PostAsync ( clientRequest ) . Result ;
592+ var response = string . Empty ;
593+ using ( var compressedStream = new MemoryStream ( data ) )
594+ using ( var zipStream = new GZipStream ( compressedStream , CompressionMode . Decompress ) )
595+ using ( var resultStream = new MemoryStream ( ) )
596+ {
597+ zipStream . CopyTo ( resultStream ) ;
598+ response = Encoding . UTF8 . GetString ( resultStream . ToArray ( ) ) ;
599+ }
600+
591601 if ( string . IsNullOrEmpty ( response ) )
592602 {
593603 // This can happen with Open-Tibia servers where their login service doesn't handle all
@@ -598,29 +608,41 @@ private void BeginGetContextCallback(IAsyncResult ar)
598608
599609 _client . Logger . Debug ( $ "Server response: { response } ") ;
600610
601- // Login data is the only thing we have to modify, everything else can be piped through.
602- dynamic loginData = JsonConvert . DeserializeObject ( response ) ;
603- if ( loginData != null && loginData . session != null )
611+ try
604612 {
605- // Change the address and port of each game world to that of the TCP listener so that
606- // the Tibia client connects to the TCP listener instead of a game world.
607- var address = ( ( IPEndPoint ) _tcpListener . LocalEndpoint ) . Address . ToString ( ) ;
608- var port = ( ( IPEndPoint ) _tcpListener . LocalEndpoint ) . Port ;
609- foreach ( var world in loginData . playdata . worlds )
613+ // Login data is the only thing we have to modify, everything else can be piped through.
614+ dynamic loginData = JsonConvert . DeserializeObject ( response ) ;
615+ if ( loginData != null && loginData . session != null )
610616 {
611- world . externaladdressprotected = address ;
612- world . externaladdressunprotected = address ;
613- world . externalportprotected = port ;
614- world . externalportunprotected = port ;
615- }
617+ // Change the address and port of each game world to that of the TCP listener so that
618+ // the Tibia client connects to the TCP listener instead of a game world.
619+ var address = ( ( IPEndPoint ) _tcpListener . LocalEndpoint ) . Address . ToString ( ) ;
620+ var port = ( ( IPEndPoint ) _tcpListener . LocalEndpoint ) . Port ;
621+ foreach ( var world in loginData . playdata . worlds )
622+ {
623+ world . externaladdressprotected = address ;
624+ world . externaladdressunprotected = address ;
625+ world . externalportprotected = port ;
626+ world . externalportunprotected = port ;
627+ }
616628
617- // Store the original login data so when the Tibia client tries to connect to a game world
618- // the server socket can recall the address and port to connect to.
619- _loginData = JsonConvert . DeserializeObject ( response ) ;
620- response = JsonConvert . SerializeObject ( loginData ) ;
629+ // Store the original login data so when the Tibia client tries to connect to a game world
630+ // the server socket can recall the address and port to connect to.
631+ _loginData = JsonConvert . DeserializeObject ( response ) ;
632+ response = JsonConvert . SerializeObject ( loginData ) ;
633+ }
634+ }
635+ catch ( JsonReaderException )
636+ {
637+ // This exception can occur if the login server responds with something other than JSON.
638+ // This is usually HTML when Tibia is down for maintenance. Ignore the exception and continue on.
639+ }
640+ catch
641+ {
642+ throw ;
621643 }
622644
623- var data = Encoding . UTF8 . GetBytes ( response ) ;
645+ data = Encoding . UTF8 . GetBytes ( response ) ;
624646 context . Response . ContentLength64 = data . Length ;
625647 context . Response . OutputStream . Write ( data , 0 , data . Length ) ;
626648 context . Response . Close ( ) ;
@@ -952,25 +974,29 @@ private void BeginReceiveServerCallback(IAsyncResult ar)
952974 /// <returns>
953975 /// The response from CipSoft's web service.
954976 /// </returns>
955- private async Task < string > PostAsync ( string content )
977+ private async Task < byte [ ] > PostAsync ( string content )
956978 {
957979 try
958980 {
959981 using ( var httpClient = new HttpClient ( ) )
960982 {
961- httpClient . DefaultRequestHeaders . Add ( "user-agent" , "Mozilla/5.0" ) ;
983+ httpClient . DefaultRequestHeaders . Add ( "User-Agent" , "Mozilla/5.0" ) ;
984+ httpClient . DefaultRequestHeaders . Add ( "Connection" , "Keep-Alive" ) ;
985+ httpClient . DefaultRequestHeaders . Add ( "Accept-Language" , "en-US,*" ) ;
986+ httpClient . DefaultRequestHeaders . Add ( "Accept-Encoding" , "gzip, deflate" ) ;
962987 var postContent = new StringContent ( content , Encoding . UTF8 , "application/json" ) ;
988+ postContent . Headers . ContentType = new System . Net . Http . Headers . MediaTypeHeaderValue ( "application/json" ) ;
963989 using ( var response = await httpClient . PostAsync ( new Uri ( GetLoginWebService ( ) ) , postContent ) . ConfigureAwait ( false ) )
964990 {
965991 postContent . Dispose ( ) ;
966- return await response . Content . ReadAsStringAsync ( ) . ConfigureAwait ( false ) ;
992+ return await response . Content . ReadAsByteArrayAsync ( ) . ConfigureAwait ( false ) ;
967993 }
968994 }
969995 }
970996 catch ( Exception ex )
971997 {
972998 _client . Logger . Error ( ex . ToString ( ) ) ;
973- return string . Empty ;
999+ return Array . Empty < byte > ( ) ;
9741000 }
9751001 }
9761002
0 commit comments