Commit f3efe28a authored by Kim, Chaerin's avatar Kim, Chaerin
Browse files

서버 구축 중... 고칠거 많음...

parent 3611461a
PG_DATABASE=boradb
PG_USER=test
PG_PASSWORD=test
\ No newline at end of file
const endpoints = {
API_BASE_URL: "https://localhost:8080/api",
HOME_API: "/",
ROOM_API: "/room",
PROFILE_API: "/profile",
};
export default endpoints;
import axios from "axios";
import { API_BASE_URL } from "./endpoints";
const login = async (email, password) => {
const payload = { email, password };
const { data } = await axios.post(`${API_BASE_URL}/user`, payload);
return data;
};
export default login;
let http = require('http');
let express = require('express');
let cors = require('cors');
let socketio = require('socket.io');
let wrtc = require('wrtc');
const app = express();
const server = http.createServer(app);
app.use(cors());
let receiverPCs = {};
let senderPCs = {};
let users = {};
let socketToRoom = {};
const pc_config = {
"iceServers": [
// {
// urls: 'stun:[STUN_IP]:[PORT]',
// 'credentials': '[YOR CREDENTIALS]',
// 'username': '[USERNAME]'
// },
{
urls : 'stun:stun.l.google.com:19302'
}
]
}
const isIncluded = (array, id) => {
let len = array.length;
for (let i = 0; i < len; i++) {
if (array[i].id === id) return true;
}
return false;
}
const createReceiverPeerConnection = (socketID, socket, roomID) => {
let pc = new wrtc.RTCPeerConnection(pc_config);
if (receiverPCs[socketID]) receiverPCs[socketID] = pc;
else receiverPCs = {...receiverPCs, [socketID]: pc};
pc.onicecandidate = (e) => {
//console.log(`socketID: ${socketID}'s receiverPeerConnection icecandidate`);
socket.to(socketID).emit('getSenderCandidate', {
candidate: e.candidate
});
}
pc.oniceconnectionstatechange = (e) => {
//console.log(e);
}
pc.ontrack = (e) => {
if (users[roomID]) {
if (!isIncluded(users[roomID], socketID)) {
users[roomID].push({
id: socketID,
stream: e.streams[0]
});
} else return;
} else {
users[roomID] = [{
id: socketID,
stream: e.streams[0]
}];
}
socket.broadcast.to(roomID).emit('userEnter', {id: socketID});
}
return pc;
}
const createSenderPeerConnection = (receiverSocketID, senderSocketID, socket, roomID) => {
let pc = new wrtc.RTCPeerConnection(pc_config);
if (senderPCs[senderSocketID]) {
senderPCs[senderSocketID].filter(user => user.id !== receiverSocketID);
senderPCs[senderSocketID].push({id: receiverSocketID, pc: pc});
}
else senderPCs = {...senderPCs, [senderSocketID]: [{id: receiverSocketID, pc: pc}]};
pc.onicecandidate = (e) => {
//console.log(`socketID: ${receiverSocketID}'s senderPeerConnection icecandidate`);
socket.to(receiverSocketID).emit('getReceiverCandidate', {
id: senderSocketID,
candidate: e.candidate
});
}
pc.oniceconnectionstatechange = (e) => {
//console.log(e);
}
const sendUser = users[roomID].filter(user => user.id === senderSocketID);
sendUser[0].stream.getTracks().forEach(track => {
pc.addTrack(track, sendUser[0].stream);
});
return pc;
}
const getOtherUsersInRoom = (socketID, roomID) => {
let allUsers = [];
if (!users[roomID]) return allUsers;
let len = users[roomID].length;
for (let i = 0; i < len; i++) {
if (users[roomID][i].id === socketID) continue;
allUsers.push({id: users[roomID][i].id});
}
return allUsers;
}
const deleteUser = (socketID, roomID) => {
let roomUsers = users[roomID];
if (!roomUsers) return;
roomUsers = roomUsers.filter(user => user.id !== socketID);
users[roomID] = roomUsers;
if (roomUsers.length === 0) {
delete users[roomID];
}
delete socketToRoom[socketID];
}
const closeRecevierPC = (socketID) => {
if (!receiverPCs[socketID]) return;
receiverPCs[socketID].close();
delete receiverPCs[socketID];
}
const closeSenderPCs = (socketID) => {
if (!senderPCs[socketID]) return;
let len = senderPCs[socketID].length;
for (let i = 0; i < len; i++) {
senderPCs[socketID][i].pc.close();
let _senderPCs = senderPCs[senderPCs[socketID][i].id];
let senderPC = _senderPCs.filter(sPC => sPC.id === socketID);
if (senderPC[0]) {
senderPC[0].pc.close();
senderPCs[senderPCs[socketID][i].id] = _senderPCs.filter(sPC => sPC.id !== socketID);
}
}
delete senderPCs[socketID];
}
const io = socketio.listen(server);
io.sockets.on('connection', (socket) => {
socket.on('joinRoom', (data) => {
try {
let allUsers = getOtherUsersInRoom(data.id, data.roomID);
io.to(data.id).emit('allUsers', { users: allUsers });
} catch (error) {
console.log(error);
}
});
socket.on('senderOffer', async(data) => {
try {
socketToRoom[data.senderSocketID] = data.roomID;
let pc = createReceiverPeerConnection(data.senderSocketID, socket, data.roomID);
await pc.setRemoteDescription(data.sdp);
let sdp = await pc.createAnswer({offerToReceiveAudio: true, offerToReceiveVideo: true});
await pc.setLocalDescription(sdp);
socket.join(data.roomID);
io.to(data.senderSocketID).emit('getSenderAnswer', { sdp });
} catch (error) {
console.log(error);
}
});
socket.on('senderCandidate', async(data) => {
try {
let pc = receiverPCs[data.senderSocketID];
await pc.addIceCandidate(new wrtc.RTCIceCandidate(data.candidate));
} catch (error) {
console.log(error);
}
});
socket.on('receiverOffer', async(data) => {
try {
let pc = createSenderPeerConnection(data.receiverSocketID, data.senderSocketID, socket, data.roomID);
await pc.setRemoteDescription(data.sdp);
let sdp = await pc.createAnswer({offerToReceiveAudio: false, offerToReceiveVideo: false});
await pc.setLocalDescription(sdp);
io.to(data.receiverSocketID).emit('getReceiverAnswer', { id: data.senderSocketID, sdp });
} catch (error) {
console.log(error);
}
});
socket.on('receiverCandidate', async(data) => {
try {
const senderPC = senderPCs[data.senderSocketID].filter(sPC => sPC.id === data.receiverSocketID);
await senderPC[0].pc.addIceCandidate(new wrtc.RTCIceCandidate(data.candidate));
} catch (error) {
console.log(error);
}
});
socket.on('disconnect', () => {
try {
let roomID = socketToRoom[socket.id];
deleteUser(socket.id, roomID);
closeRecevierPC(socket.id);
closeSenderPCs(socket.id);
socket.broadcast.to(roomID).emit('userExit', {id: socket.id});
} catch (error) {
console.log(error);
}
});
});
server.listen(process.env.PORT || 8080, () => {
console.log('server running on 8080');
})
\ No newline at end of file
......@@ -4,17 +4,30 @@
"description": "Streaming Service",
"main": "index.js",
"scripts": {
"start": "nodemon index.js",
"dev": "nodemon src/index.ts",
"start": "nodemon server/index.js",
"dev": "nodemon -r esm server/index.js",
"build": "tsc -p ."
},
"repository": {
"type": "git",
"url": "https://compmath.korea.ac.kr/gitlab/research/bora_it.git"
},
"keywords": [],
"author": "",
"author": "Chaerin Kim,",
"license": "ISC",
"dependencies": {
"bcryptjs": "^2.4.3",
"cookie-parser": "^1.4.5",
"cors": "2.8.5",
"dotenv": "^10.0.0",
"esm": "^3.2.25",
"express": "4.17.1",
"http": "0.0.1-security",
"jsonwebtoken": "^8.5.1",
"nodemon": "^2.0.7",
"pg": "^8.6.0",
"pg-hstore": "^2.3.4",
"sequelize": "^6.6.5",
"socket.io": "2.3.0",
"wrtc": "0.4.6"
},
......
// express 설정 파일
import express from "express";
import fs from "fs";
import cookieParser from "cookie-parser";
import mainRouter from "./routes/index.js";
// fs.readdir('uploads', (error) => {
// if (error) {
// fs.mkdirSync('uploads');
// }
// })
const app = express();
app.use(express.json());
// app.use('/uploads', express.static('uploads'))
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());
app.use("/api", mainRouter);
export default app;
const config = {
env: process.env.NODE_ENV === 'production' ? 'production' : 'development',
port: process.env.PORT || 8080,
jwtSecret: 'ThisIsSecretKeyOFBoraIt!',
jwtExpires: '1d',
cookieName: 'borabora',
cookieMaxAge: 60 * 60 * 24 * 7 * 1000,
}
export default config
\ No newline at end of file
const config = {
host: 'localhost',
username: process.env.PG_USER || 'test',
password: process.env.PG_PASSWORD || 'test',
database: process.env.PG_DATABASE || 'testdb',
dialect: 'postgres',
pool: {
max: 10,
min: 0,
acquire: 30000,
idle: 10000,
}
}
export default config
\ No newline at end of file
import { Sequelize } from "sequelize";
import UserModel from "../models/user.model.js";
import dbConfig from "../config/db.config.js";
const sequelize = new Sequelize(
String(dbConfig.database),
String(dbConfig.username),
dbConfig.password,
{
host: dbConfig.host,
dialect: dbConfig.dialect,
// pool: {
// max: dbConfig.pool?.max,
// min: dbConfig.pool?.min,
// acquire: dbConfig.pool?.acquire,
// idle: dbConfig.pool?.idle,
// },
}
);
const User = UserModel(sequelize);
export { sequelize, User };
// server 진입점
import dotenv from "dotenv";
import app from "./app.js";
import appConfig from "./config/app.config.js";
import { sequelize, User } from "./db/index.js";
dotenv.config({
path: `${
process.env.NODE_ENV === "production" ? ".env" : ".env.development"
}`,
});
// production
// sequelize.sync().then(() => {
// app.listen(appConfig.port, () => {
// console.log(`Server is running on port ${appConfig.port}`)
// })
// })
// development
// 주의!!!: {force: true}는 서버가 다시 시작되면 기존 디비 모두 삭제되고 새로운 디비 생성
sequelize
.sync({ force: true })
.then(async () => {
// await Promise.all(
// Object.keys(ROLE_NAME).map((name) => {
// return Role.create({ name });
// })
// );
// const adminRole = await Role.findOne({ where: { name: "admin" } });
await User.create({
name: "admin",
id: "admin",
password: "admin!",
idNumber: "0000",
});
app.listen(appConfig.port, () => {
console.log(`Server is running on port ${appConfig.port}`);
});
})
.catch((err) => {
console.log(err);
});
import bcrypt from "bcryptjs";
import { DataTypes } from "sequelize";
const RoomModel = (sequelize) => {
const Room = sequelize.define(
"room",
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
},
owner: {
type: DataTypes.STRING,
},
member: {
type: DataTypes.ARRAY(DataTypes.INTEGER),
},
channel: {
type: DataTypes.ARRAY(DataTypes.JSON),
},
},
{ timestamps: true }
);
return Room;
};
export default RoomModel;
import bcrypt from "bcryptjs";
import { DataTypes } from "sequelize";
const UserModel = (sequelize) => {
const User = sequelize.define(
"user",
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
},
email: {
type: DataTypes.STRING,
},
password: {
type: DataTypes.STRING,
},
gender: {
type: DataTypes.INTEGER,
},
phone: {
type: DataTypes.STRING,
},
img: {
type: DataTypes.ARRAY(DataTypes.INTEGER),
},
roomNumber: {
type: DataTypes.ARRAY(DataTypes.STRING),
},
},
{ timestamps: true }
);
User.beforeSave(async (user) => {
if (!user.changed("password")) {
return;
}
if (user.password) {
const hashedPassword = await bcrypt.hash(user.password, 10);
user.password = hashedPassword;
}
});
User.prototype.toJSON = function toJSON() {
const values = Object.assign({}, this.get());
delete values.password;
return values;
};
User.prototype.comparePassword = async function (plainPassword) {
const passwordMatch = await bcrypt.compare(plainPassword, this.password);
return passwordMatch;
};
return User;
};
export default UserModel;
import express from "express";
import userRouter from "./user.route.js";
const router = express.Router();
router.use("/user", userRouter);
export default router;
import express from "express";
// import authCrtl from "../controllers/auth.controller.js";
const router = express.Router();
// router.route("/").get(authCrtl.requireLogin);
export default router;
\ No newline at end of file
import express from "express";
// import authCrtl from "../controllers/auth.controller";
// import userCtrl from "../controllers/user.controller";
const router = express.Router();
// router.route("/").get(authCrtl.requireLogin);
export default router;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment