Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2a556e5

Browse files
committed
Always bind to localhost for connectors
This change makes it such that we always bind on a localhost interface to avoid repls being marked as being servers when they just want to debug. This is a tiny bit of a hack, but this was needed to avoid relying on a modified Eclipse JDT.
1 parent a976037 commit 2a556e5

File tree

7 files changed

+767
-2
lines changed

7 files changed

+767
-2
lines changed

com.microsoft.java.debug.plugin/src/main/java/com/microsoft/java/debug/plugin/internal/AdvancedLaunchingConnector.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import org.eclipse.jdi.internal.VirtualMachineImpl;
2121
import org.eclipse.jdi.internal.VirtualMachineManagerImpl;
2222
import org.eclipse.jdi.internal.connect.SocketLaunchingConnectorImpl;
23-
import org.eclipse.jdi.internal.connect.SocketListeningConnectorImpl;
2423

2524
import com.microsoft.java.debug.core.DebugUtility;
2625
import com.sun.jdi.VirtualMachine;
@@ -76,7 +75,7 @@ public VirtualMachine launch(Map<String, ? extends Argument> connectionArgs)
7675
// do nothing.
7776
}
7877

79-
SocketListeningConnectorImpl listenConnector = new SocketListeningConnectorImpl(
78+
LocalhostSocketListeningConnector listenConnector = new LocalhostSocketListeningConnector(
8079
virtualMachineManager());
8180
Map<String, Connector.Argument> args = listenConnector.defaultArguments();
8281
((Connector.IntegerArgument) args.get("timeout")).setValue(ACCEPT_TIMEOUT); //$NON-NLS-1$
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2017-2021 Microsoft Corporation and others.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v1.0
5+
* which accompanies this distribution, and is available at
6+
* http://www.eclipse.org/legal/epl-v10.html
7+
*
8+
* Contributors:
9+
* Microsoft Corporation - initial API and implementation
10+
*******************************************************************************/
11+
12+
package com.microsoft.java.debug.plugin.internal;
13+
14+
import java.io.File;
15+
import java.io.IOException;
16+
import java.nio.file.Files;
17+
import java.nio.file.Paths;
18+
import java.util.Map;
19+
20+
import org.eclipse.jdi.internal.VirtualMachineManagerImpl;
21+
import org.eclipse.jdi.internal.connect.ConnectMessages;
22+
import org.eclipse.jdi.internal.connect.SocketListeningConnectorImpl;
23+
import org.eclipse.jdi.internal.connect.SocketTransportImpl;
24+
25+
import com.sun.jdi.VirtualMachine;
26+
import com.sun.jdi.connect.Connector;
27+
import com.sun.jdi.connect.IllegalConnectorArgumentsException;
28+
import com.sun.jdi.connect.ListeningConnector;
29+
30+
/**
31+
* An advanced launching connector that supports cwd and enviroment variables.
32+
*
33+
*/
34+
public class AdvancedListeningConnector extends SocketListeningConnectorImpl implements ListeningConnector {
35+
private static final int ACCEPT_TIMEOUT = 10 * 1000;
36+
37+
public AdvancedListeningConnector(VirtualMachineManagerImpl virtualMachineManager) {
38+
super(virtualMachineManager);
39+
40+
// Create communication protocol specific transport.
41+
this.fTransport = new LocalhostSocketTransport();
42+
}
43+
44+
@Override
45+
public String name() {
46+
return "com.microsoft.java.debug.AdvancedListeningConnector";
47+
}
48+
49+
/**
50+
* Retrieves connection port.
51+
*/
52+
private int getConnectionPort(Map<String, ? extends Connector.Argument> connectionArgs) throws IllegalConnectorArgumentsException {
53+
String attribute = "port"; //$NON-NLS-1$
54+
try {
55+
// If listening port is not specified, use port 0
56+
IntegerArgument argument = (IntegerArgument) connectionArgs
57+
.get(attribute);
58+
if (argument != null && argument.value() != null) {
59+
return argument.intValue();
60+
} else {
61+
return 0;
62+
}
63+
} catch (ClassCastException e) {
64+
throw new IllegalConnectorArgumentsException(
65+
ConnectMessages.SocketListeningConnectorImpl_Connection_argument_is_not_of_the_right_type_6,
66+
attribute);
67+
} catch (NullPointerException e) {
68+
throw new IllegalConnectorArgumentsException(
69+
ConnectMessages.SocketListeningConnectorImpl_Necessary_connection_argument_is_null_7,
70+
attribute);
71+
} catch (NumberFormatException e) {
72+
throw new IllegalConnectorArgumentsException(
73+
ConnectMessages.SocketListeningConnectorImpl_Connection_argument_is_not_a_number_8,
74+
attribute);
75+
}
76+
}
77+
78+
/**
79+
* Listens for one or more connections initiated by target VMs.
80+
*
81+
* @return Returns the address at which the connector is listening for a
82+
* connection.
83+
*/
84+
@Override
85+
public String startListening(Map<String, ? extends Connector.Argument> connectionArgs) throws IOException, IllegalConnectorArgumentsException {
86+
int port = getConnectionPort(connectionArgs);
87+
String result = null;
88+
try {
89+
result = ((LocalhostSocketTransport) fTransport).startListening(port);
90+
} catch (IllegalArgumentException e) {
91+
throw new IllegalConnectorArgumentsException(
92+
ConnectMessages.SocketListeningConnectorImpl_ListeningConnector_Socket_Port,
93+
"port"); //$NON-NLS-1$
94+
}
95+
return result;
96+
}
97+
98+
/* (non-Javadoc)
99+
* @see com.sun.jdi.connect.ListeningConnector#stopListening(java.util.Map)
100+
*/
101+
@Override
102+
public void stopListening(Map<String, ? extends Connector.Argument> connectionArgs) throws IOException {
103+
((LocalhostSocketTransport) fTransport).stopListening();
104+
}
105+
106+
/**
107+
* Waits for a target VM to attach to this connector.
108+
*
109+
* @return Returns a connected Virtual Machine.
110+
*/
111+
@Override
112+
public VirtualMachine accept(Map<String, ? extends Connector.Argument> connectionArgs) throws IOException, IllegalConnectorArgumentsException {
113+
LocalhostSocketConnection connection = (LocalhostSocketConnection) ((LocalhostSocketTransport) fTransport)
114+
.accept(ACCEPT_TIMEOUT, 0);
115+
return establishedConnection(connection);
116+
}
117+
}

com.microsoft.java.debug.plugin/src/main/java/com/microsoft/java/debug/plugin/internal/AdvancedVirtualMachineManager.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.sun.jdi.VirtualMachine;
2222
import com.sun.jdi.VirtualMachineManager;
2323
import com.sun.jdi.connect.LaunchingConnector;
24+
import com.sun.jdi.connect.ListeningConnector;
2425

2526
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
2627
import org.eclipse.core.runtime.preferences.InstanceScope;
@@ -46,6 +47,14 @@ public List<LaunchingConnector> launchingConnectors() {
4647
return connectors;
4748
}
4849

50+
@Override
51+
public List<ListeningConnector> listeningConnectors() {
52+
List<ListeningConnector> connectors = new ArrayList<>();
53+
connectors.add(new AdvancedListeningConnector(this));
54+
connectors.addAll(super.listeningConnectors());
55+
return connectors;
56+
}
57+
4958
@Override
5059
public void update(DebugSettings oldSettings, DebugSettings newSettings) {
5160
int currentTimeout = getGlobalRequestTimeout();
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/**
2+
* Copyright (c) 2000, 2016 IBM Corporation and others.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* IBM Corporation - initial API and implementation
13+
* Google Inc - add support for accepting multiple connections
14+
*******************************************************************************/
15+
package com.microsoft.java.debug.plugin.internal;
16+
17+
import java.io.DataInputStream;
18+
import java.io.IOException;
19+
import java.io.InputStream;
20+
import java.io.OutputStream;
21+
import java.net.Socket;
22+
23+
import org.eclipse.jdi.internal.connect.SocketConnection;
24+
25+
import com.sun.jdi.connect.spi.ClosedConnectionException;
26+
import com.sun.jdi.connect.spi.Connection;
27+
28+
public class LocalhostSocketConnection extends Connection {
29+
// for attaching connector
30+
private Socket fSocket;
31+
32+
private InputStream fInput;
33+
34+
private OutputStream fOutput;
35+
36+
LocalhostSocketConnection(Socket socket, InputStream in, OutputStream out) {
37+
fSocket = socket;
38+
fInput = in;
39+
fOutput = out;
40+
}
41+
42+
/*
43+
* (non-Javadoc)
44+
*
45+
* @see com.sun.jdi.connect.spi.Connection#close()
46+
*/
47+
@Override
48+
public synchronized void close() throws IOException {
49+
if (fSocket == null)
50+
return;
51+
52+
fSocket.close();
53+
fSocket = null;
54+
}
55+
56+
/*
57+
* (non-Javadoc)
58+
*
59+
* @see com.sun.jdi.connect.spi.Connection#isOpen()
60+
*/
61+
@Override
62+
public synchronized boolean isOpen() {
63+
return fSocket != null;
64+
}
65+
66+
/*
67+
* (non-Javadoc)
68+
*
69+
* @see com.sun.jdi.connect.spi.Connection#readPacket()
70+
*/
71+
@Override
72+
public byte[] readPacket() throws IOException {
73+
DataInputStream stream;
74+
synchronized (this) {
75+
if (!isOpen()) {
76+
throw new ClosedConnectionException();
77+
}
78+
stream = new DataInputStream(fInput);
79+
}
80+
synchronized (stream) {
81+
int packetLength = 0;
82+
try {
83+
packetLength = stream.readInt();
84+
} catch (IOException e) {
85+
throw new ClosedConnectionException();
86+
}
87+
88+
if (packetLength < 11) {
89+
throw new IOException("JDWP Packet under 11 bytes"); //$NON-NLS-1$
90+
}
91+
92+
byte[] packet = new byte[packetLength];
93+
packet[0] = (byte) ((packetLength >>> 24) & 0xFF);
94+
packet[1] = (byte) ((packetLength >>> 16) & 0xFF);
95+
packet[2] = (byte) ((packetLength >>> 8) & 0xFF);
96+
packet[3] = (byte) ((packetLength >>> 0) & 0xFF);
97+
98+
stream.readFully(packet, 4, packetLength - 4);
99+
return packet;
100+
}
101+
}
102+
103+
/*
104+
* (non-Javadoc)
105+
*
106+
* @see com.sun.jdi.connect.spi.Connection#writePacket(byte[])
107+
*/
108+
@Override
109+
public void writePacket(byte[] packet) throws IOException {
110+
if (!isOpen()) {
111+
throw new ClosedConnectionException();
112+
}
113+
if (packet == null) {
114+
throw new IllegalArgumentException(
115+
"Invalid JDWP Packet, packet cannot be null"); //$NON-NLS-1$
116+
}
117+
if (packet.length < 11) {
118+
throw new IllegalArgumentException(
119+
"Invalid JDWP Packet, must be at least 11 bytes. PacketSize:" + packet.length); //$NON-NLS-1$
120+
}
121+
122+
int packetSize = getPacketLength(packet);
123+
if (packetSize < 11) {
124+
throw new IllegalArgumentException(
125+
"Invalid JDWP Packet, must be at least 11 bytes. PacketSize:" + packetSize); //$NON-NLS-1$
126+
}
127+
128+
if (packetSize > packet.length) {
129+
throw new IllegalArgumentException(
130+
"Invalid JDWP packet: Specified length is greater than actual length"); //$NON-NLS-1$
131+
}
132+
133+
OutputStream stream = null;
134+
synchronized (this) {
135+
if (!isOpen()) {
136+
throw new ClosedConnectionException();
137+
}
138+
stream = fOutput;
139+
}
140+
141+
synchronized (stream) {
142+
// packet.length can be > packetSize. Sending too much will cause
143+
// errors on the other side
144+
stream.write(packet, 0, packetSize);
145+
}
146+
}
147+
148+
private int getPacketLength(byte[] packet) {
149+
int len = 0;
150+
if (packet.length >= 4) {
151+
len = (((packet[0] & 0xFF) << 24) + ((packet[1] & 0xFF) << 16)
152+
+ ((packet[2] & 0xFF) << 8) + ((packet[3] & 0xFF) << 0));
153+
}
154+
return len;
155+
}
156+
}

0 commit comments

Comments
 (0)