From 97b3ce61414ded808893838668ba30b6d84010a8 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Wed, 2 Feb 2022 08:32:54 +1000
Subject: Add Haiku support


diff --git a/CMakeLists.txt b/CMakeLists.txt
index a9246d4..fdd079b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -186,7 +186,7 @@ endif()
 include(cmake/libwebrtcbuild.cmake)
 target_link_libraries(tg_owt PUBLIC tg_owt::libwebrtcbuild)
 
-if (UNIX AND NOT APPLE)
+if (UNIX AND NOT APPLE AND NOT HAIKU)
     link_x11(tg_owt)
     link_glib(tg_owt)
 endif()
@@ -1527,6 +1527,9 @@ PRIVATE
     modules/video_capture/device_info_impl.cc
     modules/video_capture/linux/device_info_linux.cc
     modules/video_capture/linux/video_capture_linux.cc
+    modules/video_capture/haiku/device_info_haiku.cc
+    modules/video_capture/haiku/video_capture_haiku.cc
+    modules/video_capture/haiku/video_consumer.cc
     modules/video_capture/windows/device_info_ds.cc
     modules/video_capture/windows/device_info_ds.h
     modules/video_capture/windows/help_functions_ds.cc
@@ -2100,6 +2103,7 @@ PRIVATE
     modules/desktop_capture/mouse_cursor.h
     modules/desktop_capture/mouse_cursor_monitor.h
     modules/desktop_capture/mouse_cursor_monitor_linux.cc
+    modules/desktop_capture/mouse_cursor_monitor_haiku.cc
     modules/desktop_capture/mouse_cursor_monitor_mac.mm
     modules/desktop_capture/mouse_cursor_monitor_win.cc
     modules/desktop_capture/resolution_tracker.cc
@@ -2111,8 +2115,10 @@ PRIVATE
     modules/desktop_capture/screen_capturer_helper.h
     modules/desktop_capture/screen_capturer_darwin.mm
     modules/desktop_capture/screen_capturer_linux.cc
+    modules/desktop_capture/screen_capturer_haiku.cc
     modules/desktop_capture/screen_capturer_win.cc
     modules/desktop_capture/window_capturer_linux.cc
+    modules/desktop_capture/window_capturer_haiku.cc
     modules/desktop_capture/window_capturer_mac.mm
     modules/desktop_capture/window_capturer_win.cc
     modules/desktop_capture/window_finder.cc
@@ -2127,6 +2133,10 @@ PRIVATE
     modules/desktop_capture/screen_capturer_null.cc
     modules/desktop_capture/window_capturer_null.cc
 
+    # haiku specific
+    modules/desktop_capture/haiku/screen_capturer_haiku.cc
+    modules/desktop_capture/haiku/screen_capturer_haiku.h
+
     # linux specific
     modules/desktop_capture/linux/base_capturer_pipewire.cc
     modules/desktop_capture/linux/base_capturer_pipewire.h
diff --git a/cmake/libusrsctp.cmake b/cmake/libusrsctp.cmake
index 949102a..3c6f359 100644
--- a/cmake/libusrsctp.cmake
+++ b/cmake/libusrsctp.cmake
@@ -25,6 +25,11 @@ elseif (APPLE)
         HAVE_SA_LEN
         HAVE_SCONN_LEN
     )
+elseif (HAIKU)
+    target_compile_definitions(libusrsctp
+    PRIVATE
+        __Userspace_os_Haiku
+    )
 else()
     target_compile_definitions(libusrsctp
     PRIVATE
diff --git a/cmake/libwebrtcbuild.cmake b/cmake/libwebrtcbuild.cmake
index 46467d7..a380a29 100644
--- a/cmake/libwebrtcbuild.cmake
+++ b/cmake/libwebrtcbuild.cmake
@@ -53,6 +53,12 @@ if (WIN32)
     INTERFACE
         WEBRTC_WIN
     )
+elseif (HAIKU)
+    target_compile_definitions(libwebrtcbuild
+    INTERFACE
+        WEBRTC_POSIX
+        WEBRTC_HAIKU
+    )
 else()
     target_compile_definitions(libwebrtcbuild
     INTERFACE
diff --git a/cmake/nice_target_sources.cmake b/cmake/nice_target_sources.cmake
index cfc6aeb..699d0e6 100644
--- a/cmake/nice_target_sources.cmake
+++ b/cmake/nice_target_sources.cmake
@@ -15,6 +15,7 @@ function(nice_target_sources target_name src_loc)
     set(not_win_sources "")
     set(not_mac_sources "")
     set(not_linux_sources "")
+    set(not_haiku_sources "")
     foreach (entry ${list})
         if (${entry} STREQUAL "PRIVATE" OR ${entry} STREQUAL "PUBLIC" OR ${entry} STREQUAL "INTERFACE")
             set(writing_now ${entry})
@@ -23,12 +24,19 @@ function(nice_target_sources target_name src_loc)
             if (${entry} MATCHES "(^|/)win/" OR ${entry} MATCHES "(^|/)winrc/" OR ${entry} MATCHES "(^|/)windows/" OR ${entry} MATCHES "[_\\/]win\\.")
                 list(APPEND not_mac_sources ${full_name})
                 list(APPEND not_linux_sources ${full_name})
+                list(APPEND not_haiku_sources ${full_name})
             elseif (${entry} MATCHES "(^|/)mac/" OR ${entry} MATCHES "(^|/)darwin/" OR ${entry} MATCHES "(^|/)osx/" OR ${entry} MATCHES "[_\\/]mac\\." OR ${entry} MATCHES "[_\\/]darwin\\." OR ${entry} MATCHES "[_\\/]osx\\.")
                 list(APPEND not_win_sources ${full_name})
                 list(APPEND not_linux_sources ${full_name})
+                list(APPEND not_haiku_sources ${full_name})
             elseif (${entry} MATCHES "(^|/)linux/" OR ${entry} MATCHES "[_\\/]linux\\.")
                 list(APPEND not_win_sources ${full_name})
                 list(APPEND not_mac_sources ${full_name})
+                list(APPEND not_haiku_sources ${full_name})
+            elseif (${entry} MATCHES "(^|/)haiku/" OR ${entry} MATCHES "[_\\/]haiku\\.")
+                list(APPEND not_win_sources ${full_name})
+                list(APPEND not_mac_sources ${full_name})
+                list(APPEND not_linux_sources ${full_name})
             elseif (${entry} MATCHES "(^|/)posix/" OR ${entry} MATCHES "[_\\/]posix\\.")
                 list(APPEND not_win_sources ${full_name})
             endif()
@@ -64,6 +72,9 @@ function(nice_target_sources target_name src_loc)
     elseif (APPLE)
         set_source_files_properties(${not_mac_sources} PROPERTIES HEADER_FILE_ONLY TRUE)
         set_source_files_properties(${not_mac_sources} PROPERTIES SKIP_AUTOGEN TRUE)
+    elseif (HAIKU)
+        set_source_files_properties(${not_haiku_sources} PROPERTIES HEADER_FILE_ONLY TRUE)
+        set_source_files_properties(${not_haiku_sources} PROPERTIES SKIP_AUTOGEN TRUE)
     else()
         set_source_files_properties(${not_linux_sources} PROPERTIES HEADER_FILE_ONLY TRUE)
         set_source_files_properties(${not_linux_sources} PROPERTIES SKIP_AUTOGEN TRUE)
diff --git a/src/api/task_queue/BUILD.gn b/src/api/task_queue/BUILD.gn
index 1072057..745f5b7 100644
--- a/src/api/task_queue/BUILD.gn
+++ b/src/api/task_queue/BUILD.gn
@@ -82,7 +82,7 @@ rtc_library("default_task_queue_factory") {
   sources = [ "default_task_queue_factory.h" ]
   deps = [ ":task_queue" ]
 
-  if (rtc_enable_libevent) {
+  if (rtc_enable_libevent && !is_haiku) {
     sources += [ "default_task_queue_factory_libevent.cc" ]
     deps += [ "../../rtc_base:rtc_task_queue_libevent" ]
   } else if (is_mac || is_ios) {
diff --git a/src/modules/desktop_capture/haiku/screen_capturer_haiku.cc b/src/modules/desktop_capture/haiku/screen_capturer_haiku.cc
new file mode 100644
index 0000000..b6f4d24
--- /dev/null
+++ b/src/modules/desktop_capture/haiku/screen_capturer_haiku.cc
@@ -0,0 +1,91 @@
+/*
+ *  Copyright 2021 Gerasim Troeglazov
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/desktop_capture/haiku/screen_capturer_haiku.h"
+
+#include <stdint.h>
+#include <string.h>
+
+#include <memory>
+#include <utility>
+
+#include "modules/desktop_capture/desktop_capture_options.h"
+#include "modules/desktop_capture/desktop_capturer.h"
+#include "modules/desktop_capture/desktop_frame.h"
+#include "modules/desktop_capture/desktop_geometry.h"
+#include "modules/desktop_capture/screen_capture_frame_queue.h"
+#include "modules/desktop_capture/screen_capturer_helper.h"
+#include "modules/desktop_capture/shared_desktop_frame.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/sanitizer.h"
+#include "rtc_base/time_utils.h"
+#include "rtc_base/trace_event.h"
+
+namespace webrtc {
+
+ScreenCapturerHaiku::ScreenCapturerHaiku() {
+	screen_ = new BScreen(B_MAIN_SCREEN_ID);
+	screen_->GetBitmap(&bitmap_);
+}
+
+ScreenCapturerHaiku::~ScreenCapturerHaiku() {
+	delete screen_;
+	delete bitmap_;
+}
+
+bool ScreenCapturerHaiku::Init(const DesktopCaptureOptions& options) {
+  options_ = options;
+  return true;
+}
+
+void ScreenCapturerHaiku::Start(Callback* callback) {
+  RTC_DCHECK(!callback_);
+  RTC_DCHECK(callback);
+  callback_ = callback;
+  lastShot_ = system_time();
+}
+
+void ScreenCapturerHaiku::CaptureFrame() {
+  int64_t capture_start_time_nanos = rtc::TimeNanos();
+  bigtime_t now_ = system_time();
+  if (now_ - lastShot_ > 1000000) {
+    screen_->ReadBitmap(bitmap_);
+    lastShot_ = now_;
+  }
+  DesktopRect r = DesktopRect::MakeXYWH(0, 0, bitmap_->Bounds().Width() + 1, bitmap_->Bounds().Height() + 1);
+  std::unique_ptr<DesktopFrame> frame(new BasicDesktopFrame(r.size()));
+  frame->CopyPixelsFrom((const uint8_t*)bitmap_->Bits(), bitmap_->BytesPerRow(), r);
+  frame->set_capture_time_ms((rtc::TimeNanos() - capture_start_time_nanos) / rtc::kNumNanosecsPerMillisec);
+  callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
+}
+
+bool ScreenCapturerHaiku::GetSourceList(SourceList* sources) {
+  sources->push_back({kFullDesktopScreenId, "Active Desktop"});
+  return true;
+}
+
+bool ScreenCapturerHaiku::SelectSource(SourceId id) {
+  return id == kFullDesktopScreenId;
+}
+
+
+// static
+std::unique_ptr<DesktopCapturer> ScreenCapturerHaiku::CreateRawScreenCapturer(
+    const DesktopCaptureOptions& options) {
+  std::unique_ptr<ScreenCapturerHaiku> capturer(new ScreenCapturerHaiku());
+  if (!capturer.get()->Init(options)) {
+    return nullptr;
+  }
+
+  return std::move(capturer);
+}
+
+}  // namespace webrtc
diff --git a/src/modules/desktop_capture/haiku/screen_capturer_haiku.h b/src/modules/desktop_capture/haiku/screen_capturer_haiku.h
new file mode 100644
index 0000000..b541795
--- /dev/null
+++ b/src/modules/desktop_capture/haiku/screen_capturer_haiku.h
@@ -0,0 +1,58 @@
+/*
+ *  Copyright 2021 Gerasim Troeglazov
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_DESKTOP_CAPTURE_HAIKU_SCREEN_CAPTURER_HAIKU_H_
+#define MODULES_DESKTOP_CAPTURE_HAIKU_SCREEN_CAPTURER_HAIKU_H_
+
+#include <memory>
+
+#include "modules/desktop_capture/desktop_capture_options.h"
+#include "modules/desktop_capture/desktop_capturer.h"
+#include "modules/desktop_capture/desktop_frame.h"
+#include "modules/desktop_capture/desktop_region.h"
+#include "modules/desktop_capture/screen_capture_frame_queue.h"
+#include "modules/desktop_capture/screen_capturer_helper.h"
+#include "modules/desktop_capture/shared_desktop_frame.h"
+#include "rtc_base/constructor_magic.h"
+
+#include <OS.h>
+#include <InterfaceKit.h>
+
+namespace webrtc {
+
+class ScreenCapturerHaiku : public DesktopCapturer {
+ public:
+  ScreenCapturerHaiku();
+  ~ScreenCapturerHaiku() override;
+
+  static std::unique_ptr<DesktopCapturer> CreateRawScreenCapturer(
+      const DesktopCaptureOptions& options);
+
+  bool Init(const DesktopCaptureOptions& options);
+  
+  void Start(Callback* delegate) override;
+  void CaptureFrame() override;
+  bool GetSourceList(SourceList* sources) override;
+  bool SelectSource(SourceId id) override;
+
+ private:
+  BScreen* screen_;
+  BBitmap* bitmap_;
+  bigtime_t lastShot_;
+
+  DesktopCaptureOptions options_;
+  Callback* callback_ = nullptr;
+
+  RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerHaiku);
+};
+
+}
+
+#endif  // MODULES_DESKTOP_CAPTURE_HAIKU_SCREEN_CAPTURER_HAIKU_H_
diff --git a/src/modules/desktop_capture/mouse_cursor_monitor_haiku.cc b/src/modules/desktop_capture/mouse_cursor_monitor_haiku.cc
new file mode 100644
index 0000000..8ea2aa2
--- /dev/null
+++ b/src/modules/desktop_capture/mouse_cursor_monitor_haiku.cc
@@ -0,0 +1,39 @@
+/*
+ *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <memory>
+
+#include "modules/desktop_capture/desktop_capture_types.h"
+#include "modules/desktop_capture/mouse_cursor_monitor.h"
+//#include "modules/desktop_capture/haiku/mouse_cursor_monitor.h"
+
+namespace webrtc {
+
+// static
+MouseCursorMonitor* MouseCursorMonitor::CreateForWindow(
+    const DesktopCaptureOptions& options,
+    WindowId window) {
+  return nullptr;
+}
+
+// static
+MouseCursorMonitor* MouseCursorMonitor::CreateForScreen(
+    const DesktopCaptureOptions& options,
+    ScreenId screen) {
+  return nullptr;
+}
+
+// static
+std::unique_ptr<MouseCursorMonitor> MouseCursorMonitor::Create(
+    const DesktopCaptureOptions& options) {
+  return nullptr;
+}
+
+}  // namespace webrtc
diff --git a/src/modules/desktop_capture/screen_capturer_haiku.cc b/src/modules/desktop_capture/screen_capturer_haiku.cc
new file mode 100644
index 0000000..63ceecc
--- /dev/null
+++ b/src/modules/desktop_capture/screen_capturer_haiku.cc
@@ -0,0 +1,26 @@
+/*
+ *  Copyright 2021 Gerasim Troeglazov
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <memory>
+
+#include "modules/desktop_capture/desktop_capture_options.h"
+#include "modules/desktop_capture/desktop_capturer.h"
+
+#include "modules/desktop_capture/haiku/screen_capturer_haiku.h"
+
+namespace webrtc {
+
+// static
+std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawScreenCapturer(
+    const DesktopCaptureOptions& options) {
+  return ScreenCapturerHaiku::CreateRawScreenCapturer(options);
+}
+
+}  // namespace webrtc
diff --git a/src/modules/desktop_capture/window_capturer_haiku.cc b/src/modules/desktop_capture/window_capturer_haiku.cc
new file mode 100644
index 0000000..dab0db5
--- /dev/null
+++ b/src/modules/desktop_capture/window_capturer_haiku.cc
@@ -0,0 +1,66 @@
+/*
+ *  Copyright 2021 Gerasim Troeglazov
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/desktop_capture/desktop_capturer.h"
+#include "modules/desktop_capture/desktop_frame.h"
+#include "rtc_base/constructor_magic.h"
+
+#include <assert.h>
+
+namespace webrtc {
+
+namespace {
+
+class WindowCapturerHaiku : public DesktopCapturer {
+ public:
+  WindowCapturerHaiku();
+  ~WindowCapturerHaiku() override;
+
+  void Start(Callback* callback) override;
+  void CaptureFrame() override;
+  bool GetSourceList(SourceList* sources) override;
+  bool SelectSource(SourceId id) override;
+
+ private:
+  Callback* callback_ = nullptr;
+  RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerHaiku);
+};
+
+WindowCapturerHaiku::WindowCapturerHaiku() {}
+WindowCapturerHaiku::~WindowCapturerHaiku() {}
+
+bool WindowCapturerHaiku::GetSourceList(SourceList* sources) {
+  return false;
+}
+
+bool WindowCapturerHaiku::SelectSource(SourceId id) {
+  return false;
+}
+
+void WindowCapturerHaiku::Start(Callback* callback) {
+  assert(!callback_);
+  assert(callback);
+
+  callback_ = callback;
+}
+
+void WindowCapturerHaiku::CaptureFrame() {
+  callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
+}
+
+}  // namespace
+
+// static
+std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawWindowCapturer(
+    const DesktopCaptureOptions& options) {
+  return std::unique_ptr<DesktopCapturer>(new WindowCapturerHaiku());
+}
+
+}  // namespace webrtc
diff --git a/src/modules/video_capture/haiku/device_info_haiku.cc b/src/modules/video_capture/haiku/device_info_haiku.cc
new file mode 100644
index 0000000..aeddaef
--- /dev/null
+++ b/src/modules/video_capture/haiku/device_info_haiku.cc
@@ -0,0 +1,150 @@
+/*
+ *  Copyright 2021 Gerasim Troeglazov
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/video_capture/haiku/device_info_haiku.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include <vector>
+
+#include "modules/video_capture/video_capture.h"
+#include "modules/video_capture/video_capture_defines.h"
+#include "modules/video_capture/video_capture_impl.h"
+#include "rtc_base/logging.h"
+
+namespace webrtc {
+namespace videocapturemodule {
+VideoCaptureModule::DeviceInfo* VideoCaptureImpl::CreateDeviceInfo() {
+  return new videocapturemodule::DeviceInfoHaiku();
+}
+
+DeviceInfoHaiku::DeviceInfoHaiku() : DeviceInfoImpl() {}
+
+int32_t DeviceInfoHaiku::Init() {
+  return 0;
+}
+
+DeviceInfoHaiku::~DeviceInfoHaiku() {}
+
+uint32_t DeviceInfoHaiku::NumberOfDevices() {
+	status_t err = B_OK;
+
+	int32_t countDevices = 0;
+
+	dormant_node_info dni[30];
+	int32 ioCount = 30;
+	media_format out;
+	out.type = B_MEDIA_RAW_VIDEO;
+	err = BMediaRoster::Roster()->GetDormantNodes(dni, &ioCount, 0, &out, 0, B_BUFFER_PRODUCER);
+	if (err < B_OK)
+		return countDevices;
+
+	for (int ix=0; ix<ioCount; ix++) {
+		media_node_id running = -1;
+		if ((B_OK == BMediaRoster::CurrentRoster()->GetInstancesFor(
+				dni[ix].addon, dni[ix].flavor_id, &running)) && (running > -1)) {
+			media_node node;
+			BMediaRoster::CurrentRoster()->GetNodeFor(running, &node);
+			int32 count = 1;
+			media_output videoOutput;
+			BMediaRoster::CurrentRoster()->GetAllOutputsFor(node, &videoOutput, 1, &count);
+			if (count > 0)
+				countDevices++;
+			BMediaRoster::CurrentRoster()->ReleaseNode(node);
+		}
+	}
+
+	return countDevices;
+}
+
+int32_t DeviceInfoHaiku::GetDeviceName(uint32_t deviceNumber,
+                                       char* deviceNameUTF8,
+                                       uint32_t deviceNameLength,
+                                       char* deviceUniqueIdUTF8,
+                                       uint32_t deviceUniqueIdUTF8Length,
+                                       char* productUniqueIdUTF8,
+                                       uint32_t productUniqueIdUTF8Length) {
+	if (deviceNumber >= NumberOfDevices())
+		return -1;
+
+	status_t err = B_OK;
+
+	int32_t countDevices = 0;
+
+	media_output videoOutput;
+
+	dormant_node_info dni[30];
+	int32 ioCount = 30;
+	media_format out;
+	out.type = B_MEDIA_RAW_VIDEO;
+	err = BMediaRoster::Roster()->GetDormantNodes(dni, &ioCount, 0, &out, 0, B_BUFFER_PRODUCER);
+	if (err < B_OK)
+		return countDevices;
+
+	err = B_ERROR;
+
+	for (int ix=0; ix<ioCount; ix++) {
+		media_node_id running = -1;
+		if ((B_OK == BMediaRoster::CurrentRoster()->GetInstancesFor(
+				dni[ix].addon, dni[ix].flavor_id, &running)) && (running > -1)) {
+			media_node node;
+			BMediaRoster::CurrentRoster()->GetNodeFor(running, &node);
+			int32 count = 1;
+			BMediaRoster::CurrentRoster()->GetAllOutputsFor(node, &videoOutput, 1, &count);
+			BMediaRoster::CurrentRoster()->ReleaseNode(node);
+			if (count > 0) {
+				if (countDevices == deviceNumber) {
+					if (deviceNameLength > strlen(videoOutput.name)) {
+						strncpy(deviceNameUTF8, videoOutput.name, deviceNameLength);
+						strncpy(deviceUniqueIdUTF8, videoOutput.name, deviceUniqueIdUTF8Length);
+						err = B_OK;
+					} else
+						err = B_ERROR;
+					break;
+				}
+				countDevices++;
+			}
+			BMediaRoster::CurrentRoster()->ReleaseNode(node);
+		}
+	}
+	return err == B_OK ? 0 : -1;
+}
+
+int32_t DeviceInfoHaiku::CreateCapabilityMap(const char* deviceUniqueIdUTF8) {
+	_captureCapabilities.clear();
+
+	VideoCaptureCapability cap;
+	cap.width = 640;
+	cap.height = 480;
+	cap.videoType = VideoType::kARGB;
+	cap.maxFPS = 30;
+
+	_captureCapabilities.push_back(cap);
+
+	return _captureCapabilities.size();
+}
+
+int32_t DeviceInfoHaiku::DisplayCaptureSettingsDialogBox(
+    const char* deviceUniqueIdUTF8,
+    const char* dialogTitleUTF8,
+    void* parentWindow,
+    uint32_t positionX,
+    uint32_t positionY) {
+	return -1;
+}
+
+}  // namespace videocapturemodule
+}  // namespace webrtc
diff --git a/src/modules/video_capture/haiku/device_info_haiku.h b/src/modules/video_capture/haiku/device_info_haiku.h
new file mode 100644
index 0000000..b5ffe94
--- /dev/null
+++ b/src/modules/video_capture/haiku/device_info_haiku.h
@@ -0,0 +1,43 @@
+/*
+ *  Copyright 2021 Gerasim Troeglazov
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_VIDEO_CAPTURE_MAIN_SOURCE_HAIKU_DEVICE_INFO_HAIKU_H_
+#define MODULES_VIDEO_CAPTURE_MAIN_SOURCE_HAIKU_DEVICE_INFO_HAIKU_H_
+
+#include <stdint.h>
+#include <MediaKit.h>
+
+#include "modules/video_capture/device_info_impl.h"
+
+namespace webrtc {
+namespace videocapturemodule {
+class DeviceInfoHaiku : public DeviceInfoImpl {
+ public:
+  DeviceInfoHaiku();
+  ~DeviceInfoHaiku() override;
+  uint32_t NumberOfDevices() override;
+  int32_t GetDeviceName(uint32_t deviceNumber,
+                        char* deviceNameUTF8,
+                        uint32_t deviceNameLength,
+                        char* deviceUniqueIdUTF8,
+                        uint32_t deviceUniqueIdUTF8Length,
+                        char* productUniqueIdUTF8 = 0,
+                        uint32_t productUniqueIdUTF8Length = 0) override;
+  int32_t CreateCapabilityMap(const char* deviceUniqueIdUTF8) override;
+  int32_t DisplayCaptureSettingsDialogBox(const char*,
+                                          const char*,
+                                          void*,
+                                          uint32_t,
+                                          uint32_t) override;
+  int32_t Init() override;
+};
+}  // namespace videocapturemodule
+}  // namespace webrtc
+#endif  // MODULES_VIDEO_CAPTURE_MAIN_SOURCE_HAIKU_DEVICE_INFO_HAIKU_H_
diff --git a/src/modules/video_capture/haiku/video_capture_haiku.cc b/src/modules/video_capture/haiku/video_capture_haiku.cc
new file mode 100644
index 0000000..86d8d20
--- /dev/null
+++ b/src/modules/video_capture/haiku/video_capture_haiku.cc
@@ -0,0 +1,201 @@
+/*
+ *  Copyright 2021 Gerasim Troeglazov
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/video_capture/haiku/video_capture_haiku.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/select.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <new>
+#include <string>
+
+#include "api/scoped_refptr.h"
+#include "media/base/video_common.h"
+#include "modules/video_capture/video_capture.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/ref_counted_object.h"
+
+namespace webrtc {
+namespace videocapturemodule {
+rtc::scoped_refptr<VideoCaptureModule> VideoCaptureImpl::Create(
+    const char* deviceUniqueId) {
+  rtc::scoped_refptr<VideoCaptureModuleHaiku> implementation(
+      new rtc::RefCountedObject<VideoCaptureModuleHaiku>());
+
+  if (implementation->Init(deviceUniqueId) != 0)
+    return nullptr;
+
+  return implementation;
+}
+
+VideoCaptureModuleHaiku::VideoCaptureModuleHaiku()
+    : VideoCaptureImpl(),
+      _currentWidth(-1),
+      _currentHeight(-1),
+      _currentFrameRate(-1),
+      _captureStarted(false),
+      _captureVideoType(VideoType::kARGB) {}
+
+int32_t VideoCaptureModuleHaiku::Init(const char* deviceUniqueIdUTF8) {
+  int len = strlen((const char*)deviceUniqueIdUTF8);
+  _deviceUniqueId = new (std::nothrow) char[len + 1];
+  if (_deviceUniqueId) {
+    memcpy(_deviceUniqueId, deviceUniqueIdUTF8, len + 1);
+  }
+
+  return 0;
+}
+
+VideoCaptureModuleHaiku::~VideoCaptureModuleHaiku() {
+  StopCapture();
+}
+
+int32_t VideoCaptureModuleHaiku::StartCapture(
+	const VideoCaptureCapability& capability) {
+	if (_captureStarted) {
+		if (capability.width == _currentWidth &&
+			capability.height == _currentHeight &&
+			_captureVideoType == capability.videoType) {
+			return 0;
+		} else {
+			StopCapture();
+		}
+	}
+
+	_currentWidth = 640;
+	_currentHeight = 480;
+	_currentFrameRate = 30;
+
+	status_t fStatus;
+	fMediaRoster = BMediaRoster::Roster(&fStatus);
+	if (fStatus != B_OK)
+		return -1;
+
+	media_node fTimeSource;
+	fStatus = fMediaRoster->GetTimeSource(&fTimeSource);
+	if (fStatus != B_OK)
+		return -1;
+	
+	fVideoConsumer = new VideoConsumer("Telegram", NULL, 0);
+	fVideoConsumer->SetVideoCapture(this);
+
+	dormant_node_info dni[30];
+	int32 ioCount = 30;
+	media_format out;
+	out.type = B_MEDIA_RAW_VIDEO;
+	fStatus = BMediaRoster::Roster()->GetDormantNodes(dni, &ioCount, 0, &out, 0, B_BUFFER_PRODUCER);
+	if (fStatus < B_OK)
+		return -1;
+
+	fStatus = B_ERROR;
+	for (int ix=0; ix<ioCount; ix++) {
+		media_node_id running = -1;
+		if ((B_OK == BMediaRoster::CurrentRoster()->GetInstancesFor(
+				dni[ix].addon, dni[ix].flavor_id, &running)) && (running > -1)) {
+			BMediaRoster::CurrentRoster()->GetNodeFor(running, &fProducerNode);
+			int32 count = 1;
+			BMediaRoster::CurrentRoster()->GetFreeOutputsFor(
+				fProducerNode, &videoOutput, 1, &count, B_MEDIA_RAW_VIDEO);
+			if (count > 0) {
+				if (strcmp(videoOutput.name, _deviceUniqueId) == 0) {
+					fStatus = B_OK;
+					break;
+				}
+			}
+			BMediaRoster::CurrentRoster()->ReleaseNode(fProducerNode);
+		}
+	}
+	if (fStatus != B_OK)
+		return -1;
+
+	fStatus = fMediaRoster->RegisterNode(fVideoConsumer);
+	if (fStatus != B_OK)
+		return -1;
+	fConsumerNode = fVideoConsumer->Node();
+
+	int32 count = 1;
+	fStatus = fMediaRoster->GetFreeInputsFor(fConsumerNode, &videoInput, 1, &count, B_MEDIA_RAW_VIDEO);
+	if (fStatus != B_OK || count < 1)
+		return -1;
+
+	// connect the nodes
+	media_format format;
+	format.type = B_MEDIA_RAW_VIDEO;
+	media_raw_video_format videoFormat = {
+		29.97f, 1, 0,
+		639,
+		B_VIDEO_TOP_LEFT_RIGHT, 1, 1,
+		{
+			B_RGB32,
+			(uint32)(640),
+			(uint32)(480),
+			0, 0, 0
+		}
+	};
+	format.u.raw_video = videoFormat;
+	
+	fStatus = fMediaRoster->Connect(videoOutput.source, videoInput.destination,
+		&format, &videoOutput, &videoInput);
+
+	if (fStatus != B_OK)
+		return -1;
+		
+	timeSource = fMediaRoster->MakeTimeSourceFor(fTimeSource);
+	bigtime_t real = BTimeSource::RealTime();
+	bigtime_t perf = timeSource->PerformanceTimeFor(real) + 3000000;
+
+	fStatus = fMediaRoster->StartNode(fConsumerNode, perf);
+	if (fStatus != B_OK)
+		return -1;
+
+	fStatus = fMediaRoster->StopNode(fProducerNode, perf, true);
+	fStatus = fMediaRoster->StartNode(fProducerNode, perf);
+	if (fStatus != B_OK)
+		return -1;
+
+	_captureStarted = true;
+	return 0;
+}
+
+int32_t VideoCaptureModuleHaiku::StopCapture() {
+  if (_captureStarted) {
+  	fMediaRoster->StopNode(fProducerNode, BTimeSource::RealTime(), true);
+  	fMediaRoster->Disconnect(fProducerNode.node, videoOutput.source,
+  		fConsumerNode.node, videoInput.destination);
+  	fMediaRoster->UnregisterNode(fVideoConsumer);
+  	delete fVideoConsumer;
+    _captureStarted = false;
+  }
+
+  return 0;
+}
+
+bool VideoCaptureModuleHaiku::CaptureStarted() {
+  return _captureStarted;
+}
+
+int32_t VideoCaptureModuleHaiku::CaptureSettings(
+    VideoCaptureCapability& settings) {
+  settings.width = _currentWidth;
+  settings.height = _currentHeight;
+  settings.maxFPS = _currentFrameRate;
+  settings.videoType = _captureVideoType;
+
+  return 0;
+}
+}  // namespace videocapturemodule
+}  // namespace webrtc
diff --git a/src/modules/video_capture/haiku/video_capture_haiku.h b/src/modules/video_capture/haiku/video_capture_haiku.h
new file mode 100644
index 0000000..5bce5bd
--- /dev/null
+++ b/src/modules/video_capture/haiku/video_capture_haiku.h
@@ -0,0 +1,58 @@
+/*
+ *  Copyright 2021 Gerasim Troeglazov
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_VIDEO_CAPTURE_MAIN_SOURCE_HAIKU_VIDEO_CAPTURE_HAIKU_H_
+#define MODULES_VIDEO_CAPTURE_MAIN_SOURCE_HAIKU_VIDEO_CAPTURE_HAIKU_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+
+#include <MediaKit.h>
+
+#include "modules/video_capture/video_capture_defines.h"
+#include "modules/video_capture/video_capture_impl.h"
+#include "rtc_base/platform_thread.h"
+#include "rtc_base/synchronization/mutex.h"
+
+#include "video_consumer.h"
+
+namespace webrtc {
+namespace videocapturemodule {
+class VideoCaptureModuleHaiku : public VideoCaptureImpl {
+ public:
+  VideoCaptureModuleHaiku();
+  ~VideoCaptureModuleHaiku() override;
+  int32_t Init(const char* deviceUniqueId);
+  int32_t StartCapture(const VideoCaptureCapability& capability) override;
+  int32_t StopCapture() override;
+  bool CaptureStarted() override;
+  int32_t CaptureSettings(VideoCaptureCapability& settings) override;
+
+ private:
+	BMediaRoster *fMediaRoster;
+	VideoConsumer *fVideoConsumer;
+	BTimeSource* timeSource;
+	media_node fProducerNode;
+	media_node fConsumerNode;
+	media_input videoInput;
+	media_output videoOutput;
+	
+  int32_t _currentWidth;
+  int32_t _currentHeight;
+  int32_t _currentFrameRate;
+  bool _captureStarted;
+  VideoType _captureVideoType;
+};
+}  // namespace videocapturemodule
+}  // namespace webrtc
+
+#endif  // MODULES_VIDEO_CAPTURE_MAIN_SOURCE_HAIKU_VIDEO_CAPTURE_HAIKU_H_
diff --git a/src/modules/video_capture/haiku/video_consumer.cc b/src/modules/video_capture/haiku/video_consumer.cc
new file mode 100644
index 0000000..556d846
--- /dev/null
+++ b/src/modules/video_capture/haiku/video_consumer.cc
@@ -0,0 +1,475 @@
+/*
+ *  Copyright 2021 Gerasim Troeglazov
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <Buffer.h>
+#include <BufferGroup.h>
+#include <NodeInfo.h>
+#include <Bitmap.h>
+#include <View.h>
+#include <scheduler.h>
+#include <TimeSource.h>
+#include <MediaRoster.h>
+
+#include "video_consumer.h"
+
+namespace webrtc {
+namespace videocapturemodule {
+
+VideoConsumer::VideoConsumer(const char* name, BMediaAddOn* addon,
+		const uint32 internal_id)
+	: BMediaNode(name),
+	  BMediaEventLooper(),
+	  BBufferConsumer(B_MEDIA_RAW_VIDEO),
+	  fInternalID(internal_id),
+	  fAddOn(addon),
+	  fConnectionActive(false),
+	  fMyLatency(3000),
+	  fOurBuffers(false),
+	  fBuffers(NULL),
+	  fLastBufferIndex(-1),
+	  fVideoCapture(NULL)
+{
+	AddNodeKind(B_PHYSICAL_OUTPUT);
+	SetEventLatency(0);
+
+	for (uint32 i = 0; i < kBufferCount; i++) {
+		fBitmap[i] = NULL;
+		fBufferMap[i] = NULL;
+	}
+
+	SetPriority(B_DISPLAY_PRIORITY);
+}
+
+
+VideoConsumer::~VideoConsumer()
+{
+	Quit();
+	DeleteBuffers();
+}
+
+
+void
+VideoConsumer::SetVideoCapture(VideoCaptureImpl *impl)
+{
+	fVideoCapture = impl;
+}
+
+
+BMediaAddOn*
+VideoConsumer::AddOn(int32* cookie) const
+{
+	*cookie = fInternalID;
+	return fAddOn;
+}
+
+
+void
+VideoConsumer::NodeRegistered()
+{
+	fIn.destination.port = ControlPort();
+	fIn.destination.id = 0;
+	fIn.source = media_source::null;
+	fIn.format.type = B_MEDIA_RAW_VIDEO;
+	// wild cards yet
+	fIn.format.u.raw_video = media_raw_video_format::wildcard;
+	fIn.format.u.raw_video.interlace = 1;
+	fIn.format.u.raw_video.display.format = B_NO_COLOR_SPACE;
+	fIn.format.u.raw_video.display.bytes_per_row = 0;
+	fIn.format.u.raw_video.display.line_width = 0;
+	fIn.format.u.raw_video.display.line_count = 0;
+
+	Run();
+}
+
+
+status_t
+VideoConsumer::RequestCompleted(const media_request_info& info)
+{
+	switch(info.what) {
+		case media_request_info::B_SET_OUTPUT_BUFFERS_FOR:
+			if (info.status != B_OK)
+				fprintf(stderr, "VideoConsumer::RequestCompleted: Not using our buffers!\n");
+			break;
+		default:
+			break;
+	}
+	return B_OK;
+}
+
+
+status_t
+VideoConsumer::HandleMessage(int32 message, const void* data, size_t size)
+{
+	return B_OK;
+}
+
+
+void
+VideoConsumer::BufferReceived(BBuffer* buffer)
+{
+	if (RunState() == B_STOPPED) {		
+		buffer->Recycle();
+		return;
+	}
+	media_timed_event event(buffer->Header()->start_time,
+		BTimedEventQueue::B_HANDLE_BUFFER, buffer,
+		BTimedEventQueue::B_RECYCLE_BUFFER);
+	EventQueue()->AddEvent(event);
+}
+
+
+void
+VideoConsumer::ProducerDataStatus(const media_destination& forWhom,
+	int32 status, bigtime_t atMediaTime)
+{
+	if (forWhom != fIn.destination)
+		return;
+}
+
+
+status_t
+VideoConsumer::CreateBuffers(const media_format& format)
+{
+	DeleteBuffers();	
+
+	status_t status = B_OK;
+
+	uint32 width = format.u.raw_video.display.line_width;
+	uint32 height = format.u.raw_video.display.line_count;	
+	color_space colorSpace = format.u.raw_video.display.format;
+
+	fBuffers = new BBufferGroup();
+	status = fBuffers->InitCheck();
+	if (B_OK != status)
+		return status;
+
+	BRect bounds(0, 0, width - 1, height - 1);
+	for (uint32 i = 0; i < kBufferCount; i++) {
+		uint32 bitmapFlags = 0;
+		bitmapFlags = B_BITMAP_IS_LOCKED;
+			
+		fBitmap[i] = new BBitmap(bounds, bitmapFlags, colorSpace);
+		status = fBitmap[i]->InitCheck();
+		if (status >= B_OK) {
+			buffer_clone_info info;
+
+			uint8* bits = (uint8*)fBitmap[i]->Bits();
+			info.area = area_for(bits);
+			area_info bitmapAreaInfo;
+			status = get_area_info(info.area, &bitmapAreaInfo);
+			if (status != B_OK) {
+				fprintf(stderr, "VideoConsumer::CreateBuffers() - "
+					"get_area_info(): %s\n", strerror(status));
+				return status;
+			}
+
+			info.offset = bits - (uint8*)bitmapAreaInfo.address;
+			info.size = (size_t)fBitmap[i]->BitsLength();
+			info.flags = 0;
+			info.buffer = 0;
+
+			BBuffer* buffer = NULL;
+			if ((status = fBuffers->AddBuffer(info, &buffer)) != B_OK) {
+				fprintf(stderr, "VideoConsumer::CreateBuffers - ERROR ADDING BUFFER "
+					"TO GROUP (%" B_PRId32 "): %s\n", i, strerror(status));
+				return status;
+			}
+			fBufferMap[i] = buffer;
+		} else {
+			fprintf(stderr, "VideoConsumer::CreateBuffers - ERROR CREATING VIDEO RING "
+				"BUFFER (Index %" B_PRId32 " Width %" B_PRId32 " Height %"
+				B_PRId32 " Colorspace %d: %s\n", i, width, height, colorSpace,
+				strerror(status));
+			return status;
+		}
+	}
+
+	return status;
+}
+
+
+void
+VideoConsumer::DeleteBuffers()
+{
+	if (fBuffers) {
+		fTargetLock.Lock();
+		if (fLastBufferIndex >= 0) {
+			fLastBufferIndex = -1;
+		}
+		fTargetLock.Unlock();
+
+		delete fBuffers;
+		fBuffers = NULL;
+
+		for (uint32 i = 0; i < kBufferCount; i++) {
+			snooze(20000);
+			delete fBitmap[i];
+			fBitmap[i] = NULL;
+		}
+	}
+}
+
+
+status_t
+VideoConsumer::Connected(const media_source& producer,
+	const media_destination& where, const media_format& format,
+	media_input* outInput)
+{
+	fIn.source = producer;
+	fIn.format = format;
+	fIn.node = Node();
+	sprintf(fIn.name, "Video Consumer");
+	*outInput = fIn;
+
+	uint32 userData = 0;
+	int32 changeTag = 1;
+	status_t ret = CreateBuffers(format);
+	if (ret == B_OK) {
+		ret = SetOutputBuffersFor(producer, fIn.destination, 
+			fBuffers, &userData, &changeTag, true);
+		if (ret != B_OK)
+			fprintf(stderr, "SetOutputBuffersFor() failed: %s\n", strerror(ret));
+
+		fIn.format.u.raw_video.display.bytes_per_row
+			= fBitmap[0]->BytesPerRow();
+	} else {
+		fprintf(stderr, "VideoConsumer::Connected - COULDN'T CREATE BUFFERS\n");
+		return ret;
+	}
+
+	*outInput = fIn;
+	fConnectionActive = true;
+
+	return B_OK;
+}
+
+
+void
+VideoConsumer::Disconnected(const media_source& producer,
+	const media_destination& where)
+{
+	if (where != fIn.destination || producer != fIn.source)
+		return;
+
+	int32 changeTag = 0;
+	SetOutputBuffersFor(producer, fIn.destination, NULL, NULL, &changeTag,
+		false);
+	if (fOurBuffers) {
+		status_t reclaimError = fBuffers->ReclaimAllBuffers();
+		if (reclaimError != B_OK) {
+			fprintf(stderr, "VideoConsumer::Disconnected() - Failed to "
+				"reclaim our buffers: %s\n", strerror(reclaimError));
+		}
+	}
+	// disconnect the connection
+	fIn.source = media_source::null;
+	fConnectionActive = false;
+
+	_UnsetTargetBuffer();
+}
+
+
+status_t
+VideoConsumer::AcceptFormat(const media_destination& dest, media_format* format)
+{
+	if (dest != fIn.destination) {
+		fprintf(stderr, "VideoConsumer::AcceptFormat - BAD DESTINATION\n");
+		return B_MEDIA_BAD_DESTINATION;	
+	}
+	
+	if (format->type == B_MEDIA_NO_TYPE)
+		format->type = B_MEDIA_RAW_VIDEO;
+	
+	if (format->type != B_MEDIA_RAW_VIDEO) {
+		fprintf(stderr, "VideoConsumer::AcceptFormat - BAD FORMAT\n");
+		return B_MEDIA_BAD_FORMAT;
+	}
+
+	if (format->u.raw_video.display.format
+			!= media_raw_video_format::wildcard.display.format) {
+		uint32 flags = 0;
+		bool supported = bitmaps_support_space(
+			format->u.raw_video.display.format, &flags);
+
+		if (!supported) {
+			fprintf(stderr, "AcceptFormat - unsupported color space for BBitmaps !\n");
+			return B_MEDIA_BAD_FORMAT;
+		}
+		if (flags & B_VIEWS_SUPPORT_DRAW_BITMAP == 0) {
+			fprintf(stderr, "AcceptFormat - BViews cannot draw bitmaps in given colorspace !\n");
+			return B_MEDIA_BAD_FORMAT;
+		}
+	}
+
+	return B_OK;
+}
+
+
+status_t
+VideoConsumer::GetNextInput(int32* cookie, media_input* outInput)
+{
+	if (*cookie < 1) {
+		fIn.node = Node();
+		fIn.destination.id = *cookie;
+		sprintf(fIn.name, "Video Consumer");
+		*outInput = fIn;
+		(*cookie)++;
+		return B_OK;
+	}
+	return B_MEDIA_BAD_DESTINATION;
+}
+
+
+void
+VideoConsumer::DisposeInputCookie(int32 /*cookie*/)
+{
+}
+
+
+status_t
+VideoConsumer::GetLatencyFor(const media_destination& whom,
+	bigtime_t* _latency, media_node_id* _timeSource)
+{
+	if (whom != fIn.destination)
+		return B_MEDIA_BAD_DESTINATION;
+	
+	*_latency = fMyLatency;
+	*_timeSource = TimeSource()->ID();
+	return B_OK;
+}
+
+
+status_t
+VideoConsumer::FormatChanged(const media_source& producer,
+	const media_destination& consumer, int32 fromChangeCount,
+	const media_format& format)
+{
+	if (consumer != fIn.destination)
+		return B_MEDIA_BAD_DESTINATION;
+
+	if (producer != fIn.source)
+		return B_MEDIA_BAD_SOURCE;
+
+	fIn.format = format;
+
+	return CreateBuffers(format);
+}
+
+
+void
+VideoConsumer::HandleEvent(const media_timed_event* event, bigtime_t lateness,
+	bool realTimeEvent)
+{
+	switch (event->type) {
+		case BTimedEventQueue::B_START:
+			_SetPerformanceTimeBase(event->event_time);
+			break;
+		case BTimedEventQueue::B_WARP:
+		case BTimedEventQueue::B_SEEK:
+			_SetPerformanceTimeBase(event->bigdata);
+			break;
+		case BTimedEventQueue::B_STOP:
+			EventQueue()->FlushEvents(event->event_time, BTimedEventQueue::B_ALWAYS,
+				true, BTimedEventQueue::B_HANDLE_BUFFER);
+			_UnsetTargetBuffer();
+			break;
+		case BTimedEventQueue::B_HANDLE_BUFFER:
+			_HandleBuffer(static_cast<BBuffer*>(event->pointer));
+			break;
+		default:
+			fprintf(stderr, "VideoConsumer::HandleEvent - BAD EVENT\n");
+			break;
+	}			
+}
+
+
+void
+VideoConsumer::_SetPerformanceTimeBase(bigtime_t performanceTime)
+{
+	fPerformanceTimeBase = performanceTime;
+}
+
+
+void
+VideoConsumer::_HandleBuffer(BBuffer* buffer)
+{
+	if (RunState() != B_STARTED || !fConnectionActive) {
+		buffer->Recycle();
+		return;
+	}
+
+	uint32 index = 0;
+	fOurBuffers = true;
+	while (index < kBufferCount) {
+		if (buffer->ID() == fBufferMap[index]->ID())
+			break;
+		else
+			index++;
+	}
+	if (index == kBufferCount) {
+		fOurBuffers = false;
+		index = (fLastBufferIndex + 1) % kBufferCount;
+	}
+
+	bool recycle = true;
+	bigtime_t now = TimeSource()->Now();
+
+	if (!fOurBuffers) {
+		memcpy(fBitmap[index]->Bits(), buffer->Data(),
+			fBitmap[index]->BitsLength());
+	}
+
+	bigtime_t tooEarly = buffer->Header()->start_time - now;
+	if (tooEarly > 3000)
+		snooze(tooEarly);
+
+	fTargetLock.Lock();
+
+	VideoCaptureCapability frameInfo;
+	frameInfo.width = fBitmap[index]->Bounds().Width() + 1;
+	frameInfo.height = fBitmap[index]->Bounds().Height() + 1;
+	frameInfo.videoType = VideoType::kARGB;
+
+	fVideoCapture->IncomingFrame((unsigned char*)fBitmap[index]->Bits(),
+		fBitmap[index]->BitsLength(), frameInfo);
+
+	if (fOurBuffers) {
+		if (fLastBufferIndex >= 0)
+			fBufferMap[fLastBufferIndex]->Recycle();
+		recycle = false;
+	}
+	fLastBufferIndex = index;
+
+	fTargetLock.Unlock();
+
+	if (recycle)
+		buffer->Recycle();
+}
+
+
+void
+VideoConsumer::_UnsetTargetBuffer()
+{
+	fTargetLock.Lock();
+	if (fLastBufferIndex >= 0) {
+		if (fOurBuffers)
+			fBufferMap[fLastBufferIndex]->Recycle();
+		fLastBufferIndex = -1;
+	}
+	fTargetLock.Unlock();
+}
+
+}
+}
diff --git a/src/modules/video_capture/haiku/video_consumer.h b/src/modules/video_capture/haiku/video_consumer.h
new file mode 100644
index 0000000..7308f0c
--- /dev/null
+++ b/src/modules/video_capture/haiku/video_consumer.h
@@ -0,0 +1,123 @@
+/*
+ *  Copyright 2021 Gerasim Troeglazov
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef VIDEO_CONSUMER_H
+#define VIDEO_CONSUMER_H
+
+#include "modules/video_capture/video_capture_defines.h"
+#include "modules/video_capture/video_capture_impl.h"
+
+#include <BufferConsumer.h>
+#include <Locker.h>
+#include <MediaEventLooper.h>
+
+class BBitmap;
+
+namespace webrtc {
+namespace videocapturemodule {
+
+static const unsigned int kBufferCount = 4;
+
+
+class VideoConsumer : public BMediaEventLooper, public BBufferConsumer {
+public:
+								VideoConsumer(
+									const char* name,
+									BMediaAddOn* addon,
+									const uint32 internal_id);
+								~VideoConsumer();
+public:
+	void						SetVideoCapture(VideoCaptureImpl *impl);
+	// BMediaNode interface
+public:
+	virtual	BMediaAddOn*		AddOn(int32* cookie) const;
+	
+protected:
+	virtual void				NodeRegistered();
+	virtual	status_t		 	RequestCompleted(
+									const media_request_info& info);
+							
+	virtual	status_t 			HandleMessage(int32 message, const void* data,
+									size_t size);
+
+	// BMediaEventLooper interface
+protected:
+	virtual void				HandleEvent(const media_timed_event* event,
+									bigtime_t lateness, bool realTimeEvent);
+
+	// BBufferConsumer interface
+public:
+	virtual	status_t			AcceptFormat(const media_destination& dest,
+									media_format* format);
+	virtual	status_t			GetNextInput(int32* cookie,
+									media_input* _input);
+							
+	virtual	void				DisposeInputCookie(int32 cookie);
+	
+protected:
+	virtual	void				BufferReceived(BBuffer* buffer);
+	
+private:
+	virtual	void				ProducerDataStatus(
+									const media_destination& forWhom,
+									int32 status,
+									bigtime_t atMediaTime);									
+	virtual	status_t			GetLatencyFor(
+									const media_destination& forWhom,
+									bigtime_t* outLatency,
+									media_node_id* outId);	
+	virtual	status_t			Connected(const media_source& producer,
+									const media_destination& where,
+									const media_format& withFormat,
+									media_input* outInput);
+	virtual	void				Disconnected(const media_source& producer,
+									const media_destination& where);							
+	virtual	status_t			FormatChanged(const media_source& producer,
+									const media_destination& consumer, 
+									int32 from_change_count,
+									const media_format& format);
+							
+	// VideoConsumer
+public:
+			status_t			CreateBuffers(
+									const media_format& withFormat);
+							
+			void				DeleteBuffers();
+
+private:
+			void				_SetPerformanceTimeBase(
+									bigtime_t performanceTime);
+			void				_HandleBuffer(BBuffer* buffer);
+			void				_UnsetTargetBuffer();
+
+private:
+			int32				fInternalID;
+			BMediaAddOn*		fAddOn;
+
+			bool				fConnectionActive;
+			media_input			fIn;
+			bigtime_t			fMyLatency;
+			bigtime_t			fPerformanceTimeBase;
+
+			BBitmap*			fBitmap[kBufferCount];
+			bool				fOurBuffers;
+			BBufferGroup*		fBuffers;
+			BBuffer*			fBufferMap[kBufferCount];	
+
+			BLocker				fTargetLock;
+			int32				fLastBufferIndex;
+
+			VideoCaptureImpl 	*fVideoCapture;
+};
+
+}  // namespace videocapturemodule
+}  // namespace webrtc
+
+#endif // VIDEO_CONSUMER_H
diff --git a/src/rtc_base/BUILD.gn b/src/rtc_base/BUILD.gn
index 5165a3e..146c787 100644
--- a/src/rtc_base/BUILD.gn
+++ b/src/rtc_base/BUILD.gn
@@ -508,7 +508,7 @@ rtc_source_set("rtc_operations_chain") {
   absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
 }
 
-if (rtc_enable_libevent) {
+if (rtc_enable_libevent && !is_haiku) {
   rtc_library("rtc_task_queue_libevent") {
     visibility = [ "../api/task_queue:default_task_queue_factory" ]
     sources = [
diff --git a/src/rtc_base/byte_order.h b/src/rtc_base/byte_order.h
index f1f87e3..7b8bd85 100644
--- a/src/rtc_base/byte_order.h
+++ b/src/rtc_base/byte_order.h
@@ -88,7 +88,7 @@
 #error WEBRTC_ARCH_BIG_ENDIAN or WEBRTC_ARCH_LITTLE_ENDIAN must be defined.
 #endif  // defined(WEBRTC_ARCH_LITTLE_ENDIAN)
 
-#elif defined(WEBRTC_LINUX)
+#elif defined(WEBRTC_LINUX) || defined(WEBRTC_HAIKU)
 #include <endian.h>
 #elif defined(WEBRTC_FREEBSD)
 #include <sys/endian.h>
diff --git a/src/rtc_base/ip_address.cc b/src/rtc_base/ip_address.cc
index a5498c6..3e829bf 100644
--- a/src/rtc_base/ip_address.cc
+++ b/src/rtc_base/ip_address.cc
@@ -11,6 +11,9 @@
 #if defined(WEBRTC_POSIX)
 #include <netinet/in.h>
 #include <sys/socket.h>
+#if defined(WEBRTC_HAIKU)
+#include <netinet6/in6.h>
+#endif
 #ifdef OPENBSD
 #include <netinet/in_systm.h>
 #endif
@@ -30,6 +33,15 @@
 namespace rtc {
 
 // Prefixes used for categorizing IPv6 addresses.
+#if defined(WEBRTC_HAIKU)
+static const in6_addr kV4MappedPrefix = {
+    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0}};
+static const in6_addr k6To4Prefix = {{0x20, 0x02, 0}};
+static const in6_addr kTeredoPrefix = {{0x20, 0x01, 0x00, 0x00}};
+static const in6_addr kV4CompatibilityPrefix = {{0}};
+static const in6_addr k6BonePrefix = {{0x3f, 0xfe, 0}};
+static const in6_addr kPrivateNetworkPrefix = {{0xFD}};
+#else
 static const in6_addr kV4MappedPrefix = {
     {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0}}};
 static const in6_addr k6To4Prefix = {{{0x20, 0x02, 0}}};
@@ -37,6 +49,7 @@ static const in6_addr kTeredoPrefix = {{{0x20, 0x01, 0x00, 0x00}}};
 static const in6_addr kV4CompatibilityPrefix = {{{0}}};
 static const in6_addr k6BonePrefix = {{{0x3f, 0xfe, 0}}};
 static const in6_addr kPrivateNetworkPrefix = {{{0xFD}}};
+#endif
 
 static bool IPIsHelper(const IPAddress& ip,
                        const in6_addr& tomatch,
diff --git a/src/rtc_base/logging.cc b/src/rtc_base/logging.cc
index 4ebeebe..ce09db9 100644
--- a/src/rtc_base/logging.cc
+++ b/src/rtc_base/logging.cc
@@ -124,7 +124,11 @@ LogMessage::LogMessage(const char* file,
 
   if (thread_) {
     PlatformThreadId id = CurrentThreadId();
+#ifdef WEBRTC_HAIKU
+	print_stream_ << "[" << (uint64_t)id << "] ";
+#else
     print_stream_ << "[" << id << "] ";
+#endif
   }
 
   if (file != nullptr) {
diff --git a/src/rtc_base/network.cc b/src/rtc_base/network.cc
index 870f22a..8a6f605 100644
--- a/src/rtc_base/network.cc
+++ b/src/rtc_base/network.cc
@@ -564,7 +564,7 @@ void BasicNetworkManager::ConvertIfAddrs(struct ifaddrs* interfaces,
       continue;
     }
     // Skip ones which are down.
-    if (!(cursor->ifa_flags & IFF_RUNNING)) {
+    if (!(cursor->ifa_flags & IFF_LINK)) {
       continue;
     }
     // Skip unknown family.
diff --git a/src/rtc_base/physical_socket_server.cc b/src/rtc_base/physical_socket_server.cc
index d89139d..6d1cae3 100644
--- a/src/rtc_base/physical_socket_server.cc
+++ b/src/rtc_base/physical_socket_server.cc
@@ -325,7 +325,7 @@ int PhysicalSocket::SetOption(Option opt, int value) {
     value <<= 2;
 #endif
   }
-#if defined(WEBRTC_POSIX)
+#if defined(WEBRTC_POSIX) && !defined(WEBRTC_HAIKU)
   if (sopt == IPV6_TCLASS) {
     // Set the IPv4 option in all cases to support dual-stack sockets.
     // Don't bother checking the return code, as this is expected to fail if
@@ -585,7 +585,7 @@ int PhysicalSocket::TranslateOption(Option opt, int* slevel, int* sopt) {
       *sopt = TCP_NODELAY;
       break;
     case OPT_DSCP:
-#if defined(WEBRTC_POSIX)
+#if defined(WEBRTC_POSIX) && !defined(WEBRTC_HAIKU)
       if (family_ == AF_INET6) {
         *slevel = IPPROTO_IPV6;
         *sopt = IPV6_TCLASS;
diff --git a/src/rtc_base/platform_thread_types.h b/src/rtc_base/platform_thread_types.h
index 6b9101e..0ae52e5 100644
--- a/src/rtc_base/platform_thread_types.h
+++ b/src/rtc_base/platform_thread_types.h
@@ -38,6 +38,9 @@ typedef DWORD PlatformThreadRef;
 #elif defined(WEBRTC_FUCHSIA)
 typedef zx_handle_t PlatformThreadId;
 typedef zx_handle_t PlatformThreadRef;
+#elif defined(WEBRTC_HAIKU)
+typedef pthread_t PlatformThreadId;
+typedef pthread_t PlatformThreadRef;
 #elif defined(WEBRTC_POSIX)
 typedef pid_t PlatformThreadId;
 typedef pthread_t PlatformThreadRef;
diff --git a/src/rtc_base/system/rtc_export.h b/src/rtc_base/system/rtc_export.h
index d1eb60a..9dc761d 100644
--- a/src/rtc_base/system/rtc_export.h
+++ b/src/rtc_base/system/rtc_export.h
@@ -28,7 +28,7 @@
 
 #else  // WEBRTC_WIN
 
-#if __has_attribute(visibility) && defined(WEBRTC_LIBRARY_IMPL)
+#if defined(WEBRTC_LIBRARY_IMPL)
 #define RTC_EXPORT __attribute__((visibility("default")))
 #endif
 
diff --git a/src/rtc_base/system/rtc_export_template.h b/src/rtc_base/system/rtc_export_template.h
index 4ac7043..5fe950f 100644
--- a/src/rtc_base/system/rtc_export_template.h
+++ b/src/rtc_base/system/rtc_export_template.h
@@ -185,7 +185,7 @@
 
 RTC_EXPORT_TEMPLATE_TEST(DEFAULT, );  // NOLINT
 RTC_EXPORT_TEMPLATE_TEST(DEFAULT, __attribute__((visibility("default"))));
-RTC_EXPORT_TEMPLATE_TEST(MSVC_HACK, __declspec(dllexport));
+//RTC_EXPORT_TEMPLATE_TEST(MSVC_HACK, __declspec(dllexport));
 RTC_EXPORT_TEMPLATE_TEST(DEFAULT, __declspec(dllimport));
 
 #undef RTC_EXPORT_TEMPLATE_TEST
diff --git a/src/third_party/openh264/src/codec/common/src/WelsThreadLib.cpp b/src/third_party/openh264/src/codec/common/src/WelsThreadLib.cpp
index 8aa67f1..5c2b6e1 100644
--- a/src/third_party/openh264/src/codec/common/src/WelsThreadLib.cpp
+++ b/src/third_party/openh264/src/codec/common/src/WelsThreadLib.cpp
@@ -48,7 +48,7 @@
 #include <sys/types.h>
 #include <sys/param.h>
 #include <unistd.h>
-#ifndef __Fuchsia__
+#if !defined(__Fuchsia__) && !defined(__HAIKU__)
 #include <sys/sysctl.h>
 #endif
 #ifdef __APPLE__
@@ -244,7 +244,7 @@ WELS_THREAD_ERROR_CODE    WelsThreadCreate (WELS_THREAD_HANDLE* thread,  LPWELS_
   err = pthread_attr_init (&at);
   if (err)
     return err;
-#if !defined(__ANDROID__) && !defined(__Fuchsia__)
+#if !defined(__ANDROID__) && !defined(__Fuchsia__) && !defined(__HAIKU__)
   err = pthread_attr_setscope (&at, PTHREAD_SCOPE_SYSTEM);
   if (err)
     return err;
@@ -517,6 +517,10 @@ WELS_THREAD_ERROR_CODE    WelsQueryLogicalProcessInfo (WelsLogicalProcessInfo* p
 
   return WELS_THREAD_ERROR_OK;
 
+#elif defined(__HAIKU__)
+  pInfo->ProcessorCount = 1;
+  return WELS_THREAD_ERROR_OK;
+
 #elif defined(__EMSCRIPTEN__)
 
   // There is not yet a way to determine CPU count in emscripten JS environment.
diff --git a/src/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp.h b/src/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp.h
old mode 100755
new mode 100644
index f0dc35a..626ee9f
--- a/src/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp.h
+++ b/src/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp.h
@@ -40,7 +40,7 @@ __FBSDID("$FreeBSD: head/sys/netinet/sctp.h 366750 2020-10-16 10:44:48Z tuexen $
 #ifndef _NETINET_SCTP_H_
 #define _NETINET_SCTP_H_
 
-#if defined(__APPLE__) || defined(__linux__)
+#if defined(__APPLE__) || defined(__linux__) || defined(__HAIKU__)
 #include <stdint.h>
 #endif
 #include <sys/types.h>
diff --git a/src/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_input.c b/src/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_input.c
old mode 100755
new mode 100644
index 517189f..6352509
--- a/src/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_input.c
+++ b/src/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_input.c
@@ -6349,11 +6349,11 @@ sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port)
 #if defined(_WIN32) && !defined(__Userspace__)
 	NTOHS(ip->ip_len);
 #endif
-#if defined(__linux__) || (defined(_WIN32) && defined(__Userspace__))
+#if defined(__linux__) || defined(__HAIKU__) || (defined(_WIN32) && defined(__Userspace__))
 	ip->ip_len = ntohs(ip->ip_len);
 #endif
 #if defined(__Userspace__)
-#if defined(__linux__) || defined(_WIN32)
+#if defined(__linux__) || defined(__HAIKU__) || defined(_WIN32)
 	length = ip->ip_len;
 #else
 	length = ip->ip_len + iphlen;
diff --git a/src/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_os_userspace.h b/src/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_os_userspace.h
old mode 100755
new mode 100644
index 1476660..6bb232e
--- a/src/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_os_userspace.h
+++ b/src/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_os_userspace.h
@@ -283,7 +283,7 @@ typedef char* caddr_t;
 
 #else /* !defined(Userspace_os_Windows) */
 #include <sys/socket.h>
-#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__native_client__) || defined(__Fuchsia__) || defined(__EMSCRIPTEN_PTHREADS__)
+#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__linux__) || defined(__HAIKU__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__native_client__) || defined(__Fuchsia__) || defined(__EMSCRIPTEN_PTHREADS__)
 #include <pthread.h>
 #endif
 typedef pthread_mutex_t userland_mutex_t;
@@ -1132,7 +1132,7 @@ sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header, int how, int a
 
 #define SCTP_IS_LISTENING(inp) ((inp->sctp_flags & SCTP_PCB_FLAGS_ACCEPTING) != 0)
 
-#if defined(__APPLE__) || defined(__DragonFly__) || defined(__linux__) || defined(__native_client__) || defined(__NetBSD__) || defined(_WIN32) || defined(__Fuchsia__) || defined(__EMSCRIPTEN__)
+#if defined(__APPLE__) || defined(__DragonFly__) || defined(__linux__) || defined(__HAIKU__) ||defined(__native_client__) || defined(__NetBSD__) || defined(_WIN32) || defined(__Fuchsia__) || defined(__EMSCRIPTEN__)
 int
 timingsafe_bcmp(const void *, const void *, size_t);
 #endif
diff --git a/src/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_userspace.c b/src/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_userspace.c
old mode 100755
new mode 100644
index ba64aaf..b5d8cf1
--- a/src/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_userspace.c
+++ b/src/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_userspace.c
@@ -94,7 +94,7 @@ sctp_userspace_set_threadname(const char *name)
 #endif
 }
 
-#if !defined(_WIN32) && !defined(__native_client__)
+#if !defined(_WIN32) && !defined(__HAIKU__) && !defined(__native_client__)
 int
 sctp_userspace_get_mtu_from_ifn(uint32_t if_index, int af)
 {
@@ -118,7 +118,7 @@ sctp_userspace_get_mtu_from_ifn(uint32_t if_index, int af)
 }
 #endif
 
-#if defined(__native_client__)
+#if defined(__native_client__) || defined(__HAIKU__)
 int
 sctp_userspace_get_mtu_from_ifn(uint32_t if_index, int af)
 {
@@ -126,7 +126,7 @@ sctp_userspace_get_mtu_from_ifn(uint32_t if_index, int af)
 }
 #endif
 
-#if defined(__APPLE__) || defined(__DragonFly__) || defined(__linux__) || defined(__native_client__) || defined(__NetBSD__) || defined(_WIN32) || defined(__Fuchsia__) || defined(__EMSCRIPTEN__)
+#if defined(__APPLE__) || defined(__DragonFly__) || defined(__linux__) || defined(__HAIKU__) || defined(__native_client__) || defined(__NetBSD__) || defined(_WIN32) || defined(__Fuchsia__) || defined(__EMSCRIPTEN__)
 int
 timingsafe_bcmp(const void *b1, const void *b2, size_t n)
 {
diff --git a/src/third_party/usrsctp/usrsctplib/usrsctplib/user_socket.c b/src/third_party/usrsctp/usrsctplib/usrsctplib/user_socket.c
old mode 100755
new mode 100644
index 513a5a9..73fd4e2
--- a/src/third_party/usrsctp/usrsctplib/usrsctplib/user_socket.c
+++ b/src/third_party/usrsctp/usrsctplib/usrsctplib/user_socket.c
@@ -50,6 +50,9 @@
 #if defined(__linux__)
 #define __FAVOR_BSD    /* (on Ubuntu at least) enables UDP header field names like BSD in RFC 768 */
 #endif
+#if defined(__HAIKU__)
+#define UIO_MAXIOV _SC_IOV_MAX
+#endif
 #if !defined(_WIN32)
 #if defined INET || defined INET6
 #include <netinet/udp.h>
@@ -1035,7 +1038,7 @@ userspace_sctp_recvmsg(struct socket *so,
 	if (error) {
 		if ((auio.uio_resid != ulen) &&
 		    (error == EINTR ||
-#if !defined(__NetBSD__)
+#if !defined(__NetBSD__) && !defined(__HAIKU__)
 		     error == ERESTART ||
 #endif
 		     error == EWOULDBLOCK)) {
@@ -1128,7 +1131,7 @@ usrsctp_recvv(struct socket *so,
 	if (errno) {
 		if ((auio.uio_resid != ulen) &&
 		    (errno == EINTR ||
-#if !defined(__NetBSD__)
+#if !defined(__NetBSD__) && !defined(__HAIKU__)
 		     errno == ERESTART ||
 #endif
 		     errno == EWOULDBLOCK)) {
@@ -1944,7 +1947,7 @@ int user_connect(struct socket *so, struct sockaddr *sa)
 		error = pthread_cond_wait(SOCK_COND(so), SOCK_MTX(so));
 #endif
 		if (error) {
-#if defined(__NetBSD__)
+#if defined(__NetBSD__) || defined(__HAIKU__)
 			if (error == EINTR) {
 #else
 			if (error == EINTR || error == ERESTART) {
@@ -1964,7 +1967,7 @@ bad:
 	if (!interrupted) {
 		so->so_state &= ~SS_ISCONNECTING;
 	}
-#if !defined(__NetBSD__)
+#if !defined(__NetBSD__) && !defined(__HAIKU__)
 	if (error == ERESTART) {
 		error = EINTR;
 	}
diff --git a/src/third_party/usrsctp/usrsctplib/usrsctplib/user_environment.c b/src/third_party/usrsctp/usrsctplib/usrsctplib/user_environment.c
old mode 100755
new mode 100644
index 1887718..2e3409e
--- a/src/third_party/usrsctp/usrsctplib/usrsctplib/user_environment.c
+++ b/src/third_party/usrsctp/usrsctplib/usrsctplib/user_environment.c
@@ -172,7 +172,7 @@ finish_random(void)
 {
 	return;
 }
-#elif (defined(__ANDROID__) && (__ANDROID_API__ < 28)) || defined(__EMSCRIPTEN__)
+#elif (defined(__ANDROID__) && (__ANDROID_API__ < 28)) || defined(__EMSCRIPTEN__) || defined(__HAIKU__)
 #include <fcntl.h>
 
 static int fd = -1;
-- 
2.30.2

