Skip to content

Commit 5e3df45

Browse files
committed
Combine selection handling of TCP & UDP to simplify & drop dead paths
1 parent 043acfa commit 5e3df45

File tree

1 file changed

+27
-72
lines changed

1 file changed

+27
-72
lines changed

app/src/main/java/tech/httptoolkit/android/vpn/socket/SocketNIODataService.java

Lines changed: 27 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -154,16 +154,12 @@ private void runTask(){
154154

155155
Session session = ((Session) key.attachment());
156156
synchronized (session) { // Sessions are locked during processing (no VPN data races)
157-
if (selectableChannel instanceof SocketChannel) {
158-
try {
159-
processTCPSelectionKey(key);
160-
} catch (IOException e) {
161-
synchronized (key) {
162-
key.cancel();
163-
}
157+
try {
158+
processSelectionKey(key);
159+
} catch (IOException e) {
160+
synchronized (key) {
161+
key.cancel();
164162
}
165-
} else if (selectableChannel instanceof DatagramChannel) {
166-
processUDPSelectionKey(key);
167163
}
168164
}
169165

@@ -179,84 +175,43 @@ private void runTask(){
179175
Log.i(TAG, "NIO selector shutdown");
180176
}
181177

182-
private void processUDPSelectionKey(SelectionKey key){
183-
if(!key.isValid()){
184-
Log.d(TAG,"Invalid SelectionKey for UDP");
178+
private void processSelectionKey(SelectionKey key) throws IOException {
179+
if (!key.isValid()) {
180+
Log.d(TAG,"Invalid SelectionKey");
185181
return;
186182
}
187-
DatagramChannel channel = (DatagramChannel) key.channel();
183+
184+
SelectableChannel channel = key.channel();
188185

189186
Session session = ((Session) key.attachment());
190187
if (session == null) {
188+
Log.w(TAG, "Key fired with no session attached");
191189
return;
192190
}
193191

194-
if (!session.isConnected() && key.isConnectable()) {
195-
String ips = PacketUtil.intToIPAddress(session.getDestIp());
196-
int port = session.getDestPort();
197-
SocketAddress address = new InetSocketAddress(ips,port);
198-
try {
199-
Log.d(TAG,"selector: connecting to remote UDP server: "+ips+":"+port);
200-
channel = channel.connect(address);
201-
session.setChannel(channel);
202-
session.setConnected(channel.isConnected());
203-
}catch (Exception e) {
204-
e.printStackTrace();
205-
session.setAbortingConnection(true);
192+
if (channel instanceof SocketChannel && !session.isConnected() && key.isConnectable()) {
193+
SocketChannel socketChannel = (SocketChannel) channel;
194+
195+
if (socketChannel.isConnectionPending()) {
196+
boolean connected = socketChannel.finishConnect();
197+
session.setConnected(connected);
198+
} else {
199+
throw new IllegalStateException("TCP channels must either be connected or pending connection");
206200
}
207201
}
208202

209-
if(channel.isConnected()){
203+
if (isConnected(channel)) {
210204
processConnectedSelection(key, session);
211205
}
212206
}
213207

214-
private void processTCPSelectionKey(SelectionKey key) throws IOException{
215-
if (!key.isValid()) {
216-
Log.d(TAG,"Invalid SelectionKey for TCP");
217-
return;
218-
}
219-
220-
SocketChannel channel = (SocketChannel)key.channel();
221-
Session session = ((Session) key.attachment());
222-
if(session == null){
223-
return;
224-
}
225-
226-
if (!session.isConnected() && key.isConnectable()) {
227-
String ips = PacketUtil.intToIPAddress(session.getDestIp());
228-
int port = session.getDestPort();
229-
SocketAddress address = new InetSocketAddress(ips, port);
230-
Log.d(TAG,"connecting to remote tcp server: " + ips + ":" + port);
231-
boolean connected = false;
232-
if(!channel.isConnected() && !channel.isConnectionPending()){
233-
try{
234-
connected = channel.connect(address);
235-
} catch (
236-
UnresolvedAddressException |
237-
UnsupportedAddressTypeException |
238-
SecurityException |
239-
IOException e
240-
) {
241-
Log.e(TAG, e.toString());
242-
session.setAbortingConnection(true);
243-
}
244-
}
245-
246-
if (connected) {
247-
session.setConnected(true);
248-
Log.d(TAG,"connected immediately to remote tcp server: "+ips+":"+port);
249-
} else {
250-
if (channel.isConnectionPending()) {
251-
connected = channel.finishConnect();
252-
session.setConnected(connected);
253-
Log.d(TAG,"connected to remote tcp server: "+ips+":"+port);
254-
}
255-
}
256-
}
257-
258-
if (channel.isConnected()) {
259-
processConnectedSelection(key, session);
208+
private boolean isConnected(SelectableChannel channel) {
209+
if (channel instanceof DatagramChannel) {
210+
return ((DatagramChannel) channel).isConnected();
211+
} else if (channel instanceof SocketChannel) {
212+
return ((SocketChannel) channel).isConnected();
213+
} else {
214+
throw new IllegalArgumentException("isConnected on unexpected channel type: " + channel);
260215
}
261216
}
262217

0 commit comments

Comments
 (0)