Skip to content

Commit b00d4bc

Browse files
committed
Handle a compressed response from the login server
1 parent 9ba60d1 commit b00d4bc

1 file changed

Lines changed: 49 additions & 23 deletions

File tree

TibiaAPI/Network/Connection.cs

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.IO;
4+
using System.IO.Compression;
45
using System.Net;
56
using System.Net.Http;
67
using 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

Comments
 (0)