com.subgraph.orchid.sockets.OrchidSocketImpl Maven / Gradle / Ivy
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.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.*;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.Lock;
public class OrchidSocketImpl extends SocketImpl {
private final TorClient torClient;
private Lock streamLock = Threading.lock("stream");
private Stream stream;
OrchidSocketImpl(TorClient torClient) {
this.torClient = torClient;
this.fd = new FileDescriptor();
}
public void setOption(int optID, Object value) throws SocketException {
throw new UnsupportedOperationException();
}
public Object getOption(int optID) throws SocketException {
if(optID == SocketOptions.SO_LINGER) {
return 0;
} else if(optID == SocketOptions.TCP_NODELAY) {
return Boolean.TRUE;
} else if(optID == SocketOptions.SO_TIMEOUT) {
return 0;
} else {
return 0;
}
}
@Override
protected void create(boolean stream) throws IOException {
}
@Override
protected void connect(String host, int port) throws IOException {
SocketAddress endpoint =
InetSocketAddress.createUnresolved(host, port);
connect(endpoint, 0);
}
@Override
protected void connect(InetAddress address, int port) throws IOException {
SocketAddress endpoint =
InetSocketAddress.createUnresolved(address.getHostAddress(), port);
connect(endpoint, 0);
}
@Override
protected void connect(SocketAddress address, int timeout)
throws IOException {
if(!(address instanceof InetSocketAddress)) {
throw new IllegalArgumentException("Unsupported address type");
}
final InetSocketAddress inetAddress = (InetSocketAddress) address;
doConnect(addressToName(inetAddress), inetAddress.getPort());
}
private String addressToName(InetSocketAddress address) {
if(address.getAddress() != null) {
return address.getAddress().getHostAddress();
} else {
return address.getHostName();
}
}
private void doConnect(String host, int port) throws IOException {
Stream stream;
// 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");
try {
stream = torClient.openExitStreamTo(host, port);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new SocketException("connect() interrupted");
} catch (TimeoutException e) {
throw new SocketTimeoutException();
} catch (OpenFailedException e) {
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();
}
}
@Override
protected void bind(InetAddress host, int port) throws IOException {
throw new UnsupportedOperationException();
}
@Override
protected void listen(int backlog) throws IOException {
throw new UnsupportedOperationException();
}
@Override
protected void accept(SocketImpl s) throws IOException {
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
protected InputStream getInputStream() throws IOException {
return getStream().getInputStream();
}
@Override
protected OutputStream getOutputStream() throws IOException {
return getStream().getOutputStream();
}
@Override
protected int available() throws IOException {
return getStream().getInputStream().available();
}
@Override
protected void close() throws IOException {
Stream toClose;
streamLock.lock();
toClose = this.stream;
this.stream = null;
streamLock.unlock();
if (toClose != null)
toClose.close();
}
@Override
protected void sendUrgentData(int data) throws IOException {
throw new UnsupportedOperationException();
}
protected void shutdownInput() throws IOException {
//throw new IOException("Method not implemented!");
}
protected void shutdownOutput() throws IOException {
//throw new IOException("Method not implemented!");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy