Why is my WebSocket server crashing?

I am currently developing an application and this requires hosting a secure WebSocket server, i.e. it needs SSL certificates. Well, I got self-signed certificates to work, but using the TooTallNate WebSocket implementation, I can only accept one connection before the whole server crashes and stops responding to any messages or new connections.

If the server is created

server = new WSServer(new InetSocketAddress(25517), activity.getApplicationContext());

            String STORETYPE = "BKS";
            String STOREPASSWORD = "titancast-androidapp";
            String KEYPASSWORD = "titancast-androidapp";

            WebSocketImpl.DEBUG = true;

            try {
                KeyStore ks = KeyStore.getInstance(STORETYPE);
                File kf = keystore;
                ks.load(new FileInputStream(kf), STOREPASSWORD.toCharArray());

                KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
                kmf.init(ks, KEYPASSWORD.toCharArray());

                TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
                tmf.init(ks);

                SSLContext sslContext = null;
                sslContext = SSLContext.getInstance("TLS");
                sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

                wsf = new DefaultSSLWebSocketServerFactory(sslContext);

                server.setWebSocketFactory(wsf);

                server.start();
                TitanCastNotification.showToast("(hopefully) success", Toast.LENGTH_LONG);
            }catch(Exception e){
                e.printStackTrace();
            }

      

Server

package com.hydrabolt.titancast;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.Build;
import android.os.Vibrator;
import android.util.Log;
import android.widget.Toast;

import com.hydrabolt.titancast.info_display.TitanCastNotification;

import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;

import java.net.InetSocketAddress;
import java.util.ArrayList;

public class WSServer extends WebSocketServer {

    private static Context context;
    private static ArrayList<WebSocket> socketList;
    private static String[] empty = {};
    private static String deviceDetails;
    private static ArrayList<String> deviceDetailsRaw;
    private Activity castActivity;

    private static WebSocket acceptedWebSocket;

    public WSServer(InetSocketAddress address, Context c) {
        super(address);

        socketList = new ArrayList<WebSocket>();

        context = c;

        deviceDetailsRaw = new ArrayList<String>();
        deviceDetailsRaw.add("device_model=" + Build.MODEL);
        deviceDetailsRaw.add("device_manufacturer=" + Build.MANUFACTURER);
        deviceDetailsRaw.add("device_android_version=" + Build.VERSION.SDK_INT);
        deviceDetailsRaw.add("titan_cast_version=" + Details.getAppVersion());
        deviceDetailsRaw.add("has_vibrator=" + ((Vibrator) c.getSystemService(c.VIBRATOR_SERVICE)).hasVibrator());

        SensorManager sm = (SensorManager) c.getSystemService(Context.SENSOR_SERVICE);

        deviceDetailsRaw.add("has_accelerometer=" + (sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null));
        deviceDetailsRaw.add("has_gyroscope=" + (sm.getDefaultSensor(Sensor.TYPE_GYROSCOPE) != null));
        deviceDetailsRaw.add("has_ambient_temperature=" + (sm.getDefaultSensor(Sensor.TYPE_AMBIENT_TEMPERATURE) != null));
        deviceDetailsRaw.add("has_gravity=" + (sm.getDefaultSensor(Sensor.TYPE_GRAVITY) != null));
        deviceDetailsRaw.add("has_heart_rate=" + (sm.getDefaultSensor(Sensor.TYPE_HEART_RATE) != null));
        deviceDetailsRaw.add("has_light=" + (sm.getDefaultSensor(Sensor.TYPE_LIGHT) != null));
        deviceDetailsRaw.add("has_magnetic_field=" + (sm.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null));
        deviceDetailsRaw.add("has_pressure=" + (sm.getDefaultSensor(Sensor.TYPE_PRESSURE) != null));
        deviceDetailsRaw.add("has_proximity=" + (sm.getDefaultSensor(Sensor.TYPE_PROXIMITY) != null));
        deviceDetailsRaw.add("has_relative_humidity=" + (sm.getDefaultSensor(Sensor.TYPE_RELATIVE_HUMIDITY) != null));
        deviceDetailsRaw.add("has_rotation=" + (sm.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR) != null));
        deviceDetailsRaw.add("has_significant_motion=" + (sm.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION) != null));
        deviceDetailsRaw.add("has_step_counter=" + (sm.getDefaultSensor(Sensor.TYPE_STEP_COUNTER) != null));
        deviceDetailsRaw.add("has_step_detector=" + (sm.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR) != null));

        deviceDetails = PacketSerializer.generatePacket("device_details", deviceDetailsRaw);
    }

    public static void rejectRequest(int index) {
        try {
            socketList.get(index).send(PacketSerializer.generatePacket("reject_connect_request", empty));
            socketList.get(index).close(0);
        }catch(IndexOutOfBoundsException e){
            TitanCastNotification.showToast("You were disconnected from the application!", Toast.LENGTH_LONG);
        }
    }

    public static void acceptRequest(int index) {

        Log.d("titancast","accept");

        try {
            socketList.get(index).send(PacketSerializer.generatePacket("accept_connect_request", empty));
            Details.setConnected(true);
            acceptedWebSocket = socketList.get(index);
        }catch(IndexOutOfBoundsException e){
            Log.d("titancast-wsserver", "error - "+e.getLocalizedMessage());
            TitanCastNotification.showToast("You were disconnected from the application!", Toast.LENGTH_LONG);
        }
    }

    public static void terminateActive() {
        if(acceptedWebSocket != null){
            acceptedWebSocket.close(0);
            acceptedWebSocket = null;
            Details.setConnected(false);
            Details.setHasViewData(false);
            CastActivity.getSensorManager().disableAccelerometerSensor();
            CastActivity.getSensorManager().setDelay(10);
            TitanCastNotification.showToast("You were disconnected from the application!", Toast.LENGTH_LONG);
        }
    }

    public static void sendCustomDataToActive(String[] data) {

        if (acceptedWebSocket != null && Details.connected() && Details.hasViewData()) {
            sendPacketToActive(PacketSerializer.generatePacket("custom_data", data));
        }
    }

    public static void sendPacketToActive(String data) {
        if (acceptedWebSocket != null && Details.connected()) {
            acceptedWebSocket.send(data);
        }
    }

    @Override
    public void onOpen(WebSocket webSocket, ClientHandshake clientHandshake) {

        if (socketList.size() > 10) {
            webSocket.close(0);
            return;
        }

        webSocket.send(deviceDetails);
        socketList.add(webSocket);

    }

    @Override
    public void onClose(WebSocket webSocket, int i, String s, boolean b) {
        socketList.remove(webSocket);
        if (webSocket == acceptedWebSocket) {
            terminateActive();
            CastActivity.close();
        }
    }

    @Override
    public void onMessage(WebSocket webSocket, String s) {

        ArrayList<String> msg = PacketSerializer.parsePacket(s);
        String type = msg.get(0);
        boolean conn = acceptedWebSocket == webSocket;
        boolean connectedAndInView = Details.hasViewData() && conn;

        switch (type) {

            case "request_connect":

                if (msg.size() == 4) {
                    if (conn) {
                        webSocket.send(PacketSerializer.generatePacket("already_connected", empty));
                    } else {
                        Intent intent = new Intent(context, RequestConnectScreen.class);
                        intent.putExtra("app_name", msg.get(1));
                        intent.putExtra("app_desc", msg.get(2));
                        intent.putExtra("client_id", socketList.indexOf(webSocket));
                        intent.putExtra("app_icon", msg.get(3));
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        context.startActivity(intent);
                    }
                }
                break;

            case "cast_view_data":

                if (!Details.hasViewData() && msg.size() == 2) {
                    String url = msg.get(1);
                    Intent intent = new Intent(context, CastActivity.class);
                    intent.putExtra("url", msg.get(1));
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                    Details.setHasViewData(true);
                    Details.setConnected(true);

                    context.startActivity(intent);
                }
                break;

            case "custom_data":
                if (msg.size() == 2) {
                    final String toSend = msg.get(1);
                    CastActivity.h.post(new Runnable() {

                        @Override
                        public void run() {
                            CastActivity.sendCustom(toSend);
                        }
                    });
                }
                break;
            case "enable_accelerometer":

                if (connectedAndInView) {
                    CastActivity.getSensorManager().enableAccelerometerSensor("websocket enabled it");
                }
                break;

            case "disable_accelerometer":

                if (connectedAndInView) {
                    CastActivity.getSensorManager().disableAccelerometerSensor();
                }
                break;

            case "set_accelerometer_speed":

                if (connectedAndInView && msg.size() == 2) {
                    int speed = SensorManager.SENSOR_DELAY_NORMAL;

                    if (msg.get(1).equals("game")) speed = SensorManager.SENSOR_DELAY_GAME;
                    if (msg.get(1).equals("fastest")) speed = SensorManager.SENSOR_DELAY_FASTEST;
                    if (msg.get(1).equals("ui")) speed = SensorManager.SENSOR_DELAY_UI;

                    CastActivity.getSensorManager().setDelay(speed);
                }
                break;
            case "set_orientation":
                if(msg.size() == 2) {

                    String orientation = msg.get(1);

                    if(castActivity == null){
                        break;
                    }

                    if (orientation.equals("portrait")) {
                        castActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                    } else if (orientation.equals("landscape")) {
                        castActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                    } else if (orientation.equals("reverse_portrait")) {
                        castActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
                    } else if (orientation.equals("reverse_landscape")) {
                        castActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
                    } else if (orientation.equals("sensor")) {
                        castActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
                    }
                }
            default:

                webSocket.send(PacketSerializer.generatePacket("unknown_command", empty));
                break;

        }

    }

    public void setCastActivity(Activity a){
        this.castActivity = a;
    }

    @Override
    public void onError(WebSocket webSocket, Exception e) {
        Log.d("titancast-wsserver", (webSocket == null ? "wsserver-interror " : "wsserror-clerror ") + e.getLocalizedMessage());
        if(webSocket != null){
            socketList.remove(webSocket);
            if (webSocket == acceptedWebSocket) {
                terminateActive();
                CastActivity.close();
            }
        }
    }

    public void end(){
        for(WebSocket ws : socketList){
            ws.close(0);
            socketList.remove(ws);
        }
    }
}

      

You can find magazines here.

This error only happens after switching from unsecured WebSockets to protect WebSockets, so it must be an SSL bug somewhere.

If I missed anything please leave a comment, this is my first time posting here;)

If you could help, that would be great! Thank!

+3


source to share





All Articles