import {SECRET_KEY} from "../Enum/EnvironmentVariable"; //TODO fix import by "_Enum/..."
import {ExtRooms, RefreshUserPositionFunction} from "../Model/Websocket/ExtRoom";
import {ExtRoomsInterface} from "_Model/Websocket/ExtRoomsInterface";
+import {ExtWebSocket} from "../../../../publicis/sources/api/src/Entities/WebSocket/ExtWebSocket";
export class IoSocketController{
Io: socketIO.Server;
(socket as ExSocketInterface).roomId = data.roomId;
//if two persone in room share
+ console.log("nb user => " + data.roomId, this.Io.sockets.adapter.rooms[data.roomId].length);
if(this.Io.sockets.adapter.rooms[data.roomId].length < 2) {
return;
}
let clients : Array<any> = Object.values(this.Io.sockets.sockets);
//send start at one client to initialise offer webrtc
- clients[0].emit('webrtc-start');
+ clients.forEach((client: ExtWebSocket, index : number) => {
+ client.emit('webrtc-start', JSON.stringify({
+ userId: client.userId,
+ initiator : index === 0
+ }));
+ });
});
- socket.on('video-offer', (message : string) => {
+ socket.on('webrtc-signal', (message : string) => {
let data : any = JSON.parse(message);
- socket.to(data.roomId).emit('video-offer', message);
- });
-
- socket.on('video-answer', (message : string) => {
- let data : any = JSON.parse(message);
- socket.to(data.roomId).emit('video-answer', message);
- });
-
- socket.on('ice-candidate', (message : string) => {
- let data : any = JSON.parse(message);
- socket.to(data.roomId).emit('ice-candidate', message);
+ console.info('webrtc-signal', message);
+ socket.to(data.roomId).emit('webrtc-signal', message);
});
});
}
},
"dependencies": {
"@types/axios": "^0.14.0",
+ "@types/simple-peer": "^9.6.0",
"@types/socket.io-client": "^1.4.32",
"phaser": "^3.22.0",
+ "simple-peer": "^9.6.2",
"socket.io-client": "^2.3.0"
},
"scripts": {
import Axios from "axios";
import {API_URL} from "./Enum/EnvironmentVariable";
+enum EventMessage{
+ WEBRTC_SIGNAL = "webrtc-signal",
+ WEBRTC_START = "webrtc-start",
+ WEBRTC_ROOM = "webrtc-room",
+ JOIN_ROOM = "join-room",
+ USER_POSITION = "user-position",
+ MESSAGE_ERROR = "message-error"
+}
+
class Message {
userId: string;
roomId: string;
roomId: string;
position: PointInterface;
}
+
class MessageUserPosition extends Message implements MessageUserPositionInterface{
position: PointInterface;
}
export interface ListMessageUserPositionInterface {
- roomId : string;
+ roomId: string;
listUsersPosition: Array<MessageUserPosition>;
}
-class ListMessageUserPosition{
- roomId : string;
+
+class ListMessageUserPosition {
+ roomId: string;
listUsersPosition: Array<MessageUserPosition>;
- constructor(roomId : string, data : any) {
+ constructor(roomId: string, data: any) {
this.roomId = roomId;
this.listUsersPosition = new Array<MessageUserPosition>();
data.forEach((userPosition: any) => {
});
}
}
+
export interface ConnexionInterface {
- socket : any;
- token : string;
- email : string;
+ socket: any;
+ token: string;
+ email: string;
userId: string;
- startedRoom : string;
- createConnexion() : Promise<any>;
- joinARoom(roomId : string) : void;
- sharePosition(roomId : string, x : number, y : number, direction : string) : void;
- positionOfAllUser() : void;
+ startedRoom: string;
+
+ createConnexion(): Promise<any>;
+
+ joinARoom(roomId: string): void;
+
+ sharePosition(roomId: string, x: number, y: number, direction: string): void;
+
+ positionOfAllUser(): void;
+
+ /*webrtc*/
+ sendWebrtcRomm(roomId: string): void;
+
+ sendWebrtcSignal(signal: any, roomId: string): void;
+
+ receiveWebrtcSignal(callBack: Function): void;
+
+ receiveWebrtcStart(callBack: Function): void;
}
-export class Connexion implements ConnexionInterface{
- socket : any;
- token : string;
- email : string;
+
+export class Connexion implements ConnexionInterface {
+ socket: any;
+ token: string;
+ email: string;
userId: string;
- startedRoom : string;
+ startedRoom: string;
GameManager: GameManagerInterface;
- constructor(email : string, GameManager: GameManagerInterface) {
+ constructor(email: string, GameManager: GameManagerInterface) {
this.email = email;
this.GameManager = GameManager;
}
- createConnexion() : Promise<ConnexionInterface>{
+ createConnexion(): Promise<ConnexionInterface> {
return Axios.post(`${API_URL}/login`, {email: this.email})
.then((res) => {
this.token = res.data.token;
* Permit to join a room
* @param roomId
*/
- joinARoom(roomId : string) : void {
+ joinARoom(roomId: string): void {
let messageUserPosition = new MessageUserPosition(this.userId, this.startedRoom, new Point(0, 0));
- this.socket.emit('join-room', messageUserPosition.toString());
+ this.socket.emit(EventMessage.JOIN_ROOM, messageUserPosition.toString());
}
/**
* @param y
* @param direction
*/
- sharePosition(roomId : string, x : number, y : number, direction : string = "none") : void{
- if(!this.socket){
+ sharePosition(roomId: string, x: number, y: number, direction: string = "none"): void {
+ if (!this.socket) {
return;
}
let messageUserPosition = new MessageUserPosition(this.userId, roomId, new Point(x, y, direction));
- this.socket.emit('user-position', messageUserPosition.toString());
+ this.socket.emit(EventMessage.USER_POSITION, messageUserPosition.toString());
}
/**
* ...
* ]
**/
- positionOfAllUser() : void {
- this.socket.on("user-position", (message: string) => {
+ positionOfAllUser(): void {
+ this.socket.on(EventMessage.USER_POSITION, (message: string) => {
let dataList = JSON.parse(message);
dataList.forEach((UserPositions: any) => {
let listMessageUserPosition = new ListMessageUserPosition(UserPositions[0], UserPositions[1]);
});
}
- errorMessage() : void {
- this.socket.on('message-error', (message : string) => {
- console.error("message-error", message);
+ sendWebrtcSignal(signal: any, roomId: string) {
+ this.socket.emit(EventMessage.WEBRTC_SIGNAL, JSON.stringify({
+ userId: this.userId,
+ roomId: roomId,
+ signal: signal
+ }));
+ }
+
+ sendWebrtcRomm(roomId: string) {
+ this.socket.emit(EventMessage.WEBRTC_ROOM, JSON.stringify({roomId: roomId}));
+ }
+
+ receiveWebrtcStart(callback: Function) {
+ this.socket.on(EventMessage.WEBRTC_START, callback);
+ }
+
+ receiveWebrtcSignal(callback: Function) {
+ this.socket.on(EventMessage.WEBRTC_SIGNAL, callback);
+ }
+
+ errorMessage(): void {
+ this.socket.on(EventMessage.MESSAGE_ERROR, (message: string) => {
+ console.error(EventMessage.MESSAGE_ERROR, message);
})
}
}
\ No newline at end of file
import {GameSceneInterface, GameScene} from "./GameScene";
import {ROOM} from "../../Enum/EnvironmentVariable"
import {Connexion, ConnexionInterface, ListMessageUserPositionInterface} from "../../Connexion";
-import {WebRtcEventManager} from "../../WebRtc/WebRtcEventManager";
+import {SimplePeer} from "../../WebRtc/SimplePeer";
export enum StatusGameManagerEnum {
IN_PROGRESS = 1,
this.configureGame();
/** TODO add loader in the page **/
//initialise cam
- new WebRtcEventManager(ConnexionInstance);
+ new SimplePeer(ConnexionInstance);
}).catch((err) => {
console.error(err);
throw err;
let webRtc = document.getElementById('webRtc');
webRtc.classList.add('active');
- this.getCamera();
+ //this.getCamera();
}
enabledCamera() {
this.constraintsMedia.video = true;
this.localStream = null;
this.myCamVideo.srcObject = null;
- this.getCamera();
+ //this.getCamera();
}
disabledCamera() {
}
this.localStream = null;
this.myCamVideo.srcObject = null;
- this.getCamera();
+ //this.getCamera();
}
enabledMicrophone() {
this.microphoneClose.style.display = "none";
this.microphone.style.display = "block";
this.constraintsMedia.audio = true;
- this.getCamera();
+ //this.getCamera();
}
disabledMicrophone() {
}
});
}
- this.getCamera();
+ //this.getCamera();
}
//get camera
getCamera() {
- this.getCameraPromise = navigator.mediaDevices.getUserMedia(this.constraintsMedia)
+ return this.getCameraPromise = navigator.mediaDevices.getUserMedia(this.constraintsMedia)
.then((stream: MediaStream) => {
- console.log("constraintsMedia", stream);
this.localStream = stream;
this.myCamVideo.srcObject = this.localStream;
this.myCamVideo.play();
+ return stream;
}).catch((err) => {
console.error(err);
this.localStream = null;
+++ /dev/null
-import {WebRtcEventManager} from "./WebRtcEventManager";
-import {MediaManager} from "./MediaManager";
-const offerOptions = {
- offerToReceiveAudio: 1,
- offerToReceiveVideo: 1,
- iceServers: [{url:'stun:stun.l.google.com:19302'}],
-};
-
-export class PeerConnexionManager {
-
- WebRtcEventManager: WebRtcEventManager;
- MediaManager : MediaManager;
-
- peerConnection: RTCPeerConnection;
-
- constructor(WebRtcEventManager : WebRtcEventManager) {
- this.WebRtcEventManager = WebRtcEventManager;
- this.MediaManager = new MediaManager();
- }
-
- createPeerConnection(data: any = null): Promise<any> {
- return this.MediaManager.getCameraPromise.then(() => {
- this.peerConnection = new RTCPeerConnection();
-
- //init all events peer connection
- this.createEventPeerConnection();
-
- this.MediaManager.localStream.getTracks().forEach(
- (track: MediaStreamTrack) => this.peerConnection.addTrack(track, this.MediaManager.localStream)
- );
-
- //if no data, create offer
- if (!data || !data.message) {
- return this.createOffer();
- }
-
- let description = new RTCSessionDescription(data.message);
- return this.peerConnection.setRemoteDescription(description).catch((err) => {
- console.error("createPeerConnection => setRemoteDescription", err);
- throw err;
- });
- });
- }
-
- createOffer(): Promise<any> {
- console.log('pc1 createOffer start');
- // @ts-ignore
- return this.peerConnection.createOffer(offerOptions).then((offer: RTCSessionDescriptionInit) => {
- this.peerConnection.setLocalDescription(offer).then(() => {
- let message = {message: this.peerConnection.localDescription};
- this.WebRtcEventManager.emitVideoOffer(message);
- }).catch((err) => {
- console.error("createOffer => setLocalDescription", err);
- throw err;
- });
- }).catch((err: Error) => {
- console.error("createOffer => createOffer", err);
- throw err;
- });
- }
-
- createAnswer(): Promise<any> {
- return this.peerConnection.createAnswer().then((answer : RTCSessionDescriptionInit) => {
- this.peerConnection.setLocalDescription(answer).then(() => {
- //push video-answer
- let messageSend = {message: this.peerConnection.localDescription};
- this.WebRtcEventManager.emitVideoAnswer(messageSend);
- console.info("video-answer => send", messageSend);
- }).catch((err) => {
- console.error("eventVideoOffer => createAnswer => setLocalDescription", err);
- throw err;
- })
- }).catch((err) => {
- console.error("eventVideoOffer => createAnswer", err);
- throw err;
- })
- }
-
- setRemoteDescription(data: any): Promise<any> {
- let description = new RTCSessionDescription(data.message);
- return this.peerConnection.setRemoteDescription(description).catch((err) => {
- console.error("PeerConnexionManager => setRemoteDescription", err);
- throw err;
- })
- }
-
- addIceCandidate(data: any): Promise<any> {
- return this.peerConnection.addIceCandidate(data.message)
- .catch((err) => {
- console.error("PeerConnexionManager => addIceCandidate", err);
- throw err;
- })
- }
-
- hangup() {
- console.log('Ending call');
- if (this.peerConnection) {
- this.peerConnection.close();
- }
- this.peerConnection = null;
- }
-
- createEventPeerConnection(){
- //define creator of offer
- this.peerConnection.addEventListener('icecandidate', ({candidate}) => {
- let message = {message: candidate};
- if (!candidate) {
- return;
- }
- this.WebRtcEventManager.emitIceCandidate(message);
- });
-
- this.peerConnection.addEventListener('iceconnectionstatechange', (e : Event) => {
- console.info('oniceconnectionstatechange => iceConnectionState', this.peerConnection.iceConnectionState);
- });
-
- this.peerConnection.addEventListener('negotiationneeded', (e : Event) => {
- console.info("Event:negotiationneeded => call()", e);
- this.createOffer()
- });
-
- this.peerConnection.addEventListener("track", (e:RTCTrackEvent) => {
- console.info('Event:track', e);
- if (this.MediaManager.remoteVideo.srcObject !== e.streams[0]) {
- this.MediaManager.remoteVideo.srcObject = e.streams[0];
- console.log('pc1 received remote stream');
- }
- });
-
- this.peerConnection.onicegatheringstatechange = () => {
- console.info('onicegatheringstatechange => iceConnectionState', this.peerConnection.iceConnectionState);
- };
- this.peerConnection.onsignalingstatechange = () => {
- console.info('onsignalingstatechange => iceConnectionState', this.peerConnection.iceConnectionState);
- };
- }
-}
\ No newline at end of file
--- /dev/null
+import {ConnexionInterface} from "../Connexion";
+import {MediaManager} from "./MediaManager";
+let Peer = require('simple-peer');
+
+export class SimplePeer {
+ Connexion: ConnexionInterface;
+ MediaManager: MediaManager;
+ RoomId: string;
+
+ PeerConnexion: any;
+
+ constructor(Connexion: ConnexionInterface, roomId: string = "test-webrtc") {
+ this.Connexion = Connexion;
+ this.MediaManager = new MediaManager();
+ this.RoomId = roomId;
+ this.initialise();
+ }
+
+ /**
+ * server has two person connected, start the meet
+ */
+ initialise() {
+ return this.MediaManager.getCamera().then(() => {
+ //send message to join a room
+ this.Connexion.sendWebrtcRomm(this.RoomId);
+
+ //receive message start
+ this.Connexion.receiveWebrtcStart((message : string) => {
+ this.receiveWebrtcStart(message);
+ });
+
+ //receive signal by gemer
+ this.Connexion.receiveWebrtcSignal((message : string) => {
+ this.receiveWebrtcSignal(message);
+ });
+
+ }).catch((err) => {
+ console.error(err);
+ });
+ }
+
+ /**
+ *
+ */
+ receiveWebrtcStart(message: string) {
+ let data = JSON.parse(message);
+
+ //create pear connexion of user stared
+ this.createPeerConnexion(data.initiator);
+ }
+
+ /**
+ *
+ * @param userId
+ * @param initiator
+ */
+ createPeerConnexion(initiator : boolean = false){
+ this.PeerConnexion = new Peer({initiator: initiator});
+ this.addMedia();
+
+ this.PeerConnexion.on('signal', (data: any) => {
+ this.sendWebrtcSignal(data);
+ });
+
+ this.PeerConnexion.on('stream', (stream: MediaStream) => {
+ this.stream(stream)
+ });
+ }
+
+ /**
+ * permit to send signal
+ * @param data
+ */
+ sendWebrtcSignal(data: any) {
+ this.Connexion.sendWebrtcSignal(data, this.RoomId);
+ }
+
+ /**
+ *
+ * @param message
+ */
+ receiveWebrtcSignal(message: string) {
+ let data = JSON.parse(message);
+ if(!this.PeerConnexion){
+ return;
+ }
+ this.PeerConnexion.signal(data.signal);
+ }
+
+ /**
+ * permit stream video
+ * @param stream
+ */
+ stream(stream: MediaStream) {
+ this.MediaManager.remoteStream = stream;
+ this.MediaManager.remoteVideo.srcObject = this.MediaManager.remoteStream;
+ }
+
+ /**
+ * Permit to update stream
+ * @param stream
+ */
+ addMedia () {
+ this.PeerConnexion.addStream(this.MediaManager.localStream) // <- add streams to peer dynamically
+ }
+}
\ No newline at end of file
+++ /dev/null
-import {ConnexionInterface} from "../Connexion";
-import {PeerConnexionManager} from "./PeerConnexionManager";
-
-export class WebRtcEventManager {
- Connexion: ConnexionInterface;
- PeerConnexionManager: PeerConnexionManager;
- RoomId : string;
-
- constructor(Connexion : ConnexionInterface, roomId : string = "test-webrtc") {
- this.RoomId = roomId;
- this.Connexion = Connexion;
- this.PeerConnexionManager = new PeerConnexionManager(this);
-
- this.start();
- this.eventVideoOffer();
- this.eventVideoAnswer();
- this.eventIceCandidate();
-
- //start to connect on event
- //TODO test
- this.emitWebRtcRoom();
- }
-
- /**
- * server has two person connected, start the meet
- */
- start(){
- this.Connexion.socket.on('webrtc-start', () => {
- return this.PeerConnexionManager.createPeerConnection();
- });
- }
-
- /**
- * Receive video offer
- */
- eventVideoOffer() {
- this.Connexion.socket.on("video-offer", (message : any) => {
- let data = JSON.parse(message);
- console.info("video-offer", data);
- this.PeerConnexionManager.createPeerConnection(data).then(() => {
- return this.PeerConnexionManager.createAnswer();
- });
- });
- }
-
- /**
- * Receive video answer
- */
- eventVideoAnswer() {
- this.Connexion.socket.on("video-answer", (message : any) => {
- let data = JSON.parse(message);
- console.info("video-answer", data);
- this.PeerConnexionManager.setRemoteDescription(data)
- .catch((err) => {
- console.error("video-answer => setRemoteDescription", err)
- })
- });
- }
-
- /**
- * Receive ice candidate
- */
- eventIceCandidate() {
- this.Connexion.socket.on("ice-candidate", (message : any) => {
- let data = JSON.parse(message);
- console.info("ice-candidate", data);
- this.PeerConnexionManager.addIceCandidate(data).then(() => {
- console.log(`ICE candidate:\n${data.message ? data.message.candidate : '(null)'}`);
- });
- });
- }
-
- emitWebRtcRoom(){
- //connect on the room to create a meet
- this.Connexion.socket.emit('webrtc-room', JSON.stringify({roomId: this.RoomId}));
- }
-
- emitIceCandidate(message : any){
- message.roomId = this.RoomId;
- this.Connexion.socket.emit('ice-candidate', JSON.stringify(message));
- }
-
- emitVideoOffer(message : any){
- message.roomId = this.RoomId;
- this.Connexion.socket.emit('video-offer', JSON.stringify(message));
- }
-
- emitVideoAnswer(message : any){
- message.roomId = this.RoomId;
- this.Connexion.socket.emit("video-answer", JSON.stringify(message));
- }
-}
\ No newline at end of file
version "13.11.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.11.0.tgz#390ea202539c61c8fa6ba4428b57e05bc36dc47b"
+"@types/simple-peer@^9.6.0":
+ version "9.6.0"
+ resolved "https://registry.yarnpkg.com/@types/simple-peer/-/simple-peer-9.6.0.tgz#b5828d835b7f42dde27db584ba127e7a9f9072f4"
+ integrity sha512-X2y6s+vE/3j03hkI90oqld2JH2J/m1L7yFCYYPyFV/whrOK1h4neYvJL3GIE+UcACJacXZqzdmDKudwec18RbA==
+ dependencies:
+ "@types/node" "*"
+
"@types/socket.io-client@^1.4.32":
version "1.4.32"
resolved "https://registry.yarnpkg.com/@types/socket.io-client/-/socket.io-client-1.4.32.tgz#988a65a0386c274b1c22a55377fab6a30789ac14"
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
+get-browser-rtc@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/get-browser-rtc/-/get-browser-rtc-1.0.2.tgz#bbcd40c8451a7ed4ef5c373b8169a409dd1d11d9"
+ integrity sha1-u81AyEUaftTvXDc7gWmkCd0dEdk=
+
get-caller-file@^1.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
version "2.1.1"
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e"
-randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5:
+queue-microtask@^1.1.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.1.2.tgz#139bf8186db0c545017ec66c2664ac646d5c571e"
+ integrity sha512-F9wwNePtXrzZenAB3ax0Y8TSKGvuB7Qw16J30hspEUTbfUM+H827XyN3rlpwhVmtm5wuZtbKIHjOnwDn7MUxWQ==
+
+randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.3, randombytes@^2.0.5:
version "2.1.0"
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
dependencies:
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
-readable-stream@^3.0.6:
+readable-stream@^3.0.6, readable-stream@^3.4.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
dependencies:
version "3.0.3"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
+simple-peer@^9.6.2:
+ version "9.6.2"
+ resolved "https://registry.yarnpkg.com/simple-peer/-/simple-peer-9.6.2.tgz#42418e77cf8f9184e4fa22ef1017b195c2bf84d7"
+ integrity sha512-EOKoImCaqtNvXIntxT1CBBK/3pVi7tMAoJ3shdyd9qk3zLm3QPiRLb/sPC1G2xvKJkJc5fkQjCXqRZ0AknwTig==
+ dependencies:
+ debug "^4.0.1"
+ get-browser-rtc "^1.0.0"
+ queue-microtask "^1.1.0"
+ randombytes "^2.0.3"
+ readable-stream "^3.4.0"
+
slice-ansi@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636"