Android VpnService: TUN ਪੜ੍ਹਤ ਅਟਕਣਾ ਬਨਾਮ ENOBUFS ਲਿਖਤ ਗਲਤੀਆਂ
ਕਦੇ ਨਾ ਮੁੜਨ ਵਾਲੀ ਪੜ੍ਹਤ ਅਤੇ ENOBUFS ਨਾਲ ਅਸਫਲ ਹੋਣ ਵਾਲੀ ਲਿਖਤ ਦੇ ਕਾਰਨ ਉਲਟ ਹਨ। ਸੁਧਾਰ ਚੁਣਨ ਲਈ ਘੋਸ਼ਿਤ ਵਿੰਡੋ ਅਤੇ ਪੈਕੇਟ ਦੀ ਲੰਬਾਈ ਮਾਪੋ।
ਇੱਕੋ VpnService ਲੂਪ ਵਿੱਚ ਦੋ ਲੱਛਣ ਦਿਸਦੇ ਹਨ ਅਤੇ ਦੋਵਾਂ ਨੂੰ ਇੱਕੋ ਚੀਜ਼ ਦਾ ਦੋਸ਼ ਦਿੱਤਾ ਜਾਂਦਾ ਹੈ: ਕਦੇ ਨਾ ਮੁੜਨ ਵਾਲਾ ਪਾਠਕ, ਅਤੇ ENOBUFS ਨਾਲ ਅਸਫਲ ਹੋਣ ਵਾਲੀ ਲਿਖਤ। ਇਹ ਇੱਕ ਬੱਗ ਦੀਆਂ ਕਿਸਮਾਂ ਨਹੀਂ ਹਨ। ਅਟਕੀ ਹੋਈ ਪੜ੍ਹਤ ਪੀਅਰ ਨਾਲ ਪ੍ਰਵਾਹ ਨਿਯੰਤਰਣ ਬਾਰੇ ਅਸਹਿਮਤੀ ਹੈ; ਅਸਫਲ ਲਿਖਤ ਉਹ ਪੈਕੇਟ ਹੈ ਜੋ ਇੰਟਰਫੇਸ ਸਵੀਕਾਰ ਨਹੀਂ ਕਰੇਗਾ। ਜੇ ਤੁਸੀਂ ਇਨ੍ਹਾਂ ਨੂੰ ਇੱਕ ਸਮੱਸਿਆ ਮੰਨੋਗੇ, ਤਾਂ ਤੁਸੀਂ ਉਹ ਬਫਰ ਟਿਊਨ ਕਰਨ ਵਿੱਚ ਇੱਕ ਦਿਨ ਬਿਤਾਓਗੇ ਜੋ ਕਦੇ ਸ਼ਾਮਲ ਹੀ ਨਹੀਂ ਸਨ। ਹੇਠਾਂ ਦਿੱਤੀ ਵੰਡ ਇਹ ਹੈ ਕਿ ਲੂਪ ਦਾ ਕਿਹੜਾ ਅੱਧਾ ਹਿੱਸਾ ਪਹਿਲਾਂ ਮਾਪਣਾ ਹੈ।
ਇੱਕ ਲੂਪ, ਦੋ ਸੁਤੰਤਰ ਅਸਫਲਤਾ ਬਿੰਦੂ
ਤੁਹਾਡੀ ਸੇਵਾ TUN ਫਾਈਲ ਡਿਸਕ੍ਰਿਪਟਰ ਤੋਂ IP ਪੈਕੇਟ ਪੜ੍ਹਦੀ ਹੈ, ਉਸ ਦੀ ਜਾਂਚ ਕਰਦੀ ਹੈ ਅਤੇ ਉਸੇ ਡਿਸਕ੍ਰਿਪਟਰ ਵਿੱਚ ਜਵਾਬ ਲਿਖਦੀ ਹੈ। ਉਸ ਰਾਹ ਵਿੱਚ ਜੋ ਵੀ ਟੁੱਟਦਾ ਹੈ ਉਹ ਉਨ੍ਹਾਂ ਦੋ ਕਾਲਾਂ ਵਿੱਚੋਂ ਇੱਕ ਵਿੱਚ ਦਿਸਦਾ ਹੈ, ਇਸ ਲਈ ਦੋਵਾਂ ਨੂੰ ਟਨਲ ਟੁੱਟਿਆ ਦੱਸਿਆ ਜਾਂਦਾ ਹੈ। ਕਾਲਾਂ ਦੇ ਸਮਝੌਤੇ ਵੱਖਰੇ ਹਨ। ਪੜ੍ਹਤ ਉਡੀਕਦੀ ਹੈ ਕਿ ਕਰਨਲ ਤੁਹਾਨੂੰ ਪੈਕੇਟ ਦੇਵੇ, ਅਤੇ ਲਿਖਤ ਕਰਨਲ ਨੂੰ ਉਹ ਪੈਕੇਟ ਦਿੰਦੀ ਹੈ ਜਿਸ ਨੂੰ ਨਕਾਰਨ ਦਾ ਅਧਿਕਾਰ ਉਸ ਕੋਲ ਹੈ।
ਪੜ੍ਹਤ ਸੋਚਣ ਲਈ ਸੌਖਾ ਅੱਧਾ ਹਿੱਸਾ ਹੈ। ਜੋ ਪੜ੍ਹਤ ਕੁਝ ਵੀ ਵਾਪਸ ਨਹੀਂ ਦਿੰਦੀ ਉਹ ਜਾਂ ਤਾਂ ਕਦੇ ਨਾ ਆਉਣ ਵਾਲੇ ਟ੍ਰੈਫਿਕ ਦੀ ਉਡੀਕ ਕਰ ਰਹੀ ਹੈ ਜਾਂ ਪੀਅਰ ਦੇ ਭੇਜਣਾ ਬੰਦ ਕਰਨ ਕਾਰਨ ਉਡੀਕ ਕਰ ਰਹੀ ਹੈ।
ਅਟਕੀ ਹੋਈ ਪੜ੍ਹਤ ਪ੍ਰਵਾਹ ਨਿਯੰਤਰਣ ਬਾਰੇ ਅਸਹਿਮਤੀ ਹੈ
TUN ਡਿਵਾਈਸ ਪੜ੍ਹਨਾ ਪੈਕੇਟ ਉਪਲਬਧ ਹੋਣ ਤੱਕ ਬਲਾਕ ਕਰਦਾ ਹੈ। ਇਹ ਡਿਜ਼ਾਈਨ ਕੀਤਾ ਵਿਵਹਾਰ ਹੈ, ਅਤੇ ਇਸੇ ਲਈ read ਦੇ ਅੰਦਰ ਖੜ੍ਹਾ ਥ੍ਰੈਡ ਨਿਸ਼ਕ੍ਰਿਯ ਲਿੰਕ ਉੱਤੇ ਆਮ ਦਿਸਦਾ ਹੈ। ਇਹ ਹੈਂਗ ਬਣਦਾ ਹੈ ਜਦੋਂ ਤੁਹਾਡਾ ਆਪਣਾ TCP ਸਟੈਕ ਸਥਾਨਕ ਐਪ ਤੋਂ ਡੇਟਾ ਸਵੀਕਾਰ ਕਰਦਾ ਰਹਿੰਦਾ ਹੈ ਪਰ ਦੂਰ ਦੇ ਪੀਅਰ ਨੂੰ ਹੋਰ ਭੇਜਣ ਲਈ ਲੋੜੀਂਦੀ ਵਿੰਡੋ ਕਦੇ ਘੋਸ਼ਿਤ ਨਹੀਂ ਕਰਦਾ। ਪੀਅਰ ਤੁਹਾਡੀ ਘੋਸ਼ਿਤ ਵਿੰਡੋ ਭਰਦਾ ਹੈ, ACK ਅਤੇ ਵਿੰਡੋ ਅੱਪਡੇਟ ਦੀ ਉਡੀਕ ਕਰਦਾ ਹੈ, ਅਤੇ ਰੁਕ ਜਾਂਦਾ ਹੈ। ਫਿਰ ਤੁਹਾਡੇ ਪਾਠਕ ਕੋਲ ਵਾਪਸ ਦੇਣ ਲਈ ਕੁਝ ਨਹੀਂ ਹੁੰਦਾ, ਅਤੇ ਐਪ ਨੂੰ ਖੁੱਲ੍ਹਾ ਪਰ ਚੁੱਪ ਕਨੈਕਸ਼ਨ ਦਿਸਦਾ ਹੈ।
ਆਮ ਕਾਰਨ ਉਹ ਸਟੈਕ ਹੈ ਜੋ ਘੋਸ਼ਿਤ ਵਿੰਡੋ ਟ੍ਰੈਕ ਕੀਤੇ ਬਿਨਾਂ ਸਾਕਟ ਵਿੱਚ ਲਿਖਦਾ ਹੈ, ਅਤੇ ਦੂਜਾ ਜੋ ਆਪਣਾ ਬਫਰ ਖਾਲੀ ਕਰਨ ਤੋਂ ਬਾਅਦ ਵਿੰਡੋ ਅੱਪਡੇਟ ਭੇਜਣਾ ਭੁੱਲ ਜਾਂਦਾ ਹੈ। ਬਾਹਰੋਂ ਦੋਵੇਂ ਇੱਕੋ ਜਿਹੇ ਦਿਸਦੇ ਹਨ: ਬਾਈਟ ਬਾਹਰ ਜਾਂਦੇ ਹਨ, ਕੁਝ ਵਾਪਸ ਨਹੀਂ ਆਉਂਦਾ, ਕੋਈ ਗਲਤੀ ਨਹੀਂ ਉੱਠਦੀ। ਪਾਠਕ ਥ੍ਰੈਡ ਨੂੰ ਪਾਰਸਿੰਗ, DNS ਰੈਜ਼ੋਲਿਊਸ਼ਨ ਜਾਂ ਡਿਸਕ I/O ਉੱਤੇ ਬਲਾਕ ਕਰਨਾ ਅਸੰਬੰਧਿਤ ਕਾਰਨ ਨਾਲ ਉਸੇ ਆਕਾਰ ਦਾ ਲੱਛਣ ਪੈਦਾ ਕਰਦਾ ਹੈ, ਇਸ ਲਈ ਪ੍ਰਵਾਹ ਨਿਯੰਤਰਣ ਨੂੰ ਦੋਸ਼ ਦੇਣ ਤੋਂ ਪਹਿਲਾਂ ਪੁਸ਼ਟੀ ਕਰੋ ਕਿ ਥ੍ਰੈਡ ਸੱਚਮੁੱਚ read ਦੇ ਅੰਦਰ ਹੈ।
ਪੀਅਰ ਦੀ ਭੇਜਣ ਕਤਾਰ ਅਤੇ ਉਸ ਨੇ ਆਖਰੀ ਵਾਰ ਜੋ ਵਿੰਡੋ ਦੇਖੀ ਉਹ ਜਾਂਚੋ। ਜੇ ਤੁਹਾਡੀ ਵਿੰਡੋ ਜ਼ੀਰੋ ਹੋਣ ਕਾਰਨ ਪੀਅਰ ਡੇਟਾ ਰੋਕ ਰਿਹਾ ਹੈ, ਤਾਂ ਸੁਧਾਰ ਤੁਹਾਡੇ ACK ਰਾਹ ਵਿੱਚ ਹੈ, TUN ਪੜ੍ਹਤ ਵਿੱਚ ਨਹੀਂ।
ENOBUFS ਆਕਾਰ ਦੀ ਸਮੱਸਿਆ ਹੈ, ਬਫਰ ਦੀ ਘਾਟ ਨਹੀਂ
TUN ਇੰਟਰਫੇਸ ਉੱਤੇ ENOBUFS ਵਾਪਸ ਕਰਨ ਵਾਲੀ ਲਿਖਤ ਆਮ ਤੌਰ ਉੱਤੇ ਪੈਕੇਟ ਦੀ ਲੰਬਾਈ ਨਕਾਰਦੀ ਹੈ। ਇੰਟਰਫੇਸ ਦੀ MTU ਹੁੰਦੀ ਹੈ, ਉਸ ਤੋਂ ਵੱਡਾ ਪੈਕੇਟ ਕਤਾਰ ਵਿੱਚ ਨਹੀਂ ਪੈ ਸਕਦਾ, ਅਤੇ ਉਹੀ ਪੈਕੇਟ ਦੁਬਾਰਾ ਅਜ਼ਮਾਉਣ ਉੱਤੇ ਹਰ ਵਾਰ ਉਸੇ ਤਰ੍ਹਾਂ ਅਸਫਲ ਹੁੰਦਾ ਹੈ। ਇਹ ਨਿਸ਼ਚਿਤਤਾ ਹੀ ਸੰਕੇਤ ਹੈ। ਸੱਚੀ ਬਫਰ ਘਾਟ ਦਬਾਅ ਘਟਣ ਨਾਲ ਮਿਟ ਜਾਂਦੀ ਹੈ, ਪਰ ਆਕਾਰ ਦਾ ਨਕਾਰ ਤੁਸੀਂ ਕਿੰਨੀ ਦੇਰ ਉਡੀਕੋਗੇ ਇਸ ਦੀ ਪਰਵਾਹ ਨਹੀਂ ਕਰਦਾ।
TCP ਕੋਲ ਇਸੇ ਲਈ ਇੱਕ ਵਿਧੀ ਹੈ, ਅਤੇ ਉਹੀ ਲੋਕ ਛੱਡਦੇ ਹਨ ਉਹ ਕਦਮ: MSS ਕਲੈਂਪ। ਜਦੋਂ ਤੁਸੀਂ ਯੂਜ਼ਰ ਸਪੇਸ ਵਿੱਚ ਸੈਗਮੈਂਟ ਸੰਸ਼ਲੇਸ਼ਿਤ ਕਰਦੇ ਹੋ ਤਾਂ ਪੇਲੋਡ ਦਾ ਆਕਾਰ ਤੁਸੀਂ ਚੁਣਦੇ ਹੋ, ਅਤੇ ਉਸ ਨੂੰ ਟਨਲ ਦੀ MTU ਦੀ ਥਾਂ ਸਥਾਨਕ ਇੰਟਰਫੇਸ ਦੀ MTU ਤੋਂ ਲੈਣ ਨਾਲ ਉਹ ਸੈਗਮੈਂਟ ਨਿਕਲਦੇ ਹਨ ਜੋ ਟਨਲ ਢੋ ਨਹੀਂ ਸਕਦੀ। ਦੋਵਾਂ ਵਿੱਚੋਂ ਛੋਟੇ ਉੱਤੇ ਸੀਮਿਤ ਕਰੋ। ਕਲੈਂਪ ਸਿਰਫ਼ TCP ਨੂੰ ਕਵਰ ਕਰਦਾ ਹੈ, ਇਸ ਲਈ ਬਹੁਤ ਵੱਡਾ UDP ਡੇਟਾਗ੍ਰਾਮ ਤੁਹਾਡੇ ਕੋਡ ਨੂੰ ਟੁਕੜੇ ਕਰਨੇ ਜਾਂ ਛੱਡਣੇ ਪੈਣਗੇ।
ਡੀਬੱਗ ਕਰਦਿਆਂ ਤੁਸੀਂ ਲਿਖੋ ਹਰ ਪੈਕੇਟ ਦੀ ਲੰਬਾਈ ਲੌਗ ਕਰੋ। ਜੋ ਲੰਬਾਈ ਅਸਫਲ ਹੁੰਦੀ ਹੈ ਉਹੀ ਜਵਾਬ ਹੈ, ਅਤੇ ਉਹ ਕੋਸ਼ਿਸ਼ਾਂ ਵਿਚਕਾਰ ਨਹੀਂ ਬਦਲੇਗੀ।
ਤਿੰਨ ਮਾਪ ਜੋ ਕੇਸ ਵੱਖ ਕਰਦੇ ਹਨ
ਦੋਵਾਂ ਵਿੱਚੋਂ ਕਿਸੇ ਵੀ ਅਸਫਲਤਾ ਲਈ ਤੁਹਾਨੂੰ ਡੀਬੱਗਰ ਦੀ ਲੋੜ ਨਹੀਂ। ਸਹੀ ਭਾਗ ਵੱਲ ਲਿਜਾਣ ਲਈ ਤਿੰਨ ਨਿਰੀਖਣ ਕਾਫ਼ੀ ਹਨ, ਅਤੇ ਉਹ ਦੁਬਾਰਾ ਬਣਾਉਣ ਨਾਲੋਂ ਘੱਟ ਸਮਾਂ ਲੈਂਦੇ ਹਨ।
| What you see | Where to look |
|---|---|
| Reader parked, peer send queue empty, last advertised window zero | Window updates in your ACK path |
| Write fails on one length and succeeds on a smaller one | MSS clamp and tunnel MTU |
| Both directions look fine, app still sees no data | Protected socket and routing loop |
ਜੇ ਤੀਜੀ ਕਤਾਰ ਮੇਲ ਖਾਂਦੀ ਹੈ, ਤਾਂ ਲੂਪ ਆਪ ਠੀਕ ਹੈ ਅਤੇ ਸਮੱਸਿਆ ਉੱਥੇ ਹੈ ਜਿੱਥੇ ਟਨਲ ਇਸ ਨੂੰ ਦੇਖ ਨਹੀਂ ਸਕਦੀ: ਇੱਕ ਅਸੁਰੱਖਿਅਤ ਟ੍ਰਾਂਸਪੋਰਟ ਸਾਕਟ ਜੋ ਤੁਹਾਡਾ ਆਪਣਾ VPN ਟ੍ਰੈਫਿਕ ਟਨਲ ਵਿੱਚ ਵਾਪਸ ਲਿਜਾਂਦਾ ਹੈ, ਜੋ ਆਮ ਤੌਰ ਉੱਤੇ ਸਫਲ ਹੋ ਕੇ ਫਿਰ ਕੁਝ ਨਾ ਪਹੁੰਚਾਉਣ ਵਾਲੇ ਕਨੈਕਸ਼ਨ ਵਜੋਂ ਦਿਸਦਾ ਹੈ।
ਦੋਵੇਂ ਰਾਹ ਜਿਸ ਪਲੰਬਿੰਗ ਉੱਤੇ ਨਿਰਭਰ ਹਨ ਉਸ ਨੂੰ ਠੀਕ ਕਰੋ
ਇੰਟਰਫੇਸ ਸਹੀ ਤਰ੍ਹਾਂ ਬਣਨ ਤੱਕ ਕਿਸੇ ਲੱਛਣ ਦਾ ਪਿੱਛਾ ਕਰਨਾ ਲਾਭਦਾਇਕ ਨਹੀਂ। ਮਹੱਤਵਪੂਰਨ builder ਕਾਲ ਪਤਾ, ਰੂਟ, MTU ਅਤੇ ਸਹਿਮਤੀ ਹਨ, ਇਸੇ ਕ੍ਰਮ ਵਿੱਚ:
Builder()
.addAddress(10.8.0.2, 32)
.addRoute(0.0.0.0, 0)
.setMtu(1400)
.establish()MTU ਨੂੰ ਨਮੂਨੇ ਵੱਲੋਂ ਵਰਤੇ ਮੁੱਲ ਉੱਤੇ ਛੱਡਣ ਦੀ ਥਾਂ ਟਨਲ ਦੇ ਅਸਲ ਮੁੱਲ ਉੱਤੇ ਸੈੱਟ ਕਰੋ। ਬਾਅਦ ਵਿੱਚ ਤੁਸੀਂ ਜੋ ਵੀ ਲਿਖੋਗੇ ਉਹ ਉਸ ਸੰਖਿਆ ਨਾਲ ਸੀਮਿਤ ਹੈ, ਅਤੇ ਤੁਸੀਂ ਸੈੱਟ ਕਰਦੇ MTU ਅਤੇ ਜਿਸ MSS ਉੱਤੇ ਸੀਮਿਤ ਕਰਦੇ ਹੋ ਉਨ੍ਹਾਂ ਵਿਚਕਾਰ ਅੰਤਰ ਸੁਧਾਰ ਤੋਂ ਬਾਅਦ ਲਿਖਤ ਅਸਫਲਤਾ ਦੁਬਾਰਾ ਲਿਆਉਣ ਦਾ ਸਭ ਤੋਂ ਆਮ ਤਰੀਕਾ ਹੈ। ਫਿਰ VPN ਸਰਵਰ ਤੱਕ ਟ੍ਰੈਫਿਕ ਲਿਜਾਣ ਵਾਲੇ ਸਾਕਟ ਦੀ ਰੱਖਿਆ ਕਰੋ। protect ਤੋਂ ਬਿਨਾਂ ਉਹ ਪੈਕੇਟ ਤੁਹਾਡੇ ਆਪਣੇ ਟਨਲ ਵਿੱਚ ਵਾਪਸ ਰੂਟ ਹੋ ਜਾਂਦੇ ਹਨ ਅਤੇ ਕਨੈਕਸ਼ਨ ਕਦੇ ਪੂਰਾ ਨਹੀਂ ਹੁੰਦਾ, ਜੋ ਅਟਕੀ ਪੜ੍ਹਤ ਵਰਗਾ ਦਿਸਦਾ ਹੈ ਪਰ ਰੂਟਿੰਗ ਲੂਪ ਹੈ।
ਸਹਿਮਤੀ ਟਾਲੀ ਨਹੀਂ ਜਾ ਸਕਦੀ। prepare null ਵਾਪਸ ਨਾ ਕਰਨ 'ਤੇ ਸ਼ੁਰੂ ਕੀਤੀ ਸੇਵਾ ਨੂੰ ਇੰਟਰਫੇਸ ਨਹੀਂ ਮਿਲਦਾ, ਅਤੇ establish ਸੁੱਟਣ ਦੀ ਥਾਂ null ਵਾਪਸ ਕਰਦਾ ਹੈ, ਇਸ ਲਈ ਲੂਪ ਸ਼ੁਰੂ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਡਿਸਕ੍ਰਿਪਟਰ ਜਾਂਚੋ। VpnService ਸੰਦਰਭ ਨਮੂਨਾ ਕਾਪੀ ਕਰਨ ਦੀ ਥਾਂ builder ਸਮਝੌਤਾ ਪੁਸ਼ਟੀ ਕਰਨ ਦੀ ਥਾਂ ਹੈ।
ਇੱਕ ਸਮੇਂ ਇੱਕ ਦਿਸ਼ਾ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ
TCP ਨੂੰ ਛੂਹਣ ਤੋਂ ਪਹਿਲਾਂ ਟਨਲ ਰਾਹੀਂ UDP ਗੂੰਜ ਭੇਜੋ ਅਤੇ ਪੈਕੇਟ ਲੰਬਾਈ ਦੇਖੋ। ਫਿਰ ਹੈਂਡਸ਼ੇਕ ਖੋਲ੍ਹੋ ਅਤੇ ਪੁਸ਼ਟੀ ਕਰੋ ਕਿ ਸੈਗਮੈਂਟ ਤੁਹਾਡੇ ਗਿਣੇ MSS ਤੋਂ ਥੱਲੇ ਰਹਿੰਦੇ ਹਨ। ਕਨੈਕਸ਼ਨਾਂ ਦੀ ਥਾਂ ਪੈਕੇਟ ਗਿਣੋ, ਤਾਂ ਜੋ ਰੁਕਾਵਟ ਅਟਕੇ ਸਾਕਟ ਦੀ ਥਾਂ ਕਾਊਂਟਰ ਵਿੱਚ ਖਾਲੀ ਥਾਂ ਵਜੋਂ ਦਿਸੇ। ਲਿਖਤਾਂ ਦੀ ਲਹਿਰ ਤੋਂ ਬਾਅਦ ਪੜ੍ਹਤ ਰੁਕ ਜਾਵੇ ਤਾਂ ਵਿੰਡੋ ਸ਼ੱਕੀ ਹੈ; ਲਿਖਤਾਂ ਤੁਰੰਤ ਅਸਫਲ ਹੋਣ ਤਾਂ ਲੰਬਾਈ।
ਫਿਰ ਡਿਵਾਈਸ ਰੀਬੂਟ ਕਰੋ ਅਤੇ ਇੱਕ ਵਾਰ ਦੁਹਰਾਓ, ਕਿਉਂਕਿ ਜੋ VpnService ਸਿਰਫ਼ ਪਹਿਲੇ ਨੈੱਟਵਰਕ ਬਦਲਾਅ ਤੱਕ ਕੰਮ ਕਰਦੀ ਹੈ ਉਹ ਪ੍ਰਵਾਹ ਨਿਯੰਤਰਣ ਦੀ ਨਹੀਂ, ਰੂਟਿੰਗ ਦੀ ਸਮੱਸਿਆ ਹੈ।