Class: Cakewalk::DCC::Outgoing::Send

Inherits:
Object
  • Object
show all
Defined in:
lib/cakewalk/dcc/outgoing/send.rb

Overview

DCC SEND is a protocol for transferring files, usually found in IRC. While the handshake, i.e. the details of the file transfer, are transferred over IRC, the actual file transfer happens directly between two clients. As such it doesn’t put stress on the IRC server.

Cakewalk allows sending files by either using User#dcc_send, which takes care of all parameters as well as setting up resume support, or by creating instances of this class directly. The latter will only be useful to people working on the Cakewalk code itself.

User#dcc_send expects an object to send as well as optionaly a file name, which is sent to the receiver as a suggestion where to save the file. If no file name is provided, the method will use the object’s #path method to determine it.

Any object that implements DCCableObject can be sent, but sending files will probably be the most common case.

If you’re behind a NAT it is necessary to explicitly set the external IP using the dcc.own_ip option.

Examples:

Sending a file to a user

match "send me something"
def execute(m)
  m.user.dcc_send(open("/tmp/cookies"))
end

Since:

  • 2.0.0

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ Send

Returns a new instance of Send.

Parameters:

  • opts (Hash) (defaults to: {})

Options Hash (opts):

Since:

  • 2.0.0



44
45
46
# File 'lib/cakewalk/dcc/outgoing/send.rb', line 44

def initialize(opts = {})
  @receiver, @filename, @io, @own_ip = opts.values_at(:receiver, :filename, :io, :own_ip)
end

Instance Method Details

#listen

Note:

This method blocks.

This method returns an undefined value.

Listen for an incoming connection.

This starts listening for an incoming connection to the server started by #start_server. After a client successfully connected, the server socket will be closed and the file transferred to the client.

Raises:

  • (Timeout::Error)

    Raised if the receiver did not connect within 30 seconds

Since:

  • 2.0.0



75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/cakewalk/dcc/outgoing/send.rb', line 75

def listen
  begin
    fd = nil
    Timeout.timeout(30) do
      fd, _ = @socket.accept
    end
    send_data(fd)
    fd.close
  ensure
    @socket.close
  end
end

#portFixnum

Returns The port used for the socket.

Returns:

  • (Fixnum)

    The port used for the socket

Since:

  • 2.0.0



98
99
100
# File 'lib/cakewalk/dcc/outgoing/send.rb', line 98

def port
  @port ||= @socket.addr[1]
end

#seek(pos)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Seek to pos in the data.

Parameters:

  • pos (Integer)

Since:

  • 2.0.0



93
94
95
# File 'lib/cakewalk/dcc/outgoing/send.rb', line 93

def seek(pos)
  @io.seek(pos)
end

#send_handshake

This method returns an undefined value.

Send the handshake to the user.

Since:

  • 2.0.0



59
60
61
62
# File 'lib/cakewalk/dcc/outgoing/send.rb', line 59

def send_handshake
  handshake = "\001DCC SEND %s %d %d %d\001" % [@filename, IPAddr.new(@own_ip).to_i, port, @io.size]
  @receiver.send(handshake)
end

#start_server

This method returns an undefined value.

Start the server

Since:

  • 2.0.0



51
52
53
54
# File 'lib/cakewalk/dcc/outgoing/send.rb', line 51

def start_server
  @socket = TCPServer.new(0)
  @socket.listen(1)
end