Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
8ebeeb4bc8 | |||
|
2b3d73e035 |
8
Makefile
8
Makefile
@ -3,13 +3,13 @@
|
|||||||
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
docker-compose build
|
docker compose build
|
||||||
|
|
||||||
dev: build
|
dev: build
|
||||||
docker-compose up -d --force-recreate
|
docker compose up -d --force-recreate
|
||||||
|
|
||||||
devf: dev
|
devf: dev
|
||||||
docker-compose logs -f
|
docker compose logs -f
|
||||||
|
|
||||||
up:
|
up:
|
||||||
docker compose up -d --force-recreate
|
docker compose up -d --force-recreate
|
||||||
@ -18,7 +18,7 @@ upf: up
|
|||||||
docker compose logs -f
|
docker compose logs -f
|
||||||
|
|
||||||
logs:
|
logs:
|
||||||
docker-compose logs -f
|
docker compose logs -f
|
||||||
|
|
||||||
|
|
||||||
stop:
|
stop:
|
||||||
|
33
package-lock.json
generated
33
package-lock.json
generated
@ -14,16 +14,14 @@
|
|||||||
"@testing-library/jest-dom": "^5.11.9",
|
"@testing-library/jest-dom": "^5.11.9",
|
||||||
"@testing-library/react": "^13.3.0",
|
"@testing-library/react": "^13.3.0",
|
||||||
"@testing-library/user-event": "^12.6.3",
|
"@testing-library/user-event": "^12.6.3",
|
||||||
"@types/ip": "^1.1.3",
|
|
||||||
"@types/jest": "^26.0.20",
|
"@types/jest": "^26.0.20",
|
||||||
"@types/node": "^12.20.55",
|
"@types/node": "^12.19.15",
|
||||||
"@types/react": "^18.0.17",
|
"@types/react": "^18.0.17",
|
||||||
"@types/react-dom": "^18.0.6",
|
"@types/react-dom": "^18.0.6",
|
||||||
"@types/react-router": "^5.1.11",
|
"@types/react-router": "^5.1.11",
|
||||||
"@types/react-router-dom": "^5.1.7",
|
"@types/react-router-dom": "^5.1.7",
|
||||||
"history": "^4.9.0",
|
"history": "^4.9.0",
|
||||||
"ionicons": "^7.0.0",
|
"ionicons": "^7.0.0",
|
||||||
"ip": "^2.0.1",
|
|
||||||
"os": "^0.1.2",
|
"os": "^0.1.2",
|
||||||
"os-browserify": "^0.3.0",
|
"os-browserify": "^0.3.0",
|
||||||
"peerjs": "^1.5.4",
|
"peerjs": "^1.5.4",
|
||||||
@ -49,7 +47,6 @@
|
|||||||
"workbox-streams": "^5.1.4"
|
"workbox-streams": "^5.1.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/uuid": "^10.0.0",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^5.59.2",
|
"@typescript-eslint/eslint-plugin": "^5.59.2",
|
||||||
"@typescript-eslint/parser": "^5.59.2",
|
"@typescript-eslint/parser": "^5.59.2",
|
||||||
"eslint": "^8.35.0",
|
"eslint": "^8.35.0",
|
||||||
@ -3770,15 +3767,6 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/ip": {
|
|
||||||
"version": "1.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/ip/-/ip-1.1.3.tgz",
|
|
||||||
"integrity": "sha512-64waoJgkXFTYnCYDUWgSATJ/dXEBanVkaP5d4Sbk7P6U7cTTMhxVyROTckc6JKdwCrgnAjZMn0k3177aQxtDEA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/node": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/istanbul-lib-coverage": {
|
"node_modules/@types/istanbul-lib-coverage": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
|
||||||
@ -3864,8 +3852,7 @@
|
|||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "12.20.55",
|
"version": "12.20.55",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz",
|
||||||
"integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==",
|
"integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ=="
|
||||||
"license": "MIT"
|
|
||||||
},
|
},
|
||||||
"node_modules/@types/node-forge": {
|
"node_modules/@types/node-forge": {
|
||||||
"version": "1.3.11",
|
"version": "1.3.11",
|
||||||
@ -4012,13 +3999,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
|
||||||
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="
|
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/uuid": {
|
|
||||||
"version": "10.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz",
|
|
||||||
"integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/@types/ws": {
|
"node_modules/@types/ws": {
|
||||||
"version": "8.5.12",
|
"version": "8.5.12",
|
||||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz",
|
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz",
|
||||||
@ -8939,12 +8919,6 @@
|
|||||||
"@stencil/core": "^4.0.3"
|
"@stencil/core": "^4.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ip": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz",
|
|
||||||
"integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/ipaddr.js": {
|
"node_modules/ipaddr.js": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz",
|
||||||
@ -11493,8 +11467,7 @@
|
|||||||
"node_modules/os": {
|
"node_modules/os": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/os/-/os-0.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/os/-/os-0.1.2.tgz",
|
||||||
"integrity": "sha512-ZoXJkvAnljwvc56MbvhtKVWmSkzV712k42Is2mA0+0KTSRakq5XXuXpjZjgAt9ctzl51ojhQWakQQpmOvXWfjQ==",
|
"integrity": "sha512-ZoXJkvAnljwvc56MbvhtKVWmSkzV712k42Is2mA0+0KTSRakq5XXuXpjZjgAt9ctzl51ojhQWakQQpmOvXWfjQ=="
|
||||||
"license": "MIT"
|
|
||||||
},
|
},
|
||||||
"node_modules/os-browserify": {
|
"node_modules/os-browserify": {
|
||||||
"version": "0.3.0",
|
"version": "0.3.0",
|
||||||
|
@ -9,16 +9,14 @@
|
|||||||
"@testing-library/jest-dom": "^5.11.9",
|
"@testing-library/jest-dom": "^5.11.9",
|
||||||
"@testing-library/react": "^13.3.0",
|
"@testing-library/react": "^13.3.0",
|
||||||
"@testing-library/user-event": "^12.6.3",
|
"@testing-library/user-event": "^12.6.3",
|
||||||
"@types/ip": "^1.1.3",
|
|
||||||
"@types/jest": "^26.0.20",
|
"@types/jest": "^26.0.20",
|
||||||
"@types/node": "^12.20.55",
|
"@types/node": "^12.19.15",
|
||||||
"@types/react": "^18.0.17",
|
"@types/react": "^18.0.17",
|
||||||
"@types/react-dom": "^18.0.6",
|
"@types/react-dom": "^18.0.6",
|
||||||
"@types/react-router": "^5.1.11",
|
"@types/react-router": "^5.1.11",
|
||||||
"@types/react-router-dom": "^5.1.7",
|
"@types/react-router-dom": "^5.1.7",
|
||||||
"history": "^4.9.0",
|
"history": "^4.9.0",
|
||||||
"ionicons": "^7.0.0",
|
"ionicons": "^7.0.0",
|
||||||
"ip": "^2.0.1",
|
|
||||||
"os": "^0.1.2",
|
"os": "^0.1.2",
|
||||||
"os-browserify": "^0.3.0",
|
"os-browserify": "^0.3.0",
|
||||||
"peerjs": "^1.5.4",
|
"peerjs": "^1.5.4",
|
||||||
@ -44,7 +42,6 @@
|
|||||||
"workbox-streams": "^5.1.4"
|
"workbox-streams": "^5.1.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/uuid": "^10.0.0",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^5.59.2",
|
"@typescript-eslint/eslint-plugin": "^5.59.2",
|
||||||
"@typescript-eslint/parser": "^5.59.2",
|
"@typescript-eslint/parser": "^5.59.2",
|
||||||
"eslint": "^8.35.0",
|
"eslint": "^8.35.0",
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
"use strict";
|
|
||||||
import React, { useState, useEffect, useCallback } from 'react';
|
import React, { useState, useEffect, useCallback } from 'react';
|
||||||
import InputContainer from './Input';
|
|
||||||
import { IonButton, IonContent, IonText, IonModal, IonIcon, IonLoading } from '@ionic/react';
|
|
||||||
import { call as callIcon, close as hangUpIcon, shirt } from 'ionicons/icons';
|
|
||||||
import Peer, { MediaConnection } from 'peerjs';
|
|
||||||
import './ExploreContainer.css';
|
import './ExploreContainer.css';
|
||||||
import { randomBytes } from 'crypto';
|
import InputContainer from './Input';
|
||||||
|
import {
|
||||||
|
IonButton, IonContent, IonFooter, IonToolbar, IonText, IonModal, IonIcon
|
||||||
|
} from '@ionic/react';
|
||||||
|
import { call as callIcon, close as hangUpIcon } from 'ionicons/icons';
|
||||||
|
import Peer, { MediaConnection } from 'peerjs';
|
||||||
|
|
||||||
const ExploreContainer: React.FC = () => {
|
const ExploreContainer: React.FC = () => {
|
||||||
const [callString, setCallString] = useState("");
|
const [callString, setCallString] = useState("");
|
||||||
@ -15,61 +14,27 @@ const ExploreContainer: React.FC = () => {
|
|||||||
const [localStream, setLocalStream] = useState<MediaStream | null>(null);
|
const [localStream, setLocalStream] = useState<MediaStream | null>(null);
|
||||||
const [connectionInfo, setConnectionInfo] = useState<string | null>(null);
|
const [connectionInfo, setConnectionInfo] = useState<string | null>(null);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [isConnecting, setIsConnecting] = useState(false);
|
|
||||||
const [isCallActive, setIsCallActive] = useState(false);
|
const [isCallActive, setIsCallActive] = useState(false);
|
||||||
const [callDuration, setCallDuration] = useState<number>(0);
|
const [callDuration, setCallDuration] = useState<number>(0);
|
||||||
const [callInterval, setCallInterval] = useState<NodeJS.Timeout | null>(null);
|
const [callInterval, setCallInterval] = useState<NodeJS.Timeout | null>(null);
|
||||||
const [currentCallId, setCurrentCallId] = useState<string | null>(null);
|
const [currentCallId, setCurrentCallId] = useState<string | null>(null);
|
||||||
const [showCopyNotification, setShowCopyNotification] = useState(false);
|
const [connectionSpeed, setConnectionSpeed] = useState<string>("0 kbps");
|
||||||
const [ipv5, setIpv5] = useState<string | null>('')
|
const [activeCall, setActiveCall] = useState<MediaConnection | null>(null);
|
||||||
|
const [isScreenOff, setIsScreenOff] = useState(false);
|
||||||
|
const [isCopied, setIsCopied] = useState(false);
|
||||||
const getLocalIP = async () => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const peerConnection = new RTCPeerConnection({ });
|
|
||||||
// Обрабатываем события ICE-кандидатов, которые будут содержать IP-адрес
|
|
||||||
peerConnection.onicecandidate = (event) => {
|
|
||||||
if (event.candidate) {
|
|
||||||
const ip = event.candidate.candidate.split(" ")[4];
|
|
||||||
console.log(event.candidate)
|
|
||||||
resolve(ip);
|
|
||||||
peerConnection.onicecandidate = null; // Завершаем обработку
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// Создаём пустой канал данных для инициирования связи
|
|
||||||
peerConnection.createDataChannel("");
|
|
||||||
peerConnection.createOffer()
|
|
||||||
.then((offer) => peerConnection.setLocalDescription(offer))
|
|
||||||
.catch((err) => reject(err));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Использование функции
|
|
||||||
getLocalIP().then((ip) => {
|
|
||||||
console.log("Local IP Address in function getLocalIp:", ip);
|
|
||||||
// Debug this func!!
|
|
||||||
setIpv5(ip as string) // ip is eq of "peer-string".local !!??
|
|
||||||
}).catch((err) => {
|
|
||||||
setIpv5(null)
|
|
||||||
console.error("Error getting IP address:", err);
|
|
||||||
});
|
|
||||||
|
|
||||||
const initializePeer = () => {
|
const initializePeer = () => {
|
||||||
console.log(ipv5)
|
const newPeer = new Peer({ debug: 3 });
|
||||||
// ERROR CAST SET AS RANDOMIZE : "error_cast%s", where %s - random string or int
|
|
||||||
const newPeer = new Peer( ipv5 ? ipv5 : "error_cast",{ debug: 3 });
|
|
||||||
setPeer(newPeer);
|
setPeer(newPeer);
|
||||||
|
|
||||||
newPeer.on('open', (id) => {
|
newPeer.on('open', (id) => {
|
||||||
console.log(`Peer successfully opened with ID: ${id}`);
|
console.log(`Peer успешно открыт с ID: ${id}`);
|
||||||
setConnectionInfo(id);
|
setConnectionInfo(id);
|
||||||
});
|
});
|
||||||
|
|
||||||
newPeer.on('call', (call: MediaConnection) => handleIncomingCall(call));
|
newPeer.on('call', (call: MediaConnection) => handleIncomingCall(call));
|
||||||
newPeer.on('error', (err) => console.error('Peer error:', err));
|
newPeer.on('error', (err) => console.error('Ошибка Peer:', err));
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
newPeer.destroy();
|
newPeer.destroy();
|
||||||
@ -80,51 +45,72 @@ const ExploreContainer: React.FC = () => {
|
|||||||
return cleanup;
|
return cleanup;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleProximity = (event: any) => {
|
||||||
|
if (event.value) {
|
||||||
|
// Если телефон близко к лицу, гасим экран
|
||||||
|
setIsScreenOff(true);
|
||||||
|
} else {
|
||||||
|
// Если телефон не близко, включаем экран
|
||||||
|
setIsScreenOff(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('deviceproximity', handleProximity);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('deviceproximity', handleProximity);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleIncomingCall = useCallback((call: MediaConnection) => {
|
const handleIncomingCall = useCallback((call: MediaConnection) => {
|
||||||
console.log('Incoming call received');
|
console.log('Получен входящий звонок');
|
||||||
setCurrentCallId(call.peer);
|
setCurrentCallId(call.peer);
|
||||||
setIsConnecting(true); // Show connecting screen
|
setActiveCall(call);
|
||||||
navigator.mediaDevices.getUserMedia({ audio: true }).then((stream) => {
|
navigator.mediaDevices.getUserMedia({ audio: true }).then((stream) => {
|
||||||
setLocalStream(stream);
|
setLocalStream(stream);
|
||||||
call.answer(stream);
|
call.answer(stream);
|
||||||
call.on('stream', (remoteStream: MediaStream) => {
|
call.on('stream', (remoteStream: MediaStream) => {
|
||||||
console.log('Remote stream received');
|
console.log('Получен удалённый поток');
|
||||||
playAudio(remoteStream);
|
playAudio(remoteStream);
|
||||||
setIsConnecting(false); // Hide connecting screen once audio is received
|
|
||||||
startCallTimer();
|
startCallTimer();
|
||||||
setIsCallActive(true);
|
setIsCallActive(true);
|
||||||
|
monitorConnectionSpeed(call);
|
||||||
|
});
|
||||||
|
call.on('close', () => {
|
||||||
|
endCall();
|
||||||
});
|
});
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.error('Failed to get local stream for answer', err);
|
console.error('Не удалось получить локальный поток для ответа', err);
|
||||||
setIsConnecting(false); // Hide connecting screen in case of error
|
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const makeCall = useCallback(() => {
|
const makeCall = useCallback(() => {
|
||||||
if (peer && callString) {
|
if (peer && callString) {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
setIsConnecting(true); // Show connecting screen
|
console.log(`Попытка звонка на: ${callString}`);
|
||||||
console.log(`Attempting to call: ${callString}`);
|
|
||||||
|
|
||||||
navigator.mediaDevices.getUserMedia({ audio: true }).then((stream) => {
|
navigator.mediaDevices.getUserMedia({ audio: true }).then((stream) => {
|
||||||
setLocalStream(stream);
|
setLocalStream(stream);
|
||||||
const call = peer.call(callString, stream);
|
const call = peer.call(callString, stream);
|
||||||
|
setActiveCall(call);
|
||||||
setCurrentCallId(callString);
|
setCurrentCallId(callString);
|
||||||
call.on('stream', (remoteStream: MediaStream) => {
|
call.on('stream', (remoteStream: MediaStream) => {
|
||||||
console.log('Remote stream received during call');
|
console.log('Получен удалённый поток во время вызова');
|
||||||
playAudio(remoteStream);
|
playAudio(remoteStream);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
setIsConnecting(false); // Hide connecting screen once audio is received
|
|
||||||
startCallTimer();
|
startCallTimer();
|
||||||
setIsCallActive(true);
|
setIsCallActive(true);
|
||||||
|
monitorConnectionSpeed(call);
|
||||||
|
});
|
||||||
|
call.on('close', () => {
|
||||||
|
endCall();
|
||||||
});
|
});
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.error('Failed to get local stream', err);
|
console.error('Не удалось получить локальный поток', err);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
setIsConnecting(false); // Hide connecting screen on error
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.warn('Call not possible: Peer or callString is missing');
|
console.warn('Звонок невозможен: отсутствует Peer или callString');
|
||||||
}
|
}
|
||||||
}, [peer, callString]);
|
}, [peer, callString]);
|
||||||
|
|
||||||
@ -132,6 +118,9 @@ const ExploreContainer: React.FC = () => {
|
|||||||
if (localStream) {
|
if (localStream) {
|
||||||
localStream.getTracks().forEach(track => track.stop());
|
localStream.getTracks().forEach(track => track.stop());
|
||||||
}
|
}
|
||||||
|
if (activeCall) {
|
||||||
|
activeCall.close();
|
||||||
|
}
|
||||||
setIsCallActive(false);
|
setIsCallActive(false);
|
||||||
setIsEnable(true);
|
setIsEnable(true);
|
||||||
if (callInterval) {
|
if (callInterval) {
|
||||||
@ -139,7 +128,8 @@ const ExploreContainer: React.FC = () => {
|
|||||||
}
|
}
|
||||||
setCallDuration(0);
|
setCallDuration(0);
|
||||||
setCurrentCallId(null);
|
setCurrentCallId(null);
|
||||||
}, [localStream, callInterval]);
|
setConnectionSpeed("0 kbps");
|
||||||
|
}, [localStream, callInterval, activeCall]);
|
||||||
|
|
||||||
const startCallTimer = useCallback(() => {
|
const startCallTimer = useCallback(() => {
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
@ -152,9 +142,25 @@ const ExploreContainer: React.FC = () => {
|
|||||||
const audioElement = document.createElement('audio');
|
const audioElement = document.createElement('audio');
|
||||||
audioElement.srcObject = stream;
|
audioElement.srcObject = stream;
|
||||||
audioElement.play().then(() => {
|
audioElement.play().then(() => {
|
||||||
console.log('Audio playback started');
|
console.log('Аудио начато воспроизведение');
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
console.error('Audio playback error', error);
|
console.error('Ошибка воспроизведения аудио', error);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const monitorConnectionSpeed = useCallback((call: MediaConnection) => {
|
||||||
|
call.on('iceStateChanged', () => {
|
||||||
|
if (call.peerConnection) {
|
||||||
|
const stats = call.peerConnection.getStats();
|
||||||
|
stats.then((report) => {
|
||||||
|
report.forEach((result) => {
|
||||||
|
if (result.type === 'candidate-pair' && result.state === 'succeeded') {
|
||||||
|
const speed = `${Math.round(result.currentRoundTripTime * 1000)} kbps`;
|
||||||
|
setConnectionSpeed(speed);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -162,30 +168,24 @@ const ExploreContainer: React.FC = () => {
|
|||||||
if (connectionInfo) {
|
if (connectionInfo) {
|
||||||
navigator.clipboard.writeText(connectionInfo)
|
navigator.clipboard.writeText(connectionInfo)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
console.log('Peer ID copied to clipboard');
|
console.log('Peer ID скопирован в буфер обмена');
|
||||||
setShowCopyNotification(true);
|
setIsCopied(true);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setShowCopyNotification(false);
|
setIsCopied(false);
|
||||||
}, 2000);
|
}, 2000);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error('Failed to copy Peer ID', err);
|
console.error('Не удалось скопировать Peer ID', err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [connectionInfo]);
|
}, [connectionInfo]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<IonContent fullscreen={true} className="ion-padding">
|
<IonContent fullscreen={true} className={`ion-padding ${isScreenOff ? 'screen-off' : ''}`}>
|
||||||
{/* Connecting Indicator */}
|
|
||||||
<IonLoading
|
|
||||||
isOpen={isConnecting}
|
|
||||||
message={'Connecting...'}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div id="container">
|
<div id="container">
|
||||||
<div className="peer-id-container">
|
<div className="peer-id-container">
|
||||||
<IonText className="peer-id-text">Your Peer ID: {connectionInfo}</IonText>
|
<IonText className="peer-id-text">Ваш Peer ID: {connectionInfo}</IonText>
|
||||||
<button className="copy-button" onClick={copyPeerId}>
|
<button className="copy-button" onClick={copyPeerId}>
|
||||||
<svg width="51" height="51" fill="none" stroke="#34554a" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
<svg width="51" height="51" fill="none" stroke="#34554a" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M19.078 6H8.672A2.672 2.672 0 0 0 6 8.672v10.406a2.672 2.672 0 0 0 2.672 2.672h10.406a2.672 2.672 0 0 0 2.672-2.672V8.672A2.672 2.672 0 0 0 19.078 6Z"></path>
|
<path d="M19.078 6H8.672A2.672 2.672 0 0 0 6 8.672v10.406a2.672 2.672 0 0 0 2.672 2.672h10.406a2.672 2.672 0 0 0 2.672-2.672V8.672A2.672 2.672 0 0 0 19.078 6Z"></path>
|
||||||
@ -193,11 +193,7 @@ const ExploreContainer: React.FC = () => {
|
|||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{showCopyNotification && (
|
{isCopied && <div className="copy-notification">Peer ID скопирован</div>}
|
||||||
<div className="copy-notification">
|
|
||||||
Peer ID copied
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className="input-container">
|
<div className="input-container">
|
||||||
<InputContainer
|
<InputContainer
|
||||||
callString={callString}
|
callString={callString}
|
||||||
@ -210,14 +206,15 @@ const ExploreContainer: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Call Modal */}
|
{/* Модальное окно для звонка */}
|
||||||
<IonModal isOpen={isCallActive}>
|
<IonModal isOpen={isCallActive}>
|
||||||
<IonContent className="ion-padding">
|
<IonContent className="ion-padding">
|
||||||
<div className="call-info-container">
|
<div className="call-info-container">
|
||||||
{/* Add GIF */}
|
{/* Добавляем гифку */}
|
||||||
<img src="/monkey-monkey-with-drone.gif" alt="Monkey with Drone" className="drone-gif" />
|
<img src="/monkey-monkey-with-drone.gif" alt="Monkey with Drone" className="drone-gif" />
|
||||||
<IonText className="call-info-text">Peer ID: {currentCallId}</IonText>
|
<IonText className="call-info-text">Peer ID: {currentCallId}</IonText>
|
||||||
<IonText className="call-duration-text">{Math.floor(callDuration / 60)}:{callDuration % 60}</IonText>
|
<IonText className="call-duration-text">{Math.floor(callDuration / 60)}:{callDuration % 60}</IonText>
|
||||||
|
<IonText className="connection-speed-text">Скорость соединения: {connectionSpeed}</IonText>
|
||||||
<button onClick={endCall} className="custom-hang-up-button">
|
<button onClick={endCall} className="custom-hang-up-button">
|
||||||
<svg width="51" height="51" fill="#cd1818" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
<svg width="51" height="51" fill="#cd1818" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M18.327 22.5c-.915 0-2.2-.331-4.125-1.407-2.34-1.312-4.15-2.524-6.478-4.846-2.245-2.243-3.337-3.695-4.865-6.476C1.132 6.63 1.426 4.984 1.755 4.28c.392-.842.97-1.345 1.718-1.844a8.263 8.263 0 0 1 1.343-.712l.13-.057c.231-.105.583-.263 1.028-.094.297.112.562.34.978.75.852.84 2.015 2.71 2.445 3.63.288.619.479 1.028.48 1.486 0 .537-.27.95-.598 1.397l-.182.242c-.356.469-.435.604-.383.846.104.486.884 1.933 2.165 3.212 1.281 1.278 2.686 2.008 3.174 2.112.253.054.39-.027.875-.397.069-.053.14-.107.215-.162.5-.372.894-.635 1.418-.635h.003c.456 0 .847.198 1.493.524.844.426 2.771 1.575 3.616 2.427.412.415.64.679.753.976.169.447.01.797-.094 1.031l-.057.129a8.27 8.27 0 0 1-.716 1.34c-.499.745-1.004 1.322-1.846 1.714a3.16 3.16 0 0 1-1.386.304Z"></path>
|
<path d="M18.327 22.5c-.915 0-2.2-.331-4.125-1.407-2.34-1.312-4.15-2.524-6.478-4.846-2.245-2.243-3.337-3.695-4.865-6.476C1.132 6.63 1.426 4.984 1.755 4.28c.392-.842.97-1.345 1.718-1.844a8.263 8.263 0 0 1 1.343-.712l.13-.057c.231-.105.583-.263 1.028-.094.297.112.562.34.978.75.852.84 2.015 2.71 2.445 3.63.288.619.479 1.028.48 1.486 0 .537-.27.95-.598 1.397l-.182.242c-.356.469-.435.604-.383.846.104.486.884 1.933 2.165 3.212 1.281 1.278 2.686 2.008 3.174 2.112.253.054.39-.027.875-.397.069-.053.14-.107.215-.162.5-.372.894-.635 1.418-.635h.003c.456 0 .847.198 1.493.524.844.426 2.771 1.575 3.616 2.427.412.415.64.679.753.976.169.447.01.797-.094 1.031l-.057.129a8.27 8.27 0 0 1-.716 1.34c-.499.745-1.004 1.322-1.846 1.714a3.16 3.16 0 0 1-1.386.304Z"></path>
|
||||||
|
@ -7,14 +7,6 @@
|
|||||||
// code you'd like.
|
// code you'd like.
|
||||||
// You can also remove this file if you'd prefer not to use a
|
// You can also remove this file if you'd prefer not to use a
|
||||||
// service worker, and the Workbox build step will be skipped.
|
// service worker, and the Workbox build step will be skipped.
|
||||||
/** Гигачады
|
|
||||||
* Люднев Виталий
|
|
||||||
Баранова Софья
|
|
||||||
Белков Семен
|
|
||||||
Корнеев Владимир
|
|
||||||
Иноземцев Василий
|
|
||||||
Болганюк Константин
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { clientsClaim } from 'workbox-core';
|
import { clientsClaim } from 'workbox-core';
|
||||||
import { ExpirationPlugin } from 'workbox-expiration';
|
import { ExpirationPlugin } from 'workbox-expiration';
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
FROM golang:1.22.5-alpine3.20
|
|
||||||
LABEL author="moxitech"
|
|
||||||
WORKDIR /var/moxitech_goturn
|
|
||||||
COPY app /var/moxitech_goturn
|
|
||||||
|
|
||||||
RUN go get ./...;
|
|
||||||
RUN go build -o main cmd/main.go
|
|
||||||
EXPOSE 3434
|
|
||||||
CMD "./main"
|
|
@ -1,71 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/pion/turn/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
publicIP := flag.String("public-ip", "127.0.0.1", "") //"154.194.52.123"
|
|
||||||
port := flag.Int("port", 8081, "")
|
|
||||||
users := flag.String("users", "moxitech=moxitech", "") // user=pass,user=pass
|
|
||||||
realm := flag.String("realm", "callcoocall", "")
|
|
||||||
flag.Parse()
|
|
||||||
if len(*publicIP) == 0 {
|
|
||||||
log.Fatalf("public-ip is required")
|
|
||||||
}
|
|
||||||
if len(*users) == 0 {
|
|
||||||
log.Fatalf("'users' is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
udpListener, err := net.ListenPacket("udp4", "0.0.0.0:"+strconv.Itoa(*port))
|
|
||||||
if err != nil {
|
|
||||||
log.Panicf("Ошибка создания TURN сервера: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
usersMap := map[string][]byte{}
|
|
||||||
for _, kv := range regexp.MustCompile(`(\w+)=(\w+)`).FindAllStringSubmatch(*users, -1) {
|
|
||||||
usersMap[kv[1]] = turn.GenerateAuthKey(kv[1], *realm, kv[2])
|
|
||||||
}
|
|
||||||
|
|
||||||
s, err := turn.NewServer(turn.ServerConfig{
|
|
||||||
Realm: *realm,
|
|
||||||
AuthHandler: func(username string, realm string, srcAddr net.Addr) ([]byte, bool) {
|
|
||||||
if key, ok := usersMap[username]; ok {
|
|
||||||
return key, true
|
|
||||||
}
|
|
||||||
return nil, false
|
|
||||||
},
|
|
||||||
|
|
||||||
PacketConnConfigs: []turn.PacketConnConfig{
|
|
||||||
{
|
|
||||||
PacketConn: udpListener,
|
|
||||||
RelayAddressGenerator: &turn.RelayAddressGeneratorPortRange{
|
|
||||||
RelayAddress: net.ParseIP(*publicIP),
|
|
||||||
Address: "0.0.0.0",
|
|
||||||
MinPort: 50000,
|
|
||||||
MaxPort: 55000,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
sigs := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
|
||||||
<-sigs
|
|
||||||
|
|
||||||
if err = s.Close(); err != nil {
|
|
||||||
log.Panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
module moxitech/turn
|
|
||||||
|
|
||||||
go 1.22.5
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/pion/dtls/v2 v2.2.7 // indirect
|
|
||||||
github.com/pion/logging v0.2.2 // indirect
|
|
||||||
github.com/pion/randutil v0.1.0 // indirect
|
|
||||||
github.com/pion/stun v0.6.1 // indirect
|
|
||||||
github.com/pion/transport/v2 v2.2.1 // indirect
|
|
||||||
github.com/pion/turn/v2 v2.1.6 // indirect
|
|
||||||
golang.org/x/crypto v0.8.0 // indirect
|
|
||||||
golang.org/x/sys v0.9.0 // indirect
|
|
||||||
)
|
|
@ -1,63 +0,0 @@
|
|||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8=
|
|
||||||
github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
|
|
||||||
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
|
|
||||||
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
|
|
||||||
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
|
|
||||||
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
|
|
||||||
github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4=
|
|
||||||
github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8=
|
|
||||||
github.com/pion/transport/v2 v2.2.1 h1:7qYnCBlpgSJNYMbLCKuSY9KbQdBFoETvPNETv0y4N7c=
|
|
||||||
github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g=
|
|
||||||
github.com/pion/turn/v2 v2.1.6 h1:Xr2niVsiPTB0FPtt+yAWKFUkU1eotQbGgpTIld4x1Gc=
|
|
||||||
github.com/pion/turn/v2 v2.1.6/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
|
||||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
|
||||||
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
|
|
||||||
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
|
||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
|
||||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
|
|
||||||
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
|
||||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
@ -1,26 +0,0 @@
|
|||||||
version: '3.9'
|
|
||||||
|
|
||||||
networks:
|
|
||||||
moxitech-network:
|
|
||||||
driver: bridge
|
|
||||||
|
|
||||||
|
|
||||||
services:
|
|
||||||
|
|
||||||
|
|
||||||
turn_server:
|
|
||||||
container_name: turn
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
networks:
|
|
||||||
moxitech-network:
|
|
||||||
restart: always
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user