Skip to content

Commit 8ddd9e9

Browse files
author
Nako Sung
committed
Web socket bridge
1 parent 5033ebd commit 8ddd9e9

13 files changed

+1155
-1
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#pragma once
2+
3+
#include "ModuleInterface.h"
4+
5+
/**
6+
* Interface for the JavascriptWebSocket Module.
7+
*/
8+
class IJavascriptWebSocketModule : public IModuleInterface
9+
{
10+
public:
11+
12+
/**
13+
* Singleton-like access to this module's interface. This is just for convenience!
14+
* Beware of calling this during the shutdown phase, though. Your module might have been unloaded already.
15+
*
16+
* @return Returns singleton instance, loading the module on demand if needed
17+
*/
18+
static inline IJavascriptWebSocketModule& Get()
19+
{
20+
return FModuleManager::LoadModuleChecked< IJavascriptWebSocketModule >("JavascriptWebSocket");
21+
}
22+
23+
/**
24+
* Checks to see if this module is loaded and ready. It is only valid to call Get() if IsAvailable() returns true.
25+
*
26+
* @return True if the module is loaded and ready to use
27+
*/
28+
static inline bool IsAvailable()
29+
{
30+
return FModuleManager::Get().IsModuleLoaded("JavascriptWebSocket");
31+
}
32+
};
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using UnrealBuildTool;
2+
3+
public class JavascriptWebSocket : ModuleRules
4+
{
5+
public JavascriptWebSocket(TargetInfo Target)
6+
{
7+
PublicDependencyModuleNames.AddRange(new string[] {
8+
"Core",
9+
"CoreUObject",
10+
"Engine",
11+
"V8",
12+
"Sockets",
13+
"WebSockets",
14+
"OnlineSubSystemUtils",
15+
"Networking"
16+
});
17+
}
18+
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2+
#include "JavascriptWebSocketModule.h"
3+
#include "JavascriptWebSocket.h"
4+
#include "JavascriptWebSocketServer.h"
5+
#include "JavascriptContext.h"
6+
#include "WebSocket.h"
7+
8+
UJavascriptWebSocket* UJavascriptWebSocket::Connect(const FString& EndpointString)
9+
{
10+
FIPv4Endpoint Endpoint;
11+
12+
if (!FIPv4Endpoint::Parse(EndpointString, Endpoint))
13+
{
14+
return nullptr;
15+
}
16+
17+
auto addr = Endpoint.ToInternetAddr();
18+
return CreateFrom(new FWebSocket(*addr), GetTransientPackage());
19+
}
20+
21+
UJavascriptWebSocket* UJavascriptWebSocket::CreateFrom(FWebSocket* WebSocket, UObject* Outer)
22+
{
23+
auto instance = NewObject<UJavascriptWebSocket>(Outer);
24+
instance->WebSocket = MakeShareable<FWebSocket>(WebSocket);
25+
26+
{
27+
FWebsocketPacketRecievedCallBack callback;
28+
callback.BindUObject(instance, &UJavascriptWebSocket::OnReceivedCallback);
29+
instance->WebSocket->SetRecieveCallBack(callback);
30+
}
31+
32+
{
33+
FWebsocketInfoCallBack callback;
34+
callback.BindUObject(instance, &UJavascriptWebSocket::OnErrorCallback);
35+
instance->WebSocket->SetErrorCallBack(callback);
36+
}
37+
38+
{
39+
FWebsocketInfoCallBack callback;
40+
callback.BindUObject(instance, &UJavascriptWebSocket::OnConnectedCallback);
41+
instance->WebSocket->SetConnectedCallBack(callback);
42+
}
43+
return instance;
44+
}
45+
46+
void UJavascriptWebSocket::OnReceivedCallback(void* InData, int32 Count)
47+
{
48+
Buffer = InData;
49+
Size = Count;
50+
OnReceived.Broadcast();
51+
Buffer = InData;
52+
Size = 0;
53+
}
54+
55+
int32 UJavascriptWebSocket::GetReceivedBytes()
56+
{
57+
return Size;
58+
}
59+
60+
void UJavascriptWebSocket::CopyBuffer()
61+
{
62+
if (FArrayBufferAccessor::GetSize() >= Size)
63+
{
64+
FMemory::Memcpy(FArrayBufferAccessor::GetData(), Buffer, Size);
65+
}
66+
}
67+
68+
void UJavascriptWebSocket::OnConnectedCallback()
69+
{
70+
OnConnected.Broadcast();
71+
}
72+
73+
void UJavascriptWebSocket::OnErrorCallback()
74+
{
75+
OnError.Broadcast();
76+
77+
if (auto server = Cast<UJavascriptWebSocketServer>(GetOuter()))
78+
{
79+
server->OnConnectionLost(this);
80+
}
81+
}
82+
83+
void UJavascriptWebSocket::SendMemory(int32 NumBytes)
84+
{
85+
if (!WebSocket.IsValid()) return;
86+
87+
auto Buffer = FArrayBufferAccessor::GetData();
88+
auto Size = FArrayBufferAccessor::GetSize();
89+
90+
if (NumBytes > Size) return;
91+
92+
WebSocket->Send((uint8*)Buffer, NumBytes);
93+
}
94+
95+
FString UJavascriptWebSocket::RemoteEndPoint()
96+
{
97+
if (!WebSocket.IsValid()) return TEXT("Invalid");
98+
99+
return WebSocket->RemoteEndPoint();
100+
}
101+
102+
FString UJavascriptWebSocket::LocalEndPoint()
103+
{
104+
if (!WebSocket.IsValid()) return TEXT("Invalid");
105+
106+
return WebSocket->LocalEndPoint();
107+
}
108+
109+
void UJavascriptWebSocket::Flush()
110+
{
111+
if (!WebSocket.IsValid()) return;
112+
113+
WebSocket->Flush();
114+
}
115+
116+
void UJavascriptWebSocket::Tick()
117+
{
118+
if (!WebSocket.IsValid()) return;
119+
120+
WebSocket->Tick();
121+
}
122+
123+
void UJavascriptWebSocket::Dispose()
124+
{
125+
WebSocket.Reset();
126+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#pragma once
2+
3+
#include "JavascriptWebSocket.generated.h"
4+
5+
UCLASS()
6+
class UJavascriptWebSocket : public UObject
7+
{
8+
GENERATED_BODY()
9+
10+
public:
11+
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnWebSocketDelegate);
12+
13+
UPROPERTY(BlueprintAssignable, Category = "Scripting | Javascript")
14+
FOnWebSocketDelegate OnReceived;
15+
16+
UPROPERTY(BlueprintAssignable, Category = "Scripting | Javascript")
17+
FOnWebSocketDelegate OnConnected;
18+
19+
UPROPERTY(BlueprintAssignable, Category = "Scripting | Javascript")
20+
FOnWebSocketDelegate OnError;
21+
22+
UFUNCTION(BlueprintCallable, Category = "Scripting | Javascript")
23+
static UJavascriptWebSocket* Connect(const FString& Endpoint);
24+
25+
static UJavascriptWebSocket* CreateFrom(FWebSocket*, UObject* Outer);
26+
27+
UFUNCTION(BlueprintCallable, Category = "Scripting | Javascript")
28+
void SendMemory(int32 NumBytes);
29+
30+
UFUNCTION(BlueprintPure, Category = "Scripting | Javascript")
31+
int32 GetReceivedBytes();
32+
33+
UFUNCTION(BlueprintCallable, Category = "Scripting | Javascript")
34+
void CopyBuffer();
35+
36+
UFUNCTION(BlueprintPure, Category = "Scripting | Javascript")
37+
FString RemoteEndPoint();
38+
39+
UFUNCTION(BlueprintPure, Category = "Scripting | Javascript")
40+
FString LocalEndPoint();
41+
42+
UFUNCTION(BlueprintCallable, Category = "Scripting | Javascript")
43+
void Flush();
44+
45+
UFUNCTION(BlueprintCallable, Category = "Scripting | Javascript")
46+
void Tick();
47+
48+
UFUNCTION(BlueprintCallable, Category = "Scripting | Javascript")
49+
void Dispose();
50+
51+
private:
52+
TSharedPtr<FWebSocket> WebSocket;
53+
int32 Size{ 0 };
54+
void* Buffer{ nullptr };
55+
56+
void OnReceivedCallback(void* InData, int32 Count);
57+
void OnConnectedCallback();
58+
void OnErrorCallback();
59+
};
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#include "JavascriptWebSocketModule.h"
2+
3+
class FJavascripWebSocketModule : public IJavascriptWebSocketModule
4+
{
5+
// Begin IModuleInterface
6+
virtual void StartupModule() override;
7+
virtual void ShutdownModule() override;
8+
// End IModuleInterface
9+
10+
};
11+
12+
13+
void FJavascripWebSocketModule::StartupModule()
14+
{
15+
16+
}
17+
18+
19+
void FJavascripWebSocketModule::ShutdownModule()
20+
{
21+
22+
}
23+
24+
IMPLEMENT_MODULE(FJavascripWebSocketModule, JavascriptWebSocket);
25+
DEFINE_LOG_CATEGORY(LogWebsocket);
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#pragma once
2+
3+
#include "Core.h"
4+
#include "Engine.h"
5+
#include "Networking.h"
6+
#include "Sockets.h"
7+
#include "SocketSubsystem.h"
8+
#include "ModuleManager.h"
9+
10+
// Interfaces
11+
#include "IJavascriptWebSocketModule.h"
12+
13+
class FWebSocket;
14+
class FWebSocketServer;
15+
16+
typedef struct libwebsocket_context WebSocketInternalContext;
17+
typedef struct libwebsocket WebSocketInternal;
18+
typedef struct libwebsocket_protocols WebSocketInternalProtocol;
19+
20+
DECLARE_DELEGATE_TwoParams(FWebsocketPacketRecievedCallBack, void* /*Data*/, int32 /*Data Size*/);
21+
DECLARE_DELEGATE_OneParam(FWebsocketClientConnectedCallBack, FWebSocket* /*Socket*/);
22+
DECLARE_DELEGATE(FWebsocketInfoCallBack);
23+
24+
DECLARE_LOG_CATEGORY_EXTERN(LogWebsocket, Warning, All);
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2+
#include "JavascriptWebSocketModule.h"
3+
#include "WebSocket.h"
4+
#include "WebSocketServer.h"
5+
#include "JavascriptWebSocketServer.h"
6+
7+
UJavascriptWebSocketServer* UJavascriptWebSocketServer::Create(int32 Port)
8+
{
9+
auto instance = NewObject<UJavascriptWebSocketServer>();
10+
auto server = instance->WebSocketServer = MakeShareable<FWebSocketServer>(new FWebSocketServer);
11+
FWebsocketClientConnectedCallBack callback;
12+
callback.BindUObject(instance, &UJavascriptWebSocketServer::OnConnectedCallback);
13+
if (!server->Init(Port, callback))
14+
{
15+
return nullptr;
16+
}
17+
return instance;
18+
}
19+
20+
FString UJavascriptWebSocketServer::Info()
21+
{
22+
if (!WebSocketServer.IsValid()) return TEXT("Invalid");
23+
24+
return WebSocketServer->Info();
25+
}
26+
27+
void UJavascriptWebSocketServer::OnConnectedCallback(FWebSocket* WebSocket)
28+
{
29+
auto instance = UJavascriptWebSocket::CreateFrom(WebSocket, this);
30+
Connections.Add(instance);
31+
OnConnected.Broadcast(instance);
32+
}
33+
34+
void UJavascriptWebSocketServer::OnConnectionLost(UJavascriptWebSocket* Connection)
35+
{
36+
Connections.Remove(Connection);
37+
}
38+
39+
void UJavascriptWebSocketServer::Tick()
40+
{
41+
if (!WebSocketServer.IsValid()) return;
42+
43+
WebSocketServer->Tick();
44+
45+
for (auto Connection : Connections)
46+
{
47+
Connection->Tick();
48+
}
49+
}
50+
51+
void UJavascriptWebSocketServer::Dispose()
52+
{
53+
WebSocketServer.Reset();
54+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#pragma once
2+
3+
#include "JavascriptWebSocketServer.generated.h"
4+
5+
class FWebSocketServer;
6+
class UJavascriptWebSocket;
7+
8+
UCLASS()
9+
class UJavascriptWebSocketServer : public UObject
10+
{
11+
GENERATED_BODY()
12+
13+
public:
14+
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnWebSocketServerDelegate,UJavascriptWebSocket*,WebSocket);
15+
16+
UPROPERTY(BlueprintAssignable, Category = "Scripting | Javascript")
17+
FOnWebSocketServerDelegate OnConnected;
18+
19+
UFUNCTION(BlueprintCallable, Category = "Scripting | Javascript")
20+
static UJavascriptWebSocketServer* Create(int32 Port);
21+
22+
UFUNCTION(BlueprintPure, Category = "Scripting | Javascript")
23+
FString Info();
24+
25+
UFUNCTION(BlueprintCallable, Category = "Scripting | Javascript")
26+
void Tick();
27+
28+
UFUNCTION(BlueprintCallable, Category = "Scripting | Javascript")
29+
void Dispose();
30+
31+
UPROPERTY()
32+
TArray<UJavascriptWebSocket*> Connections;
33+
34+
void OnConnectionLost(UJavascriptWebSocket* Connection);
35+
36+
private:
37+
TSharedPtr<FWebSocketServer> WebSocketServer;
38+
39+
void OnConnectedCallback(FWebSocket*);
40+
};

0 commit comments

Comments
 (0)