-- }}}
-- private functions {{{
+-- debug_dcc {{{
+--
+-- Prints a debug message about DCC events similar to irc.debug.warn, etc.
+-- @param msg Debug message
+local function debug_dcc(msg)
+ irc_debug._message("DCC", msg, "\027[0;32m")
+end
+-- }}}
+
-- send_file {{{
--
-- Sends a file to a remote user, after that user has accepted our DCC SEND
bytes = bytes + packet:len()
local index = 1
while true do
+ local skip = false
sock:send(packet, index)
- local new_bytes = misc._int_to_str(sock:receive(4))
- if new_bytes ~= bytes then
- index = packet_size - bytes + new_bytes + 1
+ local new_bytes, err = sock:receive(4)
+ if not new_bytes then
+ if err == "timeout" then
+ skip = true
+ else
+ irc_debug._warn(err)
+ break
+ end
else
- break
+ new_bytes = misc._int_to_str(new_bytes)
+ end
+ if not skip then
+ if new_bytes ~= bytes then
+ index = packet_size - bytes + new_bytes + 1
+ else
+ break
+ end
end
end
coroutine.yield(true)
end
+ debug_dcc("File completely sent")
file:close()
sock:close()
irc._unregister_socket(sock, 'w')
-- @param file Lua file object corresponding to the file we want to send
-- @param packet_size Size of the packets to send the file in
local function handle_connect(ssock, file, packet_size)
+ debug_dcc("Offer accepted, beginning to send")
packet_size = packet_size or 1024
local sock = ssock:accept()
sock:settimeout(0.1)
ssock:close()
irc._unregister_socket(ssock, 'r')
irc._register_socket(sock, 'w',
- coroutine.wrap(function(sock)
- return send_file(sock, file, packet_size)
+ coroutine.wrap(function(s)
+ return send_file(s, file, packet_size)
end))
return true
end
file:write(packet)
coroutine.yield(true)
end
+ debug_dcc("File completely received")
file:close()
sock:close()
irc._unregister_socket(sock, 'r')
-- Accepts a file offer from a remote user. Called when the on_dcc callback
-- retuns true.
-- @param filename Name to save the file as
--- @param address IP address of the remote user
+-- @param address IP address of the remote user in low level int form
-- @param port Port to connect to at the remote user
-- @param packet_size Size of the packets the remote user will be sending
function _accept(filename, address, port, packet_size)
+ debug_dcc("Accepting a DCC SEND request from " ..
+ misc._ip_int_to_str(address) .. ":" .. port)
packet_size = packet_size or 1024
local sock = base.assert(socket.tcp())
base.assert(sock:connect(misc._ip_int_to_str(address), port))
sock:settimeout(0.1)
local file = base.assert(io.open(misc._get_unique_filename(filename), "w"))
irc._register_socket(sock, 'r',
- coroutine.wrap(function(sock)
- return accept_file(sock, file, packet_size)
+ coroutine.wrap(function(s)
+ return accept_file(s, file, packet_size)
end))
end
-- }}}
-- above)
function send(nick, filename, port)
port = port or FIRST_PORT
- local sock = base.assert(socket.tcp())
+ local sock
repeat
+ sock = base.assert(socket.tcp())
err, msg = sock:bind('*', port)
port = port + 1
until msg ~= "address already in use" and port <= LAST_PORT + 1
local size = file:seek("end")
file:seek("set")
irc._register_socket(sock, 'r',
- coroutine.wrap(function(sock)
- return handle_connect(sock, file)
+ coroutine.wrap(function(s)
+ return handle_connect(s, file)
end))
filename = misc._basename(filename)
if filename:find(" ") then filename = '"' .. filename .. '"' end
+ debug_dcc("Offering " .. filename .. " to " .. nick .. " from " ..
+ irc.get_ip() .. ":" .. port - 1)
irc.send("PRIVMSG", nick, c("DCC", "SEND", filename, ip, port - 1, size))
end
-- }}}