From 11cbb89ce8f1fa83a1e31828739b4922e3332a7c Mon Sep 17 00:00:00 2001 From: mukeran Date: Sat, 4 Jul 2020 20:09:33 +0800 Subject: [PATCH] :bug: Fixed some bugs. --- src/model/session.js | 3 +- src/request/offlineTransfer.js | 14 ++++++++ src/response/friend.js | 61 ++++++++++++++++++++++++--------- src/response/offlineTransfer.js | 10 +++--- src/response/user.js | 29 ++++++++++++++++ src/status.js | 5 ++- 6 files changed, 98 insertions(+), 24 deletions(-) diff --git a/src/model/session.js b/src/model/session.js index 9e2c63b..d6428fe 100644 --- a/src/model/session.js +++ b/src/model/session.js @@ -7,7 +7,8 @@ const SessionSchema = new mongoose.Schema({ sessionId: { type: String, required: true }, ip: { type: String, required: true }, // 用户IP controlPort: { type: String, required: true }, // 连接服务器控制信息端口 - transferPort: String // 文件传输用端口 + transferPort: String, // 文件传输用端口 + isNAT: { type: Boolean, default: false } }) /** diff --git a/src/request/offlineTransfer.js b/src/request/offlineTransfer.js index 714c6a4..7737a23 100644 --- a/src/request/offlineTransfer.js +++ b/src/request/offlineTransfer.js @@ -12,6 +12,13 @@ function sendOfflineTransfers (client) { .then(async offlineTransfers => { const requests = [] await Promise.all(offlineTransfers.map(offlineTransfer => { + if (offlineTransfer.deadline.getTime() < new Date().getTime()) { + OfflineTransferModel.deleteOne({ _id: offlineTransfer._id }) + .then(() => { + logger.debug(`Deleted expired offline transfer ${offlineTransfer._id}`) + }) + return + } return UserModel.findOne({ _id: offlineTransfer.fromUserId }) .then(user => { requests.push({ @@ -50,6 +57,13 @@ function sendOfflineTransfersByUserId (userId) { .then(async offlineTransfers => { const requests = [] await Promise.all(offlineTransfers.map(offlineTransfer => { + if (offlineTransfer.deadline.getTime() < new Date().getTime()) { + OfflineTransferModel.deleteOne({ _id: offlineTransfer._id }) + .then(() => { + logger.debug(`Deleted expired offline transfer ${offlineTransfer._id}`) + }) + return + } return UserModel.findOne({ _id: offlineTransfer.fromUserId }) .then(user => { requests.push({ diff --git a/src/response/friend.js b/src/response/friend.js index e5ae076..64f3027 100644 --- a/src/response/friend.js +++ b/src/response/friend.js @@ -26,7 +26,6 @@ function requestFriendList (packet, client) { for (const index in data.friends) { const friendId = data.friends[index] const friend = { - isNAT: false, isOnline: false } let isNotFound = false @@ -46,6 +45,7 @@ function requestFriendList (packet, client) { if (session !== null) { friend.ip = session.ip friend.port = session.transferPort + friend.isNAT = session.isNAT if (new Date().getTime() <= new Date(friend.lastSeen).getTime() + 3 * config.connection.ALIVE_PERIOD) { friend.isOnline = true } @@ -79,18 +79,39 @@ function sendFriendRequest (packet, client) { sendResponse(client, { status: status.user.NO_SUCH_USER }, packet) return } - FriendRequestsModel.create({ - fromUserId: fromUserSession.userId, - toUserId: toUser._id - }) - .then(() => { - sendResponse(client, { status: status.OK }, packet) - SessionModel.findOne({ userId: toUser._id }) - .then(session => { - if (session !== null) { - const toClient = clients.get(session.ip, session.controlPort) - request.sendFriendRequests(toClient) + if (fromUserSession.userId === toUser._id.toString()) { + sendResponse(client, { status: status.user.CANNOT_OPERATE_SELF }, packet) + return + } + UserModel.findOne({ _id: fromUserSession.userId }) + .then(fromUser => { + if (fromUser.friends.indexOf(toUser._id.toString()) !== -1) { + sendResponse(client, { status: status.user.ALREADY_FRIEND }, packet) + return + } + FriendRequestsModel.findOne({ + fromUserId: fromUserSession.userId, + toUserId: toUser._id + }) + .then(result => { + if (result !== null) { + sendResponse(client, { status: status.user.FRIEND_REQUEST_EXISTED }, packet) + return } + FriendRequestsModel.create({ + fromUserId: fromUserSession.userId, + toUserId: toUser._id + }) + .then(() => { + sendResponse(client, { status: status.OK }, packet) + SessionModel.findOne({ userId: toUser._id }) + .then(session => { + if (session !== null) { + const toClient = clients.get(session.ip, session.controlPort) + request.sendFriendRequests(toClient) + } + }) + }) }) }) }) @@ -109,13 +130,19 @@ function deleteFriend (packet, client) { sendResponse(client, { status: status.ACCESS_DENIED }, packet) return } - UserModel.findOne({ _id: session.userId }) + const p1 = UserModel.findOne({ _id: session.userId }) .then(data => { const newFriends = data.friends.filter(friend => friend !== userId) - UserModel.updateOne({ _id: session.userId }, { $set: { friends: newFriends } }) - .then(() => { - sendResponse(client, { status: status.OK }, packet) - }) + return UserModel.updateOne({ _id: session.userId }, { $set: { friends: newFriends } }) + }) + const p2 = UserModel.findOne({ _id: userId }) + .then(data => { + const newFriends = data.friends.filter(friend => friend !== session.userId) + return UserModel.updateOne({ _id: userId }, { $set: { friends: newFriends } }) + }) + Promise.all([p1, p2]) + .then(() => { + sendResponse(client, { status: status.OK }, packet) }) }) .catch(err => { diff --git a/src/response/offlineTransfer.js b/src/response/offlineTransfer.js index 0c03bc6..e105cf9 100644 --- a/src/response/offlineTransfer.js +++ b/src/response/offlineTransfer.js @@ -51,8 +51,8 @@ function queryOfflineTransfers (packet, client) { await Promise.all(offlineTransfers.map(offlineTransfer => { if (offlineTransfer.deadline.getTime() < new Date().getTime()) { OfflineTransferModel.deleteOne({ _id: offlineTransfer._id }) - .then(offlineTransferRequest => { - console.log('Offline transfer request: ' + offlineTransferRequest._id + ' is already out of date') + .then(() => { + logger.debug(`Deleted expired offline transfer ${offlineTransfer._id}`) }) return } @@ -97,10 +97,10 @@ function answerOfflineTransfer (packet, client) { return } if (transferRequest.deadline.getTime() < new Date().getTime()) { + sendResponse(client, { status: status.NOT_FOUND }, packet) OfflineTransferModel.deleteOne({ _id: transferRequest._id }) - .then(offlineTransferRequest => { - console.log('Offline transfer request: ' + offlineTransferRequest._id + ' is already out of date') - sendResponse(client, { status: status.NOT_FOUND }, packet) + .then(() => { + logger.debug(`Deleted expired offline transfer ${transferRequest._id}`) }) return } diff --git a/src/response/user.js b/src/response/user.js index b33bd3d..9f5fa24 100644 --- a/src/response/user.js +++ b/src/response/user.js @@ -6,6 +6,7 @@ const { logger } = require('../logger') const crypto = require('crypto') const request = require('../request') const { assert } = require('console') +const net = require('net') /** * Register as a user @@ -76,6 +77,7 @@ function login (packet, client) { .then(() => { // Send all friend requests of current user to client request.sendFriendRequests(client) request.sendOfflineTransfers(client) + testNAT(client.remoteAddress, transferPort, data._id) }) UserModel.updateOne({ _id: user._id }, { $set: { lastAliveTime: new Date() } }).then(() => {}) }) @@ -231,6 +233,7 @@ function resumeSession (packet, client) { sendResponse(client, { status: status.OK }, packet) request.sendFriendRequests(client) request.sendOfflineTransfers(client) + testNAT(client.remoteAddress, transferPort, session._id) }) }) .catch(err => { @@ -250,6 +253,7 @@ function updateTransferPort (packet, client) { SessionModel.updateOne(session, { $set: { transferPort: port } }) .then(() => { sendResponse(client, { status: status.OK }, packet) + testNAT(client.remoteAddress, port, session._id) }) }) .catch(err => { @@ -258,6 +262,31 @@ function updateTransferPort (packet, client) { }) } +function testNAT (host, port, _id) { + if (typeof port === 'undefined' || port === null || port === 0) return + const setNAT = (status) => { + SessionModel.updateOne({ _id }, { $set: { isNAT: status } }) + .then(() => { + logger.debug(`Updated session ${_id}'s isNAT to ${status}`) + }) + } + const socket = net.createConnection(port, host) + const timeout = setTimeout(() => { + socket.destroy() + setNAT(true) + }, 5000) + socket.on('error', () => { + clearTimeout(timeout) + socket.destroy() + setNAT(true) + }) + socket.on('connect', () => { + clearTimeout(timeout) + socket.end() + setNAT(false) + }) +} + module.exports = { register, login, diff --git a/src/status.js b/src/status.js index b8b9063..b0168b0 100644 --- a/src/status.js +++ b/src/status.js @@ -12,7 +12,10 @@ module.exports = { user: { DUPLICATED_USERNAME: 1, WRONG_USERNAME_OR_PASSWORD: 2, - NO_SUCH_USER: 3 + NO_SUCH_USER: 3, + CANNOT_OPERATE_SELF: 4, + FRIEND_REQUEST_EXISTED: 5, + ALREADY_FRIEND: 6 }, transfer: { REQUEST: 1,