mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-02-12 10:15:52 +00:00
OrchidSocketImpl: don't hold the stream lock whilst calling into stream.
This commit is contained in:
parent
57bec6165b
commit
325cc3e8fa
@ -1,28 +1,22 @@
|
|||||||
package com.subgraph.orchid.sockets;
|
package com.subgraph.orchid.sockets;
|
||||||
|
|
||||||
|
import com.subgraph.orchid.OpenFailedException;
|
||||||
|
import com.subgraph.orchid.Stream;
|
||||||
|
import com.subgraph.orchid.Threading;
|
||||||
|
import com.subgraph.orchid.TorClient;
|
||||||
|
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.ConnectException;
|
import java.net.*;
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.net.SocketAddress;
|
|
||||||
import java.net.SocketException;
|
|
||||||
import java.net.SocketImpl;
|
|
||||||
import java.net.SocketOptions;
|
|
||||||
import java.net.SocketTimeoutException;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
import com.subgraph.orchid.OpenFailedException;
|
|
||||||
import com.subgraph.orchid.Stream;
|
|
||||||
import com.subgraph.orchid.TorClient;
|
|
||||||
|
|
||||||
public class OrchidSocketImpl extends SocketImpl {
|
public class OrchidSocketImpl extends SocketImpl {
|
||||||
|
|
||||||
private final TorClient torClient;
|
private final TorClient torClient;
|
||||||
private final Object streamLock = new Object();
|
|
||||||
|
|
||||||
|
private Lock streamLock = Threading.lock("stream");
|
||||||
private Stream stream;
|
private Stream stream;
|
||||||
|
|
||||||
OrchidSocketImpl(TorClient torClient) {
|
OrchidSocketImpl(TorClient torClient) {
|
||||||
@ -85,10 +79,17 @@ public class OrchidSocketImpl extends SocketImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void doConnect(String host, int port) throws IOException {
|
private void doConnect(String host, int port) throws IOException {
|
||||||
synchronized(streamLock) {
|
Stream stream;
|
||||||
if(stream != null) {
|
|
||||||
|
// Try to avoid holding the stream lock here whilst calling into torclient to avoid accidental inversions.
|
||||||
|
|
||||||
|
streamLock.lock();
|
||||||
|
stream = this.stream;
|
||||||
|
streamLock.unlock();
|
||||||
|
|
||||||
|
if (stream != null)
|
||||||
throw new SocketException("Already connected");
|
throw new SocketException("Already connected");
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
stream = torClient.openExitStreamTo(host, port);
|
stream = torClient.openExitStreamTo(host, port);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
@ -99,6 +100,15 @@ public class OrchidSocketImpl extends SocketImpl {
|
|||||||
} catch (OpenFailedException e) {
|
} catch (OpenFailedException e) {
|
||||||
throw new ConnectException(e.getMessage());
|
throw new ConnectException(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
streamLock.lock();
|
||||||
|
if (this.stream != null) {
|
||||||
|
// Raced with another concurrent call.
|
||||||
|
streamLock.unlock();
|
||||||
|
stream.close();
|
||||||
|
} else {
|
||||||
|
this.stream = stream;
|
||||||
|
streamLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,44 +127,41 @@ public class OrchidSocketImpl extends SocketImpl {
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Stream getStream() throws IOException {
|
||||||
|
streamLock.lock();
|
||||||
|
try {
|
||||||
|
if (stream == null)
|
||||||
|
throw new IOException("Not connected");
|
||||||
|
return stream;
|
||||||
|
} finally {
|
||||||
|
streamLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected InputStream getInputStream() throws IOException {
|
protected InputStream getInputStream() throws IOException {
|
||||||
synchronized (streamLock) {
|
return getStream().getInputStream();
|
||||||
if(stream == null) {
|
|
||||||
throw new IOException("Not connected");
|
|
||||||
}
|
|
||||||
return stream.getInputStream();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected OutputStream getOutputStream() throws IOException {
|
protected OutputStream getOutputStream() throws IOException {
|
||||||
synchronized (streamLock) {
|
return getStream().getOutputStream();
|
||||||
if(stream == null) {
|
|
||||||
throw new IOException("Not connected");
|
|
||||||
}
|
|
||||||
return stream.getOutputStream();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int available() throws IOException {
|
protected int available() throws IOException {
|
||||||
synchronized(streamLock) {
|
return getStream().getInputStream().available();
|
||||||
if(stream == null) {
|
|
||||||
throw new IOException("Not connected");
|
|
||||||
}
|
|
||||||
return stream.getInputStream().available();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void close() throws IOException {
|
protected void close() throws IOException {
|
||||||
synchronized (streamLock) {
|
Stream toClose;
|
||||||
if(stream != null) {
|
streamLock.lock();
|
||||||
stream.close();
|
toClose = this.stream;
|
||||||
stream = null;
|
this.stream = null;
|
||||||
}
|
streamLock.unlock();
|
||||||
}
|
if (toClose != null)
|
||||||
|
toClose.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user