Skip to content

Instantly share code, notes, and snippets.

@Nazmul56
Last active April 7, 2020 12:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Nazmul56/8a74f452990e5e4f67d72baeb8b7b05b to your computer and use it in GitHub Desktop.
Save Nazmul56/8a74f452990e5e4f67d72baeb8b7b05b to your computer and use it in GitHub Desktop.

Socket Connection

	//WebSocketChannelClient.java
 	//For Socket Io
        IO.Options opts = new IO.Options();
        //opts.forceNew = false;
        opts.reconnection = true;
        opts.transports = new String[]{"websocket"};
        opts.upgrade = false;
        try {
            OkHttpClient client
                    = SelfSigningClientBuilder.createClient(context);
            opts.callFactory = client;
            opts.webSocketFactory = client;
        } catch (Exception e) {
            C.DISCONNECTION_OCCURRED_IN_LAST_CALL = true;
            Lg.d(TAG, e.getMessage().toString());
            return;
        }
	
       try {
            //ws.connect(new URI(wsServerUrl), wsObserver);// connect and add listener
            //For socket Io
            mSocket = IO.socket(C.CALL_SOCKET_URL, opts);
            mSocket.io().on(Manager.EVENT_TRANSPORT, onTransport);
            mSocket.on(Socket.EVENT_CONNECT, onConnect);

            mSocket.on(Socket.EVENT_RECONNECT, onReconnect);
            mSocket.on(Socket.EVENT_DISCONNECT, onDisconnect);
            mSocket.on(Socket.EVENT_CONNECT_ERROR, onConnectionError);

            mSocket.on("connect", onUserConnect);

            mSocket.on("notify", onNotify);
	    

Event Listeners

	//WebSocketChannelClient.java
    	// region : Socket Events
    private Emitter.Listener onConnect = args -> {
        Lg.d(TAG_SOCKET_IO, "Socket Connected");
        Lg.d(TAG, "Socket Connected");
        Lg.d(TAG_SOCKET_IO, "Socket ID: " + mSocket.id());
        if(U.isEmpty(mSocket.id()))
        Lg.d(TAG, "isJoinedOnce: " + isJoinedOnce);
        mySocketId = mSocket.id();

        //Join Working
        state = WebSocketConnectionState.REGISTERED;
        if (!isJoinedOnce) {
            isJoinedOnce = true;
            join(roomID);
        } else
            rejoin(roomID);
        events.onWebSocketConnected();
    };
    private Emitter.Listener onDisconnect = args -> {
        String socketId = mSocket.id();
        Lg.d(TAG_SOCKET_IO, "Socket Disconnected: SocketId: "+socketId);
        events.onWebSocketDisconnected();
    };

    private Emitter.Listener onReconnect = args -> {
        String socketId = mSocket.id();
        Lg.d(TAG_SOCKET_IO, "Socket Reconnect: socketId: "+socketId);
    };
    private Emitter.Listener onConnectionError = args -> {
        String socketId = mSocket.id();
        Lg.d(TAG_SOCKET_IO, "Socket Connection Error socketId: "+socketId);
    };
    private Emitter.Listener onUserConnect = args -> {
        Lg.d(TAG, "User Joined");
    };
    // Do not remove this member variable. If this is removed, the observer gets garbage collected and
    // this causes test breakages.
    private Emitter.Listener onExchange = args -> {

        JSONObject exchangeMsg = (JSONObject) args[0];
        //Socket ID from this msg came
        try {
            String from = exchangeMsg.getString("from");
            Lg.d(TAG_SOCKET_IO, "OnExchanges get from:" + from);
            otherUserSocketId = from;
            String message = exchangeMsg.getString("message");
            Lg.d(TAG_SOCKET_IO, "Message: " + message);


            events.onWebSocketMessage(message);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    };

    private JSONObject cacheMultipleSocketMsg = null;
    private Emitter.Listener onNotify = args -> {
        JSONObject jsonStr = (JSONObject) args[0];

        String from = U.getStringJ(jsonStr, "from");
        if (jsonStr.equals(cacheMultipleSocketMsg) || from.equals(mySocketId)) {
            Lg.d(TAG, "ignore Socket Msg in Notify");
            return;
        }

        cacheMultipleSocketMsg = jsonStr;

        String type = U.getStringJ(jsonStr, "msgType");
        Lg.d(TAG, "onNotify " + jsonStr);
        if (type.equals(notifyTypeGeneral)) {
//            if(U.isEmpty(otherUserSocketId))
                rejoin(roomID);

            events.onIncoming(jsonStr.toString());
        } else if (type.equals(notifyTypeExchange)) {
            onExchange.call(args);
        } else  if(type.equals(notifyTypeCallStatus)) {
            events.onCallStatus(jsonStr.toString());
        }
    };

    private Emitter.Listener onTransport = args -> {

        Transport transport = (Transport) args[0];
        transport.on(Transport.EVENT_REQUEST_HEADERS, args12 -> {
            @SuppressWarnings("unchecked")
            Map<String, List<String>> headers = (Map<String, List<String>>) args12[0];
            // modify request headers
        }).on(Transport.EVENT_RESPONSE_HEADERS, args1 -> {
            @SuppressWarnings("unchecked")
            Map<String, List<String>> headers = (Map<String, List<String>>) args1[0];
        });
    };

Join

    private void join(String roomID) {
        Lg.d(TAG, "joining to roomId: " + roomID);

        if (turnServerCredentials == null) {
            Lg.d(TAG, "turnServerCredentials: null");
            return;
        }
        mSocket.emit("join", roomID, (Ack) args12 -> {
            Lg.d(TAG_SOCKET_IO, "Join Success to roomId: " + roomID);
            Lg.d(TAG, "Join Success to roomId: " + roomID);
            JSONArray ack = (JSONArray) args12[0];
            Lg.d(TAG_SOCKET_IO, " Room Member  " + ack);
            Lg.d(TAG, " socket ack: " + ack);

            for (int i = 0; i < ack.length(); ++i) {
                try {
                    String socketId = ack.getString(i);
                    otherUserSocketId = socketId;
                    //Other Users Socket id
                    Lg.d(TAG_SOCKET_IO, i + " socket: " + socketId);
                    Lg.d(TAG, i + " socket: " + socketId);
                    //exchangeMsg(socketId, "Hello");

                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }

            final boolean b = ack.length() > 0;
            // if (signalingParameters != null) { // ignoring non-call room-joins, handling only call-related room joins
            if (signalingParameters == null) {
                signalingParameters = new AppRTCClient.SignalingParameters(
                        RoomParametersFetcher.getIceServers(turnServerCredentials),
                        false, "", "", "", null, null);
            }

            signalingParameters.initiator = this.initiator; //false; //b && initiator;
            //initiator = false;

            Lg.d(TAG_SOCKET_IO, "before events.onConnectToRoom: signalingParameters!=null");

            events.onConnectToRoom(signalingParameters);

            Lg.d(TAG_SOCKET_IO, "Initiator: " + signalingParameters.initiator);
            register(roomID, clientID);
        });
    }

Re-Join

    private void rejoin(String roomID) {
        Lg.d(TAG, "re-joining to roomId: " + roomID);

        if (turnServerCredentials == null) {
            Lg.d(TAG, "turnServerCredentials: null");
            return;
        }
        mSocket.emit("join", roomID, (Ack) args12 -> {
            Lg.d(TAG_SOCKET_IO, "rejoin Success to roomId: " + roomID);
            Lg.d(TAG, "rejoin Success to roomId: " + roomID);
            JSONArray ack = (JSONArray) args12[0];
            Lg.d(TAG_SOCKET_IO, " rejoin Room Member  " + ack);
            Lg.d(TAG, "rejoin socket ack: " + ack);

            for (int i = 0; i < ack.length(); ++i) {
                try {
                    String socketId = ack.getString(i);
                    otherUserSocketId = socketId;
                    //Other Users Socket id
                    Lg.d(TAG_SOCKET_IO, i + " socket: " + socketId);
                    Lg.d(TAG, i + " socket: " + socketId);
                    //exchangeMsg(socketId, "Hello");

                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }

            final boolean b = ack.length() > 0;
            // if (signalingParameters != null) { // ignoring non-call room-joins, handling only call-related room joins
            if (signalingParameters == null) {
                signalingParameters = new AppRTCClient.SignalingParameters(
                        RoomParametersFetcher.getIceServers(turnServerCredentials),
                        false, "", "", "", null, null);
            }

            signalingParameters.initiator = this.initiator; //false; //b && initiator;
            //initiator = false;

            Lg.d(TAG_SOCKET_IO, "before events.onConnectToRoom: signalingParameters!=null");

            //events.onConnectToRoom(signalingParameters);
            // }
            // else  Lg.d(TAG_SOCKET_IO, "events.onConnectToRoom not called signalingParameters==null" );

            Lg.d(TAG_SOCKET_IO, "rejoin Initiator: " + signalingParameters.initiator);
            register(roomID, clientID);
        });
    }

Exchange Msg

    private void exchangeMsgSend(String socketId, String msg) {
        Lg.d(TAG_SOCKET_IO, " Exchange to: " + socketId + " Msg Sending: " + msg);

        JSONObject msgBody = new JSONObject();
        try {
            msgBody.put("to", roomID);
            msgBody.put("from", mySocketId);
            msgBody.put("msgType", notifyTypeExchange);
            msgBody.put("message", msg);
        } catch (JSONException e) {
            e.printStackTrace();
        }
//        if(C.IS_APP_DEBUGGABLE)
//            D.showToastShort(ge, "OFFER_SDP_SEND");
        Lg.d(TAG_SOCKET_IO, " emit notify: msgBody: "+ msgBody);

        mSocket.emit("notify", msgBody, (Ack) args12 -> {
            //JSONArray ack = (JSONArray) args12[0];
            Lg.d(TAG_SOCKET_IO, "Exchange Msg Send: ");
        });
    }

Notify Other Party

    public void notifyOtherParty(Context context,
                                 String aptId,
                                 String callId,
                                 String roomId,
                                 String doctorId,
                                 String patientId) {
        Lg.d(TAG, "notifyOtherParty " + mSocket.id());

        if (mSocket != null && mSocket.connected()) {
            rejoin(roomId);
            try {
                Lg.d(TAG, "try notifyOtherParty");
                JSONObject jo = new JSONObject();
                jo.put("to", roomId);
                jo.put("from", mySocketId);
                jo.put("msgType", notifyTypeGeneral);
                jo.put("call_id", callId);
                jo.put("appointment_id", aptId);
                jo.put("room_id", roomId);
                jo.put("caller_id", C.IS_DOCTOR_APP ? doctorId : patientId);
                jo.put("caller", P.getFullName(context));
                jo.put("caller_username", P.getUserName(context));
                jo.put("caller_image", P.getProfilePicUrl(context));

                Lg.d(TAG, "try notifyOtherParty: " + jo.toString());

                mSocket.emit("notify", jo, (Ack) res -> {
                    Lg.e(TAG, "NOTIFY event response: " + Arrays.toString(res));
                });
                Lg.i(TAG, "Thrown NOTIFY event by JSONObject: " + jo);
            } catch (Exception e) {
                e.printStackTrace();
                Lg.d(TAG, "catch notifyOtherParty");
            }
        }
    }

Disconnect

    public void disconnect(boolean waitForComplete, GenericCallbacks callbacks) {
        checkIfCalledOnValidThread();
        Lg.d(TAG, "Disconnect WebSocket. State: " + state);
        isJoinedOnce = false;
        //channelInstance=null;
        if (state == WebSocketConnectionState.REGISTERED) {
            // Send "bye" to WebSocket server.
            send("{\"type\": \"bye\"}");
            state = WebSocketConnectionState.CONNECTED;
            // Send http DELETE to http WebSocket server.
            //sendWSSMessage("DELETE", "");
        }
        // Close WebSocket in CONNECTED or ERROR states only.
        if (state == WebSocketConnectionState.CONNECTED || state == WebSocketConnectionState.ERROR) {
            //ws.disconnect();
            mSocket.disconnect();   // FIXME Do not disconnect in case of app-internal calls


            state = WebSocketConnectionState.CLOSED;
            // Wait for websocket close event to prevent websocket library from
            // sending any pending messages to deleted looper thread.
            if (waitForComplete) {
                synchronized (closeEventLock) {
                    while (!closeEvent) {
                        try {
                            closeEventLock.wait(CLOSE_TIMEOUT);
                            callbacks.onSuccess();
                            break;
                        } catch (InterruptedException e) {
                            Lg.e(TAG, "Wait error: " + e.toString());
                            callbacks.onError("Wait error");
                        }
                    }
                }
            }
        } else callbacks.onSuccess();

        Lg.d(TAG, "Disconnecting WebSocket done.");
    }

Socket Connection and Join to a Room Diagram

_________________________________________________________________________________________
⎪Patient App  |		  	    |	Server  |	     		| Dr App    	⎟
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
Socket Connection ——————————————▶︎     Socket URL 	◀︎————————————— Socket Connection
  	│									│
	▼									▼
Add Event Listener							Add Event Listener
"connect",								"connect",
"reconnect",								"reconnect",
"notify"								"notify"
"leave"									"leave"
"disconnect"								"disconnect"
	│									│
	▼									▼				 
       Join(roomId) —————▶︎ emit "join"——▶︎ Server Join ◀︎————— emit "join"◀︎—— Join(roomId) 
        |									|
	▼									▼

Peer Connection After Join Same Room

_______________________________________________________________________
Patient App		      |		      Dr App
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
CallActivity ————————————————————————————————▶︎ Incoming Activity  
					       	    │
						    ▼
					      Accept Call	
						    |
						    ▼
				             Call Activity Open 							
				       		    |
						    ▼
PeerConnectionClient <——Send Offer—————————— PeerConnectionClient
    (Set Offer)	(Set Candidate)		    (Create Offer) (Candidate)
        |
	▼
(Create Answer )  ————Send Answer ——————————> (Set Answer)
	|
	▼
  (Candidate)   ————— Send Candidate ———————> (Set Candidate)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment