class QuartzTorrent::ExtendedMetaInfo
An Extended
Metainfo
message. Used to request metadata pieces, or provide responses to those requests.
Attributes
data[RW]
This field is only set if the msgType is :piece. It contains the data for the piece.
dict[RW]
msgType[RW]
Message type as a symbol. One of :request, :data, or :reject
piece[RW]
totalSize[RW]
This field is only set if the msgType is :piece
Public Class Methods
new()
click to toggle source
Calls superclass method
QuartzTorrent::Extended::new
# File lib/quartz_torrent/peermsg.rb, line 407 def initialize super() @extendedMessageId = 0 @msgType = nil @piece = nil @totalSize = nil @data = nil @dict = {} end
Public Instance Methods
serializeTo(io)
click to toggle source
Calls superclass method
QuartzTorrent::Extended#serializeTo
# File lib/quartz_torrent/peermsg.rb, line 470 def serializeTo(io) super(io) updateDictFromProps io.write @dict.bencode raise "Extended metainfo piece messages must have piece data. This one's data was nil" if ! @data && dict['msg_type'] == 1 io.write @data if dict['msg_type'] == 1 end
unserialize(payload)
click to toggle source
Calls superclass method
QuartzTorrent::Extended#unserialize
# File lib/quartz_torrent/peermsg.rb, line 426 def unserialize(payload) # Unserialize extended message id super(payload) # Rest of the message is a bencoded dictionary. # Piece messages of this class are encoded in an interesting way: the bencoded dictionary # is concatenated with the arbitrary binary data of the piece at the end. To decode this # we need to know the position of when we've finished reading the dictionary. We do this by # using a Parser object from the bencode library which maintains a stream object which happens # to know the current offset of the parsing. payload = payload[1,payload.length] parser = BEncode::Parser.new payload begin @dict = parser.parse! rescue e = RuntimeError.new("Error bdecoding payload '#{payload}' (payload length = #{payload.length})") e.set_backtrace($!.backtrace) raise e end @msgType = @dict['msg_type'] raise "Extended Metainfo message contained no 'msg_type' key." if ! @msgType if @msgType == 0 @msgType = :request elsif @msgType == 1 @msgType = :piece elsif @msgType == 2 @msgType = :reject else raise "Unknown message type '#{@msgType}' in Extended Metainfo message" end @piece = @dict['piece'] raise "Extended Metainfo message contained no 'piece' key." if ! @piece @totalSize = @dict['total_size'] if @msgType == :piece # If this is a piece message, read the data after the dictionary. @data = parser.stream.read if @msgType == :piece end
Private Instance Methods
extendedMsgPayloadLength()
click to toggle source
# File lib/quartz_torrent/peermsg.rb, line 479 def extendedMsgPayloadLength updateDictFromProps len = @dict.bencode.length len += @data.length if dict['msg_type'] == 1 len end
msgTypeSymToVal(sym)
click to toggle source
# File lib/quartz_torrent/peermsg.rb, line 492 def msgTypeSymToVal(sym) if sym == :request 0 elsif sym == :piece 1 elsif sym == :reject 2 else raise "Unknown msg type #{sym}" end end
updateDictFromProps()
click to toggle source
# File lib/quartz_torrent/peermsg.rb, line 486 def updateDictFromProps @dict['msg_type'] = msgTypeSymToVal(@msgType) if ! @dict.has_key?('msg_type') && @msgType @dict['piece'] = @piece if ! @dict.has_key?('piece') @dict['total_size'] = @data.length if @data end