<commit_before>
const crypto = require('crypto');

const fs = require('fs');
const {execSync} = require('child_process');
const os = require('os');
const path = require('path');
const uidSafe = require('uid-safe');


const SID_LENGTH = 40; // crypto.randomBytes(30).length
const sidMap = new Map();
let sidHashMap;
let socketTmpPath;

// https://developpaper.com/question/will-building-unix-sockets-in-dev-shm-improve-performance/
// ------------------------------ init ------------------------------
function initTmpPath(){
  let tmpPath;
  try{
    // -- See https://github.com/linux-remote/linux-remote/wiki/Linux-WTF#--
    tmpPath = '/dev/shm/linux-remote';
    execSync('mkdir -m=1773 -p -- ' + tmpPath);
  }catch(e) {
    tmpPath = path.join(os.tmpdir(), 'linux-remote');
    execSync('mkdir -m=1773 -p -- ' + tmpPath);
  }
  return tmpPath;
}

function initSidHashMap(tmpPath){
  let filenames = fs.readdirSync(tmpPath);
  const map = new Map();
  filenames.forEach(name => {
    if(name[0] === '.'){
      return;
    }
    name = name.split('.');
    const hash = name[0];
    const username = name[1];
    if(!map[hash]){
      map[hash] = new Map();
    }
    map[hash].set(username, true);
  });
  return map;
}


function init(){
  socketTmpPath = initTmpPath();
  execSync('rm -rf ' + socketTmpPath + '/*');
  sidHashMap = initSidHashMap(socketTmpPath);
}

// ------------------------------ init end ------------------------------

function clearUp(){
  execSync('rm -rf ' + socketTmpPath);
}

function getTmpName(sidHash, username){
  return `${socketTmpPath}/${sidHash}.${username}`;
}

function hashSid(sid){
  return crypto.createHash('sha256').update(sid).digest('hex');
}
function genSid(){
  // node uuid/v4 equal crypto.randomBytes(16).toString('hex');
  // https://github.com/kelektiv/node-uuid/blob/master/lib/rng.js
  // npm use UUID as token.

  // And we used crypto.randomBytes(30) (uid-safe used randomBytes too)

  // Express/session will use secret to generate the signature of sid, and then add it after sid.
  // Then the question becomes: If sid is UUID, does sid need signature?

  const sid = uidSafe.sync(30);
  if(sidMap.size === sidHashMap.size && sidMap.has(sid)){
    return genSid();
  }

  const hash = hashSid(sid);
  if(sidHashMap.has(hash)){
    return genSid();
  }

  return {
    sid,
    hash
  };
}


function setSid(sid, sidHash, username){
  const userMap = new Map([[username, Date.now()]]);
  _setSidMap(sid, sidHash, userMap);
  sidHashMap.set(sidHash, userMap);
}

function _setSidMap(sid, hash, userMap){
  sidMap.set(sid, {
    hash,
    userMap
  });
}

function getSession(sid){
  // Cookie value is always string.
  if(sid && sid.length === SID_LENGTH){
    if(!sidMap.has(sid) && sidHashMap.size && sidMap.size !== sidHashMap.size){
      const sidHash = hashSid(sid);
      if(sidHashMap.has(sidHash)){
        _setSidMap(sid, sidHash, sidHashMap.get(sidHash));
      }
    }
    return sidMap.get(sid);
  }
}

function setCookie(res, sid, cookieSecure){
  res.cookie('sid', sid, {
    httpOnly: true,
    path: '/api',
    secure: cookieSecure
  });
}

function middleware(req, res, next){
  const sid = req.cookies.sid;
  const session = getSession(sid);
  if(session){
    const userMap = session.userMap;
    req.session = {
      id: sid,
      userMap,
      hash: session.hash,
      hasUser: userMap && userMap.size !== 0
    }
  } else {
    req.session = Object.create(null);
  }

  next();
}
function upUserNow(userMap, username){
  userMap.set(username, Date.now());
}
module.exports = {
  init,
  clearUp,
  genSid,
  setSid,
  hashSid,
  getSession,
  setCookie,
  middleware,
  getTmpName,
  upUserNow
}<commit_msg>remove shm<commit_after>
const crypto = require('crypto');

const fs = require('fs');
const {execSync} = require('child_process');
const os = require('os');
const path = require('path');
const uidSafe = require('uid-safe');


const SID_LENGTH = 40; // crypto.randomBytes(30).length
const sidMap = new Map();
let sidHashMap;

// https://developpaper.com/question/will-building-unix-sockets-in-dev-shm-improve-performance/
let socketTmpPath = path.join(os.tmpdir(), 'linux-remote');


// ------------------------------ init ------------------------------

function initSidHashMap(tmpPath){
  let filenames = fs.readdirSync(tmpPath);
  const map = new Map();
  filenames.forEach(name => {
    if(name[0] === '.'){
      return;
    }
    name = name.split('.');
    const hash = name[0];
    const username = name[1];
    if(!map[hash]){
      map[hash] = new Map();
    }
    map[hash].set(username, true);
  });
  return map;
}


function init(){
  execSync('rm -rf ' + socketTmpPath);
  execSync('mkdir -m=1773 -- ' + socketTmpPath);
  sidHashMap = initSidHashMap(socketTmpPath);
}

// ------------------------------ init end ------------------------------

function clearUp(){
  execSync('rm -rf ' + socketTmpPath);
}

function getTmpName(sidHash, username){
  return `${socketTmpPath}/${sidHash}.${username}`;
}

function hashSid(sid){
  return crypto.createHash('sha256').update(sid).digest('hex');
}
function genSid(){
  // node uuid/v4 equal crypto.randomBytes(16).toString('hex');
  // https://github.com/kelektiv/node-uuid/blob/master/lib/rng.js
  // npm use UUID as token.

  // And we used crypto.randomBytes(30) (uid-safe used randomBytes too)

  // Express/session will use secret to generate the signature of sid, and then add it after sid.
  // Then the question becomes: If sid is UUID, does sid need signature?

  const sid = uidSafe.sync(30);
  if(sidMap.size === sidHashMap.size && sidMap.has(sid)){
    return genSid();
  }

  const hash = hashSid(sid);
  if(sidHashMap.has(hash)){
    return genSid();
  }

  return {
    sid,
    hash
  };
}


function setSid(sid, sidHash, username){
  const userMap = new Map([[username, Date.now()]]);
  _setSidMap(sid, sidHash, userMap);
  sidHashMap.set(sidHash, userMap);
}

function _setSidMap(sid, hash, userMap){
  sidMap.set(sid, {
    hash,
    userMap
  });
}

function getSession(sid){
  // Cookie value is always string.
  if(sid && sid.length === SID_LENGTH){
    if(!sidMap.has(sid) && sidHashMap.size && sidMap.size !== sidHashMap.size){
      const sidHash = hashSid(sid);
      if(sidHashMap.has(sidHash)){
        _setSidMap(sid, sidHash, sidHashMap.get(sidHash));
      }
    }
    return sidMap.get(sid);
  }
}

function setCookie(res, sid, cookieSecure){
  res.cookie('sid', sid, {
    httpOnly: true,
    path: '/api',
    secure: cookieSecure
  });
}

function middleware(req, res, next){
  const sid = req.cookies.sid;
  const session = getSession(sid);
  if(session){
    const userMap = session.userMap;
    req.session = {
      id: sid,
      userMap,
      hash: session.hash,
      hasUser: userMap && userMap.size !== 0
    }
  } else {
    req.session = Object.create(null);
  }

  next();
}
function upUserNow(userMap, username){
  userMap.set(username, Date.now());
}
module.exports = {
  init,
  clearUp,
  genSid,
  setSid,
  hashSid,
  getSession,
  setCookie,
  middleware,
  getTmpName,
  upUserNow
}
{'fraction_non_alphanumeric': 0.18958950486669487, 'fraction_numerical': 0.006771053745239103, 'mean_word_length': 2.9171270718232045, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 5, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4351964', 'n_tokens_mistral': 2468, 'n_tokens_neox': 2439, 'n_words': 529}