[{"data":1,"prerenderedAt":418},["ShallowReactive",2],{"courses-list":3,"course-rust-webrtc-p2p":185},[4,21,163,173],{"slug":5,"title":6,"shortDescription":7,"description":8,"category":9,"level":10,"totalDuration":11,"totalLessons":12,"tags":13,"updatedAt":14,"rating":12,"reviewCount":12,"thumbnail":15,"instructor":16,"lessons":20},"rust-voip-freeswitch-media-server","Rust VoIP: Freeswitch Media Server","Khám phá sức mạnh của FreeSWITCH trong việc xây dựng hệ thống VoIP production-ready. Từ nền tảng WebRTC P2P, bạn sẽ tiến tới kiến trúc Media Server có khả năng scale lớn, xử lý hàng nghìn cuộc gọi đồng thời.","FreeSWITCH mang lại những tính năng mạnh mẽ:\n\n1. Xử lý SIP call linh hoạt (inbound\u002Foutbound, gateway, trunking)\n2. Hỗ trợ codec đa dạng (Opus, G.711, G.729…)\n3. Conference (multi-party call) với khả năng scale cao\n4. IVR (Interactive Voice Response) tùy biến bằng XML\u002FLua\n5. Ghi âm cuộc gọi (call recording) và media processing\n6. Event Socket (ESL) cho phép control realtime từ backend (Rust, Java…)\n7. Tích hợp WebRTC ↔ SIP bridge\n8. Load balancing & clustering cho hệ thống lớn\n\nPhù hợp để xây dựng các hệ thống như call center, voice app, hoặc bridge giữa WebRTC và hạ tầng viễn thông truyền thống.","Backend","Advanced","4",0,"[\"freeswitch\",\"rust\",\"bytebuffer\"]","2026-04-11 13:07:57","https:\u002F\u002Fpub-cd0f133a6f7640ca947255f10fb6c328.r2.dev\u002Fthumbnails\u002F1775912828865-ef7f2462-4ba9-4256-b115-8ee175030134.png",{"name":17,"title":18,"bio":19},"ByteBuffer","Coder cỏ tại DTS Group và IPA Solutions","Chuyên gia về Rust và hệ thống VoIP\u002FWebRTC. Nhiều năm kinh nghiệm xây dựng các hệ thống real-time communication với hiệu năng cao và độ trễ thấp.",[],{"slug":22,"title":23,"shortDescription":24,"description":25,"category":9,"level":26,"totalDuration":27,"totalLessons":28,"tags":29,"updatedAt":30,"rating":31,"reviewCount":32,"thumbnail":33,"instructor":34,"lessons":35},"rust-webrtc-p2p","WebRTC Peer to Peer với Rust","Xây dựng Signaling Server bằng Rust để thiết lập cuộc gọi audio\u002Fvideo P2P giữa hai trình duyệt với WebRTC.","Khóa học thực chiến giúp bạn xây dựng từ đầu một Signaling Server bằng Rust, xử lý các cuộc gọi audio\u002Fvideo trực tiếp giữa hai trình duyệt thông qua WebRTC Peer-to-Peer mà không cần Media Server.\n\nBạn sẽ nắm vững kiến trúc WebRTC signaling, cách trao đổi SDP Offer\u002FAnswer và ICE Candidates giữa các peer thông qua WebSocket. Khóa học sử dụng Axum + Tokio cho backend, MongoDB để lưu trữ dữ liệu, và JWT để xác thực người dùng.\n\nĐây là Phần 1 trong series 7 phần về Lập trình Rust với VoIP, bao gồm: WebRTC P2P, Media Server (Janus, LiveKit, Kurento, Asterisk, FreePBX), và hệ thống CRM\u002FQueue\u002Fnhạc chờ\u002Fchuyển tiếp cuộc gọi.\n\nYêu cầu tiên quyết: Kiến thức cơ bản về Rust (Ownership, Lifetimes, Traits, Async\u002FAwait).","Intermediate","5 giờ",16,"[\"Rust\",\"WebRTC\",\"VoIP\",\"P2P\",\"Axum\",\"Tokio\",\"WebSocket\",\"MongoDB\",\"JWT\"]","2026-04-10 00:15:52",4.8,320,"https:\u002F\u002Fpub-cd0f133a6f7640ca947255f10fb6c328.r2.dev\u002Fthumbnails\u002F1775495865592-4cdf9be1-d9ed-459c-b59b-178041ba66b5.png",{"name":17,"title":18,"bio":19},[36,44,52,60,68,76,84,92,100,108,116,124,132,140,148,156],{"slug":37,"title":38,"description":39,"duration":40,"youtubeId":41,"order":42,"thumbnail":43},"gioi-thieu-khoa-hoc","Rust WebRTC P2P #1 - Giới thiệu khóa học","Chào mừng bạn đến với series Rust VoIP! Trong bài mở đầu, bạn sẽ nắm được bức tranh toàn cảnh: mục tiêu xây dựng Signaling Server bằng Rust, kiến trúc P2P (Browser ↔ Rust Server ↔ Browser), tech stack sử dụng (Axum, Tokio, WebSocket, MongoDB, JWT), và lộ trình 7 phần của toàn bộ series từ WebRTC đến CRM\u002FQueue.","5:29","Gj9wYJ57qfA",1,"https:\u002F\u002Fpub-cd0f133a6f7640ca947255f10fb6c328.r2.dev\u002Fthumbnails\u002F1775495174815-9cda6d98-4692-4476-815d-0437bad01c59.webp",{"slug":45,"title":46,"description":47,"duration":48,"youtubeId":49,"order":50,"thumbnail":51},"voip-la-gi-webrtc-la-gi","Rust WebRTC P2P #2 - VoIP là gì? WebRTC là gì?","Hiểu bản chất VoIP — công nghệ truyền thoại\u002Fvideo qua mạng IP đứng sau Skype, Zoom, Google Meet. Sau đó khám phá WebRTC — bộ tiêu chuẩn cho phép trình duyệt giao tiếp trực tiếp peer-to-peer: media đi thẳng giữa hai browser, server chỉ làm nhiệm vụ signaling duy nhất.","7:13","Ih1lcfZwzeE",2,"https:\u002F\u002Fpub-cd0f133a6f7640ca947255f10fb6c328.r2.dev\u002Fthumbnails\u002F1775495227568-62ba7951-3528-4c10-973d-13f726732f56.webp",{"slug":53,"title":54,"description":55,"duration":56,"youtubeId":57,"order":58,"thumbnail":59},"sip-overview-why-rust","Rust WebRTC P2P #3 - SIP overview + Why choose Rust","So sánh SIP (giao thức signaling truyền thống trong telephony) với WebRTC signaling nhẹ hơn, phù hợp browser. Đi sâu vào 4 lý do chọn Rust: hiệu năng không GC pause, safety ngăn data race từ compile time (Arc, DashMap, mpsc), async mạnh mẽ với Tokio, và cơ chế bắt buộc xử lý lỗi — yếu tố sống còn khi server chịu hơn 100K cuộc gọi\u002Fngày.","3:23","SVOsqmEs2SQ",3,"https:\u002F\u002Fpub-cd0f133a6f7640ca947255f10fb6c328.r2.dev\u002Fthumbnails\u002F1775495301130-3cedf79b-354f-4035-bad9-1d2166099956.webp",{"slug":61,"title":62,"description":63,"duration":64,"youtubeId":65,"order":66,"thumbnail":67},"install-rust-rustrover-cargo","Rust WebRTC P2P #4 - Install Rust + RustRover + Cargo Commands","Thực hành cài đặt Rust Toolchain qua rustup.rs trên Windows\u002FLinux\u002FmacOS và xác thực bằng rustc, cargo, rustup. Khám phá RustRover — IDE chuyên biệt giúp code Rust nhanh hơn VS Code. Làm quen 4 lệnh Cargo thiết yếu: cargo new, cargo build, cargo build --release và cargo run.","7:36","Pzj8FiXvmwo",4,"https:\u002F\u002Fpub-cd0f133a6f7640ca947255f10fb6c328.r2.dev\u002Fthumbnails\u002F1775495334946-b2e8a644-6797-4a0a-8aa8-bc9f6926fb1b.webp",{"slug":69,"title":70,"description":71,"duration":72,"youtubeId":73,"order":74,"thumbnail":75},"hello-world-tokio-runtime-cargo-toml","Rust WebRTC P2P #5 - Hello World + Tokio Runtime + Cargo.toml","Khám phá Cargo.toml — trái tim quản lý dependencies của mọi dự án Rust. Khai báo các thư viện sẽ dùng xuyên suốt khóa học: Axum, Tokio, Serde, DashMap, UUID, Log4rs, Anyhow. Cấu hình Tokio Runtime biến hàm main thành async, tận dụng thread pool xử lý hàng nghìn kết nối đồng thời. Kết thúc bằng việc chạy thành công project Hello World đầu tiên.","5:13","HIcUJYrI_7U",5,"https:\u002F\u002Fpub-cd0f133a6f7640ca947255f10fb6c328.r2.dev\u002Fthumbnails\u002F1775495371395-6e99fb8b-7734-479f-9386-6a4bc75d6cff.webp",{"slug":77,"title":78,"description":79,"duration":80,"youtubeId":81,"order":82,"thumbnail":83},"axum-server-config-loading","Rust WebRTC P2P #6 - Axum Server + Config Loading","Chào mừng bạn quay trở lại với series WebRTC Peer-to-Peer (P2P) với Rust\n\nTrong phần 6 này:\nChúng ta bắt đầu xây dựng backend\n→ Thiết lập hệ thống cấu hình (Config)\n→ Khởi tạo Axum HTTP Server","42:44","DmHrozL4its",6,"https:\u002F\u002Fpub-cd0f133a6f7640ca947255f10fb6c328.r2.dev\u002Fthumbnails\u002F1775495482671-3d9accc9-dbe7-45e4-bdaa-2b4361dc3b34.webp",{"slug":85,"title":86,"description":87,"duration":88,"youtubeId":89,"order":90,"thumbnail":91},"mongodb-logging-with-log4rs","Rust WebRTC P2P #7 - MongoDB + Logging with log4rs","Chào mừng bạn quay trở lại với series WebRTC Peer-to-Peer (P2P) bằng Rust\n\nTrong video 7 này:\nChúng ta hoàn thiện nền tảng Signaling Server với 2 phần quan trọng:\n- Cấu hình MongoDB\n- Thiết lập hệ thống Logging với log4rs","15:44","K9D_tT1iJQ8",7,"https:\u002F\u002Fpub-cd0f133a6f7640ca947255f10fb6c328.r2.dev\u002Fthumbnails\u002F1775495650431-ec57a6c7-3937-48b5-ac5d-7c2b105d32b4.webp",{"slug":93,"title":94,"description":95,"duration":96,"youtubeId":97,"order":98,"thumbnail":99},"create-websocket-endpoint-with-axum","Rust WebRTC P2P #8 - Create WebSocket Endpoint with Axum","WebSocket là giao thức giữ kết nối hai chiều liên tục — khác HTTP request\u002Fresponse. Trong signaling server, mỗi user kết nối WebSocket và giữ kết nối suốt session\n","15:45","dX4phlMs4b4",8,"https:\u002F\u002Fpub-cd0f133a6f7640ca947255f10fb6c328.r2.dev\u002Fthumbnails\u002F1775574741518-39f6b0a5-0899-4775-bae8-2c07da84f8ee.webp",{"slug":101,"title":102,"description":103,"duration":104,"youtubeId":105,"order":106,"thumbnail":107},"connectionstate-client-online-management","Rust WebRTC P2P #9 - ConnectionState — Client Online management","Chào mừng bạn quay trở lại với series WebRTC Peer-to-Peer (P2P) bằng Rust\n\nTrong phần 9 này:\nChúng ta xây dựng một thành phần cốt lõi của Signaling Server\n→ Quản lý trạng thái kết nối (Connection State)\n→ Quản lý danh sách user đang online","8:46","DSWewq_Ft48",9,"https:\u002F\u002Fpub-cd0f133a6f7640ca947255f10fb6c328.r2.dev\u002Fthumbnails\u002F1775657276388-20da4fcb-6126-4224-b333-16adac68afe2.webp",{"slug":109,"title":110,"description":111,"duration":112,"youtubeId":113,"order":114,"thumbnail":115},"message-routing-dispatcher-pattern","Rust WebRTC P2P #10 - Message Routing — Dispatcher Pattern","Trong phần 10 này, chúng ta sẽ tiến hành chuẩn hóa cách thức trao đổi dữ liệu giữa Client và Server thông qua WebSocket bằng cách xây dựng hệ thống Message Routing và áp dụng Dispatcher Pattern.","9:37","w1o6z46nbgs",10,"https:\u002F\u002Fpub-cd0f133a6f7640ca947255f10fb6c328.r2.dev\u002Fthumbnails\u002F1775726962635-205922a3-435d-455d-bf21-f41c57ca7436.webp",{"slug":117,"title":118,"description":119,"duration":120,"youtubeId":121,"order":122,"thumbnail":123},"nginx-config-deploy-live-on-vps","Rust WebRTC P2P #11 - Nginx Config + Deploy Live on VPS","Chúng ta đưa Signaling Server từ local lên VPS thực tế\n→ Cấu hình domain\n→ Setup Nginx\n→ Thiết lập HTTPS (SSL)","16:28","CQKW3uUgm_Y",11,"https:\u002F\u002Fpub-cd0f133a6f7640ca947255f10fb6c328.r2.dev\u002Fthumbnails\u002F1775831831726-148865ca-dcbf-4682-9e0b-41435a17be0d.jpg",{"slug":125,"title":126,"description":127,"duration":128,"youtubeId":129,"order":130,"thumbnail":131},"user-model-mongodb-queries","Rust WebRTC P2P #12 - User Model + MongoDB Queries","Trong phần này, mình bắt đầu xây dựng Data Layer cho hệ thống, bao gồm User Model và các truy vấn MongoDB. Đây là nền tảng quan trọng để triển khai Login và Authentication cho cả REST API và WebSocket server.","4:34","Ov54lD682Kw",12,"https:\u002F\u002Fpub-cd0f133a6f7640ca947255f10fb6c328.r2.dev\u002Fthumbnails\u002F1775911639340-b03d16cc-a0a8-4233-a5e1-50a94743f954.png",{"slug":133,"title":134,"description":135,"duration":136,"youtubeId":137,"order":138,"thumbnail":139},"login-service-jwt-argon2","Rust WebRTC P2P #13 - Login Service + JWT + Argon2","Trong phần 13 này, chúng ta triển khai một trong những tính năng quan trọng nhất của backend: Login Service. Mục tiêu là xây dựng cơ chế xác thực an toàn, sử dụng JWT và các tiêu chuẩn bảo mật hiện đại để bảo vệ thông tin người dùng.","22:03","sICzdbRpwnw",13,"https:\u002F\u002Fpub-cd0f133a6f7640ca947255f10fb6c328.r2.dev\u002Fthumbnails\u002F1775983603748-ad6186f1-5c2f-4cf2-8e07-29b6880a9c55.png",{"slug":141,"title":142,"description":143,"duration":144,"youtubeId":145,"order":146,"thumbnail":147},"auth-middleware-http-websocket-auth-flow","Rust WebRTC P2P #14 - Auth Middleware HTTP + WebSocket Auth Flow","Trong phần 14 này, chúng ta thực hiện một bước rất quan trọng để bảo vệ hệ thống: xây dựng Middleware cho HTTP Server và thiết lập luồng xác thực cho WebSocket. Đây là lớp bảo vệ giúp đảm bảo chỉ những người dùng hợp lệ mới có thể truy cập API và thiết lập kết nối signaling.","50:35","Maz-uKSzoto",14,"https:\u002F\u002Fpub-cd0f133a6f7640ca947255f10fb6c328.r2.dev\u002Fthumbnails\u002F1776072985484-4936c485-dfcb-4919-8b83-6e364e6a1255.webp",{"slug":149,"title":150,"description":151,"duration":152,"youtubeId":153,"order":154,"thumbnail":155},"demo-login-websocket-auth-tu-postman","Rust WebRTC P2P #15 - Demo Login + WebSocket Auth từ Postman","Trong phần 15 này, chúng ta thực hiện demo toàn bộ quy trình xác thực đã xây dựng ở các phần trước. Sử dụng Postman để mô phỏng client, chúng ta sẽ kiểm tra cách server xử lý token thông qua cả HTTP và WebSocket.","5:12","8GmuMOpl_JQ",15,"https:\u002F\u002Fpub-cd0f133a6f7640ca947255f10fb6c328.r2.dev\u002Fthumbnails\u002F1776176649415-701f3222-2da2-43a7-b9ad-7f52a41386b4.webp",{"slug":157,"title":158,"description":159,"duration":160,"youtubeId":161,"order":28,"thumbnail":162},"state-pattern-p2pcallstatehandler-trait","Rust WebRTC P2P #16 - State Pattern — P2PCallStateHandler Trait","Trong phần 16 này, chúng ta đi vào một thành phần rất quan trọng trong kiến trúc của signaling server: State Pattern. Đây là phần “trái tim” giúp điều khiển toàn bộ luồng xử lý của một cuộc gọi, từ lúc bắt đầu cho đến khi kết thúc.","12:04","6BrjxQmROU0","https:\u002F\u002Fpub-cd0f133a6f7640ca947255f10fb6c328.r2.dev\u002Fthumbnails\u002F1776240875283-0880cb67-c8fd-4f77-975f-0d05d3fa6394.png",{"slug":164,"title":165,"shortDescription":166,"description":167,"category":9,"level":10,"totalDuration":11,"totalLessons":12,"tags":168,"updatedAt":169,"rating":12,"reviewCount":12,"thumbnail":170,"instructor":171,"lessons":172},"rust-voip-asterisk-media-server","Rust VoIP: Asterisk Media Server","Làm chủ công nghệ VoIP với khóa học \"Lập trình VoIP với Rust: Asterisk Media Server\". Vượt qua những giới hạn của WebRTC P2P để xây dựng hệ thống tổng đài và media server chuyên nghiệp. Khám phá sức mạnh của Asterisk kết hợp cùng Rust để xử lý các bài toán quy mô lớn, từ gọi App-to-App đến tích hợp hệ thống SIP và Auto Callout mạnh mẽ.","Từ WebRTC P2P đến Hệ thống Media Server thực thụ\nNếu bạn đã hiểu cách kết nối trực tiếp giữa các trình duyệt qua WebRTC P2P, bạn sẽ nhận ra rằng mô hình đó chỉ là bước khởi đầu\n. Để xây dựng những ứng dụng Voice IP có thể scale lớn và dùng trong sản xuất (production), chúng ta cần một giải pháp mạnh mẽ hơn để giải quyết 4 vấn đề cốt lõi của P2P:\n\n- Khả năng mở rộng không giới hạn: Thay vì để 10 người tạo ra 90 kết nối chéo gây nghẽn mạng\n, chúng ta sẽ tập trung mọi luồng media về một điểm duy nhất.\n- Tối ưu tài nguyên thiết bị: Giảm tải tối đa CPU và pin cho người dùng mobile bằng cách không bắt thiết bị phải upload nhiều luồng media cùng lúc\n- Ghi âm tập trung (Centralized Recording): Dễ dàng lưu trữ và quản lý mọi cuộc gọi ngay tại server, điều mà mô hình P2P gần như không thể thực hiện\n- Vượt qua rào cản NAT: Xử lý triệt để vấn đề NAT nghiêm ngặt (NAT strict) vốn chiếm tới 15% người dùng, giúp kết nối luôn thông suốt mà không làm tăng chi phí relay phức tạp.\n\nTại sao lại là Asterisk và Rust?\nTrong khóa học này, chúng ta sẽ sử dụng Asterisk — một tượng đài trong thế giới VoIP — làm Media Server trung gian. Thay vì để các peer kết nối trực tiếp, tất cả client sẽ gửi dữ liệu lên Asterisk để server xử lý và phân phối lại.\n\nViệc kết hợp với ngôn ngữ Rust mang lại hiệu suất tối ưu và tính an toàn cao khi xây dựng các logic điều khiển cuộc gọi. Asterisk đóng vai trò là \"trái tim\" xử lý WebRTC, signaling và networking, giúp hệ thống dễ dàng scale lên hàng trăm, thậm chí hàng nghìn người dùng\n\nNội dung thực hành trọng tâm\nKhóa học sẽ dẫn dắt bạn đi từ những bước cơ bản nhất đến khi hoàn thiện một hệ thống Voice IP thực tế với đầy đủ các tính năng\n\n1. Call App to App: Lập trình cuộc gọi giữa hai ứng dụng WebRTC thông qua Asterisk.\n2. Call App to SIP: Kết nối thế giới Web\u002FApp với hệ thống tổng đài SIP truyền thống.\n3. Call SIP to App: Nhận cuộc gọi ngược lại từ các đầu số SIP về trình duyệt hoặc ứng dụng di động.\n4. Auto Callout: Xây dựng hệ thống tự động gọi ra chuyên nghiệp phục vụ cho thông báo hoặc CSKH.\n\nKết quả đạt được\nToàn bộ khóa học được thiết kế để bạn có thể tự mình xây dựng, vận hành và triển khai một hệ thống VoIP thực tế\n. Đây không chỉ là lý thuyết, mà là những kỹ năng thực chiến để bạn làm chủ công nghệ truyền thông thời gian thực.","[\"asterisk\",\"rust\",\"b2bua\",\"kamailio\"]","2026-04-09 14:19:52","https:\u002F\u002Fpub-cd0f133a6f7640ca947255f10fb6c328.r2.dev\u002Fthumbnails\u002F1775728872332-8cae7a0a-719d-4c6f-bf67-8829e2a9cf42.png",{"name":17,"title":18,"bio":19},[],{"slug":174,"title":175,"shortDescription":176,"description":177,"category":9,"level":26,"totalDuration":178,"totalLessons":12,"tags":179,"updatedAt":180,"rating":66,"reviewCount":181,"thumbnail":182,"instructor":183,"lessons":184},"rust-voip-janus-media-server","Rust VoIP: Janus Media Server","Chinh phục VoIP với khóa học \"Lập trình VoIP với Rust: Janus Media Server\". Bước tiếp từ nền tảng WebRTC P2P để xây dựng các hệ thống Media Server quy mô lớn, có khả năng scale thực tế và dùng trong production. Bạn sẽ làm chủ Janus Audiobridge để giải quyết triệt để các bài toán về băng thông, ghi âm tập trung và kết nối đa phương thức từ App-to-App đến SIP","Nâng tầm ứng dụng WebRTC của bạn lên quy mô Production\nNếu bạn đã hiểu cách các trình duyệt kết nối trực tiếp qua WebRTC P2P, thì đây chính là bước đi tiếp theo để đưa ứng dụng của bạn vào thực tế\n\nMô hình P2P rất tuyệt vời cho các kết nối đơn giản, nhưng khi đối mặt với các bài toán lớn hơn, nó bộc lộ 4 hạn chế nghiêm trọng:\n1. Khả năng mở rộng: Với 10 người dùng, hệ thống P2P cần tới 90 kết nối trực tiếp, khiến việc mở rộng là gần như không thể\n2. Tốn tài nguyên: Client phải upload đồng thời nhiều luồng media, gây ngốn CPU và nhanh hết pin, đặc biệt là trên thiết bị di động\n3. Không thể ghi âm tập trung: Media truyền trực tiếp giữa các peer nên không có cách nào ghi lại cuộc gọi một cách tập trung tại server\n4. Vấn đề NAT: Khoảng 15% người dùng gặp lỗi kết nối do NAT nghiêm ngặt\n\nGiải pháp đột phá với Janus Media Server\nKhóa học này sẽ hướng dẫn bạn sử dụng Janus Media Server – một thành phần trung gian mạnh mẽ để thay thế mô hình kết nối trực tiếp\n. Thay vì gửi dữ liệu cho nhau, tất cả client sẽ gửi media lên server để server xử lý và phân phối lại\nChúng ta sẽ tập trung sâu vào kiến trúc Modular của Janus, đặc biệt là Audiobridge plugin\nCơ chế Mixing: Server sẽ trộn (mix) các luồng audio lại thành một luồng duy nhất, giúp giảm đáng kể băng thông và tải cho phía người dùng\n\nKhả năng Scale: Hệ thống có thể đáp ứng hàng trăm, thậm chí hàng nghìn người dùng cùng lúc\n\nBạn sẽ học được gì?\nXuyên suốt khóa học, chúng ta sẽ cùng nhau lập trình bằng ngôn ngữ Rust để xây dựng một hệ thống hoàn chỉnh với các tính năng thực tế nhất:\n\nCall App to App: Kết nối giọng nói giữa hai ứng dụng WebRTC.\nCall App to SIP: Tích hợp gọi từ Web\u002FApp sang hệ thống tổng đài SIP truyền thống.\nCall SIP to App: Nhận cuộc gọi ngược lại từ hệ thống SIP về Web\u002FApp.\nAuto Callout: Phát triển hệ thống tự động gọi ra chuyên nghiệp.\n\nMục tiêu khóa học\nToàn bộ nội dung được thiết kế theo lộ trình từ cơ bản đến nâng cao, giúp bạn không chỉ hiểu về mặt lý thuyết mà còn có đủ kỹ năng để tự tay xây dựng một hệ thống Voice IP thực tế.","3","[\"janus\",\"kamailio\",\"rtpengine\",\"b2bua\",\"rust\",\"bytebuffer\"]","2026-04-09 14:18:48",190,"https:\u002F\u002Fpub-cd0f133a6f7640ca947255f10fb6c328.r2.dev\u002Fthumbnails\u002F1775728211540-3d1f7ec5-ba21-4176-9aa3-ca9775e232ba.png",{"name":17,"title":18,"bio":19},[],{"slug":22,"title":23,"shortDescription":24,"description":25,"category":9,"level":26,"totalDuration":27,"totalLessons":28,"tags":29,"updatedAt":30,"rating":31,"reviewCount":32,"thumbnail":33,"instructor":186,"lessons":187},{"name":17,"title":18,"bio":19},[188,211,228,245,262,279,286,291,308,324,343,361,375,385,402,409],{"slug":37,"title":38,"description":39,"duration":40,"youtubeId":41,"order":42,"thumbnail":43,"sections":189},[190,193,196,199,202,205,208],{"title":191,"content":192},"Giới thiệu khóa học","Chào mừng bạn đến với khóa học Lập trình Rust với VoIP - Phần 1: WebRTC Peer-to-Peer.\n\nĐây là series thực chiến giúp bạn xây dựng từ đầu một Signaling Server → Xử lý các cuộc gọi audio\u002Fvideo trực tiếp giữa hai trình duyệt → Không cần thông qua Media Server.",{"title":194,"content":195},"Nội dung chính trong video","• Mục tiêu khóa học: Xây dựng hoàn chỉnh một Signaling Server bằng Rust → Thiết lập kết nối P2P giữa hai trình duyệt.\n\n• Kiến trúc hệ thống: Browser A gửi SDP Offer qua Rust Server → chuyển tiếp đến Browser B. Trao đổi ICE Candidates để tìm đường kết nối tối ưu.\n\n• Media Exchange (RTP): Dữ liệu audio\u002Fvideo truyền trực tiếp giữa 2 browser. Rust Server không can thiệp vào luồng media.",{"title":197,"content":198},"Kiến trúc tổng thể","\u003Cp>Browser A ↔ Rust Server (WebSocket) ↔ Browser B Browser A ⇄ P2P Media ⇄ Browser B Lưu ý: Media không đi qua server → Chỉ signaling đi qua Rust backend.\u003C\u002Fp>\u003Cfigure class=\"image-figure\" style=\"margin: 32px 0px; text-align: center; display: flex; flex-direction: column; align-items: center;\">\u003Cimg src=\"https:\u002F\u002Fpub-cd0f133a6f7640ca947255f10fb6c328.r2.dev\u002Fthumbnails\u002F1775885347095-841c25ac-be6b-43bc-8995-61a6a9ea4b65.png\" alt=\"\" style=\"max-width: 100%; height: auto; border-radius: 6px;\">\u003Cfigcaption style=\"margin-top: 12px; font-size: 14px; color: rgb(96, 98, 102); font-style: italic; text-align: center; max-width: 80%;\">Mô hình Peer to Peer\u003C\u002Ffigcaption>\u003C\u002Ffigure>\u003Cp>\u003C\u002Fp>",{"title":200,"content":201},"Tech stack sử dụng","• Rust\n• Axum + Tokio (backend)\n• WebSocket\n• MongoDB\n• JWT Authentication",{"title":203,"content":204},"Lộ trình series (7 phần)","• Phần 1 (hiện tại): WebRTC Peer-to-Peer\n• Phần 2 - 6: Làm việc với Media Server — Janus, LiveKit, Kurento, Asterisk, FreePBX\n• Phần 7: CRM, Queue, nhạc chờ, chuyển tiếp cuộc gọi",{"title":206,"content":207},"Kết quả sau khóa học","Bạn sẽ có một signaling server hoàn chỉnh, cho phép 2 browser thực hiện audio\u002Fvideo call P2P thực tế.",{"title":209,"content":210},"Yêu cầu tiên quyết","Bạn nên có kiến thức cơ bản về Rust:\n• Ownership\n• Lifetimes\n• Traits\n• Async\u002FAwait",{"slug":45,"title":46,"description":47,"duration":48,"youtubeId":49,"order":50,"thumbnail":51,"sections":212},[213,216,219,222,225],{"title":214,"content":215},"VoIP là gì?","VoIP (Voice over Internet Protocol) là công nghệ truyền thoại và video qua mạng IP thay vì mạng điện thoại truyền thống (PSTN).\n\n• Ứng dụng phổ biến: Skype, Zoom, Google Meet, Discord, WhatsApp Call\n• Ưu điểm: Chi phí thấp, tích hợp dễ dàng vào ứng dụng web\u002Fmobile, hỗ trợ cả audio và video\n• Giao thức nền tảng: RTP (Real-time Transport Protocol) để truyền media, SIP hoặc WebRTC để signaling",{"title":217,"content":218},"WebRTC là gì?","WebRTC (Web Real-Time Communication) là bộ tiêu chuẩn mở cho phép trình duyệt giao tiếp trực tiếp peer-to-peer mà không cần plugin.\n\n• Được hỗ trợ native trên Chrome, Firefox, Safari, Edge\n• Ba thành phần chính: MediaStream (truy cập camera\u002Fmic), RTCPeerConnection (kết nối P2P), RTCDataChannel (truyền dữ liệu)\n• Media đi thẳng giữa hai browser — server chỉ làm nhiệm vụ signaling duy nhất",{"title":220,"content":221},"So sánh VoIP truyền thống vs WebRTC","• VoIP truyền thống: Cần cài phần mềm client, sử dụng SIP để signaling, thường cần Media Server trung gian\n• WebRTC: Chạy trực tiếp trên trình duyệt, signaling linh hoạt (WebSocket, HTTP), P2P trực tiếp giữa các peer\n\n→ WebRTC phù hợp hơn cho ứng dụng web hiện đại vì không yêu cầu cài đặt thêm và tận dụng được hạ tầng trình duyệt.",{"title":223,"content":224},"Luồng hoạt động của WebRTC","1. Browser A tạo SDP Offer (mô tả khả năng media: codec, resolution...)\n2. Gửi Offer qua Signaling Server đến Browser B\n3. Browser B tạo SDP Answer và gửi ngược lại\n4. Cả hai trao đổi ICE Candidates để tìm đường kết nối tối ưu (STUN\u002FTURN)\n5. Kết nối P2P được thiết lập → Media truyền trực tiếp",{"title":226,"content":227},"Vai trò của Signaling Server","Signaling Server là \"người mai mối\" — giúp hai browser tìm thấy nhau và thỏa thuận kết nối.\n\n• Chuyển tiếp SDP Offer\u002FAnswer giữa các peer\n• Chuyển tiếp ICE Candidates\n• Quản lý trạng thái phòng\u002Fcuộc gọi\n• Không xử lý media — chỉ xử lý metadata\n\n→ Đây chính là thứ chúng ta sẽ xây dựng bằng Rust trong khóa học này.",{"slug":53,"title":54,"description":55,"duration":56,"youtubeId":57,"order":58,"thumbnail":59,"sections":229},[230,233,236,239,242],{"title":231,"content":232},"SIP Overview","SIP (Session Initiation Protocol) là giao thức signaling truyền thống trong hệ thống telephony.\n\n• Được dùng rộng rãi trong VoIP enterprise: tổng đài, call center, IP PBX\n• Hoạt động theo mô hình request\u002Fresponse tương tự HTTP\n• Các method chính: INVITE (mời gọi), ACK (xác nhận), BYE (kết thúc), REGISTER (đăng ký)\n• Nhược điểm: Phức tạp, nhiều header, khó triển khai trên web browser",{"title":234,"content":235},"SIP vs WebRTC Signaling","• SIP: Giao thức chuẩn hóa, cứng nhắc, phù hợp hệ thống telephony truyền thống\n• WebRTC Signaling: Không quy định giao thức cụ thể — bạn tự chọn (WebSocket, HTTP, MQTT...)\n\n→ WebRTC linh hoạt hơn, nhẹ hơn, và phù hợp với ứng dụng web hiện đại. SIP vẫn quan trọng khi cần tích hợp với hạ tầng telephony có sẵn.",{"title":237,"content":238},"Tại sao chọn Rust?","4 lý do chọn Rust để xây dựng Signaling Server:\n\n1. Hiệu năng cao: Không có Garbage Collector → Không bị GC pause, latency ổn định — yếu tố sống còn cho real-time communication.\n\n2. Memory Safety: Ownership system ngăn data race từ compile time. Sử dụng Arc, DashMap, mpsc channel an toàn khi xử lý hàng nghìn kết nối đồng thời.\n\n3. Async mạnh mẽ: Tokio runtime với thread pool xử lý hàng nghìn WebSocket connection hiệu quả mà không cần tạo thread cho mỗi connection.\n\n4. Error Handling bắt buộc: Result\u003CT, E> buộc dev phải xử lý mọi trường hợp lỗi — giảm thiểu crash trong production khi server chịu hơn 100K cuộc gọi\u002Fngày.",{"title":240,"content":241},"So sánh Rust với các ngôn ngữ khác","• Node.js: Dễ viết, ecosystem lớn, nhưng single-threaded và GC pause có thể gây jitter trong audio\n• Go: Concurrency tốt với goroutine, nhưng GC vẫn là vấn đề với latency nhạy cảm\n• C\u002FC++: Hiệu năng cao nhưng dễ gặp memory leak, buffer overflow, data race\n• Rust: Kết hợp hiệu năng của C\u002FC++ với safety của ngôn ngữ bậc cao → Lựa chọn tối ưu cho VoIP server",{"title":243,"content":244},"Khi nào nên dùng Rust cho VoIP?","• Hệ thống yêu cầu latency thấp và ổn định (\u003C 150ms cho audio call)\n• Server cần xử lý lượng lớn concurrent connections (10K+ WebSocket)\n• Môi trường production cần độ tin cậy cao, ít crash\n• Team sẵn sàng đầu tư learning curve để đổi lấy hiệu năng và safety dài hạn",{"slug":61,"title":62,"description":63,"duration":64,"youtubeId":65,"order":66,"thumbnail":67,"sections":246},[247,250,253,256,259],{"title":248,"content":249},"Cài đặt Rust Toolchain","Cài đặt Rust thông qua rustup — công cụ quản lý phiên bản chính thức:\n\n• Truy cập rustup.rs và chạy lệnh cài đặt cho hệ điều hành của bạn\n• Windows: Tải rustup-init.exe, cần cài Visual Studio Build Tools trước\n• macOS\u002FLinux: curl --proto '=https' --tlsv1.2 -sSf https:\u002F\u002Fsh.rustup.rs | sh\n\nXác thực cài đặt thành công:\n• rustc --version → Kiểm tra compiler\n• cargo --version → Kiểm tra package manager\n• rustup --version → Kiểm tra toolchain manager",{"title":251,"content":252},"RustRover — IDE chuyên biệt cho Rust","RustRover là IDE của JetBrains được thiết kế riêng cho Rust:\n\n• Code completion thông minh, hiểu sâu type system của Rust\n• Inline error highlighting — phát hiện lỗi trước khi compile\n• Debugger tích hợp với breakpoint, watch variables\n• Refactoring tools: rename, extract function, inline variable\n• Tích hợp Cargo commands trực tiếp từ IDE\n\nSo với VS Code + rust-analyzer: RustRover mượt hơn với project lớn, ít cần cấu hình thủ công.",{"title":254,"content":255},"4 lệnh Cargo thiết yếu","Cargo là build system và package manager của Rust:\n\n1. cargo new project_name → Tạo project Rust mới với cấu trúc chuẩn (src\u002Fmain.rs, Cargo.toml)\n2. cargo build → Compile project ở chế độ debug (nhanh compile, chậm runtime)\n3. cargo build --release → Compile với tối ưu hóa cho production (chậm compile, nhanh runtime)\n4. cargo run → Build và chạy project trong một lệnh duy nhất",{"title":257,"content":258},"Cấu trúc project Rust","Sau khi chạy cargo new, bạn sẽ có:\n\nproject_name\u002F\n├── Cargo.toml    → File cấu hình project (tên, version, dependencies)\n├── Cargo.lock    → Lock file cho dependencies (tự sinh)\n└── src\u002F\n    └── main.rs   → Entry point của ứng dụng\n\n• Cargo.toml tương tự package.json (Node.js) hoặc go.mod (Go)\n• src\u002F chứa toàn bộ source code\n• target\u002F (tự sinh sau build) chứa compiled output",{"title":260,"content":261},"Các lệnh Cargo bổ sung","• cargo check → Kiểm tra lỗi compile mà không tạo binary (nhanh hơn cargo build)\n• cargo test → Chạy unit test và integration test\n• cargo doc --open → Sinh documentation và mở trên browser\n• cargo add \u003Ccrate_name> → Thêm dependency vào Cargo.toml\n• cargo update → Cập nhật dependencies lên phiên bản mới nhất",{"slug":69,"title":70,"description":71,"duration":72,"youtubeId":73,"order":74,"thumbnail":75,"sections":263},[264,267,270,273,276],{"title":265,"content":266},"Cargo.toml — Trái tim quản lý dependencies","Cargo.toml là file cấu hình trung tâm của mọi dự án Rust:\n\n• [package]: Tên project, version, edition (2021)\n• [dependencies]: Danh sách thư viện bên ngoài (crates)\n• Mỗi dependency có thể chỉ định version, features cụ thể\n\nVí dụ: tokio = { version = \"1\", features = [\"full\"] } → Sử dụng Tokio với tất cả features bao gồm runtime, io, net, sync, time.",{"title":268,"content":269},"Dependencies sử dụng trong khóa học","Các thư viện sẽ dùng xuyên suốt khóa học:\n\n• Axum — Web framework nhẹ, hiệu năng cao, built on top of Tokio\n• Tokio — Async runtime cho Rust, hỗ trợ multi-threaded task scheduling\n• Serde + serde_json — Serialization\u002FDeserialization (JSON ↔ Rust struct)\n• DashMap — Concurrent HashMap, thread-safe mà không cần Mutex\n• UUID — Sinh unique identifier cho mỗi user\u002Fsession\n• Log4rs — Logging framework linh hoạt với multiple appenders\n• Anyhow — Simplified error handling cho application code",{"title":271,"content":272},"Tokio Runtime là gì?","Tokio là async runtime phổ biến nhất của Rust:\n\n• Biến hàm main thành async với macro #[tokio::main]\n• Multi-threaded runtime: Tận dụng tất cả CPU cores\n• Task scheduling: Hàng nghìn async task chạy đồng thời trên thread pool nhỏ\n• Không tạo OS thread cho mỗi connection → Tiết kiệm memory, xử lý 10K+ connections dễ dàng\n\nSo sánh: Node.js chạy single-threaded event loop, Tokio chạy multi-threaded event loop.",{"title":274,"content":275},"Hello World với Tokio","Chuyển từ synchronous main sang async main:\n\n• Thêm #[tokio::main] macro trước fn main()\n• Hàm main trở thành async fn main() → Có thể dùng .await\n• Tokio tự động tạo thread pool và scheduler\n• Mọi I\u002FO operation (network, file) đều non-blocking\n\nKết quả: Chạy thành công project Hello World đầu tiên với Tokio runtime — nền tảng cho toàn bộ signaling server.",{"title":277,"content":278},"Bước tiếp theo","Sau bài này, bạn đã có:\n• Project Rust với đầy đủ dependencies\n• Tokio runtime sẵn sàng xử lý async operations\n• Hiểu vai trò của từng thư viện trong hệ thống\n\n→ Bài tiếp theo sẽ bắt đầu xây dựng HTTP server với Axum và thiết lập WebSocket endpoint cho signaling.",{"slug":77,"title":78,"description":79,"duration":80,"youtubeId":81,"order":82,"thumbnail":83,"sections":280},[281,283],{"title":282,"content":79},"1. Giới thiệu",{"title":284,"content":285},"2. Nội dung trọng tâm","(1) Thiết lập hệ thống cấu hình (Config Loading)\n\n- Tạo thư mục config và file config.yaml\n- Quản lý các thông số:\n  + host_name\n  + port (4004)\n  + jwt_key\n  + thời gian hết hạn token\n\n- Sử dụng Serde YAML:\n  → Chuyển dữ liệu từ file YAML sang Struct Rust\n\n- Sử dụng once_cell:\n  → Khởi tạo Global Config an toàn\n  → Truy cập config từ mọi nơi trong ứng dụng\n\n--------------------------------------------------\n\n(2) Quản lý AppState\n\n- Định nghĩa AppState:\n  → Lưu trữ và chia sẻ cấu hình toàn hệ thống\n\n- Sử dụng Arc (Atomically Reference Counted):\n  → Clone và truyền AppState vào các routes\n  → Đảm bảo hiệu năng và an toàn\n\n--------------------------------------------------\n\n(3) Khởi tạo Axum HTTP Server\n\n- Sử dụng Tokio TcpListener:\n  → Lắng nghe kết nối tại port đã cấu hình\n\n- Thiết lập router cơ bản\n- Chạy thử HTTP server đầu tiên với Axum\n\n--------------------------------------------------\n\n(4) Tổ chức mã nguồn (Refactoring)\n\n- Tách router ra file riêng: router.rs\n- Tạo thư mục controller:\n  + Ví dụ: auth_controller.rs\n\n→ Chuẩn bị cho các tính năng:\n- Login\n- Authentication",{"slug":85,"title":86,"description":87,"duration":88,"youtubeId":89,"order":90,"thumbnail":91,"sections":287},[288,289],{"title":282,"content":87},{"title":284,"content":290},"(1) Cấu hình MongoDB\n\n- Bổ sung thông tin vào config.yaml:\n  + host\n  + username\n  + password\n  + database name\n\n- Định nghĩa Struct trong Rust:\n  → Ánh xạ chính xác với cấu hình YAML\n\n- Khởi tạo Global MongoDB Client:\n  → Sử dụng tokio::sync::OnceCell\n  → Client tồn tại xuyên suốt vòng đời ứng dụng\n  → Có thể truy cập từ mọi nơi\n\n- Kiểm tra kết nối:\n  → Gửi lệnh ping đến database\n  → Xác nhận kết nối thành công\n\n--------------------------------------------------\n\n(2) Thiết lập Logging với log4rs\n\n- Thay thế println! bằng hệ thống log chuyên nghiệp\n→ Giúp debug và theo dõi hệ thống hiệu quả hơn\n\n- Cấu hình 2 đầu ra chính:\n\nConsole:\n- Hiển thị log trên terminal\n- Format chi tiết:\n  + thời gian\n  + thread\n  + level\n  + file\u002Fline\n\nFile:\n- Ghi log vào file\n- Quan trọng trong môi trường production\n→ Khi không có console để theo dõi\n\n- Xử lý lỗi thiếu thư viện nén log (gzip)\n→ Đảm bảo hệ thống hoạt động ổn định\n\n--------------------------------------------------\n\n3. Kết quả đạt được\n\nSau bài học này, bạn sẽ có:\n\n- Kết nối MongoDB hoàn chỉnh\n- Hệ thống logging chuyên nghiệp\n- Nền tảng backend sẵn sàng cho production\n- Sẵn sàng xử lý logic phức tạp ở các phần tiếp theo",{"slug":93,"title":94,"description":95,"duration":96,"youtubeId":97,"order":98,"thumbnail":99,"sections":292},[293,296,299,302,305],{"title":294,"content":295},"Cơ chế WebSocket","\u003Cp>- Quy trình handshake:\u003Cbr> Client gửi HTTP request\u003Cbr> Server trả về 101 Switching Protocols\u003Cbr> → Nâng cấp lên WebSocket connection\u003Cbr>\u003Cbr>- Dọn dẹp warning trong project\u003Cbr>→ Giữ code sạch trước khi triển khai\u003C\u002Fp>",{"title":297,"content":298},"Triển khai WebSocket với Axum","\u003Cp>- Tạo module websocket và \u003Ca target=\"_blank\" href=\"http:\u002F\u002Fhandler.rs\">handler.rs\u003C\u002Fa>\u003Cbr>- Sử dụng:\u003Cbr> + WebSocketUpgrade\u003Cbr> + Headers\u003Cbr>\u003Cbr>- Truyền AppState và ConnectInfo:\u003Cbr> → Quản lý state chung\u003Cbr> → Lấy IP user (remote address)\u003C\u002Fp>",{"title":300,"content":301},"Xử lý Socket","\u003Cp>- Tách socket thành:\u003Cbr> + Read\u003Cbr> + Write\u003Cbr>\u003Cbr>- Sử dụng async loop:\u003Cbr> → Lắng nghe message liên tục\u003Cbr> → Không ngắt kết nối\u003C\u002Fp>",{"title":303,"content":304},"Test thực tế","\u003Cp>- Dùng Postman test WebSocket\u003Cbr>- Gửi message:\u003Cbr> + \"ABC\"\u003Cbr> + \"Hello\"\u003Cbr>\u003Cbr>→ Kiểm tra log server nhận dữ liệu\u003C\u002Fp>",{"title":306,"content":307},"Kết quả đạt được:","\u003Cp>- Xây dựng thành công WebSocket Server\u003Cbr>- Duy trì kết nối realtime ổn định\u003Cbr>- Nền tảng cho:\u003Cbr> + SDP Exchange\u003Cbr> + ICE Candidates\u003C\u002Fp>",{"slug":101,"title":102,"description":103,"duration":104,"youtubeId":105,"order":106,"thumbnail":107,"sections":309},[310,313,316,319,322],{"title":311,"content":312},"Cấu trúc dữ liệu cho Client","\u003Cp>- Định nghĩa struct ClientInfo:\u003C\u002Fp>\u003Cp>  + user_id\u003C\u002Fp>\u003Cp>  + client_id (duy nhất cho mỗi kết nối)\u003C\u002Fp>\u003Cp>  + device_id\u003C\u002Fp>\u003Cp>- Sử dụng Unbounded Sender:\u003C\u002Fp>\u003Cp>  → Gửi message xuống client theo kiểu async\u003C\u002Fp>",{"title":314,"content":315},"Quản lý kết nối với ConnectionState","\u003Cp>- Client Map:\u003C\u002Fp>\u003Cp>  → Mapping client_id → ClientInfo\u003C\u002Fp>\u003Cp>- User Map:\u003C\u002Fp>\u003Cp>  → Mapping user_id → danh sách client_id\u003C\u002Fp>\u003Cp>→ Cho phép:\u003C\u002Fp>\u003Cp>- Một user đăng nhập nhiều thiết bị\u003C\u002Fp>\u003Cp>- Quản lý nhiều kết nối song song\u003C\u002Fp>",{"title":317,"content":318},"Các logic xử lý chính","\u003Cp>- add_client:\u003C\u002Fp>\u003Cp>  → Thêm client khi có kết nối mới\u003C\u002Fp>\u003Cp>- remove_client:\u003C\u002Fp>\u003Cp>  → Xóa client khi disconnect\u003C\u002Fp>\u003Cp>  → Tự động cleanup nếu user không còn connection\u003C\u002Fp>\u003Cp>- send_to_user:\u003C\u002Fp>\u003Cp>  → Gửi message đến tất cả connection của user\u003C\u002Fp>",{"title":320,"content":321},"Tối ưu hiệu năng","\u003Cp>- Sử dụng Arc&lt;String&gt; thay vì clone String\u003C\u002Fp>\u003Cp>→ Giảm chi phí bộ nhớ khi broadcast message\u003C\u002Fp>\u003Cp>→ Tối ưu khi một user có nhiều connection\u003C\u002Fp>",{"title":306,"content":323},"\u003Cp>- Server có khả năng quản lý danh sách user online\u003C\u002Fp>\u003Cp>- Mapping chính xác giữa user và connection\u003C\u002Fp>\u003Cp>- Nền tảng cho:\u003C\u002Fp>\u003Cp>  + Gọi P2P đúng người\u003C\u002Fp>\u003Cp>  + Routing signaling message\u003C\u002Fp>",{"slug":109,"title":110,"description":111,"duration":112,"youtubeId":113,"order":114,"thumbnail":115,"sections":325},[326,329,332,335,338,341],{"title":327,"content":328},"Trong phần 10 này:","\u003Cp>Chúng ta chuẩn hóa cách trao đổi dữ liệu giữa Client và Server\u003C\u002Fp>\u003Cp>→ Xây dựng Message Routing\u003C\u002Fp>\u003Cp>→ Áp dụng Dispatcher Pattern\u003C\u002Fp>",{"title":330,"content":331},"Định nghĩa giao thức bản tin","\u003Cp>- Sử dụng JSON thay cho text tự do\u003C\u002Fp>\u003Cp>→ Dễ mở rộng và chuẩn hóa\u003C\u002Fp>\u003Cp>- Cấu trúc message:\u003C\u002Fp>\u003Cp>  + cmd: mã lệnh (auth, send_sdp_request...)\u003C\u002Fp>\u003Cp>  + param: dữ liệu đi kèm (username, SDP...)\u003C\u002Fp>",{"title":333,"content":334},"Xử lý JSON với Serde","\u003Cp>- Sử dụng serde_json để parse dữ liệu từ WebSocket\u003C\u002Fp>\u003Cp>- Trích xuất cmd và param an toàn\u003C\u002Fp>\u003Cp>→ Tránh crash khi dữ liệu không hợp lệ\u003C\u002Fp>",{"title":336,"content":337},"Dispatcher Pattern","\u003Cp>- Mapping cmd → handler function\u003C\u002Fp>\u003Cp>→ Mỗi lệnh có 1 hàm xử lý riêng\u003C\u002Fp>\u003Cp>- Tổ chức code:\u003C\u002Fp>\u003Cp>  + Dễ mở rộng\u003C\u002Fp>\u003Cp>  + Dễ maintain\u003C\u002Fp>",{"title":339,"content":340},"Xử lý lỗi & bảo mật","\u003Cp>- Tránh panic khi nhận dữ liệu sai format\u003C\u002Fp>\u003Cp>- Loại bỏ unwrap() trong production\u003C\u002Fp>\u003Cp>→ Đảm bảo hệ thống ổn định\u003C\u002Fp>",{"title":306,"content":342},"\u003Cp>- Xây dựng \"ngôn ngữ chung\" giữa client và server\u003C\u002Fp>\u003Cp>- Chuẩn hóa message protocol\u003C\u002Fp>\u003Cp>- Sẵn sàng mở rộng:\u003C\u002Fp>\u003Cp>  + Gọi WebRTC\u003C\u002Fp>\u003Cp>  + Nhắn tin realtime\u003C\u002Fp>\u003Cp>  + Trao đổi dữ liệu\u003C\u002Fp>",{"slug":117,"title":118,"description":119,"duration":120,"youtubeId":121,"order":122,"thumbnail":123,"sections":344},[345,348,351,354,357,359],{"title":346,"content":347},"Cấu hình Domain","\u003Cp>- Trỏ subdomain về IP VPS\u003C\u002Fp>\u003Cp>→ Sử dụng DNS A record\u003C\u002Fp>\u003Cp>- Ví dụ:\u003C\u002Fp>\u003Cp>\u003Ca target=\"_blank\" href=\"http:\u002F\u002Ftest.bytebuffer.com\">test.bytebuffer.com\u003C\u002Fa> → IP server\u003C\u002Fp>",{"title":349,"content":350},"Cài đặt Nginx","\u003Cp>- Cài đặt trên Linux (Debian \u002F CentOS)\u003C\u002Fp>\u003Cp>- Kiểm tra hoạt động:\u003C\u002Fp>\u003Cp>  + Port 80 (HTTP)\u003C\u002Fp>\u003Cp>  + Port 443 (HTTPS)\u003C\u002Fp>",{"title":352,"content":353},"Deploy ứng dụng Rust","\u003Cp>- Cài đặt Rust trên VPS\u003C\u002Fp>\u003Cp>- Build ứng dụng\u003C\u002Fp>\u003Cp>- Upload:\u003C\u002Fp>\u003Cp>  + File executable\u003C\u002Fp>\u003Cp>  + Thư mục config\u003C\u002Fp>\u003Cp>→ Sử dụng SFTP\u003C\u002Fp>\u003Cp>- Chạy server:\u003C\u002Fp>\u003Cp>  + Ví dụ port 1006\u003C\u002Fp>\u003Cp>  + Thiết lập biến môi trường\u003C\u002Fp>",{"title":355,"content":356},"Nginx Reverse Proxy & SSL","\u003Cp>- Tạo SSL với Cloudflare Origin Server\u003C\u002Fp>\u003Cp>- Cấu hình Nginx:\u003C\u002Fp>\u003Cp>  + Redirect HTTP → HTTPS\u003C\u002Fp>\u003Cp>  + Reverse proxy về port 1006\u003C\u002Fp>\u003Cp>- Quan trọng:\u003C\u002Fp>\u003Cp>  + Cấu hình header để hỗ trợ WebSocket\u003C\u002Fp>\u003Cp>  → Upgrade connection\u003C\u002Fp>\u003Cp>\u003C\u002Fp>\u003Cpre>\u003Ccode>server\n{\n        listen 80;\n        server_name test-p2p.bytebuffer.co;\n        return 301 https:\u002F\u002F$host$request_uri;\n}\n\nserver\n{\n\n        client_max_body_size 20M;\n        listen 443 ssl;\n        ssl_certificate \u002Froot\u002Fssl\u002Fbytebuffer.co\u002Fcertificate.pem;\n        ssl_certificate_key \u002Froot\u002Fssl\u002Fbytebuffer.co\u002Fprivate-key.pem;\n        server_name test-p2p.bytebuffer.co;\n\n        root \u002Fusr\u002Fshare\u002Fnginx\u002Fbytebuffer-p2p;\n        index index.php index.html index.htm;\n\n        location = \u002Fcall\n        {\n                proxy_pass http:\u002F\u002F127.0.0.1:10006\u002Fcall;\n                proxy_http_version 1.1;\n                proxy_set_header Upgrade $http_upgrade;\n                proxy_set_header Connection \"upgrade\";\n                proxy_set_header Host $host;\n                proxy_read_timeout 300s;\n        }\n\n        location \u002F\n        {\n                proxy_pass http:\u002F\u002F127.0.0.1:10006\u002F;\n                proxy_http_version 1.1;\n                proxy_set_header Upgrade $http_upgrade;\n                proxy_set_header Connection 'upgrade';\n                proxy_set_header Host $host;\n                proxy_cache_bypass $http_upgrade;\n\n                proxy_request_buffering off;\n                proxy_read_timeout 300s;\n                proxy_connect_timeout 300s;\n                proxy_send_timeout 300s;\n\n                proxy_set_header X-Real-IP $remote_addr;\n                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n                proxy_set_header X-Forwarded-Proto $scheme;\n        }\n\n}\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>\u003C\u002Fp>",{"title":303,"content":358},"\u003Cp>- Test login qua domain thật\u003C\u002Fp>\u003Cp>→ Kiểm tra response và log\u003C\u002Fp>\u003Cp>- Test WebSocket:\u003C\u002Fp>\u003Cp>  → Kết nối qua domain\u003C\u002Fp>\u003Cp>  → Kiểm tra cookie authentication\u003C\u002Fp>",{"title":306,"content":360},"\u003Cp>- Deploy thành công ứng dụng Rust lên VPS\u003C\u002Fp>\u003Cp>- Cấu hình domain + HTTPS hoàn chỉnh\u003C\u002Fp>\u003Cp>- Thiết lập reverse proxy cho WebSocket\u003C\u002Fp>\u003Cp>- Sẵn sàng chạy production cho WebRTC\u003C\u002Fp>",{"slug":125,"title":126,"description":127,"duration":128,"youtubeId":129,"order":130,"thumbnail":131,"sections":362},[363,366,369,372],{"title":364,"content":365},"Nội dung chính:","\u003Cp>Định nghĩa User Model: Xây dựng struct User và UserStatus trong Rust, mapping trực tiếp với document trong MongoDB.\u003Cbr>Thiết kế dữ liệu: Bao gồm các field như ID, Username, Email, Password, Phone number... để quản lý user một cách rõ ràng.\u003Cbr>Xây dựng User Repository: Triển khai các hàm truy vấn dữ liệu như get_user_by_id, get_all_users và search_user_by_keyword.\u003C\u002Fp>",{"title":367,"content":368},"Cấu trúc dữ liệu","\u003Cpre>\u003Ccode>#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]\npub enum UserStatus {\n    Pending,\n    Active,\n    Inactive,\n    Locked,\n    Suspended,\n    Deleted,\n}\n\n#[derive(Serialize, Deserialize, Clone, Debug)]\npub struct User {\n    pub id: String,\n    pub network: String,\n    pub username: String,\n    pub email: String,\n    pub password: String,\n    pub first_name: String,\n    pub last_name: String,\n    pub phone_number: Option&lt;String&gt;,\n    pub language_code: Option&lt;String&gt;,\n    pub time_zone: Option&lt;String&gt;,\n    pub date_format: Option&lt;u8&gt;,\n    pub time_format: Option&lt;u8&gt;,\n    pub number_format: Option&lt;u8&gt;,\n    pub photo_url: Option&lt;String&gt;,\n    pub created_at: Option&lt;i64&gt;,\n    pub updated_at: Option&lt;i64&gt;,\n    pub current_balance: f64,\n    pub status: Option&lt;UserStatus&gt;,\n}\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>\u003C\u002Fp>",{"title":370,"content":371},"Bản ghi database","\u003Cpre>\u003Ccode>{ \n    \"_id\" : ObjectId(\"68792e60c9ea0a3b0b56f141\"), \n    \"id\" : \"7dZdmdweeEQpnRCfmo0Q\", \n    \"network\" : \"web\", \n    \"username\" : \"heoluoibieng@bytebuffer.co\", \n    \"email\" : \"heoluoibieng@bytebuffer.co\", \n    \"password\" : \"$argon2id$v=19$m=19456,t=2,p=1$aWmfMcPDyuxzbKt0bnXcQg$wMeYKsojeyCZJgr9ADXH\u002FMz0Rjs36RLDWly1wQX+hLE\", \n    \"first_name\" : \"Heo\", \n    \"last_name\" : \"Lười Biếng\", \n    \"language_code\" : \"en\", \n    \"photo_url\" : \"https:\u002F\u002Favatar.bytebuffer.co\u002Fheo-luoi-bieng.jpg\", \n    \"created_at\" : NumberLong(1752772192881), \n    \"updated_at\" : NumberLong(1752772192881), \n    \"current_balance\" : 0.0\n}\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>\u003C\u002Fp>",{"title":373,"content":374},"Kết quả","\u003Cp>Sau phần này, bạn sẽ có một Data Layer hoàn chỉnh, code rõ ràng, dễ maintain và sẵn sàng tích hợp JWT Authentication ở bước tiếp theo.\u003C\u002Fp>",{"slug":133,"title":134,"description":135,"duration":136,"youtubeId":137,"order":138,"thumbnail":139,"sections":376},[377,380,383],{"title":378,"content":379},"Nội dung chính","\u003Cp>Triển khai JSON Web Token (JWT): Thiết kế TokenClaim để lưu trữ các thông tin cần thiết như User ID, Display Name, Avatar và Title. Xây dựng helper để tạo token dựa trên secret key từ file cấu hình.\u003C\u002Fp>\u003Cp>Bảo mật với Argon2: Mã hóa mật khẩu trước khi lưu trữ và khi so sánh trong database, giúp đảm bảo an toàn cho dữ liệu người dùng.\u003C\u002Fp>\u003Cp>Xây dựng Login Service: Định nghĩa LoginRequest, validate dữ liệu đầu vào (định dạng email, mật khẩu tối thiểu 6 ký tự) và xử lý logic trả về AuthResponse bao gồm result code, message và token.\u003C\u002Fp>\u003Cp>Quản lý Cookie: Tạo và trả về header Set-Cookie cho trình duyệt. Cấu hình cookie với thời hạn dài, HttpOnly, SameSite và Secure để giảm thiểu rủi ro XSS và CSRF.\u003C\u002Fp>\u003Cp>Demo thực tế: Test login qua API, quan sát cách server trả về token và tự động set cookie trên trình duyệt.\u003C\u002Fp>",{"title":381,"content":382},"Công nghệ sử dụng","\u003Cp>Rust với các thư viện jsonwebtoken, argon2, axum, serde_json, cookie. Database sử dụng MongoDB.\u003C\u002Fp>\u003Cp>Trong phần này, dữ liệu người dùng đã được insert sẵn để tập trung hoàn toàn vào logic xác thực.\u003C\u002Fp>",{"title":306,"content":384},"\u003Cp>Sau bài học này, bạn sẽ có một Login Service hoàn chỉnh, áp dụng các chuẩn bảo mật phổ biến, sẵn sàng tích hợp vào hệ thống WebRTC signaling.\u003C\u002Fp>",{"slug":141,"title":142,"description":143,"duration":144,"youtubeId":145,"order":146,"thumbnail":147,"sections":386},[387,390,393,396,399],{"title":388,"content":389},"Xây dựng HTTP Middleware","\u003Cp>Tìm hiểu cách Middleware hoạt động như một lớp gatekeeper cho các route cần xác thực. Triển khai việc đọc JWT từ cookie header, verify thông tin người dùng và inject dữ liệu user vào controller thông qua Extension của Axum. Đồng thời xử lý các trường hợp lỗi với mã 401 Unauthorized một cách rõ ràng.\u003C\u002Fp>",{"title":391,"content":392},"Xác thực WebSocket","\u003Cp>Thực hiện auth ngay từ bước handshake bằng cách lấy token từ header. Thiết lập cơ chế timeout bằng tokio::spawn, nếu client không xác thực trong vòng 30 giây thì tự động đóng kết nối để tránh lãng phí tài nguyên. Duy trì kết nối bằng cách gửi ping định kỳ mỗi 10 giây.\u003C\u002Fp>",{"title":394,"content":395},"Xử lý bất đồng bộ","\u003Cp>Sử dụng MPSC Channel và One-shot Channel để truyền dữ liệu xác thực giữa các task khác nhau, đảm bảo luồng xử lý rõ ràng và không block.\u003C\u002Fp>",{"title":397,"content":398},"Testing thực tế","\u003Cp>Sử dụng Postman để test API get_me, kiểm tra luồng xác thực HTTP. Demo quá trình kết nối WebSocket từ trạng thái bị từ chối khi thiếu token đến khi xác thực thành công và có thể trao đổi dữ liệu WebRTC.\u003C\u002Fp>",{"title":400,"content":401},"Kết quả đạt được","\u003Cp>Sau bài học này, bạn sẽ nắm được cách xây dựng Middleware trong Axum, hiểu cách tổ chức luồng xác thực cho cả HTTP và WebSocket, cũng như cách quản lý kết nối trong hệ thống realtime.\u003C\u002Fp>",{"slug":149,"title":150,"description":151,"duration":152,"youtubeId":153,"order":154,"thumbnail":155,"sections":403},[404,407],{"title":405,"content":406},"Nội dung chính trong video:","\u003Cul>\u003Cli>\u003Cp>Demo HTTP Login: Kiểm tra flow đăng nhập, từ việc gọi LoginService để xác thực user trong database đến việc kiểm tra mật khẩu. Quan sát cách server trả về JWT token thông qua response body và header Set-Cookie.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>Kiểm tra Auth Middleware: Sử dụng cookie nhận được từ bước login để gọi API get_me. Xác nhận middleware có thể bóc tách thông tin user từ request và xử lý chính xác.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>Xác thực WebSocket: Thử nghiệm kết nối WebSocket và quan sát cơ chế tự động ngắt kết nối nếu không xác thực trong thời gian quy định. Thực hiện xác thực bằng cách gửi cookie trực tiếp trong header ngay từ bước handshake, giúp server nhận diện user mà không cần gửi message auth riêng.\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>Theo dõi Server Logs: Kiểm tra log để xác nhận trạng thái authenticate thành công và cách server xử lý các message dựa trên cmd.\u003C\u002Fp>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>\u003C\u002Fp>",{"title":306,"content":408},"\u003Cp>Sau phần này, bạn đã hoàn thiện toàn bộ hệ thống xác thực cho cả HTTP và WebSocket. Đây là nền tảng quan trọng để bước sang giai đoạn tiếp theo: xây dựng signaling giữa hai browser trong WebRTC.\u003C\u002Fp>",{"slug":157,"title":158,"description":159,"duration":160,"youtubeId":161,"order":28,"thumbnail":162,"sections":410},[411,414,416],{"title":412,"content":413},"Tại sao cần State Pattern","\u003Cp>Một cuộc gọi P2P sẽ đi qua nhiều trạng thái như ringing, connecting, talking hoặc ended. Nếu xử lý bằng if-else, code sẽ nhanh chóng trở nên phức tạp và khó bảo trì. State Pattern giúp tách từng trạng thái thành các struct riêng, nhưng vẫn tuân theo một chuẩn chung thông qua trait, giúp hệ thống rõ ràng và dễ mở rộng.\u003C\u002Fp>",{"title":194,"content":415},"\u003Cp>\u003Cspan style=\"color: rgb(13, 13, 13);\">→ \u003C\u002Fspan>Thiết kế State Machine: Tổ chức cấu trúc thư mục theo hướng mở rộng như call, call_flow, call_types, giúp dễ dàng phát triển thêm các loại cuộc gọi trong tương lai.\u003C\u002Fp>\u003Cp>\u003Cspan style=\"color: rgb(13, 13, 13);\">→ \u003C\u002Fspan>Xây dựng P2PCallStateHandler Trait: Định nghĩa các hành vi chung cho mọi trạng thái, bao gồm name để định danh, on_enter và on_exit để xử lý khi chuyển trạng thái, on_event để xử lý các sự kiện và on_timer cho các logic liên quan đến thời gian.\u003C\u002Fp>\u003Cp>\u003Cspan style=\"color: rgb(13, 13, 13);\">→ \u003C\u002Fspan>Quản lý Action và Event: Xây dựng các enum cho state transition và hangup, giúp điều phối luồng xử lý một cách rõ ràng và nhất quán.\u003C\u002Fp>\u003Cp>\u003Cspan style=\"color: rgb(13, 13, 13);\">→ \u003C\u002Fspan>Tối ưu về concurrency: Sử dụng các đặc tính Send và Sync trong Rust để đảm bảo thread-safety khi xử lý các tác vụ bất đồng bộ liên quan đến cuộc gọi.\u003C\u002Fp>",{"title":400,"content":417},"\u003Cp>Sau phần này, bạn sẽ hiểu cách thiết kế State Machine trong Rust, cách sử dụng trait để quản lý logic phức tạp và xây dựng một kiến trúc rõ ràng, dễ maintain cho hệ thống realtime.\u003C\u002Fp>",1776241158914]