从 TooTallNate/Java-Websockets 调用 libwebsockets 服务器失败
calling libwebsockets server from TooTallNate/Java-Websockets fails
我已经用 C++ 和 libwebsockets 实现了一个 websockets 服务器。当我使用或不使用 TLS 从任何 Web 浏览器进行调用时,它都有效。当我使用 TooTallNate/Java-Websockets 库从 android 应用程序调用它时,如果服务器不使用数字证书它就可以工作,但如果它使用(如果我想使用 TLS 则需要)服务器是被阻止(并且不响应新消息)并且应用程序在 onClose(int code,String reason,boolean remote)上收到 1006 错误。无论我是否在客户端上使用 SSL,它都会发生。
问题出在 libwebsockets.c:
的第 2040 行
eff_buf.token_len = SSL_read(wsi->ssl, buf, sizeof buf);
它在服务器上阻塞,直到我终止 android 应用程序。
这是App上的相关代码:
class WebSocketChatClient extends WebSocketClient {
public WebSocketChatClient( URI serverUri ) {
super( serverUri );
}
public WebSocketChatClient( URI serverUri , Draft protocolDraft , Map<String,String> httpHeaders )
{
super(serverUri,protocolDraft,httpHeaders);
}
@Override
public void onOpen( ServerHandshake handshakedata ) {
System.out.println( "Connected" );
send("prueba");
}
@Override
public void onMessage( String message ) {
System.out.println( "got: " + message );
}
@Override
public void onClose( int code, String reason, boolean remote ) {
System.out.println( "Disconnected" );
//System.exit( 0 );
}
@Override
public void onError( Exception ex ) {
ex.printStackTrace();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = getApplicationContext();
URI uri;
try
{
uri=new URI("wss://192.168.1.128:8080");
Map<String,String> headers=new HashMap<String,String>();
headers.put("Sec-WebSocket-Protocol", "dumb-increment-protocol");
headers.put("User-Agent", "My Android App");
wsClient = new WebSocketChatClient(uri,new Draft_17(),headers);
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance( "TLS" );
sslContext.init( null, null, null ); // will use java's default key and trust store which is sufficient unless you deal with self-signed certificates
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
wsClient.setWebSocketFactory( new DefaultSSLWebSocketClientFactory( sslContext ) );
wsClient.connect();
}
catch(URISyntaxException e)
{
e.printStackTrace();
}
}
这是服务器上的相关代码:
int port = 8080;
const char *intrface = NULL;
struct libwebsocket_context *context;
// we're not using ssl
const char *cert_path = "c:\mydir\1921681128.crt";
const char *key_path = "c:\mydir\1921681128.key";
// no special options
int opts = 0;
// create libwebsocket context representing this server
context = libwebsocket_create_context(port, intrface, protocols,
libwebsocket_internal_extensions,
cert_path, key_path, NULL,-1, -1, opts);
if (context == NULL) {
fprintf(stderr, "libwebsocket init failed\n");
return -1;
}
printf("starting server...\n");
// infinite loop, to end this server send SIGTERM. (CTRL+C)
int k=0;
while (1) {
int res=libwebsocket_service(context, 50);
// libwebsocket_service will process all waiting events with their
// callback functions and then wait 50 ms.
// (this is a single threaded webserver and this will keep our server
// from generating load while there are not requests to process)
}
我想知道我这边是否有任何错误,或者它是否是 libwebsockets、openssl 或 java websockets 客户端库中的错误。如果我调用此服务器,客户端将工作:ws://echo.websocket.org 使用或不使用 TLS。即使 java 客户端存在错误,我也想知道 ssl_read 没有 return 并且即使客户端已经检测到问题也会被阻止的行为是否正确returns 是一个错误。 (openssl 代码中的 ssl_read 对我来说有点混淆)
此致,
胡安乔
更新:libwebsockets.c 代码在这里:https://github.com/davidgaleano/libwebsockets/blob/master/lib/libwebsockets.c 看来我有以前的版本。现在该行是 2037。鉴于没有任何版本,而且它似乎是原始版本 warmcat/libwebsockets 的旧版本的分支,我想主要问题出在那个库中。
解决方案是使用原始的 libwebsockets 库(不是分支)并实现一个 TrustManager 包装器以传递给 sslContext.init。此包装器独立验证服务器证书。
我已经用 C++ 和 libwebsockets 实现了一个 websockets 服务器。当我使用或不使用 TLS 从任何 Web 浏览器进行调用时,它都有效。当我使用 TooTallNate/Java-Websockets 库从 android 应用程序调用它时,如果服务器不使用数字证书它就可以工作,但如果它使用(如果我想使用 TLS 则需要)服务器是被阻止(并且不响应新消息)并且应用程序在 onClose(int code,String reason,boolean remote)上收到 1006 错误。无论我是否在客户端上使用 SSL,它都会发生。 问题出在 libwebsockets.c:
的第 2040 行eff_buf.token_len = SSL_read(wsi->ssl, buf, sizeof buf);
它在服务器上阻塞,直到我终止 android 应用程序。
这是App上的相关代码:
class WebSocketChatClient extends WebSocketClient {
public WebSocketChatClient( URI serverUri ) {
super( serverUri );
}
public WebSocketChatClient( URI serverUri , Draft protocolDraft , Map<String,String> httpHeaders )
{
super(serverUri,protocolDraft,httpHeaders);
}
@Override
public void onOpen( ServerHandshake handshakedata ) {
System.out.println( "Connected" );
send("prueba");
}
@Override
public void onMessage( String message ) {
System.out.println( "got: " + message );
}
@Override
public void onClose( int code, String reason, boolean remote ) {
System.out.println( "Disconnected" );
//System.exit( 0 );
}
@Override
public void onError( Exception ex ) {
ex.printStackTrace();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = getApplicationContext();
URI uri;
try
{
uri=new URI("wss://192.168.1.128:8080");
Map<String,String> headers=new HashMap<String,String>();
headers.put("Sec-WebSocket-Protocol", "dumb-increment-protocol");
headers.put("User-Agent", "My Android App");
wsClient = new WebSocketChatClient(uri,new Draft_17(),headers);
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance( "TLS" );
sslContext.init( null, null, null ); // will use java's default key and trust store which is sufficient unless you deal with self-signed certificates
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
wsClient.setWebSocketFactory( new DefaultSSLWebSocketClientFactory( sslContext ) );
wsClient.connect();
}
catch(URISyntaxException e)
{
e.printStackTrace();
}
}
这是服务器上的相关代码:
int port = 8080;
const char *intrface = NULL;
struct libwebsocket_context *context;
// we're not using ssl
const char *cert_path = "c:\mydir\1921681128.crt";
const char *key_path = "c:\mydir\1921681128.key";
// no special options
int opts = 0;
// create libwebsocket context representing this server
context = libwebsocket_create_context(port, intrface, protocols,
libwebsocket_internal_extensions,
cert_path, key_path, NULL,-1, -1, opts);
if (context == NULL) {
fprintf(stderr, "libwebsocket init failed\n");
return -1;
}
printf("starting server...\n");
// infinite loop, to end this server send SIGTERM. (CTRL+C)
int k=0;
while (1) {
int res=libwebsocket_service(context, 50);
// libwebsocket_service will process all waiting events with their
// callback functions and then wait 50 ms.
// (this is a single threaded webserver and this will keep our server
// from generating load while there are not requests to process)
}
我想知道我这边是否有任何错误,或者它是否是 libwebsockets、openssl 或 java websockets 客户端库中的错误。如果我调用此服务器,客户端将工作:ws://echo.websocket.org 使用或不使用 TLS。即使 java 客户端存在错误,我也想知道 ssl_read 没有 return 并且即使客户端已经检测到问题也会被阻止的行为是否正确returns 是一个错误。 (openssl 代码中的 ssl_read 对我来说有点混淆)
此致, 胡安乔
更新:libwebsockets.c 代码在这里:https://github.com/davidgaleano/libwebsockets/blob/master/lib/libwebsockets.c 看来我有以前的版本。现在该行是 2037。鉴于没有任何版本,而且它似乎是原始版本 warmcat/libwebsockets 的旧版本的分支,我想主要问题出在那个库中。
解决方案是使用原始的 libwebsockets 库(不是分支)并实现一个 TrustManager 包装器以传递给 sslContext.init。此包装器独立验证服务器证书。