From 7c22b677edd3485b0d49d535b7a37f365224d2fc Mon Sep 17 00:00:00 2001
From: Murat Dogan <doganmurat@gmail.com>
Date: Thu, 10 Dec 2020 11:19:58 +0300
Subject: [PATCH] add binary message support

---
 CMakeLists.txt               |  2 +-
 README.md                    |  1 +
 lib/index.d.ts               |  3 ++-
 package-lock.json            |  2 +-
 package.json                 |  2 +-
 src/data-channel-wrapper.cpp | 41 +++++++++++++++++++++++++++++++++---
 src/data-channel-wrapper.h   |  1 +
 test/connectivity.js         |  1 +
 8 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 672f0900..336d2571 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.15)
 cmake_policy(SET CMP0091 NEW)
-project(node_datachannel VERSION 0.0.17)
+project(node_datachannel VERSION 0.0.18)
     
 include_directories(${CMAKE_JS_INC})
 
diff --git a/README.md b/README.md
index db7946d3..c41fa4bc 100644
--- a/README.md
+++ b/README.md
@@ -78,6 +78,7 @@ peer2.onDataChannel((dc) => {
 dc1 = peer1.createDataChannel("test");
 dc1.onOpen(() => {
     dc1.sendMessage("Hello from Peer1");
+    // Binary message: Use sendMessageBinary(Buffer)
 });
 dc1.onMessage((msg) => {
     console.log('Peer1 Received Msg:', msg);
diff --git a/lib/index.d.ts b/lib/index.d.ts
index 3580e98f..6ce39d4e 100644
--- a/lib/index.d.ts
+++ b/lib/index.d.ts
@@ -46,6 +46,7 @@ export class DataChannel {
     close: () => void;
     getLabel: () => string;
     sendMessage: (msg: string) => boolean;
+    sendMessageBinary: (buffer: Buffer) => boolean;
     isOpen: () => boolean;
     availableAmount: () => Number;
     bufferedAmount: () => Number;
@@ -56,7 +57,7 @@ export class DataChannel {
     onError: (cb: (err: string) => void) => void;
     onAvailable: (cb: () => void) => void;
     onBufferedAmountLow: (cb: () => void) => void;
-    onMessage: (cb: (msg: string) => void) => void;
+    onMessage: (cb: (msg: string | Buffer) => void) => void;
 }
 
 export class PeerConnection {
diff --git a/package-lock.json b/package-lock.json
index 286f60ba..01a5a87b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "node-datachannel",
-  "version": "0.0.17",
+  "version": "0.0.18",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
diff --git a/package.json b/package.json
index a1983804..ad3e25fe 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "node-datachannel",
-  "version": "0.0.17",
+  "version": "0.0.18",
   "description": "libdatachannel node bindings",
   "main": "lib/index.js",
   "typings": "lib/index.d.ts",
diff --git a/src/data-channel-wrapper.cpp b/src/data-channel-wrapper.cpp
index e9c03936..c37105bd 100644
--- a/src/data-channel-wrapper.cpp
+++ b/src/data-channel-wrapper.cpp
@@ -12,6 +12,7 @@ Napi::Object DataChannelWrapper::Init(Napi::Env env, Napi::Object exports)
         {InstanceMethod("close", &DataChannelWrapper::close),
          InstanceMethod("getLabel", &DataChannelWrapper::getLabel),
          InstanceMethod("sendMessage", &DataChannelWrapper::sendMessage),
+         InstanceMethod("sendMessageBinary", &DataChannelWrapper::sendMessageBinary),
          InstanceMethod("isOpen", &DataChannelWrapper::isOpen),
          InstanceMethod("availableAmount", &DataChannelWrapper::availableAmount),
          InstanceMethod("bufferedAmount", &DataChannelWrapper::bufferedAmount),
@@ -87,9 +88,14 @@ DataChannelWrapper::DataChannelWrapper(const Napi::CallbackInfo &info) : Napi::O
                 // This will run in main thread and needs to construct the
                 // arguments for the call
                 Napi::Object payload = Napi::Object::New(env);
-                // FIX ME
-                // Binary Message?
-                args = {Napi::String::New(env, std::get<std::string>(message))};
+                if (std::holds_alternative<std::string>(message))
+                {
+                    args = {Napi::String::New(env, std::get<std::string>(message))};
+                }
+                else
+                {
+                    args = {Napi::Buffer<std::byte>::Copy(env, std::get<rtc::binary>(message).data(), std::get<rtc::binary>(message).size())};
+                }
             });
     });
 }
@@ -171,6 +177,35 @@ Napi::Value DataChannelWrapper::sendMessage(const Napi::CallbackInfo &info)
     }
 }
 
+Napi::Value DataChannelWrapper::sendMessageBinary(const Napi::CallbackInfo &info)
+{
+    if (!mDataChannelPtr)
+    {
+        Napi::Error::New(info.Env(), "It seems data-channel is destroyed!").ThrowAsJavaScriptException();
+        return info.Env().Null();
+    }
+
+    Napi::Env env = info.Env();
+    int length = info.Length();
+
+    if (length < 1 || !info[0].IsBuffer())
+    {
+        Napi::TypeError::New(env, "Buffer expected").ThrowAsJavaScriptException();
+        return info.Env().Null();
+    }
+
+    try
+    {
+        Napi::Uint8Array buffer = info[0].As<Napi::Uint8Array>();
+        return Napi::Boolean::New(info.Env(), mDataChannelPtr->send((std::byte *)buffer.Data(), buffer.ByteLength()));
+    }
+    catch (std::exception &ex)
+    {
+        Napi::Error::New(env, std::string("libdatachannel error while sending dataChannel msg# ") + ex.what()).ThrowAsJavaScriptException();
+        return Napi::Boolean::New(info.Env(), false);
+    }
+}
+
 Napi::Value DataChannelWrapper::isOpen(const Napi::CallbackInfo &info)
 {
     Napi::Env env = info.Env();
diff --git a/src/data-channel-wrapper.h b/src/data-channel-wrapper.h
index 2fbb1539..8013ee90 100644
--- a/src/data-channel-wrapper.h
+++ b/src/data-channel-wrapper.h
@@ -21,6 +21,7 @@ class DataChannelWrapper : public Napi::ObjectWrap<DataChannelWrapper>
   void close(const Napi::CallbackInfo &info);
   Napi::Value getLabel(const Napi::CallbackInfo &info);
   Napi::Value sendMessage(const Napi::CallbackInfo &info);
+  Napi::Value sendMessageBinary(const Napi::CallbackInfo &info);
   Napi::Value isOpen(const Napi::CallbackInfo &info);
   Napi::Value availableAmount(const Napi::CallbackInfo &info);
   Napi::Value bufferedAmount(const Napi::CallbackInfo &info);
diff --git a/test/connectivity.js b/test/connectivity.js
index 59cc3840..ac832a3c 100644
--- a/test/connectivity.js
+++ b/test/connectivity.js
@@ -60,6 +60,7 @@ peer2.onDataChannel((dc) => {
 dc1 = peer1.createDataChannel("test");
 dc1.onOpen(() => {
     dc1.sendMessage("Hello from Peer1");
+    // Binary message: Use sendMessageBinary(Buffer)
 });
 dc1.onMessage((msg) => {
     console.log('Peer1 Received Msg:', msg);