Skip to content

Commit

Permalink
feat: add Peer native class
Browse files Browse the repository at this point in the history
  • Loading branch information
JadlionHD committed Jul 6, 2024
1 parent 97a95d8 commit 076b8ea
Show file tree
Hide file tree
Showing 14 changed files with 206 additions and 44 deletions.
1 change: 1 addition & 0 deletions binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"sources": [
"lib/main.cc",
"lib/client.cc",
"lib/client_peer.cc",
"<!@(node -p \"require('fs').readdirSync('./lib/include').map(file=>'lib/include/'+file).join(' ')\")",
"<!@(node -p \"require('fs').readdirSync('./lib/src').map(file=>'lib/src/'+file).join(' ')\")"
],
Expand Down
28 changes: 16 additions & 12 deletions lib/client.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <client.h>
#include <client_peer.h>

Napi::FunctionReference Client::constructor;

Expand Down Expand Up @@ -218,22 +219,26 @@ Napi::Value Client::connect(NAPI_CB)
return Napi::Boolean::New(env, true);
}

Napi::Value Client::getPeerState(NAPI_CB)
Napi::Value Client::getPeer(NAPI_CB)
{
Napi::Env env = info.Env();
uint32_t peerID = info[0].As<Napi::Number>().Uint32Value();
ENetPeer *peer = this->peers[peerID];

return Napi::Number::New(env, peer->state);
}
if (this->peers.find(peerID) == this->peers.end())
{
Napi::TypeError::New(env, "Invalid peer ID").ThrowAsJavaScriptException();
return env.Null();
}

Napi::Value Client::getPeerRTT(NAPI_CB)
{
Napi::Env env = info.Env();
uint32_t peerID = info[0].As<Napi::Number>().Uint32Value();
ENetPeer *peer = this->peers[peerID];
ENetPeer *enetPeer = this->peers[peerID];

Napi::Function peerConstructor = env.GetInstanceData<Napi::FunctionReference>()->Value();
Napi::Object peerObj = peerConstructor.New({});
ClientPeer *peer = Napi::ObjectWrap<ClientPeer>::Unwrap(peerObj);

peer->SetENetPeer(enetPeer);

return Napi::Number::New(env, peer->roundTripTime);
return peerObj;
}

Napi::Object Client::Init(Napi::Env env, Napi::Object exports)
Expand All @@ -251,8 +256,7 @@ Napi::Object Client::Init(Napi::Env env, Napi::Object exports)
InstanceMethod<&Client::disconnectLater>("disconnectLater"),
InstanceMethod<&Client::disconnectNow>("disconnectNow"),
InstanceMethod<&Client::toggleNewPacket>("toggleNewPacket"),
InstanceMethod<&Client::getPeerRTT>("getPeerRTT"),
InstanceMethod<&Client::getPeerState>("getPeerState"),
InstanceMethod<&Client::getPeer>("getPeer"),
InstanceMethod<&Client::connect>("connect")
});
// clang-format on
Expand Down
109 changes: 109 additions & 0 deletions lib/client_peer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#include <enet/enet.h>
#include <client_peer.h>

ClientPeer::ClientPeer(NAPI_CB) : Napi::ObjectWrap<ClientPeer>(info), peer(nullptr) {}

Napi::Value ClientPeer::GetRTT(NAPI_CB)
{
Napi::Env env = info.Env();
return Napi::Number::New(env, peer->roundTripTime);
}

Napi::Value ClientPeer::GetState(NAPI_CB)
{
Napi::Env env = info.Env();
return Napi::Number::New(env, peer->state);
}

Napi::Value ClientPeer::GetChannelCount(NAPI_CB)
{
Napi::Env env = info.Env();
return Napi::Number::New(env, peer->channelCount);
}

Napi::Value ClientPeer::GetConnectID(NAPI_CB)
{
Napi::Env env = info.Env();
return Napi::Number::New(env, peer->connectID);
}

Napi::Value ClientPeer::GetIncomingBandwidth(NAPI_CB)
{
Napi::Env env = info.Env();
return Napi::Number::New(env, peer->incomingBandwidth);
}

Napi::Value ClientPeer::GetOutgoingBandwidth(NAPI_CB)
{
Napi::Env env = info.Env();
return Napi::Number::New(env, peer->outgoingBandwidth);
}

Napi::Value ClientPeer::GetPacketsLost(NAPI_CB)
{
Napi::Env env = info.Env();
return Napi::Number::New(env, peer->packetsLost);
}

Napi::Value ClientPeer::GetPacketsSent(NAPI_CB)
{
Napi::Env env = info.Env();
return Napi::Number::New(env, peer->packetsSent);
}

Napi::Value ClientPeer::GetPacketLoss(NAPI_CB)
{
Napi::Env env = info.Env();
return Napi::Number::New(env, peer->packetLoss);
}

Napi::Value ClientPeer::GetTotalWaitingData(NAPI_CB)
{
Napi::Env env = info.Env();
return Napi::Number::New(env, peer->totalWaitingData);
}

Napi::Value ClientPeer::GetAddress(NAPI_CB)
{
Napi::Env env = info.Env();

Napi::Object obj = Napi::Object::New(env);

char ipStr[INET_ADDRSTRLEN];
if (inet_ntop(AF_INET, &(peer->address.host), ipStr, INET_ADDRSTRLEN) == NULL)
{
Napi::Error::New(env, "Failed to convert IP address").ThrowAsJavaScriptException();
return env.Null();
}

obj.Set("address", Napi::String::New(env, ipStr));
obj.Set("port", Napi::Number::New(env, peer->address.port));
return obj;
}

Napi::Object ClientPeer::Init(Napi::Env env, Napi::Object exports)
{

// clang-format off
Napi::Function func = DefineClass(env, "Peer", {
InstanceMethod("getRTT", &ClientPeer::GetRTT),
InstanceMethod("getState", &ClientPeer::GetState),
InstanceMethod("getChannelCount", &ClientPeer::GetChannelCount),
InstanceMethod("getConnectID", &ClientPeer::GetConnectID),
InstanceMethod("getIncomingBandwidth", &ClientPeer::GetIncomingBandwidth),
InstanceMethod("getOutgoingBandwidth", &ClientPeer::GetOutgoingBandwidth),
InstanceMethod("getPacketsLost", &ClientPeer::GetPacketsLost),
InstanceMethod("getPacketsSent", &ClientPeer::GetPacketsSent),
InstanceMethod("getPacketLoss", &ClientPeer::GetPacketLoss),
InstanceMethod("getTotalWaitingData", &ClientPeer::GetTotalWaitingData),
InstanceMethod("getAddress", &ClientPeer::GetAddress)
});
// clang-format on

Napi::FunctionReference *constructor = new Napi::FunctionReference();
*constructor = Napi::Persistent(func);
exports.Set("Peer", func);
env.SetInstanceData(constructor);

return exports;
}
7 changes: 1 addition & 6 deletions lib/include/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,8 @@ class Client : public Napi::ObjectWrap<Client>
void disconnectNow(NAPI_CB);
void toggleNewPacket(NAPI_CB);

ENetPeer *getPeer(uint32_t peerID);
Napi::Value connect(NAPI_CB);

Napi::Value getPeerRTT(NAPI_CB);
Napi::Value getPeerState(NAPI_CB);
// Napi::Value getPeerPing(NAPI_CB);
// Napi::Value getPeerPing(NAPI_CB);
Napi::Value getPeer(NAPI_CB);

private:
Napi::FunctionReference eventEmit;
Expand Down
38 changes: 38 additions & 0 deletions lib/include/client_peer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include <napi.h>
#include <enet/enet.h>

#ifdef _WIN32
// Windows specific headers and code
#include <winsock2.h>
#include <ws2tcpip.h> // for InetNtop
#else
// Unix-like specific headers and code
#include <arpa/inet.h>
#endif

#define NAPI_CB const Napi::CallbackInfo &info

class ClientPeer : public Napi::ObjectWrap<ClientPeer>
{
public:
static Napi::Object Init(Napi::Env env, Napi::Object exports);
ClientPeer(NAPI_CB);

void SetENetPeer(ENetPeer *peer) { this->peer = peer; }

private:
Napi::Value GetRTT(NAPI_CB);
Napi::Value GetState(NAPI_CB);
Napi::Value GetChannelCount(NAPI_CB);
Napi::Value GetConnectID(NAPI_CB);
Napi::Value GetData(NAPI_CB);
Napi::Value GetIncomingBandwidth(NAPI_CB);
Napi::Value GetOutgoingBandwidth(NAPI_CB);
Napi::Value GetPacketsLost(NAPI_CB);
Napi::Value GetPacketsSent(NAPI_CB);
Napi::Value GetPacketLoss(NAPI_CB);
Napi::Value GetTotalWaitingData(NAPI_CB);
Napi::Value GetAddress(NAPI_CB);

ENetPeer *peer;
};
2 changes: 2 additions & 0 deletions lib/main.cc
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#include <client.h>
#include <client_peer.h>

Napi::Object init(Napi::Env env, Napi::Object exports)
{
ClientPeer::Init(env, exports);
return Client::Init(env, exports);
}

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"dev": "rimraf dist && npm run build && npm run build:ts && node test/basic-example/index.js",
"dev:nonative": "rimraf dist && npm run build:ts",
"docs:gen": "rimraf docs && typedoc",
"build": "prebuildify --napi",
"build:prebuild": "prebuildify --napi",
"build": "node-gyp-build",
"build:ts": "tsc",
"install": "node-gyp-build"
},
Expand Down
Binary file modified prebuilds/win32-x64/growtopia.js.node
Binary file not shown.
13 changes: 9 additions & 4 deletions src/structures/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,15 @@ import { Peer } from "./Peer.js";
import type { ActionEvent, LoginInfo, PeerData } from "../../types";
import { TankPacket } from "../packets/TankPacket.js";
import { WebServer } from "./WebServer.js";
import { createRequire } from "node:module";
const Native = createRequire(import.meta.url)("../../build/Release/gtjs.node").Client;
import { dirname, join } from "path";
import { fileURLToPath } from "url";

// @ts-expect-error @types/node-gyp-build not existed
import nodegyp from "node-gyp-build";
const __dirname = dirname(fileURLToPath(import.meta.url));

const Native = nodegyp(join(__dirname, "..", "..")).Client;
console.log({ Native });

class Client extends EventEmitter {
public _client: ClientType;
Expand Down Expand Up @@ -35,8 +42,6 @@ class Client extends EventEmitter {
}
};

this.config.plugins;

this._client = new Native(this.config.enet?.ip, this.config.enet?.port) as ClientType;

this.cache = {
Expand Down
14 changes: 0 additions & 14 deletions src/structures/Peer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,6 @@ class Peer<T extends PeerData> {
this.client = client;
}

/**
* Get ENetPeer Round Trip Time (RTT).
*/
public get ping() {
return this.client._client.getPeerRTT(this.data.netID);
}

/**
* Get [ENetPeerState](http://enet.bespin.org/enet_8h.html#a058bc368c507eb86cb47f3946f38d558).
*/
public get state() {
return this.client._client.getPeerState(this.data.netID);
}

/**
* Sends multiple packets to a single peer.
* @param data An argument of packets that contains the `parse()` function or just an array of Buffers.
Expand Down
6 changes: 5 additions & 1 deletion test/basic-example/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ client.on("error", (err) => {
});

client.on("connect", (netID) => {
const enetPeer = client._client.getPeer(netID);

console.log({ ping: enetPeer.getRTT() });
console.log(enetPeer.getAddress());

console.log(`Connected netID ${netID}`);
const peer = new Peer(client, netID);
peer.send(TextPacket.from(0x1));
Expand All @@ -29,7 +34,6 @@ client.on("disconnect", (netID) => {
client.on("raw", (netID, data) => {
const peer = new Peer(client, netID);
console.log("raw", data);
console.log(peer.ping, peer.state);
});

client.on("action", (peer, data) => {
Expand Down
2 changes: 0 additions & 2 deletions types/client.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,9 @@ export interface ClientType {
disconnectLater: (peerID: number) => void;
disconnectNow: (peerID: number) => void;
toggleNewPacket: () => void;
getPeerRTT: (peerID: number) => number;
/**
* Return [ENetPeerState](http://enet.bespin.org/enet_8h.html#a058bc368c507eb86cb47f3946f38d558) enum value
*/
getPeerState: (peerID: number) => number;
connect: (ipAddress: string, port: number, peerID: number) => boolean;
}

Expand Down
5 changes: 1 addition & 4 deletions types/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
export interface PeerData {
netID: number;
}

export * from "./client";
export * from "./packets";
export * from "./events";
export * from "./items";
export * from "./peer";
22 changes: 22 additions & 0 deletions types/peer.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export interface NativePeerMethod {
getRTT: () => number;
getState: () => number;
getChannelCount: () => number;
getConnectID: () => number;
getIncomingBandwidth: () => unknown;
getOutgoingBandwidth: () => number;
getPacketsLost: () => number;
getPacketsSent: () => number;
getTotalWaitingData: () => number;
getAddress: () => NativeAddress;
}

export interface NativePeerAddress {
address: string;
host: number;
}

export interface PeerData {
netID: number;
enet: NativePeerMethod;
}

0 comments on commit 076b8ea

Please sign in to comment.