|
| 1 | +// Copyright (C) <2021> Intel Corporation |
| 2 | +// |
| 3 | +// SPDX-License-Identifier: Apache-2.0 |
| 4 | + |
| 5 | +#ifndef BUILDING_NODE_EXTENSION |
| 6 | +#define BUILDING_NODE_EXTENSION |
| 7 | +#endif |
| 8 | + |
| 9 | +#include "InternalClientWrapper.h" |
| 10 | + |
| 11 | +using namespace v8; |
| 12 | + |
| 13 | +DEFINE_LOGGER(InternalClient, "InternalClientWrapper"); |
| 14 | + |
| 15 | +Nan::Persistent<Function> InternalClient::constructor; |
| 16 | + |
| 17 | +InternalClient::InternalClient() { |
| 18 | + async_stats_ = new uv_async_t; |
| 19 | + stats_callback_ = nullptr; |
| 20 | + uv_async_init(uv_default_loop(), async_stats_, &InternalClient::statsCallback); |
| 21 | +} |
| 22 | + |
| 23 | +static void destroyAsyncHandle(uv_handle_t *handle) { |
| 24 | + delete handle; |
| 25 | + handle = nullptr; |
| 26 | +} |
| 27 | + |
| 28 | +InternalClient::~InternalClient() { |
| 29 | + boost::mutex::scoped_lock lock(stats_lock); |
| 30 | + if (!uv_is_closing(reinterpret_cast<uv_handle_t*>(async_stats_))) { |
| 31 | + ELOG_DEBUG("Closing Stats handle"); |
| 32 | + uv_close(reinterpret_cast<uv_handle_t*>(async_stats_), destroyAsyncHandle); |
| 33 | + } |
| 34 | + async_stats_ = nullptr; |
| 35 | +} |
| 36 | + |
| 37 | +NAN_MODULE_INIT(InternalClient::Init) { |
| 38 | + // Constructor template |
| 39 | + Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New); |
| 40 | + tpl->SetClassName(Nan::New("InternalClient").ToLocalChecked()); |
| 41 | + tpl->InstanceTemplate()->SetInternalFieldCount(1); |
| 42 | + |
| 43 | + // Prototype |
| 44 | + Nan::SetPrototypeMethod(tpl, "close", close); |
| 45 | + Nan::SetPrototypeMethod(tpl, "addDestination", addDestination); |
| 46 | + Nan::SetPrototypeMethod(tpl, "removeDestination", removeDestination); |
| 47 | + |
| 48 | + constructor.Reset(Nan::GetFunction(tpl).ToLocalChecked()); |
| 49 | + Nan::Set(target, Nan::New("InternalClient").ToLocalChecked(), |
| 50 | + Nan::GetFunction(tpl).ToLocalChecked()); |
| 51 | +} |
| 52 | + |
| 53 | +NAN_METHOD(InternalClient::New) { |
| 54 | + if (info.Length() < 4) { |
| 55 | + Nan::ThrowError("Wrong number of arguments"); |
| 56 | + } |
| 57 | + |
| 58 | + if (info.IsConstructCall()) { |
| 59 | + Nan::Utf8String param0(Nan::To<v8::String>(info[0]).ToLocalChecked()); |
| 60 | + std::string streamId = std::string(*param0); |
| 61 | + |
| 62 | + Nan::Utf8String param1(Nan::To<v8::String>(info[1]).ToLocalChecked()); |
| 63 | + std::string protocol = std::string(*param1); |
| 64 | + |
| 65 | + Nan::Utf8String param2(Nan::To<v8::String>(info[2]).ToLocalChecked()); |
| 66 | + std::string ip = std::string(*param2); |
| 67 | + |
| 68 | + unsigned int port = Nan::To<unsigned int>(info[3]).FromJust(); |
| 69 | + |
| 70 | + InternalClient* obj = new InternalClient(); |
| 71 | + obj->me = new owt_base::InternalClient( |
| 72 | + streamId, protocol, ip, port, obj); |
| 73 | + if (info.Length() > 4 && info[4]->IsFunction()) { |
| 74 | + obj->stats_callback_ = new Nan::Callback(info[4].As<Function>()); |
| 75 | + } |
| 76 | + obj->src = obj->me; |
| 77 | + obj->Wrap(info.This()); |
| 78 | + info.GetReturnValue().Set(info.This()); |
| 79 | + } else { |
| 80 | + ELOG_WARN("Not construct call"); |
| 81 | + } |
| 82 | +} |
| 83 | + |
| 84 | +NAN_METHOD(InternalClient::close) { |
| 85 | + InternalClient* obj = ObjectWrap::Unwrap<InternalClient>(info.Holder()); |
| 86 | + obj->src = nullptr; |
| 87 | + delete obj->me; |
| 88 | + obj->me = nullptr; |
| 89 | +} |
| 90 | + |
| 91 | +NAN_METHOD(InternalClient::addDestination) { |
| 92 | + InternalClient* obj = ObjectWrap::Unwrap<InternalClient>(info.Holder()); |
| 93 | + owt_base::InternalClient* me = obj->me; |
| 94 | + |
| 95 | + Nan::Utf8String param0(Nan::To<v8::String>(info[0]).ToLocalChecked()); |
| 96 | + std::string track = std::string(*param0); |
| 97 | + |
| 98 | + FrameDestination* param = |
| 99 | + ObjectWrap::Unwrap<FrameDestination>( |
| 100 | + info[1]->ToObject(Nan::GetCurrentContext()).ToLocalChecked()); |
| 101 | + owt_base::FrameDestination* dest = param->dest; |
| 102 | + |
| 103 | + if (track == "audio") { |
| 104 | + me->addAudioDestination(dest); |
| 105 | + } else if (track == "video") { |
| 106 | + me->addVideoDestination(dest); |
| 107 | + } |
| 108 | +} |
| 109 | + |
| 110 | +NAN_METHOD(InternalClient::removeDestination) { |
| 111 | + InternalClient* obj = ObjectWrap::Unwrap<InternalClient>(info.Holder()); |
| 112 | + owt_base::InternalClient* me = obj->me; |
| 113 | + |
| 114 | + Nan::Utf8String param0(Nan::To<v8::String>(info[0]).ToLocalChecked()); |
| 115 | + std::string track = std::string(*param0); |
| 116 | + |
| 117 | + FrameDestination* param = |
| 118 | + ObjectWrap::Unwrap<FrameDestination>( |
| 119 | + info[1]->ToObject(Nan::GetCurrentContext()).ToLocalChecked()); |
| 120 | + owt_base::FrameDestination* dest = param->dest; |
| 121 | + |
| 122 | + if (track == "audio") { |
| 123 | + me->removeAudioDestination(dest); |
| 124 | + } else if (track == "video") { |
| 125 | + me->removeVideoDestination(dest); |
| 126 | + } |
| 127 | +} |
| 128 | + |
| 129 | +NAUV_WORK_CB(InternalClient::statsCallback) { |
| 130 | + Nan::HandleScope scope; |
| 131 | + InternalClient* obj = reinterpret_cast<InternalClient*>(async->data); |
| 132 | + if (!obj || !obj->me || !obj->stats_callback_) { |
| 133 | + return; |
| 134 | + } |
| 135 | + |
| 136 | + boost::mutex::scoped_lock lock(obj->stats_lock); |
| 137 | + while (!obj->stats_messages.empty()) { |
| 138 | + Local<Value> args[] = { |
| 139 | + Nan::New(obj->stats_messages.front().c_str()).ToLocalChecked() |
| 140 | + }; |
| 141 | + Nan::AsyncResource resource("InternalServer.statsCallback"); |
| 142 | + resource.runInAsyncScope(Nan::GetCurrentContext()->Global(), |
| 143 | + obj->stats_callback_->GetFunction(), |
| 144 | + 1, args); |
| 145 | + obj->stats_messages.pop(); |
| 146 | + } |
| 147 | +} |
| 148 | + |
| 149 | +void InternalClient::onConnected() { |
| 150 | + boost::mutex::scoped_lock lock(stats_lock); |
| 151 | + if (!async_stats_ || !stats_callback_) { |
| 152 | + return; |
| 153 | + } |
| 154 | + stats_messages.push("connected"); |
| 155 | + async_stats_->data = this; |
| 156 | + uv_async_send(async_stats_); |
| 157 | +} |
| 158 | + |
| 159 | +void InternalClient::onDisconnected() { |
| 160 | + boost::mutex::scoped_lock lock(stats_lock); |
| 161 | + if (!async_stats_ || !stats_callback_) { |
| 162 | + return; |
| 163 | + } |
| 164 | + stats_messages.push("disconnected"); |
| 165 | + async_stats_->data = this; |
| 166 | + uv_async_send(async_stats_); |
| 167 | +} |
0 commit comments