Skip to content

Commit

Permalink
Fixed minor bugs, switch listening connection to IPv6. Connection bre…
Browse files Browse the repository at this point in the history
…akthrough works, booya!
  • Loading branch information
TautvydasZilys committed Oct 12, 2014
1 parent fa05a2e commit b0b8735
Show file tree
Hide file tree
Showing 16 changed files with 214 additions and 107 deletions.
1 change: 1 addition & 0 deletions BackendServer/BackendServer.sln
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Global
{95742DAD-0FEC-43DE-8381-E8729C02B69E}.Debug|Win32.ActiveCfg = Debug|Any CPU
{95742DAD-0FEC-43DE-8381-E8729C02B69E}.Debug|Win32.Build.0 = Debug|Any CPU
{95742DAD-0FEC-43DE-8381-E8729C02B69E}.Release|Win32.ActiveCfg = Release|Any CPU
{95742DAD-0FEC-43DE-8381-E8729C02B69E}.Release|Win32.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
16 changes: 12 additions & 4 deletions BackendServer/BackendServer/Controllers/HomeController.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using BackendServer.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
Expand Down Expand Up @@ -31,7 +32,14 @@ public ActionResult Index(FileHostModel model)

if (host != null && SendClientIP(host, this.Request.UserHostAddress))
{
return Redirect(host.HostSocket.RemoteEndPoint.ToString());
var remoteEndpoint = host.HostSocket.RemoteEndPoint as IPEndPoint;

if (remoteEndpoint != null && remoteEndpoint.Address.IsIPv4MappedToIPv6)
{
remoteEndpoint = new IPEndPoint(remoteEndpoint.Address.MapToIPv4(), remoteEndpoint.Port);
}

return Redirect("http://" + remoteEndpoint.ToString());
}

ModelState.AddModelError("errorSummary", "The specified file host doesn't exist.");
Expand All @@ -49,10 +57,10 @@ private bool SendClientIP(HostIdentityModel host, string ip)
var requestBuilder = new StringBuilder();

requestBuilder.Append("POST api/clientip/ HTTP/1.1\n");
requestBuilder.Append("content-type: applicaton/json\n");
requestBuilder.Append("content-type: application/json\n");

var clientIdentityModel = new ClientIdentityModel() { IpAddress = ip };
var content = Json(clientIdentityModel).ToString();
var content = JsonConvert.SerializeObject(clientIdentityModel);

requestBuilder.Append("content-length: ");
requestBuilder.Append(content.Length.ToString());
Expand All @@ -63,7 +71,7 @@ private bool SendClientIP(HostIdentityModel host, string ip)

try
{
host.HostSocket.Send(Encoding.UTF8.GetBytes(content));
host.HostSocket.Send(Encoding.UTF8.GetBytes(requestBuilder.ToString()));

var buffer = new byte[256];
var bytesReceived = host.HostSocket.Receive(buffer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,19 +75,8 @@ private RegisterConnectionController(int port)
}

private void Listen()
{/*
var listener = new HttpListener();
listener.Prefixes.Add("http://localhost:" + port.ToString() + "/api/RegisterConnection/");
listener.Start();
while (listener.IsListening)
{
var context = listener.GetContext();
ThreadPool.QueueUserWorkItem((o) => IncomingConnection(context));
}*/

var listener = new TcpListener(IPAddress.Any, port);
{
var listener = TcpListener.Create(port);
listener.Start();

for (;;)
Expand All @@ -100,7 +89,17 @@ private void Listen()
private void IncomingConnection(Socket clientSocket)
{
byte[] buffer = new byte[2560];
var bytesReceived = clientSocket.Receive(buffer);
int bytesReceived = 0;

try
{
bytesReceived = clientSocket.Receive(buffer);
}
catch
{
RefuseConnection(clientSocket);
return;
}

var text = Encoding.UTF8.GetString(buffer, 0, bytesReceived);
var lines = text.Split(new[] { '\r', '\n' }, StringSplitOptions.None);
Expand Down Expand Up @@ -142,7 +141,7 @@ private void IncomingConnection(Socket clientSocket)
return;
}
}
else if (string.Equals(lineContents[1], "content-length", StringComparison.OrdinalIgnoreCase))
else if (string.Equals(lineContents[0], "content-length", StringComparison.OrdinalIgnoreCase))
{
if (!int.TryParse(lineContents[1], out contentLength))
{
Expand All @@ -162,7 +161,15 @@ private void IncomingConnection(Socket clientSocket)

while (body.Length < contentLength)
{
bytesReceived = clientSocket.Receive(buffer, Math.Min(contentLength - body.Length, buffer.Length), SocketFlags.None);
try
{
bytesReceived = clientSocket.Receive(buffer, Math.Min(contentLength - body.Length, buffer.Length), SocketFlags.None);
}
catch
{
RefuseConnection(clientSocket);
return;
}
body.Append(Encoding.UTF8.GetString(buffer, 0, bytesReceived));
}

Expand All @@ -185,10 +192,13 @@ private void IncomingConnection(Socket clientSocket)
hostIdentities[model.SystemUniqueId] = model;
}

SendResponse(clientSocket, true);
if (!SendResponse(clientSocket, true))
{
DropConnection(model.SystemUniqueId);
}
}

private void SendResponse(Socket socket, bool success)
private bool SendResponse(Socket socket, bool success)
{
string responseString;

Expand All @@ -202,7 +212,17 @@ private void SendResponse(Socket socket, bool success)
}

var bytes = Encoding.UTF8.GetBytes(responseString);
socket.Send(bytes);

try
{
socket.Send(bytes);
}
catch
{
return false;
}

return true;
}

private void RefuseConnection(Socket socket)
Expand Down
2 changes: 1 addition & 1 deletion BackendServer/BackendServer/Global.asax.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class MvcApplication : System.Web.HttpApplication
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterConnectionController.StartListening(1335);
RegisterConnectionController.StartListening(1330);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ void ClientServerConnection::Create(SOCKET connectionSocket, string&& hostname)

// Send REST request

Http::RestCommunicator::Post(connectionSocket, std::move(hostname), "/api/RegisterConnection", systemUniqueIdKey, systemUniqueIdValue);
Http::RestCommunicator::Post(connectionSocket, std::move(hostname), "/api/RegisterConnection/", systemUniqueIdKey, systemUniqueIdValue);
if (!Http::RestCommunicator::ReceiveResponse(connectionSocket))
{
Utilities::Logging::Log(L"[ERROR] Server didn't accept system unique ID.");
Expand All @@ -28,7 +28,7 @@ void ClientServerConnection::Create(SOCKET connectionSocket, string&& hostname)

// Find my port out

sockaddr_in socketAddress;
sockaddr_in6 socketAddress;
int socketAddressLength = sizeof(socketAddress);

auto result = getsockname(connectionSocket, reinterpret_cast<sockaddr*>(&socketAddress), &socketAddressLength);
Expand All @@ -37,7 +37,7 @@ void ClientServerConnection::Create(SOCKET connectionSocket, string&& hostname)
// Start listening for connection

Tcp::Listener listener;
listener.RunAsync(socketAddress.sin_addr.S_un.S_addr, socketAddress.sin_port, [](SOCKET incomingSocket, sockaddr_in clientAddress)
listener.RunAsync(socketAddress.sin6_addr, socketAddress.sin6_port, [](SOCKET incomingSocket, sockaddr_in6 clientAddress)
{
Http::Server::StartServiceClient(incomingSocket, clientAddress, &FileBrowserResponseHandler::ExecuteRequest);
});
Expand All @@ -53,21 +53,38 @@ void ClientServerConnection::Create(SOCKET connectionSocket, string&& hostname)
return;
}

static const string ipKey("ip");
static const string ipKey("IpAddress");
auto clientIp = clientInfo.find(ipKey);

if (clientIp == clientInfo.end()) // Server sent us garbage
{ // Drop connection from our side
return;
}

UINT ipNumeric = inet_addr(clientIp->second.c_str());
// Try parse as IPv6,
// f it fails, try IPv4
IN_ADDR inAddr;
IN6_ADDR in6Addr;

if (ipNumeric == 0 || ipNumeric == INADDR_NONE) // IP can't be 0
if (InetPtonA(AF_INET6, clientIp->second.c_str(), &in6Addr) != 1)
{
if (InetPtonA(AF_INET, clientIp->second.c_str(), &inAddr) != 1)
{
return;
}
else
{
IN6_SET_ADDR_V4MAPPED(&in6Addr, &inAddr);
}
}

if (in6Addr.u.Word[0] == 0 && in6Addr.u.Word[1] == 0 && in6Addr.u.Word[2] == 0 && in6Addr.u.Word[3] == 0 &&
in6Addr.u.Word[4] == 0 && in6Addr.u.Word[5] == 0 && in6Addr.u.Word[6] == 0 && in6Addr.u.Word[7] == 0) // IP can't be 0
{
return;
}

listener.WhitelistIP(ipNumeric);
listener.WhitelistIP(in6Addr);
Http::RestCommunicator::SendResponse(connectionSocket, true);
}
}
18 changes: 17 additions & 1 deletion RemoteFileBrowser/RemoteFileBrowser/Core/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,33 @@
#include "Communication\AssetDatabase.h"
#include "Communication\ClientServerConnection.h"
#include "Communication\FileBrowserResponseHandler.h"
#include "Http\Server.h"
#include "Tcp\Client.h"
#include "Tcp\Listener.h"
#include "Utilities\Event.h"
#include "Utilities\WSAInitializer.h"

int CALLBACK wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
WSAInitializer winSockContext;
AssetDatabase::Initialize();
/*
Tcp::Listener listener;
listener.WhitelistIP(0);
listener.RunAsync(INADDR_ANY, htons(18882), [](SOCKET incomingSocket, sockaddr_in clientAddress)
{
Http::Server::StartServiceClient(incomingSocket, clientAddress, &FileBrowserResponseHandler::ExecuteRequest);
});
// Wait indefinitely
Event ev(false);
ev.Wait();
*/
for (;;)
{
Tcp::Client::Connect(L"localhost", 1335, &ClientServerConnection::Create);
Tcp::Client::Connect(L"178.250.38.253", 1330, &ClientServerConnection::Create);
Sleep(2000); // If connection drops, wait 2 seconds and try again
}

Expand Down
1 change: 1 addition & 0 deletions RemoteFileBrowser/RemoteFileBrowser/Http/Request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ class RequestParser
}
}

m_BufferPosition++;
ParseBody(s);
return;

Expand Down
44 changes: 29 additions & 15 deletions RemoteFileBrowser/RemoteFileBrowser/Http/RestCommunicator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

using namespace std;

static const char kOkResponse[] = "HTTP/1.1 200 OK";
static const char kBadRequestResponse[] = "HTTP/1.1 400 Bad Request";

static void SendPostRequest(SOCKET s, const Http::Request& httpRequest)
{
auto header = httpRequest.BuildHeaderString();
Expand Down Expand Up @@ -66,8 +69,7 @@ bool Http::RestCommunicator::ReceiveResponse(SOCKET s)
return false;
}

static const char okResponse[] = "HTTP/1.1 200 OK";
return strncmp(buffer, okResponse, sizeof(okResponse) - 1) == 0; // Don't compare null terminator
return strncmp(buffer, kOkResponse, sizeof(kOkResponse) - 1) == 0; // Don't compare null terminator
}

bool Http::RestCommunicator::ReceivePost(SOCKET s, unordered_map<string, string>& results)
Expand All @@ -90,31 +92,43 @@ bool Http::RestCommunicator::ReceivePost(SOCKET s, unordered_map<string, string>
return false;
}

auto position = 1;
size_t position = 1;
while (position < content.length() - 1)
{
auto parenthesis = content.find('\"', position);
if (parenthesis == string::npos) return false;
auto quote = content.find('\"', position);
if (quote == string::npos) return false;

auto closingParenthesis = content.find('\"', parenthesis + 1);
if (closingParenthesis == string::npos) return false;
auto closingQuote = content.find('\"', quote + 1);
if (closingQuote == string::npos) return false;

auto key = content.substr(parenthesis + 1, closingParenthesis - parenthesis - 1);
auto key = content.substr(quote + 1, closingQuote - quote - 1);

position = closingParenthesis + 1;
position = closingQuote + 1;
if (position + 1 >= content.length() || content[position] != ':') return false;

parenthesis = content.find('\"', position + 2);
if (parenthesis == string::npos) return false;
quote = content.find('\"', position + 1);
if (quote == string::npos) return false;

closingParenthesis = content.find('\"', parenthesis + 1);
if (closingParenthesis == string::npos) return false;
closingQuote = content.find('\"', quote + 1);
if (closingQuote == string::npos) return false;

auto value = content.substr(parenthesis + 1, closingParenthesis - parenthesis - 1);
auto value = content.substr(quote + 1, closingQuote - quote - 1);

results.emplace(std::move(key), std::move(value));
position = closingParenthesis + 1;
position = closingQuote + 1;
}

return true;
}

void Http::RestCommunicator::SendResponse(SOCKET s, bool success)
{
if (success)
{
send(s, kOkResponse, sizeof(kOkResponse) - 1, 0);
}
else
{
send(s, kBadRequestResponse, sizeof(kBadRequestResponse) - 1, 0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace Http
bool ReceiveResponse(SOCKET s);

bool ReceivePost(SOCKET s, std::unordered_map<std::string, std::string>& results);
void SendResponse(SOCKET s, bool success);
}
}

15 changes: 6 additions & 9 deletions RemoteFileBrowser/RemoteFileBrowser/Http/Server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ using namespace Utilities;

static const int kDataBufferSize = 4096;

void Server::StartServiceClient(SOCKET incomingSocket, sockaddr_in clientAddress, HttpRequestExecutionHandler executionHandler)
void Server::StartServiceClient(SOCKET incomingSocket, sockaddr_in6 clientAddress, HttpRequestExecutionHandler executionHandler)
{
Server serverInstance(incomingSocket, clientAddress, executionHandler);
serverInstance.Run();
}

Server::Server(SOCKET incomingSocket, sockaddr_in clientAddress, HttpRequestExecutionHandler executionHandler) :
Server::Server(SOCKET incomingSocket, sockaddr_in6 clientAddress, HttpRequestExecutionHandler executionHandler) :
m_ConnectionSocket(incomingSocket), m_ClientAddress(clientAddress), m_ReceivedData(nullptr), m_HasReportedUserAgent(false), m_ExecutionHandler(executionHandler)
{
}
Expand Down Expand Up @@ -145,14 +145,11 @@ void Server::ReportUserAgent(int dataOffset)

void Server::ReportConnectionDroppedError()
{
const int bufferSize = 256;
const int bufferSize = 64;
wchar_t msgBuffer[bufferSize];

swprintf_s(msgBuffer, bufferSize, L"Connection from %d.%d.%d.%d dropped: ",
m_ClientAddress.sin_addr.S_un.S_un_b.s_b1,
m_ClientAddress.sin_addr.S_un.S_un_b.s_b2,
m_ClientAddress.sin_addr.S_un.S_un_b.s_b3,
m_ClientAddress.sin_addr.S_un.S_un_b.s_b4);
auto msgPtr = InetNtop(AF_INET6, &m_ClientAddress.sin6_addr, msgBuffer, bufferSize);
Assert(msgPtr != nullptr);

Logging::Error(WSAGetLastError(), msgBuffer);
Logging::Error(WSAGetLastError(), L"Connection from ", msgBuffer, L" dropped: ");
}
Loading

0 comments on commit b0b8735

Please sign in to comment.