- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
是否可以找到Android OpenSSLSocketImpl 关闭Socket 的原因? (如何调试 Android 内部库?)
背景:可以找到我尝试创建 SSLContext 的来源 in TLSNetSocketUtil.java在调用 resultSocket.getSession() 期间,底层套接字正在关闭。
当 Socket 关闭时,我记录了一个 Stacktrace:
at org.silvertunnel_ng.netlib.layer.logger.LoggingNetSocket.close(LoggingNetSocket.java:66)
at org.silvertunnel_ng.netlib.api.impl.NetSocket2SocketImpl.close(NetSocket2SocketImpl.java:144)
at java.net.Socket.close(Socket.java:319)
at com.android.org.conscrypt.OpenSSLSocketImpl.closeUnderlyingSocket(OpenSSLSocketImpl.java:1134)
at com.android.org.conscrypt.OpenSSLSocketImpl.shutdownAndFreeSslNative(OpenSSLSocketImpl.java:1127)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:406)
at com.android.org.conscrypt.OpenSSLSocketImpl.waitForHandshake(OpenSSLSocketImpl.java:623)
at com.android.org.conscrypt.OpenSSLSocketImpl.getSession(OpenSSLSocketImpl.java:787)
at org.silvertunnel_ng.netlib.layer.tls.TLSNetSocketUtil.createTLSSocket(TLSNetSocketUtil.java:111)
我想我已经将其确定为 OpenSSLSocketImpl.java 中的第 528 - 555 行, 所以似乎握手的某些东西没有起作用,但是什么?
在除 Android 以外的其他 JVM 上运行它工作正常。
有什么建议吗?
更新 1:来自 startHandshake-Method 的堆栈跟踪:
java.net.SocketException: Socket closed
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:318)
at org.silvertunnel_ng.netlib.layer.tls.TLSNetSocketUtil.createTLSSocket(TLSNetSocketUtil.java:110)
at org.silvertunnel_ng.netlib.layer.tls.TLSNetLayer.createNetSocket(TLSNetLayer.java:101)
at org.silvertunnel_ng.netlib.layer.logger.LoggingNetLayer.createNetSocket(LoggingNetLayer.java:130)
at org.silvertunnel_ng.netlib.layer.tor.circuit.TLSConnection.<init>(TLSConnection.java:128)
at org.silvertunnel_ng.netlib.layer.tor.circuit.TLSConnectionAdmin.getConnection(TLSConnectionAdmin.java:118)
at org.silvertunnel_ng.netlib.layer.tor.circuit.Circuit.<init>(Circuit.java:299)
at org.silvertunnel_ng.netlib.layer.tor.clientimpl.TorBackgroundMgmtThread$1.run(TorBackgroundMgmtThread.java:157)
最佳答案
com.android.org.conscrypt.NativeCrypto.SSL_do_handshake
中的 native 代码正在检查来自底层 SocketImpl
的提供的 FileDescriptor
Socket
类。
因为要伪造它并不容易,所以我必须实现 LocalSockets
的使用以使其工作。
import android.net.LocalServerSocket;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import org.silvertunnel_ng.netlib.layer.tor.util.TorException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.*;
import java.nio.channels.SocketChannel;
import java.util.UUID;
/**
* Created by b4dt0bi on 17.05.15.
*/
public class LocalProxySocket extends Socket {
private LocalServerSocket localServerSocket;
private LocalSocket localSocketSend;
private LocalSocket localSocketRecv;
private Socket originalSocket;
private static final Logger LOG = LoggerFactory.getLogger(LocalProxySocket.class);
public LocalProxySocket(Socket original) throws TorException {
super();
try {
// Prepare LocalSocket which will be used to trick the SSLSocket (or any other one)
localSocketSend = new LocalSocket();
// Local socket name
String socketName = "local" + UUID.randomUUID();
localServerSocket = new LocalServerSocket(socketName);
localSocketSend.connect(new LocalSocketAddress(socketName));
localSocketRecv = localServerSocket.accept();
this.originalSocket = original;
// Create 2 Threads which are taking care of the communication between the LocalSocket and the original Socket
LocalProxyWorker lpw1 = new LocalProxyWorker(localSocketRecv.getInputStream(), originalSocket.getOutputStream(), "to");
LocalProxyWorker lpw2 = new LocalProxyWorker(originalSocket.getInputStream(), localSocketRecv.getOutputStream(), "from");
Thread t1 = new Thread(lpw1);
Thread t2 = new Thread(lpw2);
t1.start();
t2.start();
// Prepare this Socket to contain the FileDescriptor of the LocalSocket
FileDescriptor fd = localSocketSend.getFileDescriptor();
SocketImpl socketImpl = (SocketImpl) Class.forName("java.net.PlainSocketImpl").getConstructor(FileDescriptor.class).newInstance(fd);
Field implField = this.getClass().getSuperclass().getDeclaredField("impl");
implField.setAccessible(true);
implField.set(this, socketImpl);
} catch (Exception e) {
LOG.debug("Got Exception while trying to create LocalProxySocket", e);
throw new TorException("could not create LocalProxySocket", e);
}
}
private class LocalProxyWorker implements Runnable {
private InputStream inputStream;
private OutputStream outputStream;
private String direction;
public LocalProxyWorker(InputStream inputStream, OutputStream outputStream, String direction) {
this.inputStream = inputStream;
this.outputStream = outputStream;
this.direction = direction;
}
// TODO : cleanup exception handling
@Override
public void run() {
boolean error = false;
while (!error) {
try {
if (inputStream.available() > 0) {
copyStream(inputStream, outputStream);
}
} catch (IOException e) {
LOG.debug("got Exception during copy", e);
error = true;
try {
inputStream.close();
} catch (IOException e1) {
LOG.debug("got exception during close of inputStream", e1);
}
try {
outputStream.close();
} catch (IOException e1) {
LOG.debug("got exception during close of outputStream", e1);
}
}
}
}
void copyStream(InputStream input, OutputStream output)
throws IOException {
byte[] buffer = new byte[1024]; // Adjust if you want
int bytesRead;
while ((bytesRead = input.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
}
}
/**
* Closes the originalSocket. It is not possible to reconnect or rebind to this
* originalSocket thereafter which means a new originalSocket instance has to be created.
*
* @throws IOException if an error occurs while closing the originalSocket.
*/
public synchronized void close() throws IOException {
super.close();
originalSocket.close();
localSocketRecv.close();
LOG.debug("LocalProxySocket", "close() called", new Throwable());
}
/**
* Returns the IP address of the target host this originalSocket is connected to, or null if this
* originalSocket is not yet connected.
*/
public InetAddress getInetAddress() {
LOG.debug("LocalProxySocket", "getInetAddress() called", new Throwable());
return originalSocket.getInetAddress();
}
/**
* Returns an input stream to read data from this originalSocket. If the originalSocket has an associated
* {@link SocketChannel} and that channel is in non-blocking mode then reads from the
* stream will throw a {@link java.nio.channels.IllegalBlockingModeException}.
*
* @return the byte-oriented input stream.
* @throws IOException if an error occurs while creating the input stream or the
* originalSocket is in an invalid state.
*/
public InputStream getInputStream() throws IOException {
LOG.debug("LocalProxySocket", "getInputStream() called", new Throwable());
return super.getInputStream();
}
/**
* Returns this originalSocket's {@link SocketOptions#SO_KEEPALIVE} setting.
*/
public boolean getKeepAlive() throws SocketException {
LOG.debug("LocalProxySocket", "getKeepAlive() called", new Throwable());
return originalSocket.getKeepAlive();
}
/**
* Returns the local IP address this originalSocket is bound to, or an address for which
* {@link InetAddress#isAnyLocalAddress()} returns true if the originalSocket is closed or unbound.
*/
public InetAddress getLocalAddress() {
LOG.debug("LocalProxySocket", "getLocalAddress() called", new Throwable());
return originalSocket.getLocalAddress();
}
/**
* Returns the local port this originalSocket is bound to, or -1 if the originalSocket is unbound. If the originalSocket
* has been closed this method will still return the local port the originalSocket was bound to.
*/
public int getLocalPort() {
LOG.debug("LocalProxySocket", "getLocalPort() called", new Throwable());
return originalSocket.getLocalPort();
}
/**
* Returns an output stream to write data into this originalSocket. If the originalSocket has an associated
* {@link SocketChannel} and that channel is in non-blocking mode then writes to the
* stream will throw a {@link java.nio.channels.IllegalBlockingModeException}.
*
* @return the byte-oriented output stream.
* @throws IOException if an error occurs while creating the output stream or the
* originalSocket is in an invalid state.
*/
public OutputStream getOutputStream() throws IOException {
LOG.debug("LocalProxySocket", "getOutputStream() called", new Throwable());
return super.getOutputStream();
}
/**
* Returns the port number of the target host this originalSocket is connected to, or 0 if this originalSocket
* is not yet connected.
*/
public int getPort() {
LOG.debug("LocalProxySocket", "getPort() called", new Throwable());
return originalSocket.getPort();
}
/**
* Returns this originalSocket's {@link SocketOptions#SO_LINGER linger} timeout in seconds, or -1
* for no linger (i.e. {@code close} will return immediately).
*/
public int getSoLinger() throws SocketException {
LOG.debug("LocalProxySocket", "getSoLinger() called", new Throwable());
return originalSocket.getSoLinger();
}
/**
* Returns this originalSocket's {@link SocketOptions#SO_RCVBUF receive buffer size}.
*/
public synchronized int getReceiveBufferSize() throws SocketException {
LOG.debug("LocalProxySocket", "getReceiveBufferSize() called", new Throwable());
return originalSocket.getReceiveBufferSize();
}
/**
* Returns this originalSocket's {@link SocketOptions#SO_SNDBUF send buffer size}.
*/
public synchronized int getSendBufferSize() throws SocketException {
LOG.debug("LocalProxySocket", "getSendBufferSize() called", new Throwable());
return originalSocket.getSendBufferSize();
}
/**
* Returns this originalSocket's {@link SocketOptions#SO_TIMEOUT receive timeout}.
*/
public synchronized int getSoTimeout() throws SocketException {
LOG.debug("LocalProxySocket", "getSoTimeout() called", new Throwable());
return originalSocket.getSoTimeout();
}
/**
* Returns this originalSocket's {@code SocketOptions#TCP_NODELAY} setting.
*/
public boolean getTcpNoDelay() throws SocketException {
LOG.debug("LocalProxySocket", "getTcpNoDelay() called", new Throwable());
return originalSocket.getTcpNoDelay();
}
/**
* Sets this originalSocket's {@link SocketOptions#SO_KEEPALIVE} option.
*/
public void setKeepAlive(boolean keepAlive) throws SocketException {
LOG.debug("LocalProxySocket", "setKeepAlive() called", new Throwable());
originalSocket.setKeepAlive(keepAlive);
}
/**
* Sets this originalSocket's {@link SocketOptions#SO_SNDBUF send buffer size}.
*/
public synchronized void setSendBufferSize(int size) throws SocketException {
LOG.debug("LocalProxySocket", "setSendBufferSize() called", new Throwable());
originalSocket.setSendBufferSize(size);
}
/**
* Sets this originalSocket's {@link SocketOptions#SO_RCVBUF receive buffer size}.
*/
public synchronized void setReceiveBufferSize(int size) throws SocketException {
LOG.debug("LocalProxySocket", "setReceiveBufferSize() called", new Throwable());
originalSocket.setReceiveBufferSize(size);
}
/**
* Sets this originalSocket's {@link SocketOptions#SO_LINGER linger} timeout in seconds.
* If {@code on} is false, {@code timeout} is irrelevant.
*/
public void setSoLinger(boolean on, int timeout) throws SocketException {
LOG.debug("LocalProxySocket", "setSoLinger() called", new Throwable());
originalSocket.setSoLinger(on, timeout);
}
/**
* Sets this originalSocket's {@link SocketOptions#SO_TIMEOUT read timeout} in milliseconds.
* Use 0 for no timeout.
* To take effect, this option must be set before the blocking method was called.
*/
public synchronized void setSoTimeout(int timeout) throws SocketException {
LOG.debug("LocalProxySocket", "setSoTimeout() called", new Throwable());
originalSocket.setSoTimeout(timeout);
}
/**
* Sets this originalSocket's {@link SocketOptions#TCP_NODELAY} option.
*/
public void setTcpNoDelay(boolean on) throws SocketException {
LOG.debug("LocalProxySocket", "setTcpNoDelay() called", new Throwable());
originalSocket.setTcpNoDelay(on);
}
/**
* Returns a {@code String} containing a concise, human-readable description of the
* originalSocket.
*
* @return the textual representation of this originalSocket.
*/
@Override
public String toString() {
LOG.debug("LocalProxySocket", "toString() called", new Throwable());
return "LocalProxySocket : " + super.toString() + " - " + originalSocket.toString() + " - " + localSocketSend.toString();
}
/**
* Closes the input stream of this originalSocket. Any further data sent to this
* originalSocket will be discarded. Reading from this originalSocket after this method has
* been called will return the value {@code EOF}.
*
* @throws IOException if an error occurs while closing the originalSocket input stream.
* @throws SocketException if the input stream is already closed.
*/
public void shutdownInput() throws IOException {
LOG.debug("LocalProxySocket", "shutdownInput() called", new Throwable());
originalSocket.shutdownInput();
localSocketRecv.shutdownInput();
}
/**
* Closes the output stream of this originalSocket. All buffered data will be sent
* followed by the termination sequence. Writing to the closed output stream
* will cause an {@code IOException}.
*
* @throws IOException if an error occurs while closing the originalSocket output stream.
* @throws SocketException if the output stream is already closed.
*/
public void shutdownOutput() throws IOException {
LOG.debug("LocalProxySocket", "shutdownOutput() called", new Throwable());
originalSocket.shutdownOutput();
localSocketRecv.shutdownOutput();
}
/**
* Returns the local address and port of this originalSocket as a SocketAddress or null if the originalSocket
* has never been bound. If the originalSocket is closed but has previously been bound then an address
* for which {@link InetAddress#isAnyLocalAddress()} returns true will be returned with the
* previously-bound port. This is useful on multihomed hosts.
*/
public SocketAddress getLocalSocketAddress() {
LOG.debug("LocalProxySocket", "getLocalSocketAddress() called", new Throwable());
return originalSocket.getLocalSocketAddress();
}
/**
* Returns the remote address and port of this originalSocket as a {@code
* SocketAddress} or null if the originalSocket is not connected.
*
* @return the remote originalSocket address and port.
*/
public SocketAddress getRemoteSocketAddress() {
LOG.debug("LocalProxySocket", "getRemoteSocketAddress() called", new Throwable());
return originalSocket.getRemoteSocketAddress();
}
/**
* Returns whether this originalSocket is bound to a local address and port.
*
* @return {@code true} if the originalSocket is bound to a local address, {@code
* false} otherwise.
*/
public boolean isBound() {
LOG.debug("LocalProxySocket", "isBound() called", new Throwable());
return originalSocket.isBound();
}
/**
* Returns whether this originalSocket is connected to a remote host.
*
* @return {@code true} if the originalSocket is connected, {@code false} otherwise.
*/
public boolean isConnected() {
LOG.debug("LocalProxySocket", "isConnected() called", new Throwable());
return originalSocket.isConnected();
//return true;
}
/**
* Returns whether this originalSocket is closed.
*
* @return {@code true} if the originalSocket is closed, {@code false} otherwise.
*/
public boolean isClosed() {
LOG.debug("LocalProxySocket", "isClosed() called", new Throwable());
return originalSocket.isClosed();
}
/**
* Binds this originalSocket to the given local host address and port specified by
* the SocketAddress {@code localAddr}. If {@code localAddr} is set to
* {@code null}, this originalSocket will be bound to an available local address on
* any free port.
*
* @param localAddr the specific address and port on the local machine to bind to.
* @throws IllegalArgumentException if the given SocketAddress is invalid or not supported.
* @throws IOException if the originalSocket is already bound or an error occurs while
* binding.
*/
public void bind(SocketAddress localAddr) throws IOException {
LOG.debug("LocalProxySocket", "bind(localAddr) called", new Throwable());
originalSocket.bind(localAddr);
}
/**
* Connects this originalSocket to the given remote host address and port specified
* by the SocketAddress {@code remoteAddr}.
*
* @param remoteAddr the address and port of the remote host to connect to.
* @throws IllegalArgumentException if the given SocketAddress is invalid or not supported.
* @throws IOException if the originalSocket is already connected or an error occurs while
* connecting.
*/
public void connect(SocketAddress remoteAddr) throws IOException {
LOG.debug("LocalProxySocket", "connect(remoteAddr) called", new Throwable());
originalSocket.connect(remoteAddr);
}
/**
* Connects this originalSocket to the given remote host address and port specified
* by the SocketAddress {@code remoteAddr} with the specified timeout. The
* connecting method will block until the connection is established or an
* error occurred.
*
* @param remoteAddr the address and port of the remote host to connect to.
* @param timeout the timeout value in milliseconds or {@code 0} for an infinite
* timeout.
* @throws IllegalArgumentException if the given SocketAddress is invalid or not supported or the
* timeout value is negative.
* @throws IOException if the originalSocket is already connected or an error occurs while
* connecting.
*/
public void connect(SocketAddress remoteAddr, int timeout) throws IOException {
LOG.debug("LocalProxySocket", "connect(remoteAddr, timeout) called", new Throwable());
originalSocket.connect(remoteAddr, timeout);
}
/**
* Returns whether the incoming channel of the originalSocket has already been
* closed.
*
* @return {@code true} if reading from this originalSocket is not possible anymore,
* {@code false} otherwise.
*/
public boolean isInputShutdown() {
LOG.debug("LocalProxySocket", "isInputShutdown() called", new Throwable());
return originalSocket.isInputShutdown() || localSocketRecv.isInputShutdown();
}
/**
* Returns whether the outgoing channel of the originalSocket has already been
* closed.
*
* @return {@code true} if writing to this originalSocket is not possible anymore,
* {@code false} otherwise.
*/
public boolean isOutputShutdown() {
LOG.debug("LocalProxySocket", "isOutputShutdown() called", new Throwable());
return originalSocket.isOutputShutdown() || localSocketRecv.isOutputShutdown();
}
}
关于java - getSession 关闭 Socket,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30276406/
基于 socket.io 的官方网站 http://socket.io/#how-to-use , 我找不到任何术语。socket.emit 、 socket.on 和 socket.send 之间有
我正在使用 lua-socket 3.0rc1.3(Ubuntu Trusty 附带)和 lua 5.1。我正在尝试监听 unix 域套接字,我能找到的唯一示例代码是 this -- send std
这两者有什么区别? 我注意到如果我在一个工作程序中从 socket.emit 更改为 socket.send ,服务器无法接收到消息,虽然我不明白为什么。 我还注意到,在我的程序中,如果我从 sock
使用套接字在两台服务器之间发送数据是个好主意,还是应该使用 MQ 之类的东西来移动数据。 我的问题:套接字是否可靠,如果我只需要一次/有保证的数据传输? 还有其他解决方案吗? 谢谢。 最佳答案 套接字
引自 this socket tutorial : Sockets come in two primary flavors. An active socket is connected to a
我已经安装了在端口81上运行的流服务器“Lighttpd”(light-tpd)。 我有一个C程序,它使用套接字api创建的服务器套接字在端口80上监听http请求。 我希望从客户端收到端口80上的请
这是我正在尝试做的事情: 当有新消息可用时,服务器会将消息发送给已连接的客户端。另一方面,客户端在连接时尝试使用send()向服务器发送消息,然后使用recv()接收消息,此后,客户端调用close(
如何将消息发送到动态 session 室,以及当服务器收到该消息时,如何将该消息发送到其他成员所在的同一个 session 室? table_id是房间,它将动态设置。 客户: var table_i
这是我尝试但不起作用的方法。我可以将传入的消息从WebSocket连接转发到NetSocket,但是只有NetSocket收到的第一个消息才到达WebSocket后面的客户端。 const WebSo
我正在实现使用boost将xml发送到客户端的服务器。我面临的问题是缓冲区不会立即发送并累积到一个点,然后发送整个内容。这在我的客户端造成了一个问题,当它解析xml时,它可能具有不完整的xml标记(不
尝试使用Nginx代理Gunicorn套接字。 /etc/systemd/system/gunicorn.service文件 [Unit] Description=gunicorn daemon Af
我正在使用Lua套接字和TCP制作像聊天客户端和服务器这样的IRC。我要弄清楚的主要事情是如何使客户端和服务器监听消息并同时发送它们。由于在服务器上执行socket:accept()时,它将暂停程序,
我看了一下ZMQ PUSH/PULL套接字,尽管我非常喜欢简单性(特别是与我现在正在通过UDP套接字在系统中实现的自定义碎片/ack相比),但我还是希望有自定义负载平衡功能,而不是幼稚的回合-robi
我正在编写一个应用程序,其中有多个 socket.io 自定义事件,并且所有工作正常,除了这个: socket.on("incomingImg", function(data) {
在我的应用程序中,我向服务器发送了两条小消息(类似 memcached 的服务)。在类似 Python 的伪代码中,这看起来像: sock.send("add some-key 0") ignored
很抱歉再次发布此问题,但大多数相关帖子都没有回答我的问题。我在使用 socket.io 的多个连接时遇到问题我没有使用“socket.socket.connect”方法,但我从第一次连接中得到了反馈。
我尝试使用 socket.io 客户端连接到非 socket.io websocket 服务器。但我做不到。我正在尝试像这样连接到套接字服务器: var socket = io.connect('ws
我遇到了一个奇怪的问题。在我非常基本的服务器中,我有: server.listen(8001); io.listen(server); var sockets = io.sockets; 不幸的是,套
我正在使用带套接字 io 的sailsjs。帆的版本是 0.10.5。我有以下套接字客户端进行测试: var socketIOClient = require('socket.io-client');
这个问题在这里已经有了答案: What is the fundamental difference between WebSockets and pure TCP? (4 个答案) 关闭 4 年前。
我是一名优秀的程序员,十分优秀!