Noctiluca - ดูเหมือนว่าอนาคตของซอฟต์แวร์ควบคุมระยะไกลจะไม่ใช่ WebRTC แต่เป็น QUIC
(drive.google.com)สวัสดีครับ ผมคือ unstabler นี่เป็นครั้งแรกที่ผมเขียนบทความครับ
ปกติผมไม่ใช่คนที่เขียนบทความบ่อยนัก เลยอาจจะเขียนได้ไม่ค่อยเป็นระเบียบและยืดยาวไปบ้าง แต่ก็ขอฝากเนื้อฝากตัวด้วยครับ!
เพราะไม่ชอบ macOS ผมเลยเริ่มหมกมุ่นกับ macOS
ผมใช้ Linux เดสก์ท็อปเป็นหลักมาตั้งแต่ปี 2011 ผ่านทั้ง Ubuntu, Debian, Fedora และใช้ Arch Linux + KDE Plasma เป็น OS หลักมาโดยตลอด ด้วยเหตุผลหลายอย่าง ตั้งแต่ปี 2021 ผมก็ได้ตั้งบริษัทที่ทำงานคล้าย ๆ SI รับงานทุกอย่างที่ทำแล้วสนุก ไม่ว่าจะเป็น embedded C++, mobile app หรือเว็บไซต์ธรรมดา ๆ
ระหว่างนั้น งานทำ iOS app ก็เริ่มมีสัดส่วนมากขึ้นเรื่อย ๆ แต่ผมก็ไม่ได้อยากใช้ Mac เท่าไรนัก ช่วงแรกก็ลองปรับ keybind ไปมาด้วย Karabiner แล้วก็เชื่อมต่อผ่าน Google Remote Desktop เพื่อทำงาน แต่ทั้งช้ามาก และใน Xcode ก็มีทั้งปัญหาเรื่องการพิมพ์และเมาส์ทำงานแปลก ๆ บางส่วน จนเครียดมากครับ
นึกดูอีกที RDP! มี xrdp นี่นา!
จู่ ๆ ผมก็นึกถึง RDP ขึ้นมาได้ RDP เป็นโปรโตคอลที่พัฒนามาสำหรับ Microsoft Windows แต่ก็มี implementation แบบโอเพนซอร์สชื่อ xrdp อยู่ด้วย อย่างไรก็ตาม xrdp ตั้งอยู่บนสมมติฐานว่าต้องใช้ X11 เป็นหลัก และบน macOS แม้จะใช้การแชร์หน้าจอแบบมาตรฐาน + VNC backend ได้ แต่ถ้าความละเอียดหน้าจอไม่ตรงแบบ 1:1 ก็แทบใช้งานไม่ได้เลย
เพราะแบบนั้น ผมจึงสร้าง xrdp backend plugin ชื่อ ''麗 -ulalaca-' โดยอิงจาก VNC backend ของ xrdp และ ScreenCaptureKit แต่สุดท้ายก็ยังไปไม่ถึงระดับที่ใช้งานจริงได้
- การรองรับ GFX (H.264) / RFX ที่หายไปจาก Windows เวอร์ชันใหม่ (mstsc.exe):
ตอนที่ผมเริ่มพัฒนา การรองรับ codec อย่าง GFX / RemoteFX ก็เริ่มถูกถอดออกไปแล้ว ฝั่ง FreeRDP ซึ่งเป็นไคลเอนต์สำหรับ Linux ยังพอมีการรองรับเหลืออยู่ แต่ใน Windows เวอร์ชันปัจจุบันดูเหมือนจะเหลือเพียงการบีบอัดแบบ RLE เท่านั้น - ความยากระดับโหดของการพัฒนา / ดีบัก: นอกจากฟังก์ชันแสดงผลหน้าจอแล้ว อย่างอื่นพัฒนายากมาก และการดีบักก็ยากมากเช่นกัน ตอนแรกผมมีไฟเต็มที่ อยากทำทั้งเสียงออก / การซิงก์คลิปบอร์ดด้วย แต่เพราะเดิมทีก็มีอาการ ADHD อยู่แล้ว ความสนใจก็เลยลดลงอย่างรวดเร็ว
มาลองทำใหม่ด้วย WebRTC อีกสักรอบ! แต่...
หลังปล่อย ulalaca ทิ้งไว้ราวครึ่งปี พอเริ่มวางแนวคิดของ Noctiluca ผมก็คิดว่า “ลองทำให้จริงจังอีกครั้งด้วย WebRTC กันเถอะ!” แต่การทำ WebRTC เองก็ไม่ง่ายเหมือนกัน
- ความยากในการคัสตอม: เพื่อใช้ข้อมูลหน้าจอเป็น video source จำเป็นต้องดึงซอร์สโค้ดของ Google Chromium มาปรับแก้ พอแก้พารามิเตอร์ codec แล้ว hardware encoding ไม่ทำงาน ผมก็ต้องคุ้ยซอร์สโค้ดเพื่อหาสาเหตุ เพิ่ม log แล้ว build ใหม่ทุกครั้ง
- ไม่สามารถตรึงพอร์ตได้: ต้องมีทั้ง signaling server, TURN/STUN และที่สำคัญคือไม่สามารถตรึง outbound port ได้ และก็ไม่สามารถ reuse พอร์ตได้ด้วย ทรมานมากครับ
- คำสาปของ SCTP: WebRTC DataChannel ใช้ SCTP ภายใน และมีปัญหาว่าเมื่อ payload ของข้อความหนึ่งมีขนาดใหญ่กว่า MTU ก็จะเริ่มทำให้วิดีโอ / เสียงเกิดอาการหน่วง
สุดท้ายอ้อมไปอ้อมมา ก็กลับมาที่ QUIC
หลังจากเหนื่อยกับความซับซ้อนของ WebRTC ผมก็ปล่อย Noctiluca ทิ้งไว้อีกเกือบครึ่งปี ระหว่างเดินกลับจากนั่งเหม่อในคาเฟ่ จู่ ๆ ก็นึกถึง QUIC ซึ่งเป็นพื้นฐานของ HTTP/3 ขึ้นมา พอดีบน macOS / iOS ก็มี implementation ของ QUIC ให้ใน Network.framework อยู่แล้ว ดังนั้นผมจึงเอาซอร์สโค้ดเดิมมาต่อยอดทำ prototype ได้อย่างรวดเร็ว และในระดับ prototype ปัญหาด้านล่างก็ถูกแก้ได้ทันที
-
แก้ปัญหา Head-of-Line Blocking (HOL): ปัญหาใหญ่ที่สุดของโซลูชันที่อิง TCP หรือ WebRTC DataChannel ที่ใช้ SCTP ก็คือ ถ้าแพ็กเก็ตหายไปหนึ่งตัว ข้อมูลทั้งหมดที่ตามมาด้านหลังก็จะหยุดไปด้วย แต่ QUIC มี stream ที่เป็นอิสระจากกัน ดังนั้นต่อให้แพ็กเก็ตเสียงกระตุกไปหนึ่งตัว อินพุตเมาส์หรือเฟรมวิดีโอก็ยังไหลเข้ามาได้ต่อเนื่อง
-
UDP พอร์ตเดียวและ Connection Migration: ไม่จำเป็นต้องตั้งค่า signaling server หรือ STUN/TURN แบบซับซ้อนเหมือน WebRTC อีกต่อไป แค่เปิด UDP พอร์ตเดียวก็จบ ต่อให้สลับ Wi‑Fi AP การเชื่อมต่อก็ยังคงอยู่ได้ด้วย Connection Migration
สรุป: กำลังเปิดรับเบต้าเทสเตอร์!
ด้วยที่มาทั้งหมดนี้ ผมจึงอยากเปิดรับผู้ทดสอบเบต้าของซอฟต์แวร์ควบคุมระยะไกลชื่อ 'Noctiluca' ครับ
-
ใช้โปรโตคอลที่ออกแบบเองชื่อ 'Sirius' ซึ่งทำงานบน QUIC
- ถ้าสเปกและรายละเอียดต่าง ๆ ลงตัวในเร็ว ๆ นี้ ก็มีแผนจะเปิดโอเพนซอร์สครับ!
-
รองรับ H.264 / H.265 (HEVC)
- รองรับ image codec แบบ tile-based ดั้งเดิมสำหรับสภาพแวดล้อม VM ด้วย (MJPG, RLE, WebP)
-
รองรับการส่งผ่านคอนเทนต์ HDR (experimental)
-
สามารถเจรจาความต้องการด้าน codec ระหว่าง client-server ได้
-
รองรับการยืนยันตัวตนด้วย PAM (username-password), password-only และ SSH key
-
สามารถขยายฟังก์ชันได้ด้วย plugin โดยในอนาคตมีแผนจะทำ fail2ban และฟีเจอร์เสริมอื่น ๆ เพิ่มเติม
- สามารถเขียน plugin เองเพื่อขยายกลไกการยืนยันตัวตนได้
-
ตอนนี้ไคลเอนต์มีเฉพาะเวอร์ชัน iOS / macOS เท่านั้น
- มีแผนจะพัฒนาไคลเอนต์ Linux / Windows ที่อิง Qt / C++ ครับ!
จนกว่าจะถึงวันที่ผมจะสามารถพัฒนา iOS app ด้วยแล็ปท็อป Linux ของตัวเองได้!
การเดินทางเพื่อกลับไปใช้แล็ปท็อป Linux ของผมก็ยังคงดำเนินต่อไปในวันนี้
ขอบคุณครับ
(+ จริง ๆ ผมไม่แน่ใจว่าควรเอาลิงก์ Google Drive มาแปะที่นี่ตรง ๆ ได้ไหม ก็เลยขอลงเป็นลิงก์ไปยัง โพสต์บน X ที่เคยใช้แนะนำไว้ก่อนหน้านี้ แทนก่อนครับ..!)
- ลิงก์ Google Drive ของเวอร์ชันทดสอบแรก: https://drive.google.com/drive/folders/1r4m7lGZ-f988dp_piLAEwlJRLPODPNQq?usp=drive_link
(++ ระหว่างพัฒนา Noctiluca ยังมีของแถม(?) ที่ทำขึ้นจากการ vibe coding ด้วย ฝากด้วยนะครับ..!)
- swift-msquic: โมดูล wrapper ที่ทำขึ้นเพื่อให้ใช้ MsQuic กับ Swift บน iOS / macOS ได้ง่ายขึ้นครับ!
- Xuanxue: โมดูลที่ช่วยให้สามารถทำการลงลายเซ็น / ตรวจสอบลายเซ็นด้วย SSH key ใน Swift ได้ครับ! ผมขี้เกียจมากจนอยากให้ทุกอย่างทำสำเร็จรูป เลยตั้งชื่อนี้ครับ!
8 ความคิดเห็น
ยอดเยี่ยมมาก!! 👍🏻
ผมใช้ Parsec
ถ้าตัดข้อจำกัดที่ต้องใช้จอขนาดเท่ากันออกไป ก็น่าจะเป็นเครื่องมือรีโมตเข้าถึงที่ดีที่สุดเลยครับ
ส่วนที่ iPad ใช้ไม่ได้ สำหรับผมไม่ได้อยู่ในประเด็นที่สนใจอยู่แล้ว
ผมก็ใช้ parsec เหมือนกัน แต่พอรู้ว่ามือถือใช้ไม่ได้จริง ๆ ก็เหมือนจะช็อกอยู่นิดหน่อยนะครับ ไม่นึกว่าจะเป็นแบบนั้น... ฮ่าๆ
จริง ๆ แล้วสำหรับการพัฒนา iOS/macOS ก็ดูเหมือนว่าการต่อ Mac mini หรือ MacBook ผ่าน KVM แล้วใช้งานจะดีที่สุด แต่ก็แอบยุ่งเหมือนกันครับ
ถ้าผมยังพัฒนา Noctiluca ต่อไปได้ จริง ๆ แล้วผมอยากสร้างฟีเจอร์ที่คล้ายกับแนวคิด 'RemoteApp' ของ Microsoft RDP ด้วย และฟีเจอร์ USB redirection ด้วย!
ถ้าเสียบ iPhone เข้ากับ ThinkPad ของผมแล้วให้ Mac ที่อยู่คนละห้องมองเห็นเหมือนเสียบอยู่ตรงนั้นได้พอดี แถมยังดึงมาใช้เฉพาะหน้าต่าง Xcode ได้เป๊ะ ๆ โดยไม่ต้องใช้ 'เต็มหน้าจอ' ของ Mac ผมคงมีความสุขมากเลยครับ
ก็เลยกำลังออกแบบ/พัฒนาฟีเจอร์ที่เกี่ยวข้องอยู่ด้วยครับ..!
ตอนนี้ยังไม่ได้จัดระเบียบอะไรไว้เลย เลยมีให้ดูได้แค่นี้เองครับ T_T
https://gist.github.com/unstabler/25679baab3a65a3c19f747c38f30c1b3
ได้เปลี่ยนลิงก์ต้นฉบับเป็นลิงก์ Google Drive แล้ว และได้ใส่ลิงก์โพสต์ X ไว้ภายในบทความแล้ว
ผมเคยคิดอยู่ว่าจะเข้าถึง Mac ยังไงดี ก็มีแค่ความคิดลาง ๆ ว่าน่าจะพอทำได้ด้วย jetkvm กับ tailscale
ถ้าเป็นวิธีในบทความนี้ ก็คงทำได้แม้ไม่มี kvm นะครับ