Я реализовал сервер websockets на C ++ с помощью libwebsockets. Это работает, когда я звоню из любого веб-браузера, использующего или не использующего TLS. Когда я вызываю его из приложения для Android, использующего библиотеку TooTallNate / Java-Websockets, это работает, если сервер не использует цифровой сертификат, но если он это делает (что необходимо, если я хочу использовать TLS), сервер блокируется (и делает не отвечает на новые сообщения), и приложение получает ошибку 1006 на onClose (int-код, строковая причина, логический удаленный). Это происходит или нет, я использую SSL на клиенте.
Проблема в строке 2040 файла libwebsockets.c:
eff_buf.token_len = SSL_read(wsi->ssl, buf, sizeof buf);
Он блокирует на сервере, пока я не убью приложение для Android.
Это соответствующий код в приложении:
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 не возвращает и блокируется, даже когда клиент уже обнаруживает проблему и возвращает ошибку. (Ssl_read в коде openssl немного запутан для меня, чтобы понять это)
С Уважением,
Juanjo
ОБНОВЛЕНИЕ: код libwebsockets.c находится здесь: https://github.com/davidgaleano/libwebsockets/blob/master/lib/libwebsockets.c и, кажется, у меня есть предыдущая версия. Теперь строка 2037. Учитывая, что выпуска нет, и кажется, что это ветвь старой версии оригинальных warmcat / libwebsockets, я полагаю, что основная проблема в этой библиотеке.
Решением было использовать оригинальную библиотеку libwebsockets (не разветвление) и реализовать обертку TrustManager для передачи в sslContext.init. Эта оболочка проверяет сертификат сервера независимо.