f-hj/slsk-client

View on GitHub
lib/peer/download-peer-file.js

Summary

Maintainability
A
3 hrs
Test Coverage
const net = require('net')
const fs = require('fs')
const debug = require('debug')('slsk:peer:file')
const MessageFactory = require('../message-factory.js')

let stack = require('../stack')

module.exports = (host, port, token, user, noPierce) => {
  debug(`downloadPeerFile ${user}`)
  let conn = net.createConnection({
    host,
    port
  }, () => {
    if (noPierce) {
      debug(`noPierce ${user} connected`)
      conn.write(MessageFactory
        .to.peer
        .peerInit(stack.currentLogin, 'F', token)
        .getBuff())

      setTimeout(() => {
        debug(`noPierce sending 8* 00`)
        if (conn.destroyed) {
          debug(`socket closed`)
          return
        }
        conn.write(Buffer.from('00000000' + '00000000', 'hex'))
      }, 1000)
    } else {
      conn.write(MessageFactory
        .to.peer
        .pierceFw(token)
        .getBuff())
    }
  })

  let received = false
  let requestToken = noPierce ? token : undefined
  let buf = Buffer.alloc(0)
  let tok
  let down
  let i = 0

  conn.on('data', data => {
    if (!noPierce && !received) {
      requestToken = data.toString('hex', 0, 4)
      conn.write(Buffer.from('00000000' + '00000000', 'hex'))
      received = true
    } else {
      debug(`file data`)
      if (down && down.stream) {
        debug('push to stream')
        down.stream.push(data)
      }
      buf = Buffer.concat([buf, data])
    }

    if (tok) {
      if (i % 10 === 0) {
        debug(`buf: ${buf.length} size: ${tok.size}`)
      }
      i++
    } else {
      tok = stack.downloadTokens[requestToken]
      down = stack.download[tok.user + '_' + tok.file]
    }

    if (tok && buf.length >= tok.size) {
      debug(`disconnect, buf: ${buf.length} size: ${tok.size}`)
      conn.end()
    }
  })

  conn.on('close', () => {
    debug(`file socket close ${user}`)
    if (tok && down) {
      if (down.stream) down.stream.push(null)
      const filePath = down.path || getFilePathName(tok.user, tok.file)
      fs.writeFile(filePath, buf, () => {
        down.path = filePath
        down.buffer = buf
        if (typeof down.cb === 'function') down.cb(null, down)
      })
    } else {
      fs.writeFile(`${user}-${token}.mp3`, buf, () => {})
      debug(`ERROR: token ${token} not exist`)
    }
  })

  conn.on('error', () => {
    debug(`file socket error ${user}, destroying`)
    conn.destroy()
    // close event will be called (https://nodejs.org/api/net.html#net_event_error_1)
  })
}

function getFilePathName (user, file) {
  file = file.split('\\')
  return `/tmp/slsk/${user}_${file[file.length - 1]}`
}