Твојата апликација вели исклучено, мени-лентата вели поврзано, а сообраќајот очигледно тече. Таа разлика не е тркачка состојба што ја поправаш со нов обид: апликацијата и тунелот се одделни процеси, а објектот што го чита твојот код е кеширан приказ на конфигурација што системот ја чува. Personal VPN површината на Apple е контролен API, не патека за податоци, и повеќето од нејзиното чудно однесување произлегува од тој еден факт. Еве што навистина се случува при секој повик.

Објектот на менаџерот е кеширан приказ, не тунелот

NETunnelProviderManager се пополнува од складиште со поставки што го поседува системот, па неговите својства не значат ништо додека loadFromPreferences не заврши. Ако прочиташ connection.status пред тоа, добиваш стандардна вредност, и затоа првото освежување на состојбата по повторно стартување пријавува исклучено додека тунелот работи. Прво вчитај, потоа прочитај ја состојбата и конфигурацијата на протоколот од истиот обработувач за завршување. Набљудувај ги подоцнежните промени преку NEVPNStatusDidChange наместо со анкетирање, и забележи дека известувањето се активира и за врски што ги стартува On Demand, каде што воопшто нема повик од апликацијата што би вратил нешто. Истото важи и за поставките на протоколот: тие се читаат од вчитаната конфигурација, не од она што апликацијата го предала.

Самиот тунел живее во процес на давател на Network Extension, па апликацијата може да ја загуби сопствената состојба без да ја загуби врската. Сето она што го покажува интерфејсот мора да се изгради повторно од менаџерот, не да се памети од последната сесија.

Редослед на стартување: зачувај, вчитај, потоа стартувај

Врската заснована на давател бара три чекори по ред. Запиши ја конфигурацијата на давателот и повикај saveToPreferences, вчитај го менаџерот за да биде зачуваната конфигурација таа што ја држиш, потоа стартувај преку NETunnelProviderSession.startVPNTunnel(). Ако го прескокнеш зачувувањето, стартувањето нема што да стартува; ако вчиташ пред зачувувањето, менаџерот и понатаму ја одразува старата конфигурација.

Логичката вредност што ја враќа startVPNTunnel само вели дека барањето е прифатено. Неуспесите на ниво на давател доаѓаат подоцна како промена на состојбата во исклучено, што ја набљудуваш преку известувањето NEVPNStatusDidChange, а обработувачот на известувањата мора повторно да го прочита connection.status по loadFromPreferences бидејќи кешираната вредност може да е старата. Неуспесите на ниво на барање се враќаат веднаш од формата на повикот што фрла исклучок, или преку излезниот параметар за грешка на startVPNTunnelAndReturnError:. Кодот што ја третира вратената вредност како исход пријавува врска што никогаш не се воспоставила. Другиот тивок неуспех е идентификатор на пакетот на давателот што не одговара на инсталираното проширување: барањето се одбива, и ништо во пораката не упатува на идентификаторот. Ако идентификаторот е погрешен, барањето обично пропаѓа веднаш, пред да се појави кој било ред од дневникот на давателот.

Повторното вчитување на поставките по стартување е она што ги прави екраните со состојба точни. Менаџерот не ти турка нова конфигурација кога системот ќе ја смени.

Материјалот за доверба доаѓа преку профил, никогаш од кодот на апликацијата

Апликацијата нема поддржан начин да додаде коренски сертификат во складиштето за доверба на iOS, па Personal VPN конфигурацијата може да реферира само материјал во кој уредот веќе има доверба: ланец воспоставен од инсталиран профил, од управување со уред или од CA во кој системот има доверба од други причини. Апликација што создава сопствен CA при првото стартување и очекува системот да го прифати ќе пропадне при валидацијата внатре во давателот, каде што интерфејсот на апликацијата не може да ја види причината.

Третирај ја таа граница како дизајнерско ограничување какво што е и испорачај го сидрото за доверба заедно со профилот за запишување. Држи ја автентикацијата на VPN одделно од одлуката за доверба, бидејќи тие пропаѓаат на различни места и ги отстрануваат различни луѓе.

Бројачите доаѓаат од интерфејсот, не од VPN API-то

Менаџерот изложува состојба и конфигурација и ништо што брои бајти по тунел. Ако ти требаат бројки за користење, повикај getifaddrs() и прочитај if_data за соодветниот интерфејс: en0 за Wi-Fi, интерфејсите pdp_ip за мобилна мрежа и utun уред за самиот тунел. Бројачите на utun го опишуваат внатрешниот сообраќај и вклучуваат протоколен трошок.

Овие бројки се проценки, не сметководство по апликација, и се ресетираат кога интерфејсот повторно се создава. Означи ги така во интерфејсот, инаку некој ќе ги искористи за да наплати клиент. Ако ти требаат бројки по апликација, ти треба сосема друг механизам, не подобро читање на овие полиња.

Чистењето припаѓа во stopVPNTunnel, не во прекинувањето

applicationWillTerminate ти дава неколку секунди пред системот да може да го убие процесот, што не е сигурно место за расклопување на врска. Испрати го запирањето до stopVPNTunnel() или обработи го во повратниот повик за запирање на давателот, и задржи го идентификаторот на менаџерот или конфигурацијата со кој стартуваше за да може запирањето да ја погоди таа врска наместо секоја конфигурација на уредот.

Зачувај го тој идентификатор покрај профилот на кој му припаѓа, бидејќи објектот на менаџерот не запишува која конфигурација ја избрал корисникот. И запомни дека врската што ја крева On Demand воопшто нема повик од апликација зад себе, па екранот со состојба и понатаму мора да ги вчита поставките пред да нацрта нешто.

Поврзани статии