You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sockets.js 3.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. var iolib = require('socket.io')
  2. , path = require("path")
  3. , fs = require('fs')
  4. , BoardData = require("./boardData.js").BoardData;
  5. var MAX_EMIT_PER_MS = 32 / 1000; // Maximum number of emitions /ms before getting banned
  6. var boards = {
  7. "anonymous": {
  8. "data": new BoardData("anonymous"),
  9. }
  10. };
  11. function noFail(fn) {
  12. return function noFailWrapped(arg) {
  13. try {
  14. return fn(arg);
  15. } catch (e) {
  16. console.trace(e);
  17. }
  18. }
  19. }
  20. function startIO(app) {
  21. io = iolib(app);
  22. io.on('connection', noFail(socketConnection));
  23. return io;
  24. }
  25. function getBoard(name) {
  26. var board = boards[name];
  27. if (!board) {
  28. boards[name] = board = {
  29. "data": new BoardData(name)
  30. };
  31. }
  32. return board;
  33. }
  34. function socketConnection(socket) {
  35. socket.on("getboard", noFail(function onGetBoard(name) {
  36. // Default to the public board
  37. if (!name) name = "anonymous";
  38. var board_data = getBoard(name).data;
  39. // Join the board
  40. socket.join(name);
  41. //Send all the board's data as soon as it's loaded
  42. var sendIt = function () {
  43. socket.emit("broadcast", { _children: board_data.getAll() });
  44. };
  45. if (board_data.ready) sendIt();
  46. else board_data.on("ready", sendIt);
  47. }));
  48. var connectTime = Date.now();
  49. var emitCount = 0;
  50. socket.on('broadcast', noFail(function onBroadcast(message) {
  51. emitCount++;
  52. var elapsedTime = Date.now() - connectTime;
  53. if (emitCount / elapsedTime > MAX_EMIT_PER_MS) {
  54. var request = socket.client.request;
  55. console.log(JSON.stringify({
  56. event: 'banned',
  57. user_agent: request.headers['user-agent'],
  58. original_ip: request.headers['x-forwarded-for'] || request.headers['forwarded'],
  59. connect_time: connectTime,
  60. rate: emitCount / elapsedTime
  61. }));
  62. return;
  63. }
  64. if (elapsedTime > 1000 * 60) {
  65. connectTime = Date.now();
  66. emitCount = 0;
  67. }
  68. var boardName = message.board || "anonymous";
  69. var data = message.data;
  70. if (!data) {
  71. console.warn("Received invalid message: %s.", JSON.stringify(message));
  72. return;
  73. }
  74. //Send data to all other users connected on the same board
  75. socket.broadcast.to(boardName).emit('broadcast', data);
  76. saveHistory(boardName, data);
  77. }));
  78. }
  79. function saveHistory(boardName, message) {
  80. var id = message.id;
  81. var boardData = getBoard(boardName).data;
  82. switch (message.type) {
  83. case "delete":
  84. if (id) boardData.delete(id);
  85. break;
  86. case "update":
  87. delete message.type;
  88. if (id) boardData.update(id, message);
  89. break;
  90. case "child":
  91. boardData.addChild(message.parent, message);
  92. break;
  93. default: //Add data
  94. if (!id) throw new Error("Invalid message: ", message);
  95. boardData.set(id, message);
  96. }
  97. }
  98. function generateUID(prefix, suffix) {
  99. var uid = Date.now().toString(36); //Create the uids in chronological order
  100. uid += (Math.round(Math.random() * 36)).toString(36); //Add a random character at the end
  101. if (prefix) uid = prefix + uid;
  102. if (suffix) uid = uid + suffix;
  103. return uid;
  104. }
  105. if (exports) {
  106. exports.start = function (app) {
  107. getBoard("anonymous").data.on("ready", function () {
  108. startIO(app);
  109. });
  110. };
  111. }