package com.basic.security.utils.socket; import android.os.SystemClock; import com.basic.security.base.BaseApplication; import com.basic.security.model.OfficeDevice; import com.basic.security.model.OfficeDeviceMessage; import com.basic.security.model.RemoteCameraMessage; import com.basic.security.receiver.WebRtcBroadCastReceiver; import com.basic.security.utils.Constants; import com.basic.security.utils.DetectedResult; import com.basic.security.utils.SocketUtil; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class CameraYuvSocketServer { private static final int MAX_BUFFER = 1; public static List acceptedClientList = new ArrayList<>(); public static Lock acceptedClientListLock = new ReentrantLock(); public static boolean serverStarted = false; public static void setCameraData(byte[] cameraData) { acceptedClientListLock.lock(); for (AcceptedClient acceptedClient : acceptedClientList) { acceptedClient.setCameraData(cameraData); } acceptedClientListLock.unlock(); } public static void setDetectedResult(DetectedResult detectedResult) { acceptedClientListLock.lock(); for (AcceptedClient acceptedClient : acceptedClientList) { acceptedClient.setDetectedResult(detectedResult); } acceptedClientListLock.unlock(); } public static void startServer() { if (serverStarted) { return; } BaseApplication.getApplication().executorService.execute(() -> { ServerSocket server = null; try { server = new ServerSocket(Constants.cameraServerPort); } catch (Exception e) { e.printStackTrace(); } while (true) { try { if (server == null) { break; } serverStarted = true; Socket client = server.accept(); AcceptedClient faceYuvSocketClient = new AcceptedClient(client); // faceYuvSocketClient.start(); BaseApplication.getApplication().executorService.execute(faceYuvSocketClient); } catch (Exception e) { e.printStackTrace(); } finally { SystemClock.sleep(3000); } } }); } public static class AcceptedClient extends Thread { ///////////////////////////////////// private final LinkedList detectedResultQueue = new LinkedList<>(); /////////////////////////////// private final LinkedList cameraDataQueue = new LinkedList(); public long lastTimeSendFrame = 0; Socket mSocket; public AcceptedClient(Socket client) { mSocket = client; } public DetectedResult getDetectedResult() { DetectedResult mLastFrame = null; synchronized (detectedResultQueue) { if (detectedResultQueue.size() > 0) { mLastFrame = detectedResultQueue.poll(); } } return mLastFrame; } public void setDetectedResult(DetectedResult detectedResult) { synchronized (detectedResultQueue) { if (detectedResultQueue.size() == MAX_BUFFER) { detectedResultQueue.poll(); } detectedResultQueue.add(detectedResult); } } public byte[] getCameraData() { byte[] cameraData = null; synchronized (cameraDataQueue) { if (cameraDataQueue.size() > 0) { cameraData = cameraDataQueue.poll(); } } return cameraData; } public void setCameraData(byte[] cameraData) { synchronized (cameraDataQueue) { if (cameraDataQueue.size() == MAX_BUFFER) { cameraDataQueue.poll(); } cameraDataQueue.add(cameraData); } } @Override public void run() { acceptedClientListLock.lock(); acceptedClientList.add(this); acceptedClientListLock.unlock(); SocketUtil socketUtil = new SocketUtil(); try { socketUtil.setSocket(mSocket); while (true) { Map authMap = socketUtil.readMap(); socketUtil.deviceId = (String) authMap.get(OfficeDevice.deviceId); if (socketUtil.writeBitmapHeader()) { while (!Thread.currentThread().isInterrupted()) { Map map = new HashMap<>(); Map requestMap = socketUtil.readMap(); boolean isRequestFrame = Constants.TRUE.equals(requestMap.get(OfficeDeviceMessage.requestFrame)); boolean isRequestOpenDoor = Constants.TRUE.equals(requestMap.get(OfficeDeviceMessage.requestOpenDoor)); if (isRequestOpenDoor) { RelayServerUtil2.open(); } boolean isTransferVideo = Constants.TRUE.equals(requestMap.get(OfficeDeviceMessage.transferVideo)); String hasFrameData = Constants.FALSE; byte[] frameData = null; map.put(OfficeDeviceMessage.faceUpdateTime, null); boolean allowed = false; if (socketUtil.remoteIpAllowed(map)) { allowed = true; if (isTransferVideo) { if (isRequestFrame) { frameData = getCameraData(); if (frameData != null && frameData.length > 1000) { hasFrameData = Constants.TRUE; } else { SystemClock.sleep(500); } } else { SystemClock.sleep(500); } DetectedResult detectedResult = getDetectedResult(); if (detectedResult != null) { map.put(RemoteCameraMessage.stranger, detectedResult.stranger() ? Constants.TRUE : Constants.FALSE); map.put(OfficeDeviceMessage.faceUpdateTime, System.currentTimeMillis() + ""); } } else { DetectedResult detectedResult = getDetectedResult(); if (detectedResult != null) { map.put(RemoteCameraMessage.stranger, detectedResult.stranger() ? Constants.TRUE : Constants.FALSE); map.put(OfficeDeviceMessage.faceUpdateTime, System.currentTimeMillis() + ""); frameData = detectedResult.originalCameraData; if (detectedResult.originalCameraDataChanged || !isRequestFrame || System.currentTimeMillis() - lastTimeSendFrame > 2000) { lastTimeSendFrame = System.currentTimeMillis(); hasFrameData = Constants.TRUE; } } } } else { SystemClock.sleep(1000); } map.put(Constants.webRtcClientConnected, WebRtcBroadCastReceiver.webRtcClientConnected ? Constants.TRUE : Constants.FALSE); map.put(Constants.webRtcServerStarted, allowed && WebRtcBroadCastReceiver.webRtcServerStarted ? Constants.TRUE : Constants.FALSE); map.put(OfficeDeviceMessage.hasFrameData, hasFrameData); socketUtil.writeMap(map); if (Constants.TRUE.equals(hasFrameData)) { socketUtil.writeByteArray(frameData); } SystemClock.sleep(40); } } else { SystemClock.sleep(2 * 1000); } } } catch (Exception e) { e.printStackTrace(); } finally { socketUtil.close(); } acceptedClientListLock.lock(); acceptedClientList.remove(this); acceptedClientListLock.unlock(); } } }