Перейти к публикации
Форум - ComputerCraft
swg2you

TSR mail или элементарная почта с пересылкой файлов

Рекомендованные сообщения

Модуль отправки: send.lua

print('Use: send [<receiver-address>] < <filename> - for send filename,\nor: send [<receiver-address>] - for write, and Ctrl+C to send.')
local port = 9
local c = require("component")
local m = c.proxy(c.list("modem")())
local s, addr = io.read("*a"), ...
if #s>0 then
  if addr then m.send(addr, port, s)
  else m.broadcast(port, s) end
  print('Sended: '..#s..' bytes')
end

и резидентный модуль приема: tsrmail.lua

local port = 9
if _tsrmail then
  print('tsrmail already loaded @ port '.._tsrmail)
else
  local beep=0
  local c = require("component")
  local cp = require("computer")
  local fs = require("filesystem")
  local m=c.proxy(c.list("modem")())
  local pullSignal = cp.pullSignal
  cp.pullSignal = function (...)
    local e={pullSignal(...)}
    if e[1]=='modem_message' then 
      local h = fs.open('@','a')	
      h:write('--'..os.date()..' From:'..e[3]..'\n'..table.concat({table.unpack(e,6)},'\n'))
      h:close()
      beep=1
    elseif e[1]=='key_down' then
      beep=0
    elseif beep>0 then 
      cp.beep(440) 
    end
    beep=-beep
    return table.unpack(e)
  end
  m.open(port)
  print('tsrmail loaded @ port '..port)
  _G._tsrmail=port
end

сохранить на диск.

tsrmail.lua - запустить, после чего она останется резидентным модулем в памяти, и слушая 9-й порт, будет складывать всю почту в файл "@" на диске.

 

Пример использования:

 

У пользователя Коли, и еще у кого-то, есть компьютер с сетевой картой, на котором работает резидентная tsrmail.lua.

 

Программист Вася только что, получил на дискетке копию "TSR mail", запустил  tsrmail.lua, чтобы иметь возможность принимать почту, и ему не терпится заявить о себе всему миру. Он запускает send, читает две строчки справки, пишет пару строк сообщения (хеловорд конечно, что же еще может написать программист) и нажав Ctrl+C отправляет.

h_1435093437_1413607_8e11bbb269.png

 

Но пользователь Коля, как и другие пользователи "TSR mail" заняты своими делами: кормят коров, сажают желтые цветы и воюют с криперами. Хоть Колин компьютер и пищит "хозяин! почта пришла!", Коля далеко и не слышит.

 

Программисту Васе не терпится пообщаться, он хочет чтобы ему тоже прислали что-то. Хоть простенький хелловорд.

 

Немного поразмыслив, Вася соображает, что хелловорд это самодостаточная штука, и вовсе не располагает к ответам и общению. Заметив в первой строчке образец перенаправления ввода/вывода (а наш Вася программист, и знает всю мощь этого шаманства) он вновь запускает send отправляет сообщение и, поскольку под рукой больше ничего не нашлось, отправляет в сеть программку send.lua, направив содержимое send.lua во входной поток самой себя.

h_1435093438_2556843_da3e02baed.png

 

Пользователь Коля, проходив мимо компьютера, услышал писк и подошел проверить почту. Посмотрев стандартной командой cat @ содержимое файла @, с тремя сообщениями Васи, и пробурчав под нос, - Опять эти программеры фигней страдают, лучше бы коров покормили! - удалил сообщения командой rm @

h_1435093438_8163746_5ffb3896af.png

 

Если бы наш программист догадался прислать что-то поинтереснее, например новую версию пасьянса, то Коля может и сохранил бы его, переименовав mv @ pasians2.lua, и почистив edit pasians2.lua от лишних сообщений.

 

Но к сожалению, это был не пасьянс.

--==--

P.S.

Код quick and dirty, но зато simple and short. По хорошему, нужна обертка-интерфейc для send, которая будет хранить адресную книгу, дополняя адресатов из @, большие файлы пересылать порциями обходя ограничение на размер пакета, красиво показывать @ добавляя функции ответа и сохранения, ну и все такое. А в резидентный модуль неплохо бы добавить отклик "принял".

Изменено пользователем swg2you
  • Like 3

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Гоу к нам в Opennet http://computercraft.ru/topic/675-opennetoc-prodolzhenie/

Если объеденяться, то твоя программа может сразу появляться у пользователя, а нам пригодятся твои идеи и реализации сетевых алгоритмов. У нас уже и адресная книга aka DNS есть, и пересылка порциями.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

 

 

и резидентный модуль приема: tsrmail.lua

Так где здесь  пересылка файлов? Эта штука абсолютно весь пойманный эфир (возможно не только 9-й порт) будет сыпать в один файл. И зачем переопределять функцию pullSignal если можно повесить слушателя на событие?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Так где здесь  пересылка файлов? Эта штука абсолютно весь пойманный эфир (возможно не только 9-й порт) будет сыпать в один файл. И зачем переопределять функцию pullSignal если можно повесить слушателя на событие?

Как ты верно подметил, если переименовать tsrmail обратно в tsrsniffer, то мы получим сетевой сниффер, который будет фоном перехватывать все! входящие пакеты на всех! портах и складывать их в файлик. )

 

Более того, если удалить "=='modem_message'", то мы получим сниффер для всех событий.

 

upd:

моя не уметь на событие, моя уметь подменять pullSignal

Изменено пользователем swg2you

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Через event.listen swg2you можешь повесить слушателя на modem_message. Вот если не знаешь его использование:

 

 

event.listen(event: string, function: function) -- Теперь если он словит event который указан в первом аргументе будет выполнена функция со второго аргумента. Аргументы функции нужно передавать такие же, какие выдаст event.pull, т е шесть аргументов.

Например:

local function listmsg(_,_,_,_,_,msg)
    print(msg)
end
event.listen("modem_message", listmsg)
Такой код будет ловить сообщения по всем открытым портам и выводить их на экран.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Через event.listen swg2you можешь повесить слушателя на modem_message. Вот если не знаешь его использование:

 

 

event.listen(event: string, function: function) -- Теперь если он словит event который указан в первом аргументе будет выполнена функция со второго аргумента. Аргументы функции нужно передавать такие же, какие выдаст event.pull, т е шесть аргументов.

Например:

local function listmsg(_,_,_,_,_,msg)
    print(msg)
end
event.listen("modem_message", listmsg)
Такой код будет ловить сообщения по всем открытым портам и выводить их на экран.

 

Уоу, круто! 

А как это запустить чтоб оно работало в фоне?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Через event.listen swg2you можешь повесить слушателя на modem_message. Вот если не знаешь его использование:

 

 

event.listen(event: string, function: function) -- Теперь если он словит event который указан в первом аргументе будет выполнена функция со второго аргумента. Аргументы функции нужно передавать такие же, какие выдаст event.pull, т е шесть аргументов.

Например:

local function listmsg(_,_,_,_,_,msg)
    print(msg)
end
event.listen("modem_message", listmsg)
Такой код будет ловить сообщения по всем открытым портам и выводить их на экран.

 

Только их там не 6. Если ты напишешь m.broadcast(port, data1)---их будет шесть,а если ты напишешь m.broadcast(port, data1, data2)---их будет 7, и так далее

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Гоу к нам в Opennet http://computercraft.ru/topic/675-opennetoc-prodolzhenie/

Если объеденяться, то твоя программа может сразу появляться у пользователя, а нам пригодятся твои идеи и реализации сетевых алгоритмов. У нас уже и адресная книга aka DNS есть, и пересылка порциями.

Я смотрел, но OpenNet пока слишком сложна для моего понимания. Не вижу общей концепции.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Уоу, круто! 

А как это запустить чтоб оно работало в фоне?

Листен всё держит в условном фоне

Ты просто заменяешь event.pull на event.listen(event, function) и всё

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Только их там не 6. Если ты напишешь m.broadcast(port, data1)---их будет шесть,а если ты напишешь m.broadcast(port, data1, data2)---их будет 7, и так далее

Это мелочи, мы всегда можем написать

local function listmsg(...)
  print(...)
end
event.listen("modem_message", listmsg)
Главное суметь заставить работать это в фоне. Ждем LeshaInc, чтоб объяснил как это сделать.

 

Листен всё держит в условном фоне

Ты просто заменяешь event.pull на event.listen(event, function) и всё

т.е. этот код выполнится, оставит слушателя работать, а я смогу тем временем запускать другие программы? Изменено пользователем swg2you

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Покажу на примере как можно в фоне читать сеть.

local event = require("event")local m     = require("component").modemm.open(512)function listener(_,_,_,_,_,msg)    print(msg)endevent.listen ("modem_message",listener)

После запуска данного кода в фоне появится некий сниффер, который будет слушать 512 порт и писать все сообщения. Всё будет работать в фоне и ты сможешь, например, запускать любые другие программы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Это мелочи, мы всегда можем написать

local function listmsg(...)
  print(...)
end
event.listen("modem_message", listmsg)
Главное суметь заставить работать это в фоне. Ждем LeshaInc, чтоб объяснил как это сделать.

 

т.е. этот код выполнится, оставит слушателя работать, а я смогу тем временем запускать другие программы?

 

listen слушает "эфир" и выполняет данную функцию при возникновения события данного, опять же. Листенер со всем его содержимым хранятся отдельно от запускаемой программы, и события обрабатываются в фоне. Для удаления листенера необходимо в той же программе вызывать event.ignore(event, func), иначе события будут продолжать обрабатываться даже после завершения программы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

после выполнения этого кода ты сможешь например запускать любые другие программы.

Круто, а как сделать чтобы он не на экран выводил а в файл?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Круто, а как сделать чтобы он не на экран выводил а в файл?

Заменить "print(msg)" в моём коде на запись в файл и все.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Заменить "print(msg)" в моём коде на запись в файл и все.

Как именно? Пример будет? Ждем. Изменено пользователем swg2you

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Как именно? Пример будет? Ждем.

event=require"event"

function listmsg(eventName, receiverAddress, senderAddress, port, distance, ...)
      local h = fs.open('@','a')	
      h:write('--'..os.date()..' From:'..senderAddress..'\n'..table.concat({...},'\n'))
      h:close()
end

event.listen("modem_message", listmsg)

Как то так. Можно еще порт и дистанцию прилепить

Изменено пользователем Zer0Galaxy

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
event=require"event"

function listmsg(eventName, receiverAddress, senderAddress, port, distance, ...)
      local h = fs.open('@','a')	
      h:write('--'..os.date()..' From:'..senderAddress..'\n'..table.concat({...},'\n'))
      h:close()
end

event.listen("modem_message", listmsg)

Как то так. Можно еще порт и дистанцию прилепить

 

лучше io используй.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Как именно? Пример будет? Ждем.

Достаточно написать функцию-обработчик, типа этого:

 

if _tsrmail then
  print('TSR Mail is already running!')
  return
end
local cp=require'computer'
local com=require'component'
local m=com.modem
local port=9
m.open(port)
function onModemMessageOrKey(eventName, receiverAddr, sender, port, distance, msg)
  if eventName=='modem_message' then
    local h = io.open('/@','a')    
    h:write('--'..os.date()..' From:'..sender..'\n'..table.concat({table.unpack(msg)},'\n'))
    h:close()
    beep=1
  elseif eventName=='key_down' then
    beep=0
  elseif beep>0 then
    cp.beep(440)
  end
  beep=-beep
end

event.listen('modem_message',onModemMessageOrKey)
event.listen('key_down',onModemMessageOrKey)

print('TSR Mail has started!')
_G._tsrmail=port

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

 

event=require"event"

function listmsg(eventName, receiverAddress, senderAddress, port, distance, ...)
      local h = fs.open('@','a')	
      h:write('--'..os.date()..' From:'..senderAddress..'\n'..table.concat({...},'\n'))
      h:close()
end

event.listen("modem_message", listmsg)
Как то так. Можно еще порт и дистанцию прилепить

 

А как сделать, чтобы эта штука сигнализировала пользователю о том, что новое сообщение получено и записано в файл?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Достаточно написать функцию-обработчик, типа этого:

Ох ты, набежали тут, примеров накидали ) я вообще-то с LeshaInc разговаривал ))

 

Ну ладно, попробуйте event.listen повесить без OpenOS, и на этом закроем тему.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

А как сделать, чтобы эта штука сигнализировала пользователю о том, что новое сообщение получено и записано в файл?

После h:close можно написать computer.beep.

Ох ты, набежали тут, примеров накидали ) я вообще-то с LeshaInc разговаривал ))Ну ладно, попробуйте event.listen повесить без OpenOS, и на этом закроем тему.

Тут либо делать поток thread, либо через подмену, либо посмотрев реализацию event.listen.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

После h:close можно написать computer.beep.

Не вариант. Одиночный бип я могу и не услышать. Нужно чтобы хотя-бы раз в пару секунд бипать начал.

Тут либо делать поток thread, либо через подмену, либо посмотрев реализацию event.listen.

Как вариант, внутри обработчика входящих от модема можно повесить новый обработчик по таймеру

local beep=event.timer(1, function() computer.beep(440) end, math.huge)

а снаружи, добавить еще один, который будет слушать клавиатуру и по нажатию на клавишу делать

if beep then event.cancel(beep) end

 

upd:

Итак, совместные усилия превратились в код нового, хорошего и правильного tsrmail.lua

local port = 9

if _tsrmail then
  io.write('tsrmail already loaded @ port ',_tsrmail)
else
  local beep, cp, ev = false, require("computer"), require("event")
  require("component").modem.open(port)

  local function listener(...)
    local e={...}
    if e[4] == port then
      local h = io.open('@','a')	
      h:write('--', os.date(), ' from:', e[3], ' port:', e[4], '\n')
      h:write(table.concat(e,'\n',6))
      h:close()	
      if not beep then 
        beep=ev.timer(2, function() cp.beep(440) end, math.huge)
      end 
    end
  end

  local function unbeep()
    if beep then 
      ev.cancel(beep)
      beep=false 
    end
  end

  ev.listen("key_down", unbeep)
  ev.listen("modem_message", listener)

  io.write('tsrmail loaded @ port ', port)
  _G._tsrmail=port
end

Спасибо всем оппонентам, кто высказывался по делу:

Zer0Galaxy за, -можно повесить слушателя на событие

LeshaInc за, -покажу на примере

Fingercomp за, -события будут продолжать обрабатываться даже после завершения программы

Zer0Galaxy за, -можно еще порт и дистанцию прилепить

NEO за, -лучше io используй

И всем остальным за общее комментирование и множественные примеры.

Изменено пользователем swg2you

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас

×