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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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. board_data.getAll(function (data) {
  44. socket.emit("broadcast", data);
  45. });
  46. };
  47. if (board_data.ready) sendIt();
  48. else board_data.on("ready", sendIt);
  49. }));
  50. var connectTime = Date.now();
  51. var emitCount = 0;
  52. socket.on('broadcast', noFail(function onBroadcast(message) {
  53. emitCount++;
  54. var elapsedTime = Date.now() - connectTime;
  55. if (emitCount / elapsedTime > MAX_EMIT_PER_MS) {
  56. var request = socket.client.request;
  57. console.log(JSON.stringify({
  58. event: 'banned',
  59. user_agent: request.headers['user-agent'],
  60. original_ip: request.headers['x-forwarded-for'] || request.headers['forwarded'],
  61. connect_time: connectTime,
  62. rate: emitCount / elapsedTime
  63. }));
  64. return;
  65. }
  66. if (elapsedTime > 1000 * 60) {
  67. connectTime = Date.now();
  68. emitCount = 0;
  69. }
  70. var boardName = message.board || "anonymous";
  71. var data = message.data;
  72. if (!data) {
  73. console.warn("Received invalid message: %s.", JSON.stringify(message));
  74. return;
  75. }
  76. //Send data to all other users connected on the same board
  77. socket.broadcast.to(boardName).emit('broadcast', data);
  78. saveHistory(boardName, data);
  79. }));
  80. }
  81. function saveHistory(boardName, message) {
  82. var id = message.id;
  83. var boardData = getBoard(boardName).data;
  84. switch (message.type) {
  85. case "delete":
  86. if (id) boardData.delete(id);
  87. break;
  88. case "update":
  89. delete message.type;
  90. if (id) boardData.update(id, message);
  91. break;
  92. case "child":
  93. boardData.addChild(message.parent, message);
  94. break;
  95. default: //Add data
  96. if (!id) throw new Error("Invalid message: ", message);
  97. boardData.set(id, message);
  98. }
  99. }
  100. function generateUID(prefix, suffix) {
  101. var uid = Date.now().toString(36); //Create the uids in chronological order
  102. uid += (Math.round(Math.random() * 36)).toString(36); //Add a random character at the end
  103. if (prefix) uid = prefix + uid;
  104. if (suffix) uid = uid + suffix;
  105. return uid;
  106. }
  107. if (exports) {
  108. exports.start = function (app) {
  109. getBoard("anonymous").data.on("ready", function () {
  110. startIO(app);
  111. });
  112. };
  113. }