+++ /dev/null
-{
- "auto_complete":
- {
- "selected_items":
- [
- [
- "exists",
- "path.existsSync(path);"
- ],
- [
- "cons",
- "console.error();"
- ],
- [
- "D",
- "Dokumenter"
- ],
- [
- "process",
- "process.exit(code);"
- ],
- [
- "proces",
- "process.exit(code);"
- ],
- [
- "createse",
- "http.createServer(requestListener);"
- ],
- [
- "createSe",
- "http.createServer(requestListener);"
- ],
- [
- "child",
- "child_process.exec(command /*, options, callback */);"
- ],
- [
- "timeout",
- "timers.setTimeout(callback, after);"
- ],
- [
- "node",
- "node.events.EventEmitter.on Snippet: NodeJS EventEmitter"
- ]
- ]
- },
- "buffers":
- [
- {
- "file": "package.json",
- "settings":
- {
- "buffer_size": 242,
- "line_ending": "Windows",
- "name": "package.json"
- }
- },
- {
- "file": "lib/tftp.js",
- "settings":
- {
- "buffer_size": 7942,
- "line_ending": "Windows",
- "name": "tftp.js"
- }
- },
- {
- "file": "bin/tftp.js",
- "settings":
- {
- "buffer_size": 2683,
- "line_ending": "Windows"
- }
- },
- {
- "file": "README.md",
- "settings":
- {
- "buffer_size": 1790,
- "line_ending": "Windows",
- "name": "README.md"
- }
- }
- ],
- "build_system": "",
- "command_palette":
- {
- "height": 380.0,
- "selected_items":
- [
- [
- "mark",
- "Markdown Preview: preview in Browser"
- ],
- [
- "git diff",
- "Git: Diff Current File"
- ],
- [
- "markd",
- "Markdown Preview: preview in Browser"
- ],
- [
- "markdown",
- "Markdown Preview: preview in Browser"
- ],
- [
- "npm",
- "Nodejs::NPM::Command"
- ],
- [
- "npl",
- "Nodejs::NPM::List"
- ],
- [
- "install",
- "Package Control: Install Package"
- ],
- [
- "MARK",
- "Markdown Preview: preview in Browser"
- ],
- [
- "markdo",
- "Markdown Preview: preview in Browser"
- ],
- [
- "git",
- "Git: Gui"
- ],
- [
- "gitadd",
- "Git: Add..."
- ],
- [
- "remo",
- "Package Control: Remove Package"
- ],
- [
- "gut",
- "GitHub: Open Gist in Browser"
- ],
- [
- "intall",
- "Package Control: Install Package"
- ],
- [
- "snippet",
- "Snippet: setTimeout function"
- ],
- [
- "kar",
- "Package Control: Add Repository"
- ],
- [
- "ma",
- "Markdown Preview: preview in Sublime Text"
- ],
- [
- "list",
- "Package Control: List Packages"
- ],
- [
- "package",
- "Package Control: List Packages"
- ],
- [
- "mar",
- "Markdown Preview: preview in Browser"
- ],
- [
- "Package Control: list",
- "Package Control: List Packages"
- ],
- [
- "insta",
- "Package Control: Install Package"
- ],
- [
- "node",
- "Nodejs::Run::Current File"
- ],
- [
- "package up",
- "Package Control: Upgrade Package"
- ],
- [
- "list packa",
- "Package Control: Install Package"
- ],
- [
- "package install",
- "Package Control: Install Package"
- ],
- [
- "package discover",
- "Package Control: Discover Packages"
- ]
- ],
- "width": 512.0
- },
- "console":
- {
- "height": 227.0
- },
- "distraction_free":
- {
- "menu_visible": true,
- "show_minimap": false,
- "show_open_files": false,
- "show_tabs": false,
- "side_bar_visible": false,
- "status_bar_visible": false
- },
- "file_history":
- [
- "/D/Dokumenter/GitHub/TFTP-Client/TFTP-Client.sublime-project",
- "/D/Dokumenter/GitHub/TFTP-Client/.npmignore",
- "/D/Dokumenter/GitHub/TFTP-Client/example/read.js",
- "/D/Dokumenter/GitHub/TFTP-Client/example/write.js",
- "/D/Dokumenter/GitHub/TFTP-Client/bin/tftp.js",
- "/C/Users/Kristjan/AppData/Roaming/Sublime Text 2/Packages/Default/Default (Windows).sublime-keymap",
- "/D/Dokumenter/GitHub/TFTP-Client/lib/write.js",
- "/D/Dokumenter/GitHub/TFTP-Client/lib/read.js",
- "/D/Dokumenter/GitHub/TFTP-Client/example/transaction.js",
- "/D/Dokumenter/GitHub/JsControl/JsControl.sublime-project",
- "/D/Dokumenter/GitHub/JsControl/test.js",
- "/D/Dokumenter/GitHub/JsControl/.gitignore",
- "/D/Dokumenter/GitHub/JsControl/JsControl.js",
- "/D/Dokumenter/GitHub/JsControl/controller/test.js",
- "/D/Dokumenter/GitHub/JsControl/package.json",
- "/D/Dokumenter/GitHub/JsControl/plugins/playerlist/player.js",
- "/D/Dokumenter/GitHub/JsControl/controller/modules/maps.js",
- "/D/Dokumenter/GitHub/JsControl/controller/modules/game.js",
- "/D/Dokumenter/GitHub/JsControl/config/config.json",
- "/D/Dokumenter/GitHub/JsControl/Run.cmd",
- "/D/Dokumenter/GitHub/JsControl/plugins/playerlist/index.js",
- "/D/Dokumenter/GitHub/JsControl/config/players.sample.json",
- "/D/Dokumenter/GitHub/JsControl/README.md",
- "/D/Dokumenter/GitHub/JsControl/controller/modules/players/players.js",
- "/D/Dokumenter/GitHub/JsControl/config/config.sample.json",
- "/D/Dokumenter/GitHub/JsControl/todo.md",
- "/D/Dokumenter/GitHub/JsControl/Plugins/second/index.js",
- "/D/Dokumenter/GitHub/JsControl/controller/player.js",
- "/D/Dokumenter/GitHub/JsControl/config/plugins/admin.sample.json",
- "/D/Dokumenter/GitHub/JsControl/controller/players.js",
- "/D/Dokumenter/GitHub/JsControl/Plugins/admin.js",
- "/D/Dokumenter/GitHub/JsControl/plugins/commands.js",
- "/D/Dokumenter/GitHub/JsControl/plugins/database.js",
- "/C/Users/Kristjan/AppData/Roaming/Sublime Text 2/Packages/User/Distraction Free.sublime-settings",
- "/C/Users/Kristjan/AppData/Roaming/Sublime Text 2/Packages/User/Default (Windows).sublime-keymap",
- "/D/Dokumenter/GitHub/JsControl/Plugins/webcontroller/index.js",
- "/D/Dokumenter/GitHub/JsControl/config/plugins/webcontroller.json",
- "/D/Dokumenter/GitHub/JsControl/config/config.js",
- "/D/Dokumenter/GitHub/JsControl/config/plugins/webcontroller.js",
- "/D/Dokumenter/GitHub/node-gbxremote/package.json",
- "/D/Dokumenter/GitHub/node-gbxremote/lib/gbxremote.js",
- "/D/Dokumenter/GitHub/node-gbxremote/lib/client.js",
- "/D/Dokumenter/GitHub/node-gbxremote/.gitignore",
- "/D/Dokumenter/GitHub/node-gbxremote/example/client.js",
- "/D/Dokumenter/GitHub/node-gbxremote/lib/deserializer.js",
- "/D/Dokumenter/GitHub/node-gbxremote/example/authenticate.js",
- "/C/Users/Kristjan/AppData/Roaming/Sublime Text 2/Packages/Default/Preferences.sublime-settings",
- "/C/Users/Kristjan/AppData/Roaming/Sublime Text 2/Packages/User/Preferences.sublime-settings"
- ],
- "find":
- {
- "height": 34.0
- },
- "find_in_files":
- {
- "height": 0.0,
- "where_history":
- [
- "todo.md",
- "controller.js",
- ""
- ]
- },
- "find_state":
- {
- "case_sensitive": false,
- "find_history":
- [
- "Timeout",
- "- ",
- "tftp is terrible",
- "argc",
- "length",
- "args",
- "line",
- "bytes",
- "createAck",
- "this.current",
- "netascii",
- "/",
- " 2 Access violation.\n 3 Disk full or allocation exceeded.\n 4 Illegal TFTP operation.\n 5 Unknown transfer ID.\n 6 File already exists.\n 7 No such user.\n",
- "tftp",
- "________________________________________________________",
- "client",
- "players",
- "PlayerList",
- "Maps",
- "this.query",
- "playerlist",
- "name",
- "this",
- "plugins",
- ".emit",
- ".on",
- "plugin",
- "requirePlugin",
- "require",
- "!!(",
- "(fl.pop())",
- "fl.pop()",
- "spec.pop()",
- "spec",
- "Is",
- "spectator",
- "self",
- "this",
- "console",
- "ingame",
- "shift",
- "plugin",
- "ready",
- "file",
- "Connection",
- "\\\\",
- "/",
- " /##################\\\\');",
- "function",
- "s",
- "loadPlugins",
- " self.loadPlugins();\n",
- "loadPlugins",
- " self.loadPlugins();\n self.loadPlugins();\n self.loadPlugins();\n self.loadPlugins();\n self.loadPlugins();\n",
- " self.loadPlugins();\n self.loadPlugins();\n self.loadPlugins();\n self.loadPlugins();\n",
- " self.loadPlugins();\n",
- "loadPlugins",
- "function",
- "commands",
- "without",
- ".",
- "*",
- "ctrl+b",
- "Plugin",
- "password",
- "config.U",
- "config.I",
- "config.P",
- "\n\n //return;\n setTimeout(function () {\n console.log(\"Exiting!\");\n client.terminate();\n }, 1000);",
- " [\"SuperAdmin\", \"SuperAdmin\"], function(err, result) {\n if (err) {\n console.log(err);\n } else {\n if (result === true)\n console.log(\"Authenticated!\");\n }\n });\n \n client.methodCall(\"EnableCallbacks\", [true], function(err, res) {\n console.log(err, res);\n });\n\n //return;\n setTimeout(function () {\n console.log(\"Exiting!\");\n client.terminate();\n }, 1000);\n}",
- " });"
- ],
- "highlight": true,
- "in_selection": false,
- "preserve_case": false,
- "regex": false,
- "replace_history":
- [
- "-",
- "config.u",
- "config.i",
- "config.p"
- ],
- "reverse": false,
- "show_context": true,
- "use_buffer2": true,
- "whole_word": false,
- "wrap": true
- },
- "groups":
- [
- {
- "selected": 3,
- "sheets":
- [
- {
- "buffer": 0,
- "file": "package.json",
- "settings":
- {
- "buffer_size": 242,
- "regions":
- {
- },
- "selection":
- [
- [
- 242,
- 242
- ]
- ],
- "settings":
- {
- "auto_name": "package.json",
- "syntax": "Packages/JavaScript/JSON.tmLanguage"
- },
- "translation.x": 0.0,
- "translation.y": 0.0,
- "zoom_level": 1.0
- },
- "type": "text"
- },
- {
- "buffer": 1,
- "file": "lib/tftp.js",
- "settings":
- {
- "buffer_size": 7942,
- "regions":
- {
- },
- "selection":
- [
- [
- 1556,
- 1556
- ]
- ],
- "settings":
- {
- "auto_name": "tftp.js",
- "syntax": "Packages/JavaScript/JavaScript.tmLanguage",
- "translate_tabs_to_spaces": false
- },
- "translation.x": 0.0,
- "translation.y": 2077.0,
- "zoom_level": 1.0
- },
- "type": "text"
- },
- {
- "buffer": 2,
- "file": "bin/tftp.js",
- "settings":
- {
- "buffer_size": 2683,
- "regions":
- {
- },
- "selection":
- [
- [
- 2608,
- 2640
- ]
- ],
- "settings":
- {
- "syntax": "Packages/JavaScript/JavaScript.tmLanguage",
- "translate_tabs_to_spaces": false
- },
- "translation.x": 0.0,
- "translation.y": 924.0,
- "zoom_level": 1.0
- },
- "type": "text"
- },
- {
- "buffer": 3,
- "file": "README.md",
- "settings":
- {
- "buffer_size": 1790,
- "regions":
- {
- },
- "selection":
- [
- [
- 1643,
- 1643
- ]
- ],
- "settings":
- {
- "auto_name": "README.md",
- "syntax": "Packages/Markdown/Markdown.tmLanguage"
- },
- "translation.x": 0.0,
- "translation.y": 168.0,
- "zoom_level": 1.0
- },
- "type": "text"
- }
- ]
- }
- ],
- "incremental_find":
- {
- "height": 0.0
- },
- "input":
- {
- "height": 30.0
- },
- "layout":
- {
- "cells":
- [
- [
- 0,
- 0,
- 1,
- 1
- ]
- ],
- "cols":
- [
- 0.0,
- 1.0
- ],
- "rows":
- [
- 0.0,
- 1.0
- ]
- },
- "menu_visible": true,
- "output.exec":
- {
- "height": 248.0
- },
- "output.git":
- {
- "height": 545.0
- },
- "replace":
- {
- "height": 0.0
- },
- "save_all_on_build": true,
- "select_file":
- {
- "height": 0.0,
- "selected_items":
- [
- [
- "c",
- "JsControl.js"
- ],
- [
- "clien",
- "lib/client.js"
- ],
- [
- ".git",
- ".gitignore"
- ],
- [
- "packa",
- "package.json"
- ]
- ],
- "width": 0.0
- },
- "select_project":
- {
- "height": 500.0,
- "selected_items":
- [
- ],
- "width": 380.0
- },
- "show_minimap": true,
- "show_open_files": false,
- "show_tabs": true,
- "side_bar_visible": true,
- "side_bar_width": 212.0,
- "status_bar_visible": true
-}
+++ /dev/null
-#!/usr/bin/env node\r
-\r
-// Require needed modules\r
-var TFTP = require('..'), // The tftp-client module\r
- fs = require('fs'), // Simple wrappers around standard POSIX functions\r
- path = require('path'); // Contains utilities for handling and transforming file paths\r
-\r
-/**********************\\r
-|* Validate arguments *|\r
-\**********************/\r
-\r
-// Too few arguments (node + path_to_this_file + host + cmd + file = 5)\r
-if (process.argv.length < 5) {\r
- // Print usage, and exit\r
- console.log('Needs atleast 3 arguments (you had %d)', process.argv.length-2);\r
- console.log('');\r
- printUsage(true);\r
-}\r
-\r
-// Grab arguments\r
-var host = process.argv[2];\r
-var cmd = process.argv[3];\r
-var file = process.argv[4];\r
-var port = process.argv[5] || 69; // Port defaults to 69 if omitted\r
-\r
-// If cmd is neither read nor write, print usage & exit\r
-if (['read', 'write'].indexOf(cmd)===-1) {\r
- console.log('Command must be read or write (you had %s)', cmd);\r
- printUsage(true);\r
-}\r
-\r
-/*******************\\r
-|* Validation done *|\r
-\*******************/\r
-\r
-// Create the client\r
-var client = new TFTP(port, host);\r
-\r
-var basename = path.basename(file);\r
-\r
-/********\\r
-|* READ *|\r
-\********/\r
-if (cmd == 'read') {\r
- // Read from server\r
- client.read(basename, function(err, data) {\r
- // If error, output some error message\r
- if (err) {\r
- console.error('Oh noes! Error while reading file from tftp server:');\r
- console.error(err);\r
- } else {\r
-\r
- // No error, we got the file, lets write it\r
- \r
- fs.writeFile(file, data, function (err) {\r
- \r
- // If error, output some error message\r
- if (err) {\r
- console.error('Dang it! Error while writing file!');\r
- console.error(err);\r
- } else {\r
-\r
- // No error, the file has been written!\r
-\r
- console.log('File saved (%d bytes)', data.length);\r
- }\r
- });\r
- }\r
- });\r
-}\r
-/*********\\r
-|* WRITE *|\r
-\*********/\r
-else if (cmd == 'write') {\r
- // If file does not exist, print error and usage & exit\r
- if (!fs.existsSync(file)) {\r
- console.log('File (%s) does not exist!', file);\r
- printUsage(true);\r
- }\r
-\r
- // Read file first, then send to server\r
- var data = fs.readFileSync(file);\r
-\r
- client.write(basename, data, function (err, bytes) {\r
- if (err) {\r
- console.error('ERROR:');\r
- console.error(err);\r
- return;\r
- }\r
-\r
- console.log('File sent (%d bytes)', bytes);\r
- });\r
-} else {\r
- console.log('???HOW DID YOU GET HERE???');\r
-}\r
-\r
-/**\r
- * Prints usage - how to use tftp-client\r
- * @param {boolean} exit Wether it sould exit the process\r
- */\r
-function printUsage(exit) {\r
- console.log('Usage:');\r
- console.log(' tftp-client <hostname> (read|write) <filename> [<port>]');\r
- console.log('');\r
- console.log('Example:');\r
- console.log(' tftp-client localhost read 1.txt');\r
-\r
- if (exit===true)\r
- process.exit(0);\r
-}
\ No newline at end of file
+++ /dev/null
-var dgram = require('dgram'); // UDP (datagram)\r
-\r
-// Timeout for ack/data packet\r
-var TIMEOUT = 5000; // 5 seconds\r
-// Max retransmits if timeout\r
-var MAX_RETRANSMITS = 3;\r
-\r
-// type: Opcode\r
-var types = {\r
- 'rrq': 1, // Read ReQuest\r
- 'wrq': 2, // Write ReQuest\r
- 'data':3,\r
- 'ack': 4,\r
- 'err': 5,\r
-\r
- // aliases:\r
- 'read':1,\r
- 'write':2\r
-}\r
-\r
-// Error strings ([errorCode] = errorString)\r
-var errors = [\r
- 'Not defined, see error message (if any).',\r
- 'File not found.',\r
- 'Access violation.',\r
- 'Disk full or allocation exceeded.',\r
- 'Illegal TFTP operation.',\r
- 'Unknown transfer ID.',\r
- 'File already exists.',\r
- 'No such user.'\r
-];\r
-\r
-/**\r
- * Constructor\r
- * @param {Number} port Port the tftp server is listening to\r
- * @param {String} ip Ip or hostname of the tftp server\r
- */\r
-var TFTP = module.exports = function(port, ip) {\r
- this.ip = ip || '127.0.0.1';\r
- this.port = port || 69;\r
-\r
- // Hold the current operation\r
- this.current = false;\r
- // Holds the queue of the next operations\r
- this.queue = [];\r
-\r
- // Client will be created when needed\r
- this.client = null;\r
-\r
- // Display debug messages?\r
- this.debug = false;\r
-}\r
-\r
-TFTP.prototype.createClient = function() {\r
- if (this.client !== null)\r
- return;\r
-\r
- // We need this inside onMessage...\r
- var self = this;\r
- \r
- // Called when getting an message from the server\r
- var onMessage = function(msg, rinfo) {\r
-\r
- // Type of message (see `types` above)\r
- var type = msg.readUInt16BE(0);\r
-\r
- switch (type) {\r
- // Data - Respond with Ack\r
- case types.data:\r
- var block = msg.readUInt16BE(2);\r
- var data = msg.slice(4); // From byte 4 is data\r
-\r
- if (self.debug) {\r
- console.log('> Received data. Block#: %d Bytes: %d', block, data.length);\r
- console.log('< Sending ACK. Block#: %d', block);\r
- }\r
-\r
- // Concat the two buffers\r
- self.current.data = Buffer.concat([self.current.data, data]);\r
-\r
- // Create and send ACK packet\r
- var ack = createAck(block);\r
- self.send(ack);\r
-\r
- // If less than 512 bytes were received, it's the end...\r
- if (data.length < 512) {\r
- // Send the data to the callback\r
- self.current.callback(null, self.current.data);\r
-\r
- // Go to next operation in queue\r
- self.next();\r
- }\r
- break;\r
- // Ack - Respond with Data\r
- case types.ack:\r
- var block = msg.readUInt16BE(2);\r
-\r
- if (self.debug)\r
- console.log('> Received ACK. Block#: %d', block);\r
-\r
- // If this is the ack for the last block\r
- if (block == self.current.blocks) {\r
- // Send callback\r
- self.current.callback(null, self.current.data.length);\r
-\r
- // Go to next operation in queue\r
- self.next();\r
-\r
- // Break out of switch\r
- break;\r
- }\r
-\r
- if (self.debug)\r
- console.log('< Sending data. Block#: %d', block + 1);\r
-\r
- // Create the data packet for the next block of data\r
- var start = 512 * block;\r
- // End is `start + 512`, or end of data, whichever comes first\r
- var end = Math.min(start + 512, self.current.data.length);\r
- var data = self.current.data.slice(start, end);\r
-\r
- var packet = createData(block+1, data);\r
-\r
- // Send data block\r
- self.send(packet);\r
- break;\r
- // Error\r
- case types.err:\r
- // Create new Error(), and send callback\r
- var errorCode = msg.readUInt16BE(2);\r
- var errMsg = msg.toString('ascii', 4, msg.length - 1);\r
- // @TODO: Take errMsg from `errors`, unless code == 0?\r
- var err = new Error(errMsg);\r
- err.code = errorCode;\r
-\r
- if (self.debug)\r
- console.log('> Received Error. code: %d - msg: %s', errorCode, ErrMsg);\r
-\r
- // Callback\r
- self.current.callback(err);\r
-\r
- // Go to next operation in queue\r
- self.next();\r
- break;\r
- }\r
- }\r
-\r
- // Create socket, and listen to messages\r
- this.client = dgram.createSocket("udp4", onMessage);\r
-};\r
-\r
-/**\r
- * Shortcut for sending packet to server\r
- * @param {Buffer} buff The buffer to send\r
- * @param {Function} cb Callback - (err, bytes)\r
- */\r
-TFTP.prototype.send = function(buff, cb) {\r
- if (typeof cb !== 'function') cb = function() {};\r
-\r
- // We need this later\r
- var self = this;\r
- \r
- // Create function of sending this packet so that we can call it again on timeout\r
- var send = function() {\r
- self.client.send(buff, 0, buff.length, self.port, self.ip, cb);\r
- };\r
- // Send the packet already\r
- send();\r
-\r
- var onTimeout = function() {\r
- // If we have retransmitted less than MAX_RETRANSMITS\r
- if (MAX_RETRANSMITS > ++self.current.timeout.retransmits) {\r
-\r
- if (self.debug)\r
- console.log('! Timeout - Retransmitting (%d bytes)', buff.length);\r
-\r
- // Send the packet again\r
- send();\r
-\r
- // Set a new timeout for the packet we just sent\r
- self.current.timeout.id = setTimeout(onTimeout, TIMEOUT);\r
- }\r
-\r
- // If we sent too many retransmitts, the remote server did not respond...\r
- else {\r
- if (self.debug)\r
- console.log('! Timeout - End');\r
-\r
- // Create error\r
- var err = new Error("Timeout");\r
- err.code = 0;\r
-\r
- self.current.callback(err);\r
- // Reset current, and check queue - (no answer from server)\r
- self.next();\r
- }\r
- }\r
-\r
- // If there is a timeout, clear the timeout\r
- if (this.current.timeout)\r
- clearTimeout(this.current.timeout.id);\r
-\r
- // Create a timeout object where we store information about this timeout\r
- this.current.timeout = {\r
- id: setTimeout(onTimeout, TIMEOUT),\r
- retransmits: 0\r
- }\r
-};\r
-\r
-/**\r
- * Goes to next item in queue (if any). Same as `check()`, but clears current first\r
- */\r
-TFTP.prototype.next = function() {\r
- // Has to clear any timeout\r
- if (this.current && this.current.timeout)\r
- clearTimeout(this.current.timeout.id);\r
-\r
- // Reset current, and check queue\r
- this.current = false;\r
- this.check();\r
-};\r
-\r
-/**\r
- * Checks the Queue.\r
- * If no operation is currently active, go to the next item in the queue (if any).\r
- */\r
-TFTP.prototype.check = function() {\r
- // If there currently is an active operation\r
- // Or if the queue is empty, just return\r
- if (this.current !== false)\r
- return;\r
-\r
- // If there is nothing running, and the queue is empty\r
- if (this.queue.length == 0) {\r
- // Close client\r
- this.client.close();\r
- return;\r
- } else {\r
- // Create client\r
- this.createClient();\r
- }\r
-\r
- // Take the first item in queue\r
- this.current = this.queue.shift();\r
-\r
- // We need this later\r
- var self = this;\r
-\r
-\r
- if (self.debug)\r
- console.log('< Sending request');\r
-\r
- // Create the request...\r
- var buff = createRequest(this.current.type, this.current.filename);\r
- // Send the request\r
- this.send(buff, function(err, bytes) {\r
- // If there was an error sending the packet\r
- if (err) {\r
- // Create Error message\r
- var err = new Error(['Error when sending ',\r
- self.current.type,\r
- ' request for ',\r
- self.current.filename].join());\r
-\r
- // Send error to the callback of the current operation\r
- self.current.callback(err);\r
-\r
- // Reset current\r
- self.current = false;\r
-\r
- // Then check queue\r
- self.check();\r
- }\r
- });\r
-};\r
-\r
-/**\r
- * Sends a file to the server\r
- * @param {String} filename File to send\r
- * @param {Buffer} data The data to write/send to the server\r
- * @param {Function} cb Callback - (err)\r
- */\r
-TFTP.prototype.write = function(filename, data, cb) {\r
- if (typeof cb !== 'function') cb = function() {}; // Default cb to an empty function\r
- if (!Buffer.isBuffer(data)) data = new Buffer(data); // If data is not a Buffer, make it a buffer\r
-\r
- // Item to put into the queue\r
- var queueItem = {\r
- type: 'write',\r
- filename: filename,\r
- callback: cb,\r
- data: data,\r
- blocks: Math.ceil(data.length / 512) // Number of blocks to transfer data.\r
- // When we receive an ACK with this number, the transfer is finished\r
- };\r
-\r
- // Push the queueItem to the end of the queue.\r
- this.queue.push(queueItem);\r
-\r
- // Check the queue...\r
- this.check();\r
-};\r
-\r
-/**\r
- * Reads a file off the server\r
- * @param {String} filename File to read from server\r
- * @param {Function} cb Callback - (err, data)\r
- */\r
-TFTP.prototype.read = function(filename, cb) {\r
- if (typeof cb !== 'function') cb = function() {}; // Default cb to an empty function\r
-\r
- // Item to put into the queue\r
- var queueItem = {\r
- type: 'read',\r
- filename: filename,\r
- callback: cb,\r
- data: new Buffer(0) // Buffer of size 0 which will be filled up by onMessage\r
- };\r
-\r
- // Push the queueItem to the end of the queue.\r
- this.queue.push(queueItem);\r
-\r
- // Check the queue...\r
- this.check();\r
-};\r
-\r
-/**\r
- * Creates a buffer for a request.\r
-\r
- 2 bytes string 1 byte string 1 byte\r
- ------------------------------------------------\r
- | Opcode | Filename | 0 | Mode | 0 |\r
- ------------------------------------------------\r
-\r
- * @param {String|Number} type Int Opcode, or String (read|write|rrq|wrq)\r
- * @param {String} filename Filename to add in the request\r
- * @param {String} mode optional Mode (netascii|octet|email) - Defaults to octet\r
- * @return {Buffer} The Buffer\r
- */\r
-function createRequest(type, filename, mode) {\r
- // Figure out the opcode for the type\r
- if (typeof type === 'string') {\r
- type = type.toLowerCase();\r
-\r
- // If it exists in the types object, we found it\r
- if (types.hasOwnProperty(type))\r
- type = types[type];\r
- // If not, we dno what type\r
- else\r
- throw 'Unknown type (' + type + ')';\r
- }\r
- // Not a string, nor a number, then we dno what type of request it is...\r
- else if (typeof type !== 'number')\r
- throw 'Unknown type (' + type + ')';\r
-\r
- // Default mode to 'octet'\r
- mode = mode || 'octet';\r
-\r
- // Calculate the length of the buffer\r
- // mode (2 byte opcode) + length of filename + 1 null byte + length of mode + 1 null byte.\r
- var buffLen = 4 + filename.length + mode.length;\r
-\r
- // Create the buffer\r
- var buff = new Buffer(buffLen);\r
- // Write mode (as unsigned 16 bit integer) on offset 0\r
- buff.writeUInt16BE(type, 0);\r
- // Write filename as ascii on offset 2\r
- buff.write(filename, 2, 'ascii');\r
- // Write mode as ascii on offset filename.length + 3 (type + filename null termination)\r
- buff.write(mode, 2 + filename.length + 1, 'ascii');\r
-\r
- // Make sure the ends of the strings are null\r
- buff[2 + filename.length] = buff[buffLen - 1] = 0;\r
-\r
- // Return the new buffer\r
- return buff;\r
-}\r
-\r
-/**\r
- * Creates a buffer for a data packet\r
-\r
- 2 bytes 2 bytes n bytes\r
- ----------------------------------\r
- | Opcode | Block # | Data |\r
- ----------------------------------\r
-\r
- * @param {Number} blockNumber Which block of the transaction it is\r
- * @param {String} data The data to send\r
- * @return {Buffer} The Buffer\r
- */\r
-function createData(blockNumber, data) {\r
- var type = types['data'];\r
-\r
- // Type + blocknumber + length of data(max 512)\r
- var dataLen = Math.min(data.length, 512);\r
- var buffLen = 4 + dataLen;\r
-\r
- var buff = new Buffer(buffLen);\r
-\r
- buff.writeUInt16BE(type, 0); // Type as UInt16BE on offset: 0\r
- buff.writeUInt16BE(blockNumber, 2); // BlockNumber as UInt16BE on offset: 2\r
- // Copy `data` into buff on offset 4. bytes 0 to 512 from `data`.\r
- data.copy(buff, 4, 0, dataLen); // targetBuffer, targetStart, sourceStart, sourceEnd\r
-\r
- return buff;\r
-}\r
-\r
-/**\r
- * Creates a buffer for a ACK packet\r
-\r
- 2 bytes 2 bytes\r
- ---------------------\r
- | Opcode | Block # |\r
- ---------------------\r
-\r
- * @param {Number} blockNumber Which block to ack\r
- * @return {Buffer} The Buffer\r
- */\r
-function createAck(blockNumber) {\r
- var type = types['ack'];\r
-\r
- var buff = new Buffer(4);\r
- buff.writeUInt16BE(type, 0); // Type as UInt16BE on offset: 0\r
- buff.writeUInt16BE(blockNumber, 2); // BlockNumber as UInt16BE on offset: 2\r
-\r
- return buff;\r
-}\r
-\r
-/**\r
- * Creates a buffer for an ERROR packet\r
-\r
- 2 bytes 2 bytes string 1 byte\r
- -----------------------------------------\r
- | Opcode | ErrorCode | ErrMsg | 0 |\r
- -----------------------------------------\r
-\r
- * @param {Number} code ErrorCode\r
- * @param {String} msg Optional message - defaults to the message of the error code\r
- * @return {Buffer} The Buffer\r
- */\r
-function createError(code, msg) {\r
- // Default error message to the error message for the code (defined on top)\r
- msg = msg || errors[code];\r
- if (typeof msg !== 'string') msg = '';\r
-\r
- var type = types['error'];\r
-\r
- var buffLen = 4 + msg.length + 1;\r
-\r
- var buff = new Buffer(buffLen);\r
- buff.writeUInt16BE(type, 0); // Type as UInt16BE on offset: 0\r
- buff.writeUInt16BE(code, 2); // ErrorCode as UInt16BE on offset: 2\r
- buff.write(msg, 4, 'ascii'); // ErrMsg as ascii string on offset: 4\r
- buff[buffLen - 1] = 0; // Last byte is 0\r
-\r
- return buff;\r
-}\r