Repository: oney/react-native-webrtc-server
Branch: master
Commit: 42e15a3458a4
Files: 7
Total size: 11.4 KB
Directory structure:
gitextract_si75swfa/
├── .gitignore
├── README.md
├── app.js
├── fake-keys/
│ ├── certificate.pem
│ └── privatekey.pem
├── index.html
└── package.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.DS_Store
node_modules
commit_images
================================================
FILE: README.md
================================================
# react-native-webrtc-server
The signaling server for https://github.com/oney/react-native-webrtc
You can checkout this demo https://github.com/oney/RCTWebRTCDemo
Demo server: https://react-native-webrtc.herokuapp.com/
# Get started
1. `npm install`
2. `npm start`
================================================
FILE: app.js
================================================
var express = require('express');
var app = express();
var fs = require('fs');
var open = require('open');
var options = {
key: fs.readFileSync('./fake-keys/privatekey.pem'),
cert: fs.readFileSync('./fake-keys/certificate.pem')
};
var serverPort = (process.env.PORT || 4443);
var https = require('https');
var http = require('http');
var server;
if (process.env.LOCAL) {
server = https.createServer(options, app);
} else {
server = http.createServer(app);
}
var io = require('socket.io')(server);
var roomList = {};
app.get('/', function(req, res){
console.log('get /');
res.sendFile(__dirname + '/index.html');
});
server.listen(serverPort, function(){
console.log('server up and running at %s port', serverPort);
if (process.env.LOCAL) {
open('https://localhost:' + serverPort)
}
});
function socketIdsInRoom(name) {
var socketIds = io.nsps['/'].adapter.rooms[name];
if (socketIds) {
var collection = [];
for (var key in socketIds) {
collection.push(key);
}
return collection;
} else {
return [];
}
}
io.on('connection', function(socket){
console.log('connection');
socket.on('disconnect', function(){
console.log('disconnect');
if (socket.room) {
var room = socket.room;
io.to(room).emit('leave', socket.id);
socket.leave(room);
}
});
socket.on('join', function(name, callback){
console.log('join', name);
var socketIds = socketIdsInRoom(name);
callback(socketIds);
socket.join(name);
socket.room = name;
});
socket.on('exchange', function(data){
console.log('exchange', data);
data.from = socket.id;
var to = io.sockets.connected[data.to];
to.emit('exchange', data);
});
});
================================================
FILE: fake-keys/certificate.pem
================================================
-----BEGIN CERTIFICATE-----
MIICjTCCAfYCCQC8xCdh8aBfxDANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMC
VVMxEzARBgNVBAgTCldhc2hpbmd0b24xETAPBgNVBAcTCFJpY2hsYW5kMQ0wCwYD
VQQKFAQmeWV0MQswCQYDVQQLFAImITEVMBMGA1UEAxMMTmF0aGFuIEZyaXR6MSAw
HgYJKoZIhvcNAQkBFhFuYXRoYW5AYW5keWV0Lm5ldDAeFw0xMTEwMTkwNjI2Mzha
Fw0xMTExMTgwNjI2MzhaMIGKMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu
Z3RvbjERMA8GA1UEBxMIUmljaGxhbmQxDTALBgNVBAoUBCZ5ZXQxCzAJBgNVBAsU
AiYhMRUwEwYDVQQDEwxOYXRoYW4gRnJpdHoxIDAeBgkqhkiG9w0BCQEWEW5hdGhh
bkBhbmR5ZXQubmV0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRKUxB1pLV
RQ/dcUEP1p1oTIg0GoEvMPl6s7kC2Mroyovn/FaCzsgvwYhuwIeA6qgYoNIkSkXM
QRmtfTpBvJNqM6A7jpUUmYuaUgqdrh5GZ5FGJjgAGIRJBWtovqxnCaHcmBYxlj0o
/nxDmzgK655WBso7nwpixrzbsV3x7ZG45QIDAQABMA0GCSqGSIb3DQEBBQUAA4GB
ALeMY0Og6SfSNXzvATyR1BYSjJCG19AwR/vafK4vB6ejta37TGEPOM66BdtxH8J7
T3QuMki9Eqid0zPATOttTlAhBeDGzPOzD4ohJu55PwY0jTJ2+qFUiDKmmCuaUbC6
JCt3LWcZMvkkMfsk1HgyUEKat/Lrs/iaVU6TDMFa52v5
-----END CERTIFICATE-----
================================================
FILE: fake-keys/privatekey.pem
================================================
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDRKUxB1pLVRQ/dcUEP1p1oTIg0GoEvMPl6s7kC2Mroyovn/FaC
zsgvwYhuwIeA6qgYoNIkSkXMQRmtfTpBvJNqM6A7jpUUmYuaUgqdrh5GZ5FGJjgA
GIRJBWtovqxnCaHcmBYxlj0o/nxDmzgK655WBso7nwpixrzbsV3x7ZG45QIDAQAB
AoGBAJQzUtkDlJ6QhKE+8f6q7nVMZOWmMgqiBOMwHNMrkPpJKcCCRzoAEk/kLSts
N5bcraZlrQARsEr9hZgrtu+FEl1ROdKc6B3bJ5B6FigwY7m8/Z3+YdgwqV6NJGQk
3twY4PoJEdeZ7GX2QnX8RDjyFvLaZ12jiDic30Nrn1gwvOCxAkEA9Dp5r9yg4DT/
V4SE5+NPCJmeV7zwfW3XUQHWD4TaFbOCjnjWB/BnrrjXhvd3VNzwajrJvqq/UiM4
bAG4VLz0CwJBANs+IYm3tYfeP5YsYJVMOJ5TcOAZ3T9jMF+QC9/ObwepW4D1woRr
rCYxe01JyZpqqWnfeIUoJ70QL9uP8AgTrM8CQFFqGNymKL71C9XJ6GBA5zzPsPhA
lM7LSgbIHOrJd8XaNIB4CalV28pj9f0ZC5+vkzlmZZB47RRdh1aB8EfXQWcCQGa8
KI8WLNRsCrPeO6v6OZXHV99Lf2eSnTpKj6XiYBjg/WXiw7G1mseS7Ep9RyE61gQs
mZccB/MKQMLMIhhGz/UCQQDog5KBVaMhwrw1hwZ5gDyZs2YrE75522BnAU1ajQj+
VmTkcBwCtfnbXsWcHnYQnLlvz2Bi9ov2JncmJ5F1kiIw
-----END RSA PRIVATE KEY-----
================================================
FILE: index.html
================================================
<!DOCTYPE html>
<html>
<head>
<title>react-native-webrtc server</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<div id="textRoom" style="display: none;">
<div id="textRoomContent">
<h3>Text Room</h3>
</div>
<input id="textRoomInput" >
<button onclick="textRoomPress();">Send</button>
</div>
<video id="selfView" autoplay></video>
<div id="remoteViewContainer"></div>
<div id="roomIDContainer">
<input id="roomID" value="abc">
<button onclick="press();">Join/Create room</button>
</div>
</body>
<script src="/socket.io/socket.io.js"></script>
<script type="text/javascript">
var socket = io();
var RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection || window.msRTCPeerConnection;
var RTCSessionDescription = window.RTCSessionDescription || window.mozRTCSessionDescription || window.webkitRTCSessionDescription || window.msRTCSessionDescription;
navigator.getUserMedia = navigator.getUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia || navigator.msGetUserMedia;
var twilioIceServers = [
{ url: 'stun:global.stun.twilio.com:3478?transport=udp' }
// { url: 'turn:global.turn.twilio.com:3478?transport=udp',
// username: 'ea757ad2c42b932c7f2abe480295e7eb039dc2b13b78c86bc412818ed51e5eea',
// credential: 'MPnnojPRoPDI+B3kLONGF9P440Lb8NkrTq+FxxJBVro=' },
// { url: 'turn:global.turn.twilio.com:3478?transport=tcp',
// username: 'ea757ad2c42b932c7f2abe480295e7eb039dc2b13b78c86bc412818ed51e5eea',
// credential: 'MPnnojPRoPDI+B3kLONGF9P440Lb8NkrTq+FxxJBVro=' },
// { url: 'turn:global.turn.twilio.com:443?transport=tcp',
// username: 'ea757ad2c42b932c7f2abe480295e7eb039dc2b13b78c86bc412818ed51e5eea',
// credential: 'MPnnojPRoPDI+B3kLONGF9P440Lb8NkrTq+FxxJBVro=' }
];
var configuration = {"iceServers": [{"url": "stun:stun.l.google.com:19302"}]};
// configuration.iceServers = twilioIceServers;
var pcPeers = {};
var selfView = document.getElementById("selfView");
var remoteViewContainer = document.getElementById("remoteViewContainer");
var localStream;
function getLocalStream() {
navigator.getUserMedia({ "audio": true, "video": true }, function (stream) {
localStream = stream;
selfView.src = URL.createObjectURL(stream);
selfView.muted = true;
}, logError);
}
function join(roomID) {
socket.emit('join', roomID, function(socketIds){
console.log('join', socketIds);
for (var i in socketIds) {
var socketId = socketIds[i];
createPC(socketId, true);
}
});
}
function createPC(socketId, isOffer) {
var pc = new RTCPeerConnection(configuration);
pcPeers[socketId] = pc;
pc.onicecandidate = function (event) {
console.log('onicecandidate', event);
if (event.candidate) {
socket.emit('exchange', {'to': socketId, 'candidate': event.candidate });
}
};
function createOffer() {
pc.createOffer(function(desc) {
console.log('createOffer', desc);
pc.setLocalDescription(desc, function () {
console.log('setLocalDescription', pc.localDescription);
socket.emit('exchange', {'to': socketId, 'sdp': pc.localDescription });
}, logError);
}, logError);
}
pc.onnegotiationneeded = function () {
console.log('onnegotiationneeded');
if (isOffer) {
createOffer();
}
}
pc.oniceconnectionstatechange = function(event) {
console.log('oniceconnectionstatechange', event);
if (event.target.iceConnectionState === 'connected') {
createDataChannel();
}
};
pc.onsignalingstatechange = function(event) {
console.log('onsignalingstatechange', event);
};
pc.onaddstream = function (event) {
console.log('onaddstream', event);
var element = document.createElement('video');
element.id = "remoteView" + socketId;
element.autoplay = 'autoplay';
element.src = URL.createObjectURL(event.stream);
remoteViewContainer.appendChild(element);
};
pc.addStream(localStream);
function createDataChannel() {
if (pc.textDataChannel) {
return;
}
var dataChannel = pc.createDataChannel("text");
dataChannel.onerror = function (error) {
console.log("dataChannel.onerror", error);
};
dataChannel.onmessage = function (event) {
console.log("dataChannel.onmessage:", event.data);
var content = document.getElementById('textRoomContent');
content.innerHTML = content.innerHTML + '<p>' + socketId + ': ' + event.data + '</p>';
};
dataChannel.onopen = function () {
console.log('dataChannel.onopen');
var textRoom = document.getElementById('textRoom');
textRoom.style.display = "block";
};
dataChannel.onclose = function () {
console.log("dataChannel.onclose");
};
pc.textDataChannel = dataChannel;
}
return pc;
}
function exchange(data) {
var fromId = data.from;
var pc;
if (fromId in pcPeers) {
pc = pcPeers[fromId];
} else {
pc = createPC(fromId, false);
}
if (data.sdp) {
console.log('exchange sdp', data);
pc.setRemoteDescription(new RTCSessionDescription(data.sdp), function () {
if (pc.remoteDescription.type == "offer")
pc.createAnswer(function(desc) {
console.log('createAnswer', desc);
pc.setLocalDescription(desc, function () {
console.log('setLocalDescription', pc.localDescription);
socket.emit('exchange', {'to': fromId, 'sdp': pc.localDescription });
}, logError);
}, logError);
}, logError);
} else {
console.log('exchange candidate', data);
pc.addIceCandidate(new RTCIceCandidate(data.candidate));
}
}
function leave(socketId) {
console.log('leave', socketId);
var pc = pcPeers[socketId];
pc.close();
delete pcPeers[socketId];
var video = document.getElementById("remoteView" + socketId);
if (video) video.remove();
}
socket.on('exchange', function(data){
exchange(data);
});
socket.on('leave', function(socketId){
leave(socketId);
});
socket.on('connect', function(data) {
console.log('connect');
getLocalStream();
});
function logError(error) {
console.log("logError", error);
}
function press() {
var roomID = document.getElementById('roomID').value;
if (roomID == "") {
alert('Please enter room ID');
} else {
var roomIDContainer = document.getElementById('roomIDContainer');
roomIDContainer.parentElement.removeChild(roomIDContainer);
join(roomID);
}
}
function textRoomPress() {
var text = document.getElementById('textRoomInput').value;
if (text == "") {
alert('Enter something');
} else {
document.getElementById('textRoomInput').value = '';
var content = document.getElementById('textRoomContent');
content.innerHTML = content.innerHTML + '<p>' + 'Me' + ': ' + text + '</p>';
for (var key in pcPeers) {
var pc = pcPeers[key];
pc.textDataChannel.send(text);
}
}
}
</script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-68314333-1', 'auto');
ga('send', 'pageview');
</script>
</html>
================================================
FILE: package.json
================================================
{
"name": "react-native-webrtc-server",
"version": "0.0.1",
"description": "react-native-webrtc server",
"main": "app.js",
"author": "Oney",
"engines": {
"node": "v4.1.0"
},
"scripts": {
"open": "heroku open",
"logs": "heroku logs --tail",
"deploy": "git push heroku master",
"start": "LOCAL=TRUE node app.js"
},
"dependencies": {
"express": "^4.11.2",
"open": "0.0.5",
"socket.io": "1.3.4"
}
}
gitextract_si75swfa/ ├── .gitignore ├── README.md ├── app.js ├── fake-keys/ │ ├── certificate.pem │ └── privatekey.pem ├── index.html └── package.json
SYMBOL INDEX (1 symbols across 1 files)
FILE: app.js
function socketIdsInRoom (line 33) | function socketIdsInRoom(name) {
Condensed preview — 7 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (13K chars).
[
{
"path": ".gitignore",
"chars": 37,
"preview": ".DS_Store\nnode_modules\ncommit_images\n"
},
{
"path": "README.md",
"chars": 272,
"preview": "# react-native-webrtc-server\nThe signaling server for https://github.com/oney/react-native-webrtc \nYou can checkout th"
},
{
"path": "app.js",
"chars": 1723,
"preview": "var express = require('express');\nvar app = express();\nvar fs = require('fs');\nvar open = require('open');\nvar options ="
},
{
"path": "fake-keys/certificate.pem",
"chars": 944,
"preview": "-----BEGIN CERTIFICATE-----\nMIICjTCCAfYCCQC8xCdh8aBfxDANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMC\nVVMxEzARBgNVBAgTCldhc2hpbmd"
},
{
"path": "fake-keys/privatekey.pem",
"chars": 887,
"preview": "-----BEGIN RSA PRIVATE KEY-----\nMIICXQIBAAKBgQDRKUxB1pLVRQ/dcUEP1p1oTIg0GoEvMPl6s7kC2Mroyovn/FaC\nzsgvwYhuwIeA6qgYoNIkSkX"
},
{
"path": "index.html",
"chars": 7407,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <title>react-native-webrtc server</title>\n <meta http-equiv=\"Content-Type\" content=\"tex"
},
{
"path": "package.json",
"chars": 449,
"preview": "{\n \"name\": \"react-native-webrtc-server\",\n \"version\": \"0.0.1\",\n \"description\": \"react-native-webrtc server\",\n \"main\":"
}
]
About this extraction
This page contains the full source code of the oney/react-native-webrtc-server GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 7 files (11.4 KB), approximately 4.0k tokens, and a symbol index with 1 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.