Compare commits

..

97 Commits

Author SHA1 Message Date
4f044555ba Merge pull request 'Update node version in Dockerfile' (#38) from update-build into develop
Reviewed-on: #38
2025-03-07 09:35:02 +00:00
230d5b6bce Merge branch 'develop' into update-build 2025-03-07 09:34:33 +00:00
73c7700ded Update node version in Dockerfile 2025-03-07 11:33:47 +02:00
9e66772b53 Merge pull request 'update-build' (#37) from update-build into develop
Reviewed-on: #37
2025-03-07 09:14:06 +00:00
5ef66af3f8 Update build.sh 2025-03-07 11:12:56 +02:00
1b29d43580 Update build.sh 2025-03-07 11:12:12 +02:00
dd5af12c7c Merge pull request 'LINXD-2842-log-protocol-change' (#36) from LINXD-2842-log-protocol-change into develop
Reviewed-on: #36
Reviewed-by: Cristi Ene <cristi.ene@safemobile.com>
2025-03-05 21:40:24 +00:00
af21774d17 LINXD-2842: Update mediasoup version; Add handler for icestatechange; Add env PREFER_TCP; Add 3s ICE consent timeout 2025-03-05 23:37:35 +02:00
fc250c248e LINXD-2842: Update README 2025-03-04 17:01:54 +02:00
fc39d5bead LINXD-2842: Log message when protocol is changed 2025-03-03 22:30:41 +02:00
a5c00ba10a update documentation 2025-02-27 13:34:55 +02:00
f7053359a5 Merge pull request 'LINXD-2836: Add connection type(udp, tcp) configurable from env' (#35) from LINXD-2836-mediasoup-connection-type-env into develop
Reviewed-on: #35
Reviewed-by: Cristi Ene <cristi.ene@safemobile.com>
2025-02-26 09:45:03 +00:00
056858d412 Merge pull request 'LINXD-2570: Add unit to dispatcher video call diagram' (#34) from LINXD-2570-mobile-to-dispatcher-calls into develop
Reviewed-on: #34
Reviewed-by: Cristi Ene <cristi.ene@safemobile.com>
2025-02-26 09:40:55 +00:00
3f40baad3e LINX-2836: Update certs 2025-02-26 10:26:28 +02:00
Sergiu Toma
b1c8419af5 LINXD-2836: Add connection type(udp, tcp) configurable from env 2025-02-26 10:24:09 +02:00
Sergiu Toma
271768065c LINXD-2570: Add unit to dispatcher video call diagram 2023-12-06 10:26:21 +02:00
ce1fe3ca8d Merge pull request 'Update 'app.js'' (#33) from sergiu-patch-1 into develop
Reviewed-on: #33
Reviewed-by: bmamihai <mihai.bozieru@safemobile.com>
2023-06-07 12:51:12 +00:00
96b770d9c5 Update 'app.js' 2023-06-07 12:50:24 +00:00
4b1f4fab70 Merge pull request 'LH-284: Update duplex documentation workflow diagrams' (#32) from LH-284-update-and-centralize-diagrams-for-video-calls into develop
Reviewed-on: #32
Reviewed-by: Adriana <adriana.epure@safemobile.com>
2023-05-30 11:27:09 +00:00
ba7c2186af LH-284: Update duplex documentation workflow diagrams 2023-05-30 11:57:02 +03:00
636e8a9fab Merge pull request 'added build commit no' (#31) from build-commit-no into develop
Reviewed-on: #31
Reviewed-by: Cristi Ene <cristi.ene@safemobile.com>
2023-04-10 23:36:34 +00:00
5da2eb6927 update build.sh after review 2023-04-05 01:57:58 +03:00
97948a5d8c added build commit no 2023-04-02 01:17:18 +03:00
b94b1bff86 Merge pull request 'docker' (#18) from docker into develop
Reviewed-on: #18
Reviewed-by: Cristi Ene <cristi.ene@safemobile.com>
2023-02-26 22:11:02 +00:00
5c4f2bf13e Merge branch 'develop' into docker 2023-02-26 22:10:34 +00:00
df7f1987f6 Merge pull request 'LH-276: Add close-producer event handler; Update client' (#30) from LH-276-close-producer into develop
Reviewed-on: #30
Reviewed-by: Cristi Ene <cristi.ene@safemobile.com>
2023-02-23 09:46:41 +00:00
7842953faf LH-276: Refactor consumer-resume 2023-02-22 18:57:57 +02:00
4591617b1e LH-276: Fix video consume when initiator is not set yet(at start) 2023-02-22 18:50:37 +02:00
9b3f2f94c8 LH-276: Fix audio when initiator is not set yet(at start) 2023-02-22 18:46:01 +02:00
29a4cd7227 LH-276: Format code 2023-02-22 18:40:39 +02:00
c80265fe25 LH-276: Format code 2023-02-22 18:36:50 +02:00
abb1533c9b LH-276: Format code 2023-02-22 18:32:41 +02:00
6e3ce9fbb3 LH-276: Format code 2023-02-22 18:30:28 +02:00
4d8adf9eac LH-276: Refactor consume(consumeAudio/consumeVideo); Format code 2023-02-22 18:21:53 +02:00
bde02fe250 LH-276: Add close-producer event handler; Update client 2023-02-21 02:41:48 +02:00
0ddb43b4b5 Merge pull request 'LINXD-2342-dispatcher-audio' (#29) from LINXD-2342-dispatcher-audio into develop
Reviewed-on: #29
Reviewed-by: Cristi Ene <cristi.ene@safemobile.com>
2023-02-15 09:14:57 +00:00
f02d6af726 LINXD-2342: Added documentation for kind 2023-02-15 11:14:02 +02:00
7ee93d7963 LINXD-2342: Update video client 2023-02-15 10:06:39 +02:00
98212a78cb Update client to consume audio correctly 2023-02-11 21:32:53 +02:00
33ea44ac02 Update client to consume audio correctly 2023-02-11 21:30:21 +02:00
6b822142d0 Add the kind of producer on new-producer event 2023-02-11 21:13:57 +02:00
50e95b93a4 Update client 2023-02-08 19:37:32 +02:00
6eca0808c9 Merge pull request 'Update web client to work with dev' (#27) from update-web-client into develop
Reviewed-on: #27
Reviewed-by: bmamihai <mihai.bozieru@safemobile.com>
2023-01-23 20:37:27 +00:00
f728b23b7f Update web client to work with dev 2023-01-23 20:45:08 +02:00
33c0234fb0 Merge pull request 'LINXD-2303: Added client-to-client workflow; Added client-mediadoup workflow' (#26) from LINXD-2303-video-documentation-mobile-mobile into develop
Reviewed-on: #26
Reviewed-by: Cristi Ene <cristi.ene@safemobile.com>
2023-01-19 14:44:24 +00:00
f81d5b2dfa LINXD-2303: Update diagrams Mediasoup connect & produce; Update diagram Client-Client workflow 2023-01-19 16:43:46 +02:00
ae87b5bd71 LINXD-2303: Added client-to-client workflow; Added client-mediadoup workflow 2023-01-19 16:31:16 +02:00
09e82fb224 Merge pull request 'Moved 'new-producer' in 'transport-produce' handler' (#25) from new-producer-in-transport-produce into develop
Reviewed-on: #25
Reviewed-by: Cristi Ene <cristi.ene@safemobile.com>
2023-01-19 06:54:53 +00:00
1da0170261 Moved 'new-producer' in 'transport-produce' handler 2023-01-18 11:49:02 +02:00
aca0a6eac0 improved build to get also the git log to know what is on server 2023-01-17 16:00:52 +00:00
23ca56c8c6 rever build.sh 2023-01-17 15:51:55 +00:00
a2d0b6771b Merge pull request 'Add new-producer event; Update client to consume when receives new-producer event' (#24) from LAPI-675-generate-new-producer-in-mediasoup-and-client into develop
Reviewed-on: #24
Reviewed-by: Cristi Ene <cristi.ene@safemobile.com>
2023-01-16 15:40:06 +00:00
9382fd11fb LAPI-675: Remove commented code 2023-01-16 17:39:15 +02:00
fb99fd57f8 LAPI-675: Refactor transport-connect new-producer 2023-01-16 17:32:31 +02:00
0f4342777a LAPI-675: Update bundle 2023-01-13 20:12:59 +02:00
69c167e4e9 Add new-producer event; Update client to consume when receives new-producer event 2023-01-13 20:11:24 +02:00
ad4c1f27e7 Merge pull request 'LAPI-674: Parse transport-recv-connect and consume param' (#23) from LAPI-674-change-events-for-consumer-in-mediasoup-server into develop
Reviewed-on: #23
Reviewed-by: Cristi Ene <cristi.ene@safemobile.com>
2023-01-13 07:52:27 +00:00
b2128c4754 fix build 2023-01-12 16:42:44 +00:00
af53dc1610 fix build 2023-01-12 16:30:39 +00:00
f48fe4f9aa LAPI-674: Parse transport-recv-connect and consume param 2023-01-12 16:23:30 +02:00
6fd6ca9755 Merge pull request 'comsume-undefined' (#22) from comsume-undefined into develop
Reviewed-on: #22
Reviewed-by: Cristi Ene <cristi.ene@safemobile.com>
2023-01-12 13:31:46 +00:00
1b72941a32 Moved callId in consumer-resume 2023-01-12 15:09:21 +02:00
c037240f47 Refactor consumer-resume 2023-01-12 14:32:48 +02:00
9716bddd71 Added log 2023-01-12 12:50:40 +02:00
e6c08a2c1d Refactor consumer-resume v3 2023-01-12 12:46:46 +02:00
1342e812e6 Refactor consumer-resume 2023-01-12 12:45:23 +02:00
d8405eccc7 Refactor consumer-resume 2023-01-12 12:44:11 +02:00
5bf31d452f Check for initiatorConsumerAudio before resume() 2023-01-12 12:38:40 +02:00
c034610471 Rollback 2023-01-12 12:38:01 +02:00
df5b3eab90 Check for initiatorConsumerAudio before resume() 2023-01-12 12:31:52 +02:00
b0293230b6 Merge pull request 'add-diagrams-doc' (#21) from add-diagrams-doc into develop
Reviewed-on: #21
Reviewed-by: Cristi Ene <cristi.ene@safemobile.com>
2023-01-10 17:51:05 +00:00
391e8eb6f0 Added diagram for close call before accept/reject 2023-01-10 13:17:57 +02:00
3139a625a2 Added workflow diagrams 2023-01-10 12:05:29 +02:00
48eee903a5 added command for limiting cpu/memory 2023-01-05 14:31:51 +02:00
d5bc0cd1d3 run under host network 2023-01-05 13:18:13 +02:00
1c353d7c88 Merge branch 'develop' into docker 2023-01-05 01:14:56 +02:00
9d43b7ec0c Merge pull request 'LINXD-2270: Allow server and web client to have full duplex' (#20) from LINXD-2270-full-duplex into develop
Reviewed-on: #20
Reviewed-by: Cristi Ene <cristi.ene@safemobile.com>
2022-12-27 11:12:38 +00:00
342d09c3e6 LINXD-2270: Removed console logs; Update commented code 2022-12-27 13:11:06 +02:00
b3409de3ba LINXD-2270: Allow server and web client to have full duplex 2022-12-19 19:31:33 +02:00
3e31ba21bd replace individual copy with copy all 2022-12-15 13:20:22 +02:00
cdf02756d3 fix start 2022-12-14 01:32:17 +02:00
b2f9f5affa remove pm2 and watchify 2022-12-14 00:48:14 +02:00
5b9bfeaa01 improve docker 2022-12-10 03:21:59 +02:00
e3bef9b3e5 New dockerfile 2022-12-10 02:38:09 +02:00
8a9c370f02 Merge pull request 'LH-265-audio' (#17) from LH-265-audio into develop
Reviewed-on: #17
Reviewed-by: Cristi Ene <cristi.ene@safemobile.com>
2022-12-06 12:45:08 +00:00
652019b07d LH-265: Update doc; Update bundle 2022-11-29 15:35:28 +02:00
09c4a4b90e LH-265: Added audio on client and server 2022-11-29 14:19:02 +02:00
75d0e3aee7 exe right for build.sh 2022-10-31 22:26:08 +00:00
30ac997634 Merge pull request 'added build.sh' (#14) from temp-build into develop
Reviewed-on: #14
2022-10-31 22:22:20 +00:00
5aea138f6a added build.sh 2022-10-31 12:17:07 +02:00
5b01ddc2a8 Merge pull request 'LH-259-mediasoup-always-return-a-callback-response-to-clients' (#13) from LH-259-mediasoup-always-return-a-callback-response-to-clients into develop
Reviewed-on: #13
2022-10-25 16:18:54 +00:00
084ff36ebe LH-259: Refactor createRoom 2022-10-24 22:38:06 +03:00
f4ebf92783 LH-259: Added callback from transport-produce 2022-10-24 22:35:22 +03:00
b59a157b18 LH-259: Comment callback from transport-produce 2022-10-24 22:19:37 +03:00
9f8347bec5 LH-259: Update createRoom callback 2022-10-24 22:16:47 +03:00
24390c98e5 LH-259: Added callbacks 2022-10-24 22:11:14 +03:00
1a7371fe18 Parse RTC_MIN_PORT and RTC_MAX_PORT 2022-10-18 18:27:02 +03:00
28 changed files with 3015 additions and 1530 deletions

2
.dockerignore Normal file
View File

@ -0,0 +1,2 @@
node_modules
doc

14
.env
View File

@ -1,7 +1,11 @@
PORT=3000
IP=0.0.0.0 # Listening IPv4 or IPv6.
ANNOUNCED_IP=185.8.154.190 # Announced IPv4 or IPv6 (useful when running mediasoup behind NAT with private IP).
RTC_MIN_PORT=2000
RTC_MAX_PORT=2020
IP=0.0.0.0 # Listening IPv4 or IPv6.
ANNOUNCED_IP=192.168.1.199 # Announced IPv4 or IPv6 (useful when running mediasoup behind NAT with private IP).
RTC_MIN_PORT=40000
RTC_MAX_PORT=49999
SERVER_CERT="./server/ssl/cert.pem"
SERVER_KEY="./server/ssl/key.pem"
SERVER_KEY="./server/ssl/key.pem"
ENABLE_UDP=true
ENABLE_TCP=true
PREFER_UDP=true
PREFER_TCP=false

2
.gitignore vendored
View File

@ -1 +1,3 @@
/node_modules
/dist
.idea

View File

@ -1,11 +1,25 @@
FROM ubuntu
FROM ubuntu:22.04
WORKDIR /app
RUN apt-get update && \
apt-get install -y build-essential pip net-tools iputils-ping iproute2 curl
RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash -
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
RUN apt-get install -y nodejs
RUN npm install -g watchify
EXPOSE 3000
EXPOSE 2000-2020
EXPOSE 10000-10100
COPY . /app/
RUN npm install
EXPOSE 3000/tcp
EXPOSE 2000-2200/udp
CMD node app.js
#docker build -t linx-video .
# docker run -it -d --restart always -p 3000:3000/tcp -p 2000-2200:2000-2200/udp linx-video
#Run under host network
# docker run -it -d --network host --restart always -p 3000:3000/tcp -p 2000-2200:2000-2200/udp linx-video
#https://docs.docker.com/config/containers/resource_constraints/
#docker run -it -d --network host --cpus="0.25" --memory="512m" --restart always -p 3000:3000/tcp -p 2000-2200:2000-2200/udp linx-video

View File

@ -6,34 +6,54 @@
1. Go to `/server/ssl`
2. Execute `openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem`
### Development
##### To start in development mode you must:
1. Install the dependencies `npm install`.
2. Run the `npm start:dev` command to start the server in dev mode.
(Any change will trigger a refresh of the server)
1. Install the dependencies `npm install`.
2. Go to the `linx-devops/scaling-tools/private-system-truste-cert` project and generate a new server certificate and key:
sh create_certificate_for_domain.sh 192.168.1.110 #local IP
# generates files
nginx-selfsigned.crt
device.key
3. You need to update the Video Server in the provisioning to point to your private IP. ex: https://192.168.1.199:3000
4. The generated files must be moved to server/ssl and renamed as follows:
cp device.key {mediasoup_project}/server/ssl/key.pem
cp nginx-selfsigned.crt {mediosup_project}/server/ssl/cert.pem
5. Go to https://dev.linx.safemobile.com/dispatcher/resources/help/LINXHelp.html#safemobile-certificate-import and import the certificate for your system type
6. The ANNOUNCED IP in .env must be configured to use the same private IP used in generating the certificate.
7. Run the `npm start:dev` command to start the server in dev mode.
(Any change will trigger a refresh of the server)
### Production
##### To start in production mode you must:
1. Install the dependencies `npm install`.
2. Run the `npm start:prod` command to start the server in production mode.
(To connect to the terminal, use `pm2 log video-server`)
(To connect to the terminal, use `pm2 log video-server`)
---
### Web client
- The server will start by default on port 3000, and the ssl certificates will have to be configured
- The web client can be accessed using the /sfu path
ex: http://localhost:3000/sfu/?assetId=1&&accountId=1&producer=true&assetName=Adi&assetType=linx
assetId = asset id of the unit on which you are doing the test
accountId = account id of the unit on which you are doing the test
producer = it will always be true because you are the producer
(it's possible to put false, but then you have to have another client with producer true)
assetName = asset name of the unit on which you are doing the test
assetType = asset type of the unit on which you are doing the test
ex: https://HOST/sfu/?assetId=1&&accountId=1&producer=true&dest_asset_id=75&assetName=Adi
assetId = asset id of the unit on which you are doing the test
accountId = account id of the unit on which you are doing the test
producer = it will always be true because you are the producer
(it's possible to put false, but then you have to have another client with producer true)
assetName = asset name of the unit on which you are doing the test
dest_asset_id= the addressee with whom the call is made
- To make a call using this client, you need a microphone and permission to use it
- For any changes related to the client, the command `npm run watch' will have to be used to generate the bundle.js used by the web client
### Demo project
The demo project used initially and then modified for our needs `https://github.com/jamalag/mediasoup2`
The demo project used initially and then modified for our needs `https://github.com/jamalag/mediasoup2`

1020
app.js

File diff suppressed because it is too large Load Diff

75
build.sh Executable file
View File

@ -0,0 +1,75 @@
#/!bin/bash
## FUNCTIONS
function getGitVersion(){
version=$(git describe)
count=$(echo ${version%%-*} | grep -o "\." | wc -l)
if (( $count > 1 )); then
version=${version%%-*}
elif (( $count == 0 ));then
echo -e "Error: Git version \"${version%%-*}\" not respecting Safemobile standard.\n Must be like 4.xx or 4.xx.xx"
version="0.0.0"
else
if [[ "$1" == "dev" ]];then
cleanprefix=${version#*-} # remove everything before `-` including `-`
cleansuffix=${cleanprefix%-*} # remove everything after `-` including `-`
version="${version%%-*}.${cleansuffix}"
else
version="${version%%-*}.0" # one `%` remove everything after last `-`, two `%%` remove everything after all `-`
fi
fi
}
function addVersionPm2(){
file_pkg="package.json"
key=" \"version\": \""
if [ -f "$file_pkg" ] && [ ! -z "$version" ]; then
versionApp=" \"version\": \"$version\","
sed -i "s|^.*$key.*|${versionApp//\//\\/}|g" $file_pkg
text=$(cat $file_pkg | grep -c "$version")
if [ $text -eq 0 ]; then
echo "Version couldn't be set"
else
echo "Version $version successfully applied to App"
fi
fi
}
## PREBUILD PROCESS
# check dist dir to be present and empty
if [ ! -d "dist" ]; then
## MAKE DIR
mkdir "dist"
echo "Directory dist created."
else
## CLEANUP
rm -fr dist/*
fi
if [ -d "node_modules" ]; then
rm -fr node_modules
fi
# Install dependencies
npm install
## PROJECT NEEDS
echo "Building app... from $(git rev-parse --abbrev-ref HEAD)"
npm run-script build
cp -r {.env,app.js,package.json,server,public,doc,Dockerfile} dist/
#cp -r ./* dist/
# Generate Git log
dateString=$(date +"%Y%m%d-%H%M%S")
git log --pretty=format:"%ad%x09%an%x09%s" --no-merges -20 > "dist/git-$dateString.log"
# Get Git version control
getGitVersion $1
# Add version control for pm2
cd dist
addVersionPm2
## POST BUILD
cd -

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 419 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 968 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 421 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 567 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 660 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 571 KiB

1150
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -16,7 +16,7 @@
"@types/express": "^4.17.13",
"dotenv": "^16.0.1",
"express": "^4.18.1",
"mediasoup": "^3.10.4",
"mediasoup": "^3.15.5",
"mediasoup-client": "^3.6.54",
"parcel": "^2.7.0",
"socket.io": "^2.0.3",
@ -29,4 +29,4 @@
"ts-node-dev": "^2.0.0",
"watchify": "^4.0.0"
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,4 @@
module.exports = {
hubAddress: 'https://hub.dev.linx.safemobile.com/',
mediasoupAddress: 'https://video.safemobile.org/mediasoup',
// mediasoupAddress: 'http://localhost:3000/mediasoup',
mediasoupAddress: 'https://testing.video.safemobile.org/',
}

View File

@ -34,6 +34,9 @@
<body>
<body>
<div id="video">
<legend>Client options:</legend>
<input type="checkbox" id="produceAudio" name="produceAudio">
<label for="produceAudio">Produce audio</label><br>
<table>
<thead>
<th>Local Video</th>
@ -43,12 +46,24 @@
<tr>
<td>
<div id="sharedBtns">
<video id="localVideo" autoplay class="video" ></video>
<video
id="localVideo"
class="video"
autoplay
muted
playsinline
></video>
</div>
</td>
<td>
<div id="sharedBtns">
<video id="remoteVideo" autoplay class="video" ></video>
<video
id="remoteVideo"
class="video"
autoplay
muted
playsinline
></video>
</div>
</td>
</tr>
@ -60,34 +75,11 @@
</td>
<td>
<div id="sharedBtns">
<button id="btnRecvSendTransport">Consume</button>
<!-- <button id="btnRecvSendTransport">Consume</button> -->
<button id="remoteSoundControl">Unmute</button>
</div>
</td>
</tr>
<!-- <tr>
<td colspan="2">
<div id="sharedBtns">
<button id="btnRtpCapabilities">2. Get Rtp Capabilities</button>
<br />
<button id="btnDevice">3. Create Device</button>
</div>
</td>
</tr>
<tr>
<td>
<div id="sharedBtns">
<button id="btnCreateSendTransport">4. Create Send Transport</button>
<br />
<button id="btnConnectSendTransport">5. Connect Send Transport & Produce</button></td>
</div>
<td>
<div id="sharedBtns">
<button id="btnRecvSendTransport">6. Create Recv Transport</button>
<br />
<button id="btnConnectRecvTransport">7. Connect Recv Transport & Consume</button>
</div>
</td>
</tr> -->
</tbody>
</table>
<div id="closeCallBtn">

View File

@ -10,147 +10,201 @@ const ASSET_NAME = urlParams.get('assetName') || null;
const ASSET_TYPE = urlParams.get('assetType') || null;
let callId = parseInt(urlParams.get('callId')) || null;
const IS_PRODUCER = urlParams.get('producer') === 'true' ? true : false
let remoteVideo = document.getElementById('remoteVideo')
remoteVideo.defaultMuted = true
let produceAudio = false
console.log('[URL] ASSET_ID', ASSET_ID, '| ACCOUNT_ID', ACCOUNT_ID, '| callId', callId, ' | IS_PRODUCER', IS_PRODUCER)
let socket
hub = io(config.hubAddress)
console.log('🟩 config', config)
const connectToMediasoup = () => {
socket = io(config.mediasoupAddress, {
reconnection: true,
reconnectionDelay: 1000,
reconnectionDelayMax : 5000,
reconnectionAttempts: Infinity
})
socket.on('connection-success', ({ _socketId, existsProducer }) => {
console.log(`[MEDIA] ${config.mediasoupAddress} | connected: ${socket.connected} | existsProducer: ${existsProducer}`)
if (!IS_PRODUCER && existsProducer && consumer === undefined) {
goConnect()
// document.getElementById('btnRecvSendTransport').click();
produceAudioSelector = document.getElementById('produceAudio');
produceAudioSelector.addEventListener('change', e => {
if(e.target.checked) {
produceAudio = true
console.log('produce audio');
} else {
produceAudio = false
}
if (IS_PRODUCER && urlParams.get('testing') === 'true') { getLocalStream() }
})
}
if (IS_PRODUCER === true) {
hub.on('connect', async () => {
console.log(`[HUB] ${config.hubAddress} | connected: ${hub.connected}`)
connectToMediasoup()
hub.emit(
'ars',
JSON.stringify({
ars: true,
asset_id: ASSET_ID,
account_id: ACCOUNT_ID,
})
)
hub.on('video', (data) => {
const parsedData = JSON.parse(data);
if (parsedData.type === 'notify-request') {
console.log('video', parsedData)
originAssetId = parsedData.origin_asset_id;
// originAssetName = parsedData.origin_asset_name;
// originAssetTypeName = parsedData.origin_asset_type_name;
callId = parsedData.video_call_id;
console.log('[VIDEO] notify-request | IS_PRODUCER', IS_PRODUCER, 'callId', callId);
getLocalStream()
}
if (parsedData.type === 'notify-end') {
console.log('[VIDEO] notify-end | IS_PRODUCER', IS_PRODUCER, 'callId', callId);
resetCallSettings()
}
})
})
hub.on('connect_error', (error) => {
console.log('connect_error', error);
});
hub.on('connection', () => {
console.log('connection')
})
hub.on('disconnect', () => {
console.log('disconnect')
})
} else {
connectToMediasoup()
}
});
let socket, hub
let device
let rtpCapabilities
let producerTransport
let consumerTransport
let producer
let producerVideo
let producerAudio
let consumer
let originAssetId
// let originAssetName = 'Adi'
// let originAssetTypeName = 'linx'
let consumerVideo // local consumer video(consumer not transport)
let consumerAudio // local consumer audio(consumer not transport)
const remoteSoundControl = document.getElementById('remoteSoundControl');
remoteSoundControl.addEventListener('click', function handleClick() {
console.log('remoteSoundControl.textContent', remoteSoundControl.textContent);
if (remoteSoundControl.textContent === 'Unmute') {
remoteVideo.muted = false
remoteSoundControl.textContent = 'Mute';
} else {
remoteVideo.muted = true
remoteSoundControl.textContent = 'Unmute';
}
});
// https://mediasoup.org/documentation/v3/mediasoup-client/api/#ProducerOptions
// https://mediasoup.org/documentation/v3/mediasoup-client/api/#transport-produce
let params = {
// mediasoup params
let videoParams = {
encodings: [
{
rid: 'r0',
maxBitrate: 100000,
scalabilityMode: 'S1T3',
},
{
rid: 'r1',
maxBitrate: 300000,
scalabilityMode: 'S1T3',
},
{
rid: 'r2',
maxBitrate: 900000,
scalabilityMode: 'S1T3',
},
{ scaleResolutionDownBy: 4, maxBitrate: 500000 },
{ scaleResolutionDownBy: 2, maxBitrate: 1000000 },
{ scaleResolutionDownBy: 1, maxBitrate: 5000000 },
{ scalabilityMode: 'S3T3_KEY' }
],
// https://mediasoup.org/documentation/v3/mediasoup-client/api/#ProducerCodecOptions
codecOptions: {
videoGoogleStartBitrate: 1000
}
}
const streamSuccess = (stream) => {
console.log('[streamSuccess]');
localVideo.srcObject = stream
const track = stream.getVideoTracks()[0]
params = {
track,
...params
let audioParams = {
codecOptions :
{
opusStereo : true,
opusDtx : true
}
}
setTimeout(() => {
hub = io(config.hubAddress)
const connectToMediasoup = () => {
socket = io(config.mediasoupAddress, {
reconnection: true,
reconnectionDelay: 1000,
reconnectionDelayMax : 5000,
reconnectionAttempts: Infinity
})
socket.on('connection-success', ({ _socketId, existsProducer }) => {
console.log(`[MEDIA] ${config.mediasoupAddress} | connected: ${socket.connected} | existsProducer: ${existsProducer}`)
if (!IS_PRODUCER && existsProducer && consumer === undefined) {
goConnect()
}
if (IS_PRODUCER && urlParams.get('testing') === 'true') { getLocalStream() }
})
socket.on('new-producer', ({ callId, kind }) => {
console.log(`🟢 new-producer | callId: ${callId} | kind: ${kind} | Ready to consume`);
connectRecvTransport();
})
socket.on('close-producer', ({ callId, kind }) => {
console.log(`🔴 close-producer | callId: ${callId} | kind: ${kind}`);
if (kind === 'video') {
consumerVideo.close()
remoteVideo.srcObject = null
}
else if (kind === 'audio') consumerAudio.close()
})
}
if (IS_PRODUCER === true) {
hub.on('connect', async () => {
console.log(`[HUB]! ${config.hubAddress} | connected: ${hub.connected}`)
connectToMediasoup()
hub.emit(
'ars',
JSON.stringify({
ars: true,
asset_id: ASSET_ID,
account_id: ACCOUNT_ID,
})
)
hub.on('video', (data) => {
const parsedData = JSON.parse(data);
if (parsedData.type === 'notify-request') {
console.log('video', parsedData)
originAssetId = parsedData.origin_asset_id;
// originAssetName = parsedData.origin_asset_name;
// originAssetTypeName = parsedData.origin_asset_type_name;
callId = parsedData.video_call_id;
console.log('[VIDEO] notify-request | IS_PRODUCER', IS_PRODUCER, 'callId', callId);
getLocalStream()
}
if (parsedData.type === 'notify-end') {
console.log('[VIDEO] notify-end | IS_PRODUCER', IS_PRODUCER, 'callId', callId);
resetCallSettings()
}
})
})
hub.on('connect_error', (error) => {
console.log('connect_error', error);
});
hub.on('connection', () => {
console.log('connection')
})
hub.on('disconnect', () => {
console.log('disconnect')
})
} else {
connectToMediasoup()
}
}, 1600);
const streamSuccess = (stream) => {
console.log('[streamSuccess] device', device);
localVideo.srcObject = stream
console.log('stream', stream);
const videoTrack = stream.getVideoTracks()[0]
const audioTrack = stream.getAudioTracks()[0]
videoParams = {
track: videoTrack,
...videoParams
}
audioParams = {
track: audioTrack,
...audioParams
}
console.log('[streamSuccess] videoParams', videoParams, ' | audioParams', audioParams);
goConnect()
}
const getLocalStream = () => {
console.log('[getLocalStream]');
navigator.mediaDevices.getUserMedia({
audio: false,
audio: produceAudio ? true : false,
video: {
width: {
min: 640,
max: 1920,
},
height: {
min: 400,
max: 1080,
}
qvga : { width: { ideal: 320 }, height: { ideal: 240 } },
vga : { width: { ideal: 640 }, height: { ideal: 480 } },
hd : { width: { ideal: 1280 }, height: { ideal: 720 } }
}
})
.then(streamSuccess)
.catch(error => {
console.log(error.message)
})
navigator.permissions.query(
{ name: 'microphone' }
).then((permissionStatus) =>{
console.log('🟨 [PERMISSION] permissionStatus', permissionStatus); // granted, denied, prompt
// It will block the code from execution and display "Permission denied" if we don't have microphone permissions
})
}
const goConnect = () => {
@ -167,7 +221,6 @@ const goCreateTransport = () => {
// server side to send/recive media
const createDevice = async () => {
try {
console.log('[createDevice]');
device = new mediasoupClient.Device()
// https://mediasoup.org/documentation/v3/mediasoup-client/api/#device-load
@ -178,7 +231,8 @@ const createDevice = async () => {
})
console.log('Device RTP Capabilities', device.rtpCapabilities)
console.log('[createDevice] device', device);
// once the device loads, create transport
goCreateTransport()
@ -207,18 +261,20 @@ const getRtpCapabilities = () => {
}
const createSendTransport = () => {
console.log('[createSendTransport');
// see server's socket.on('createWebRtcTransport', sender?, ...)
// this is a call from Producer, so sender = true
socket.emit('createWebRtcTransport', { sender: true, callId }, ({ params }) => {
socket.emit('createWebRtcTransport', { sender: true }, (value) => {
console.log(`[createWebRtcTransport] value: ${JSON.stringify(value)}`);
const params = value.params;
// The server sends back params needed
// to create Send Transport on the client side
if (params.error) {
console.log(params.error)
return
}
console.log(params)
// creates a new WebRTC Transport to send media
// based on the server's producer transport params
// https://mediasoup.org/documentation/v3/mediasoup-client/api/#TransportOptions
@ -244,10 +300,10 @@ const createSendTransport = () => {
})
producerTransport.on('produce', async (parameters, callback, errback) => {
console.log(parameters)
console.log('[produce] parameters', parameters)
try {
// tell the server to create a Producer
// Tell the server to create a Producer
// with the following parameters and produce
// and expect back a server side producer id
// see server's socket.on('transport-produce', ...)
@ -270,21 +326,45 @@ const createSendTransport = () => {
}
const connectSendTransport = async () => {
// we now call produce() to instruct the producer transport
console.log('[connectSendTransport] producerTransport');
// We now call produce() to instruct the producer transport
// to send media to the Router
// https://mediasoup.org/documentation/v3/mediasoup-client/api/#transport-produce
// this action will trigger the 'connect' and 'produce' events above
producer = await producerTransport.produce(params)
// Produce video
let producerVideoHandler = await producerTransport.produce(videoParams)
console.log('videoParams', videoParams);
console.log('producerVideo', producerVideo);
producer.on('trackended', () => {
producerVideoHandler.on('trackended', () => {
console.log('track ended')
// close video track
})
})
producer.on('transportclose', () => {
producerVideoHandler.on('transportclose', () => {
console.log('transport ended')
// close video track
})
})
// Produce audio
if (produceAudio) {
let producerAudioHandler = await producerTransport.produce(audioParams)
console.log('audioParams', audioParams);
console.log('producerAudio', producerAudio);
producerAudioHandler.on('trackended', () => {
console.log('track ended')
// close audio track
})
producerAudioHandler.on('transportclose', () => {
console.log('transport ended')
// close audio track
})
}
const answer = {
origin_asset_id: ASSET_ID,
@ -294,7 +374,7 @@ const connectSendTransport = async () => {
origin_asset_type_name: ASSET_TYPE,
origin_asset_name: ASSET_NAME,
video_call_id: callId,
answer: 'accepted', // answer: 'rejected'
answer: 'accepted', // answer: accepted/rejected
};
console.log('SEND answer', answer);
@ -306,11 +386,13 @@ const connectSendTransport = async () => {
// Enable Close call button
const closeCallBtn = document.getElementById('btnCloseCall');
closeCallBtn.removeAttribute('disabled');
createRecvTransport();
}
const createRecvTransport = async () => {
console.log('createRecvTransport');
// see server's socket.on('consume', sender?, ...)
// See server's socket.on('consume', sender?, ...)
// this is a call from Consumer, so sender = false
await socket.emit('createWebRtcTransport', { sender: false, callId }, ({ params }) => {
// The server sends back params needed
@ -320,15 +402,15 @@ const createRecvTransport = async () => {
return
}
console.log(params)
console.log('[createRecvTransport] params', params)
// creates a new WebRTC Transport to receive media
// Creates a new WebRTC Transport to receive media
// based on server's consumer transport params
// https://mediasoup.org/documentation/v3/mediasoup-client/api/#device-createRecvTransport
consumerTransport = device.createRecvTransport(params)
// https://mediasoup.org/documentation/v3/communication-between-client-and-server/#producing-media
// this event is raised when a first call to transport.produce() is made
// This event is raised when a first call to transport.produce() is made
// see connectRecvTransport() below
consumerTransport.on('connect', async ({ dtlsParameters }, callback, errback) => {
try {
@ -345,7 +427,8 @@ const createRecvTransport = async () => {
errback(error)
}
})
connectRecvTransport()
// We call it in new-rpoducer, we don't need it here anymore
// connectRecvTransport()
})
}
@ -353,7 +436,8 @@ const resetCallSettings = () => {
localVideo.srcObject = null
remoteVideo.srcObject = null
consumer = null
producer = null
producerVideo = null
producerAudio = null
producerTransport = null
consumerTransport = null
device = undefined
@ -361,40 +445,97 @@ const resetCallSettings = () => {
const connectRecvTransport = async () => {
console.log('connectRecvTransport');
// for consumer, we need to tell the server first
// For consumer, we need to tell the server first
// to create a consumer based on the rtpCapabilities and consume
// if the router can consume, it will send back a set of params as below
await socket.emit('consume', {
rtpCapabilities: device.rtpCapabilities,
callId
}, async ({ params }) => {
if (params.error) {
console.log('Cannot Consume')
return
}
// then consume with the local consumer transport
// which creates a consumer
consumer = await consumerTransport.consume({
id: params.id,
producerId: params.producerId,
kind: params.kind,
rtpParameters: params.rtpParameters
})
// destructure and retrieve the video track from the producer
const { track } = consumer
}, async ({videoParams, audioParams}) => {
console.log(`[consume] 🟩 videoParams`, videoParams)
console.log(`[consume] 🟩 audioParams`, audioParams)
console.log('[consume] 🟩 consumerTransport', consumerTransport)
let stream = new MediaStream()
stream.addTrack(track)
// stream.removeTrack(track)
remoteVideo.srcObject = stream
socket.emit('consumer-resume')
console.log('consumer', consumer);
// Maybe the unit does not produce video or audio, so we must only consume what is produced
if (videoParams) {
console.log('❗ Have VIDEO stream to consume');
stream.addTrack(await getVideoTrask(videoParams))
} else {
console.log('❗ Don\'t have VIDEO stream to consume');
}
if (audioParams) {
console.log('❗ Have AUDIO stream to consume');
let audioTrack = await getAudioTrask(audioParams)
stream.addTrack(audioTrack)
} else {
console.log('❗ Don\'t have AUDIO stream to consume');
}
socket.emit('consumer-resume')
remoteVideo.srcObject = stream
remoteVideo.setAttribute('autoplay', true)
remoteVideo.play()
.then(() => {
console.log('remoteVideo PLAY')
})
.catch((error) => {
console.error(`remoteVideo PLAY ERROR | ${error.message}`)
})
})
}
const getVideoTrask = async (videoParams) => {
consumerVideo = await consumerTransport.consume({
id: videoParams.id,
producerId: videoParams.producerId,
kind: videoParams.kind,
rtpParameters: videoParams.rtpParameters
})
return consumerVideo.track
}
const getAudioTrask = async (audioParams) => {
consumerAudio = await consumerTransport.consume({
id: audioParams.id,
producerId: audioParams.producerId,
kind: audioParams.kind,
rtpParameters: audioParams.rtpParameters
})
consumerAudio.on('transportclose', () => {
console.log('transport closed so consumer closed')
})
const audioTrack = consumerAudio.track
audioTrack.applyConstraints({
audio: {
advanced: [
{
echoCancellation: {exact: true}
},
{
autoGainControl: {exact: true}
},
{
noiseSuppression: {exact: true}
},
{
highpassFilter: {exact: true}
}
]
}
})
return audioTrack
}
const closeCall = () => {
console.log('closeCall');
@ -416,6 +557,30 @@ const closeCall = () => {
resetCallSettings()
}
// const consume = async (kind) => {
// console.log(`[consume] kind: ${kind}`)
// console.log('createRecvTransport Consumer')
// await socket.emit('createWebRtcTransport', { sender: false, callId, dispatcher: true }, ({ params }) => {
// if (params.error) {
// console.log('createRecvTransport | createWebRtcTransport | Error', params.error)
// return
// }
// consumerTransport = device.createRecvTransport(params)
// consumerTransport.on('connect', async ({ dtlsParameters }, callback, errback) => {
// try {
// await socket.emit('transport-recv-connect', {
// dtlsParameters,
// })
// callback()
// } catch (error) {
// errback(error)
// }
// })
// connectRecvTransport()
// })
// }
btnLocalVideo.addEventListener('click', getLocalStream)
btnRecvSendTransport.addEventListener('click', goConnect)
// btnRecvSendTransport.addEventListener('click', consume)
btnCloseCall.addEventListener('click', closeCall)

22
server/ssl/cert-old.pem Normal file
View File

@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDrzCCApegAwIBAgIUfpwrZVz3ogv3YeXbtL5wqIGEXGMwDQYJKoZIhvcNAQEL
BQAwZzELMAkGA1UEBhMCUk8xDTALBgNVBAgMBEFsYmExDTALBgNVBAcMBEFsYmEx
DDAKBgNVBAoMA0FBQTEQMA4GA1UEAwwHQUFBIENPTTEaMBgGCSqGSIb3DQEJARYL
YXNkQGFzZC5jb20wHhcNMjUwMjE4MTAwMDM5WhcNMzUwMjE2MTAwMDM5WjBnMQsw
CQYDVQQGEwJSTzENMAsGA1UECAwEQWxiYTENMAsGA1UEBwwEQWxiYTEMMAoGA1UE
CgwDQUFBMRAwDgYDVQQDDAdBQUEgQ09NMRowGAYJKoZIhvcNAQkBFgthc2RAYXNk
LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL7itjfKeuH5+f7c
43gAI+ppmxiwvzqhHLmkmlQrVbSC+P93yGekHIuXpbM3sqGRnvSJL3c9SIEdtVVj
yfJCs6KIsujxtiGn3hgQD01B6LqzFjSKnfYSGz8XDsjFW8cnpD1yRi3J7DhUjleM
bhQ0ileu9joS2OOhf84mtOkXJyY8q9xJH4ypimogcR98eM6ewnrb5Vhjo8YDaix2
6rceNmO/g4biknhXnBGc58/MnyAHtwzZxsu/k1IYtZuBYMPcAo7CQEX4XxXqQpaF
zaaoEUYB8KzVDlsr+i5SJzLtrHkyiuJijHq6YyOFkTwUULuJ7Wz0YL1redDCZV4i
EIVzBAcCAwEAAaNTMFEwHQYDVR0OBBYEFErSYY3J7ukx2KaRcHmazbMlKNBlMB8G
A1UdIwQYMBaAFErSYY3J7ukx2KaRcHmazbMlKNBlMA8GA1UdEwEB/wQFMAMBAf8w
DQYJKoZIhvcNAQELBQADggEBAC3TQY6jMGeHIEDEYS7sUbNZxe+azdDlx0DdwgLK
t+Zo2O40F55nVTZOUfypjCnLJnZitekptl5P6CPGrp2VX4/C0Ok4swwr+xamsjWt
9RR9yG0IpVfnCEziT4dpBPhNf/6ilgdpnkJUWY3LO3BJhM4Js7rfP4D9NgEYHeSR
YDN3TuEbi//bp43bhDh8EBQtDx9lPGOSUiKd3I7KfRttsxvLG2wBz3M5HXRc++6p
pHE+64YfkwV5xZDvU2M/EqePLp7DdQ9g+vQ68FxI6jMCegBoz+ueyE9RhZOk/cUh
uIXwIdFowjkUXgNncuGrR1gWf1mJVCHOsdnGZf3VSykGdWg=
-----END CERTIFICATE-----

View File

@ -1,25 +1,24 @@
-----BEGIN CERTIFICATE-----
MIIEJTCCAw2gAwIBAgIURHg2am+RarQxIVY1f3CicUQgRowwDQYJKoZIhvcNAQEL
BQAwgaExCzAJBgNVBAYTAlJPMRIwEAYDVQQIDAlCdWNoYXJlc3QxEjAQBgNVBAcM
CUJ1Y2hhcmVzdDETMBEGA1UECgwKU2FmZW1vYmlsZTETMBEGA1UECwwKU2FmZW1v
YmlsZTETMBEGA1UEAwwKU2FmZW1vYmlsZTErMCkGCSqGSIb3DQEJARYcbWloYWku
Ym96aWVydUBzYWZlbW9iaWxlLmNvbTAeFw0yMjA4MDEyMjA0MjFaFw0zMjA3Mjky
MjA0MjFaMIGhMQswCQYDVQQGEwJSTzESMBAGA1UECAwJQnVjaGFyZXN0MRIwEAYD
VQQHDAlCdWNoYXJlc3QxEzARBgNVBAoMClNhZmVtb2JpbGUxEzARBgNVBAsMClNh
ZmVtb2JpbGUxEzARBgNVBAMMClNhZmVtb2JpbGUxKzApBgkqhkiG9w0BCQEWHG1p
aGFpLmJvemllcnVAc2FmZW1vYmlsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQCSEk80aBAbmWtPBLcTjFLbvVmxuzDgzrjH7h2Hg/ly8lE/o2nZ
1T2ESSuaQFsxw54ukqbj1ooQXF1DoIxSp+CiNzf/FTB6BaMkaG0ayE2Wnm2wkjKp
POnAzZgTabJoB/qeUlr9i4xiAyBhiQDk5KjdWYHxeZnSznqfIOPzAdw7ZJVYvqvT
GciHnoina5TzPUbpnLcR2LvHcLxuSuWQ6dTz/sfdZRx8lkbR3qltUazmJX+yxJJr
kagq2V3cfpfLM8DOzPPEzuKHM6sK6ZgTqbc4ti+ul7Q1V+e0v2xNDtuYHkbaOuyd
ucmaZ3R++0ryoWWan5OFWZIKjttKy/yq8MUrAgMBAAGjUzBRMB0GA1UdDgQWBBSM
nlDraef71C/filHpA7dDpwmB7zAfBgNVHSMEGDAWgBSMnlDraef71C/filHpA7dD
pwmB7zAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBNySms9mXG
PVOmFAm9YjMjRY+cUpa0Gm6saxp9VOyrAg2KzdwG6LNGgauNsIra1ytM40NASspN
r+L49gUCmASUGOqeZCpJjkKAsGspQ4WQKKI6YW8h5dsSuud2qyQtm+w1RKDq+wih
A+B82xWXcFFd52gp6nerib4Pf9ATooOmBMCHFZwC+74sKCv7fXDlzLGdCII8lmI4
uq5eFrSS1NeT3iQCwGb9SHfyFkCliaEdpskqmWhonckN0tJVV118SvknV/h9oIsw
uEMIib6YOBlrU+FInnpqpc8VuR4vv0Yro9XrvmurzLuN8k/lVVkr6NMzyNY9mbkF
9p/Sxd5yIeam
MIID9TCCAt2gAwIBAgIJAJZHglUuIBjtMA0GCSqGSIb3DQEBCwUAMIGZMQswCQYD
VQQGEwJVUzERMA8GA1UECAwISWxsaW5vaXMxGDAWBgNVBAcMD1JvbGxpbmcgTWVh
ZGl3czEYMBYGA1UECgwPU2FmZW1vYmlsZSBMTEMuMQ0wCwYDVQQLDARMSU5YMQ0w
CwYDVQQDDARMSU5YMSUwIwYJKoZIhvcNAQkBFhZzdXBwb3J0QHNhZmVtb2JpbGUu
Y29tMB4XDTI1MDIyNDEwMTAzNFoXDTM1MDIyMjEwMTAzNFowXjELMAkGA1UEBhMC
VVMxETAPBgNVBAgMCElsbGlub2lzMRgwFgYDVQQHDA9Sb2xsaW5nIE1lYWRpd3Mx
EzARBgNVBAoMClNhZmVtb2JpbGUxDTALBgNVBAMMBExJTlgwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQDEd8LMvdkD4CyZkwVYh4V/RIBMH8d9jK1Yvozd
0kPSGrC+ZXemmF7qHAD5g8RDkg1odkVuZa+jj0KlKHKtReF0p9OB/J6fNavlD7mM
UiAtEpEgoKx3VlhrYEtIoFk+EJWaN1WObhYNfPtEw8Ncfww1cyDNmOnsifkLg+yh
+aNxXzrR3toRF7pxFehrTpMRxx4LiIN2z4vHCdelvu9yJspzRAWd5QSQ6eGr3OPY
yn+9v4XfN0YgnWSbH8aJ24bysIB3vOtsULjOfNJivNcx+/gQ9yP4AFhycperiDcu
GGTiw+fwk1y6e04XulQ65mgxGTXNHlnM2ZvDyOwDZqL89Uf3AgMBAAGjejB4MB8G
A1UdIwQYMBaAFGQaM9lRXGKKghjag6SPD+uHK3K5MAkGA1UdEwQCMAAwCwYDVR0P
BAQDAgTwMB4GA1UdEQQXMBWHBMCoAceCDTE5Mi4xNjguMS4xOTkwHQYDVR0OBBYE
FHNfBgu/Ixj2j6yDTiDluw6/i3cEMA0GCSqGSIb3DQEBCwUAA4IBAQAojT+cdzfU
sVq/ODttG8wS23Du20W2iNdvlAwkgni0UgxTJQ12odtIH9WZAVS46G++t2so87Ki
gp6OK25AWtsQ7oLFK2P6VpaVGH6FwRSODFTly7Wv+7US7NmB/DO215+rG7q7C7Ag
J6zrsQgLPR6M6rZRrOs9Hd12oX6zRgEaYnbIc/Z1DVPRmCDiQISE5M8LihIO4sOW
gmDacLhM9lbuMvbHEkCNnOuAzdWRmvR06CyBXmu/9iusyWYvgwI6bHFAZRYCOTmB
+poHSGAlTmivcbNhHyZjS63NafRU7sSuc0JDzWQAdkA1AclSokfC8dJC6fnKBujY
o2WFKJMFrFS3
-----END CERTIFICATE-----

28
server/ssl/key-old.pem Normal file
View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC+4rY3ynrh+fn+
3ON4ACPqaZsYsL86oRy5pJpUK1W0gvj/d8hnpByLl6WzN7KhkZ70iS93PUiBHbVV
Y8nyQrOiiLLo8bYhp94YEA9NQei6sxY0ip32Ehs/Fw7IxVvHJ6Q9ckYtyew4VI5X
jG4UNIpXrvY6EtjjoX/OJrTpFycmPKvcSR+MqYpqIHEffHjOnsJ62+VYY6PGA2os
duq3HjZjv4OG4pJ4V5wRnOfPzJ8gB7cM2cbLv5NSGLWbgWDD3AKOwkBF+F8V6kKW
hc2mqBFGAfCs1Q5bK/ouUicy7ax5MoriYox6umMjhZE8FFC7ie1s9GC9a3nQwmVe
IhCFcwQHAgMBAAECggEAMJWSjGuwUCDoZNqC2PGsMoczjxq5aWpFXejL0P2AoGOv
jZJGwz5Nd6ge6BkWkbH3M8VQ+/fwotBVbYjrBwq8HvPNGaYf1bwctqIryt2qJw7a
6X+Yid986NdtD2PQIsXvsyYJP7FDuuimnBjlkaX3yi6BhDF026co2OcYJ7WZZM0e
nc6JR7wGFZM3Dw3ybFvGrK4k7/Iq2N6wqedzCOvDbLXUC16UtmRVIOuiuNm+THrl
BiD37AKwB/LZRcdSQ1HeiWlK42Zc+IikHPJhl0PACcJNFNB3u2rdP8maSu5aMLku
yHnKCz6w9C1vDKrI/iszW2QCky+mGBD9WKK2u6hxFQKBgQDtcfL8hMKj6Ki/dsqR
McGPs1rLgZFAH9axubUth0uLdsEQDZtkoJIzXt8RLS3exuHMKt+Ln6YAOEhKm8Cl
OqIg0E/8SNi7QryU9yfqFqcE2QBZL0QVtvYZeUuiHIOrpc0bmTdNvp8i7zWw/oz6
ymeJ6vpEWKDpOvUnfm79XJbh+wKBgQDNzVjUNfo5s6QNnZlJvwI3J2mAsfLMVQxp
++P41f+dUCoAsEPujxASthdDxRND9oIfsTodA+VkrlLhs1JyTe4PlPcfSl7D5QSV
ayXVHF9iLbGM8fWMf6zBTebdaw9GqY3KTOHBH+X+JOHPP9dI6a4l7Ok8tFE9ia8M
G8Ce7djUZQKBgDSfGDaWRXyFx0AHV4Ut/bOXD/whzsrjQ3VHrrtUTI2v18FzAoke
fMgdslngJVZFxSy2I6yRyPwrfPnr4pm7kMqs380NZ9q4Q4rP62yZcJJGdSlOrEwT
rB6hHv3iS9vydq4zGmqEYEghs0hyYVQDH0cVaDlVWvPVORdzka1co6OZAoGBAJHl
TV/DlExrqZVtcEnzeyKWchimDjYE5PQNeiPhsYBYYC50xvPLv91D8WI9x9aaXs0Q
2t3O8URawK74bS5TSL0LIdWw51WAeatjdkKKBqSXOBNvRGAB8vpmu4+kYgP6F2ae
8jvy3R06EErYO0qZPrfsJ7y9KAq0HMA8vGTuwJRxAoGBAMfWJLseheDXKUXndnR9
ovNA+spTTFECtoLwhWxwgoL3GYVqSA96RfnmdKHY4d5isQ1g/JN05Uo6bL7HKJCG
BwS9WCsa6fHhbJR31fP16UQNNknNSwTtUoeJavwarQ7MB5CT9Fz5HsaC4NGaQkve
86Barwb6tt4iu4Y8a2bcG/sE
-----END PRIVATE KEY-----

View File

@ -1,28 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCSEk80aBAbmWtP
BLcTjFLbvVmxuzDgzrjH7h2Hg/ly8lE/o2nZ1T2ESSuaQFsxw54ukqbj1ooQXF1D
oIxSp+CiNzf/FTB6BaMkaG0ayE2Wnm2wkjKpPOnAzZgTabJoB/qeUlr9i4xiAyBh
iQDk5KjdWYHxeZnSznqfIOPzAdw7ZJVYvqvTGciHnoina5TzPUbpnLcR2LvHcLxu
SuWQ6dTz/sfdZRx8lkbR3qltUazmJX+yxJJrkagq2V3cfpfLM8DOzPPEzuKHM6sK
6ZgTqbc4ti+ul7Q1V+e0v2xNDtuYHkbaOuyducmaZ3R++0ryoWWan5OFWZIKjttK
y/yq8MUrAgMBAAECggEAMRH1iaVrw9nGMsViuy5op2j0uMApq1vGt2NGiD/NjM/a
e4ZqCMOZ5tatzyPPfug4O20Io4Fu4BAnRJCqkxnSXKwwI4D6yAMcyx5JiLXBWtfe
AXMbkb7kx+BJNjxLsqb7ijQgXQyEHGjwd9OOeVZXZAStonE3O5ohl1N1QC1fzpN5
qBFPaAiNhZgaxrB+pp/uRruZXzNGCwLdhpd2HuryJfxkaAD53mqpHwHJbM7wRQl4
NJCbFR/lf4sqPO7zWJGyfU8fFVLuNspSW8AdLcsapOUSMhXTEU+vKbdWM+MYRNuk
ltJVWG1nPkbyyGQoUNEh4rSFOX+3aiN435qkPw7wAQKBgQDEPFQJe+2DpS+M0zvq
sZVVkEDxwGZfHnO0h57C4dsGPyLSX7A1r+EM8ooZhCgrXZFru3EDzFuO5isCIeml
bBET5q2qGEozdb+wUfcHOBZZKR4imY0SYi3lyJdxBeNIOPhUkEpOg3uo2RRklpi6
Fk4LYXReJ+t36yZyocTn3PfmxwKBgQC+juTHoJGZjqWtVMygUC8kP5G5GXxY9Yk1
7j4Iv8ok1c5xWM6N4GBNG9rKKOD7WQX4dD9IOs35pZqGDaNE44q7na9UabRFR92M
I+VAsi1Q2gQPyihW84ESXw6uH85pO5FfGO3fF/ppLXBCVYN85VT+1HFxG+Je2GXE
50/3e4Q6fQKBgBl/zVu+IsrseBVQjYSdts37hLTlT2gkyNw4k0S3nIJfSeMUVA1l
4VSRX6iZJ68a5X6eSL05nNwgxI3uYjIArOdtHjvwFBRDxLjgrbzeaOkFEslkMpSk
9VnaivNA1JvZ60rxxPYW18bFDoVTnFzx8QpBi6GAhnR6tfBHXRLT/9KZAoGAStHI
OiltgaFko73b6kYRfGYJTWgYTsV5bldwu/ax4+ye9hosX8Btj1kUerO6QnYdxgO+
pRmRrie7mE7agD3nRusO4FHwmhMxhcjCRriu2kP/vENfu2Q4lYIFPZD3dpIQ7gnX
u/SqOYnBvgndariQus2nDQYpx5unubwoxb8Vl/ECgYAV7nkyMjkakwbFyiAsUMz6
QvSxWC+x5OBv79Nm02bgecdwJny/PULA/R/KHNI/WXHSkM2DdeoMv4XZPdI8TNRo
bBD217yfRfOMIX2jIhZeTtTAIiOafBdIG0fUtM9nMPkgQGTvgM0FZPdfAtNY/nFu
xvrhZIQLy0ujoDPPBE8+3Q==
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDEd8LMvdkD4CyZ
kwVYh4V/RIBMH8d9jK1Yvozd0kPSGrC+ZXemmF7qHAD5g8RDkg1odkVuZa+jj0Kl
KHKtReF0p9OB/J6fNavlD7mMUiAtEpEgoKx3VlhrYEtIoFk+EJWaN1WObhYNfPtE
w8Ncfww1cyDNmOnsifkLg+yh+aNxXzrR3toRF7pxFehrTpMRxx4LiIN2z4vHCdel
vu9yJspzRAWd5QSQ6eGr3OPYyn+9v4XfN0YgnWSbH8aJ24bysIB3vOtsULjOfNJi
vNcx+/gQ9yP4AFhycperiDcuGGTiw+fwk1y6e04XulQ65mgxGTXNHlnM2ZvDyOwD
ZqL89Uf3AgMBAAECggEAM0xx+LO5bmGiQ5c31h3MpaZlOXsyw31v5bQbY+/69Wky
rQQhccZnQgl916ioHlyMU7JN/r1eVv6ZEDa3era8X5FSkKY9ZKTG9VBdyl3HOP2Y
F0Tcw2wwOhkyjwwPQT1jUpkQJdhouazgjtvursAdl/cvoX9D1RdRh8gyiTh9jKQz
Afnbwe/KOje9xsEqJRDXra8erpwBV/7TKlLqvSiGExZqGx9X5pNzU02vfl7L3WTi
2f48Ad2P3rSGv5XcOCtGvDGRHtSLWknUCyb0a1qy2aFF1bJo9wVFNAPFD4zrukhA
/WaxkS3p/Fai8f+YdHPV9sgZO+2qrjMXNvmh1+V8gQKBgQD7HPbDDk9UQ9XUwAKu
o4Np2G6CddR1wxdE2qDDG3Ej5LBxi5OdwVdywim5Cgf/TAySIiNi5qeRSKJi5Sbg
/jt0x6v3R/0c14kRXsd09RtcqvRL09jI2eZl+uAINAqtKXsGsSCQXwkiO/MQ0Klc
gm2eMKK0VUENQ0qTzhvjFoJtnwKBgQDISo5cuo+6Kd6n26ny8FBwXKY0vY9AzUAU
gvpupDb6hQ3vfFWqORTbuPlg9oUSRh+eqVBbYr+VYfuSf0u/9JWdlpHFlGJMJ3cw
mraOmvXv8u9YGMf0d2wOXVf6/C2frfmZ89BntNs0cSHflzNvMn7qJxqVfTzIAtxV
bLEva8jWqQKBgBtpU/6C52H5bbQlqaVKsCOzvox7NFAOldGsU/Q4YKdcZW5foCOO
YW9jho5ua+UQdibVlytKpmwTk7Zb8VyKJA9hZII/1394f7vnrrozr2L0Pmqwm2+B
acckFaSPmcLBTm6yky1vUl3sUWI6hOJWUoT8JiatT8aU2+U6kIy/fkldAoGBALyx
cLlvkWSDeZ6OVefn+wBAaN0bENCuDYbFdoWx85HEtEJA0rvRlxMBiv+MgAWdRsDF
Jk1SFMf5TXbQsl6fYCzc42xOxOSV8bY6q25iEv0B0/cdMZPgxk4qJm7wEVN0Jcii
aF6rhjA7vPvWiMBjxCl4uZTILfEIsOdRxQO1+boxAoGACrkNBikkV8mSsBSEkfDQ
KAqGCl9zt6hI6cxQ9mSD60JJADXifBDLqMVcNDbTo+leHVAooLxI00kziAz9tfml
bDdr3OCLeOMqwWAZervH+rx3gvWqq7cdfMLlmyLwljZEloGjd1gnA4ekNnYwS+c9
P4Hmmp4712UC4HkhQLSJ6HU=
-----END PRIVATE KEY-----