Created
June 2, 2012 17:53
-
-
Save Kami/2859346 to your computer and use it in GitHub Desktop.
luvit traceroute exec
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local Emitter = require('core').Emitter | |
local Error = require('core').Error | |
local table = require('table') | |
local childprocess = require('childprocess') | |
function split(str, pattern) | |
pattern = pattern or '[^%s]+' | |
if pattern:len() == 0 then pattern = '[^%s]+' end | |
local parts = {__index = table.insert} | |
setmetatable(parts, parts) | |
str:gsub(pattern, parts) | |
setmetatable(parts, nil) | |
parts.__index = nil | |
return parts | |
end | |
-- TODO: Move LineEmitter and split into utils or smth | |
local LineEmitter = Emitter:extend() | |
function LineEmitter:initialize(initialBuffer) | |
self._buffer = initialBuffer or '' | |
end | |
function LineEmitter:feed(chunk) | |
local line | |
self._buffer = self._buffer .. chunk | |
line = self:_popLine() | |
while line do | |
self:emit('line', line) | |
line = self:_popLine() | |
end | |
end | |
function LineEmitter:_popLine() | |
local line = false | |
local index = self._buffer:find('\n') | |
if index then | |
line = self._buffer:sub(0, index - 1) | |
self._buffer = self._buffer:sub(index + 1) | |
end | |
return line | |
end | |
local Traceroute = Emitter:extend() | |
function Traceroute:initialize(target, options) | |
self._target = target | |
self._options = options or {} | |
self._resolveIps = self._options['resolveIps'] or false | |
end | |
-- Return an EventEmitter instance which emits 'hop' events for every hop | |
function Traceroute:traceroute() | |
local emitter = self:_run(self._target) | |
emitter:on('end', function() | |
self:emit('end') | |
end) | |
emitter:on('hop', function(hop) | |
self:emit('hop', hop) | |
end) | |
emitter:on('error', function(err) | |
self:emit('error', err) | |
end) | |
end | |
function Traceroute:_run(target) | |
local args = {target} | |
if not self._resolveIps then | |
table.insert(args, '-n') | |
end | |
local child = childprocess.spawn('traceroute', args) | |
local lineEmitter = LineEmitter:new() | |
local emitter = Emitter:new() | |
local stderrBuffer = '' | |
lineEmitter:on('line', function(line) | |
local hop = self:_parseLine(line) | |
if hop then | |
emitter:emit('hop', hop) | |
end | |
end) | |
child.stdout:on('data', function(chunk) | |
lineEmitter:feed(chunk) | |
end) | |
child.stderr:on('data', function(chunk) | |
stderrBuffer = stderrBuffer .. chunk | |
end) | |
child:on('exit', function(code) | |
local err | |
if code == 0 then | |
emitter:emit('end') | |
else | |
err = Error:new('Error: ' .. stderrBuffer) | |
emitter:emit('error', err) | |
end | |
end) | |
return emitter | |
end | |
function Traceroute:_parseLine(line) | |
local result = {}, host, ip, hopsIndex | |
-- Skip first line | |
if line:find('traceroute to') then | |
return | |
end | |
local split = split(line, '[^%s]+') | |
if self._resolveIps then | |
hopsIndex = 4 | |
result['host'] = split[2] | |
result['ip'] = split[3]:gsub('%(', ''):gsub('%)', '') | |
else | |
hopsIndex = 3 | |
result['ip'] = split[2]:gsub('%(', ''):gsub('%)', '') | |
end | |
result['rtts'] = {} | |
for i=hopsIndex, #split, 1 do | |
value = split[i] | |
if not value:find('ms') then | |
if value == '*' then | |
value = nil | |
else | |
value = tonumber(value) | |
end | |
table.insert(result['rtts'], value) | |
end | |
end | |
return result | |
end | |
local utils = require('utils') | |
local tr = Traceroute:new('www.arnes.si') | |
tr:on('hop', function(hop) | |
print('hop') | |
print(utils.dump(hop)) | |
end) | |
tr:on('end', function(hop) | |
print('end') | |
end) | |
tr:on('error', function(err) | |
print('error: ' .. err.message) | |
end) | |
tr:traceroute() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment