Trình quan sát trạng thái OpenVPN bằng C#: theo dõi phiên, không phải card mạng
NetworkAvailabilityChanged không phải sự kiện VPN. Đọc luồng trạng thái của ứng dụng khách sở hữu đường hầm, phòng ngừa các lần dò cũ và công bố mức sẵn sàng theo từng kết nối.
Ứng dụng của bạn vẫn chạy trong khi đường hầm chết. Wi-Fi vẫn bật, internet vẫn trả lời, và API riêng mà ứng dụng phụ thuộc đã trở nên không thể truy cập. Sự kiện .NET mà mọi người thường chọn ở đây, NetworkAvailabilityChanged, hoàn toàn không mô tả tình huống đó. Nó báo cáo thay đổi trong trạng thái tổng hợp của máy, và trạng thái đó có thể vẫn đúng xuyên suốt việc ngắt và kết nối lại VPN. Trình quan sát phải theo dõi ứng dụng khách sở hữu đường hầm, không phải bản tóm tắt của ngăn xếp mạng.
Tính khả dụng là một tổng hợp, không phải đường hầm của bạn
NetworkAvailabilityChanged được kích hoạt khi câu trả lời khả dụng tổng hợp của máy thay đổi, và câu trả lời đó đếm mọi giao diện đang hoạt động ngoài loopback hoặc đường hầm.
VPN rớt khi Wi-Fi đang bật không thay đổi bất cứ điều gì nó đo, đó là lý do sự kiện có thể im lặng đúng trong lúc xảy ra lỗi mà bạn quan tâm.
Luồng trạng thái thuộc về ứng dụng khách sở hữu đường hầm
Xác định thành phần nào sở hữu kết nối: GUI hoặc dịch vụ OpenVPN, OpenVPN Connect, hay một tiến trình mà ứng dụng của bạn khởi chạy và điều khiển. Đây là những chủ sở hữu khác nhau với giao diện được hỗ trợ khác nhau, và trình quan sát phải dùng cái phù hợp với việc triển khai. Với một tiến trình OpenVPN mà bạn được phép tích hợp, giao diện quản lý báo cáo trạng thái hiện tại, lịch sử và thông báo thời gian thực. Phân tích các thông điệp có cấu trúc đã được tài liệu hóa thay vì tìm từ connected trong chú thích GUI đã bản địa hóa.
Kênh quản lý là một bề mặt điều khiển đặc quyền, vì vậy đừng mở trình lắng nghe mới và đừng tranh giành với GUI một kênh mà nó đã giữ.
Các chốt chặn thế hệ ngăn kết quả cũ
Mỗi quan sát thuộc về một lần thử kết nối cụ thể. Tăng bộ đếm thế hệ khi một lần thử mới bắt đầu, khi kênh bị mất và khi ứng dụng khách báo thoát.
Hãy xét một lần dò bắt đầu trong kết nối A. Đường hầm rớt, kết nối B bắt đầu, rồi thành công HTTP bị trễ của A đến sau. Không có chốt chặn, kết quả cũ đó làm màn hình xanh trong khi B vẫn đang xác thực. Việc hủy giảm công việc lãng phí, và kiểm tra thế hệ chính là thứ ngăn một hoàn tất lỗi thời trở thành trạng thái hiện tại:
var generation = _generation;
var reachable = await ProbeAsync(token);
if (generation != _generation) return;
Publish(reachable);
Áp dụng quy tắc tương tự quanh việc gửi tới UI, vì bản cập nhật đã marshal có thể đến sau khi thế hệ đã tiến lên.
Khởi tạo và kết nối lại là một vòng đời
Coi lần kết nối đầu tiên, kết nối lại và mất kênh là một vòng đời với một bộ quy tắc:
- Đọc trạng thái hiện tại và đăng ký nhận thông báo trong một bước ở nơi giao diện cho phép.
- Gắn thẻ mỗi quan sát bằng danh tính kết nối và thế hệ.
- Vô hiệu hóa mức sẵn sàng khi kết nối lại, thoát, hoặc mất kênh quan sát.
- Chỉ dò tài nguyên riêng sau khi chủ sở hữu báo việc khởi tạo đã hoàn tất.
- Chỉ công bố kết quả vẫn thuộc về thế hệ hiện tại.
Kênh bị mất nghĩa là không rõ, không phải đã ngắt. Báo không rõ trung thực hơn báo một ngắt kết nối mà bạn không thể chứng minh, và nó ngăn logic thử lại hành động dựa trên phỏng đoán.
Báo bằng chứng, không phải boolean
Trả về trạng thái phiên có tên và mức sẵn sàng của tài nguyên như hai giá trị riêng, mỗi giá trị mang một độ tuổi. Người tiêu thụ phải quyết định điều gì đó có thể thấy lần dò thành công gần nhất đã bốn mươi giây, đó là thông tin khác với thông tin tươi mới.
Tra cứu IP công cộng không phải bằng chứng rằng một API riêng đã dùng tuyến đường cần thiết, nên đừng trình bày nó như thể đúng là vậy.
Giữ việc thực thi bên ngoài trình quan sát
Callback chạy sau khi sự việc xảy ra. Nó không thể bảo đảm rằng không có gói nào rời khỏi máy giữa sự kiện và trình xử lý. Nếu thiết kế yêu cầu chặn, chính sách mạng phải cung cấp điều đó, và công việc của trình quan sát là giải thích bằng chứng cho người gọi nó. Trộn hai thứ này tạo ra mã tưởng mình là tường lửa vì nó giữ một boolean. Hãy giữ lớp thực thi nhàm chán và có thể kiểm thử, và để trình quan sát tiếp tục là người đọc.
Khi đó câu hỏi về UI trở nên đơn giản: hiển thị điều đã biết, kèm độ tuổi, và nói không rõ khi đúng là như vậy.