[Aversa-commits] aversa/lib/aversa track.rb

teamikl at rubyforge.org teamikl at rubyforge.org
Tue Sep 28 21:02:58 EDT 2004


Update of /var/cvs/aversa/aversa/lib/aversa
In directory rubyforge.org:/tmp/cvs-serv27871/lib/aversa

Modified Files:
	track.rb 
Log Message:
Added/Fixed some checking input data were missing in AnnounceHandler.


Index: track.rb
===================================================================
RCS file: /var/cvs/aversa/aversa/lib/aversa/track.rb,v
retrieving revision 1.12
retrieving revision 1.13
diff -C2 -d -r1.12 -r1.13
*** track.rb	28 Sep 2004 03:36:17 -0000	1.12
--- track.rb	29 Sep 2004 01:02:56 -0000	1.13
***************
*** 35,38 ****
--- 35,39 ----
  require 'pstore'
  require 'thread'
+ require 'ipaddr'
  
  require 'net/bittorrent/bencoding'
***************
*** 65,71 ****
  
    class BTTrackerServlet < WEBrick::HTTPServlet::AbstractServlet
!     def do_GET(req, res)
!       res.body = encode(res.body)
        res['Content-length'] = res.body.length
      end
    end
--- 66,87 ----
  
    class BTTrackerServlet < WEBrick::HTTPServlet::AbstractServlet
!     ##
!     # === Param
!     # - req ... Request
!     # - res ... Response
!     # - ret ... Return Value, which will be bencoded response body.
!     #
!     # === NOTES
!     # 
!     # - TODO I may need to return 400 Bad request error sometime.
!     #        Body is not only bencoded data.
!     #
!     def do_GET(req, res, ret)
!       res.body = encode(ret)
        res['Content-length'] = res.body.length
+       res['Content-Type'] = 'text/plain'
+       res['Connection'] = 'close'
+       res['Pragma'] = 'no-cache'
+       res['Server'] = SERVER_NAME
      end
    end
***************
*** 73,77 ****
    class AnnounceHandler < BTTrackerServlet
      #
!     # Announce Request sample
      # 
      #   info_hash=R%5B%8CwD3%27%F9%12%948%EF%E3%D1%F8%BF%B3%C3H%07
--- 89,93 ----
    class AnnounceHandler < BTTrackerServlet
      #
!     # === Announce Request sample query data
      # 
      #   info_hash=R%5B%8CwD3%27%F9%12%948%EF%E3%D1%F8%BF%B3%C3H%07
***************
*** 85,88 ****
--- 101,133 ----
      #   event= started | stopped
      #   numwant
+     #
+     #
+     # === Announce Response 
+     #
+     # success:
+     #   ret['interval'] = integer
+     #   ret['peers'] = array of peer hashes, or string(when compact=1)
+     #
+     # failure:
+     #   ret['failure reason'] = string
+     #
+     #
+     # === Data
+     #
+     # - db ... dstate data (pstore)
+     # 
+     #   db['completed'][info_hash] = integer (numbers of complated download)
+     #   db['peers'][peer_id] = { 'peer id' => }
+     # 
+     # - @@cache[info_hash] = hashes of peers
+     #
+     # - @@times[info_hash][peer_id] = Time object
+     #
+ 
+     # :stopdoc:
+     # XXX Thise should be global in file or application's instance variable.
+     @@cache = Hash.new
+     @@times = Hash.new
+     # :startdoc:
   
      ##
***************
*** 93,111 ****
      # - TODO There are 'failure reason' and 'warning message' for error/warm,
      #        Make sure the manner which should I use, for the case.
      # 
      def do_GET(req, res)
  
        query_data = req.query
  
!       # TODO check input values. (How to use Taint mode)
!       # TODO how to catch errror, and what error message return
!       unless query_data.has_key? 'downloaded' or
!              query_data.has_key? 'uploaded' or
!              query_data.has_key? 'left' or
!              query_data.has_key? 'info_hash' or
!              query_data.has_key? 'peer_id' or
!              query_data.has_key? 'event' or
!              query_data.has_key? 'port'
               
          raise TrackerFailure, 'Bad request'
        end
--- 138,161 ----
      # - TODO There are 'failure reason' and 'warning message' for error/warm,
      #        Make sure the manner which should I use, for the case.
+     # - TODO make class for dstate data
+     # = TODO check input values. (How to use Taint mode and safe level)
      # 
      def do_GET(req, res)
  
+       ret = Hash.new
+       ret['interval'] = REREQUEST_INTERVAL
+ 
        query_data = req.query
  
!       unless query_data.has_key? 'downloaded' and
!              query_data.has_key? 'uploaded' and
!              query_data.has_key? 'left' and
!              query_data.has_key? 'info_hash' and
!              query_data.has_key? 'peer_id' and
!              query_data.has_key? 'event' and
!              query_data.has_key? 'port' and
!              query_data.has_key? 'key'
               
+         # TODO Response should be 400 Bad request.
          raise TrackerFailure, 'Bad request'
        end
***************
*** 119,127 ****
        end
  
!       unless query_data['peer_id'].length == 8
          raise TrackerFailure, 'Bad length of peer id'
        end
  
!       # Expect GC early collects the query hash and request object, -> .dup
        downloaded  = query_data['downloaded'].to_i
        uploaded    = query_data['uploaded'].to_i
--- 169,180 ----
        end
  
!       unless query_data['peer_id'].length == 20
          raise TrackerFailure, 'Bad length of peer id'
        end
  
!       unless query_data['key'].length == 8
!         raise TrackerFailure, 'Bad length of key'
!       end
! 
        downloaded  = query_data['downloaded'].to_i
        uploaded    = query_data['uploaded'].to_i
***************
*** 131,178 ****
        event       = query_data['event'].dup
        port        = query_data['port'].to_i
        ip          = (query_data.has_key? 'ip')  ? query_data['ip'].dup \
                                                  : req.peeraddr.last.dup
        
!       # peer = { 'ip' => ip, 'port' => port.to_i, 'peer id' => peer_id }
!       peer = Hash.new
!       peer['ip'] = ip
!       peer['port'] = port.to_i
!       peer['peer id'] = peer_id
!       
!       # Set return value
!       ret = Hash.new
!       ret['peers'] = Array.new
!       ret['interval'] = REREQUEST_INTERVAL
        
-       # Read/Write dstate data
-       # TODO cache
-       # TODO make class for dstate data
        db = PStore.new(DSTATE_FILE)
        db.transaction do
!         db['completed'][info_hash] ||= 0
!         db['peers'][info_hash]     ||= {}
          db['peers'][info_hash][peer_id] = peer
  
!         # Event (started|stopped|completed)
!         case event
          when 'started'
!           if db['peers'].has_key? info_hash
!             ret['peers'] = db['peers'][info_hash].values.dup
!           end
          when 'completed'
!           raise NotImplementedError
          when 'stopped'
            raise NotImplementedError
          else
            raise "Not come here"
          end
!         
!       end # of db.transaction.
  
      rescue NotImplementedError 
!       ret = { 'failure reason' => 'This feature was not implemented, yet' }
      
!     rescue TrackerFailure => e
!       ret = { 'failure reason' => e.reason }
  
      ## Don't catch while debug.
--- 184,255 ----
        event       = query_data['event'].dup
        port        = query_data['port'].to_i
+       key         = query_data['key'].dup
        ip          = (query_data.has_key? 'ip')  ? query_data['ip'].dup \
                                                  : req.peeraddr.last.dup
+       # override ip should be option.
        
!       begin
!         unless IPAddr.new(ip).ipv4?
!           raise TrackerFailure, 'This tracker can accept IPv4 address only.'
!         end
!       rescue ArgumentError
!         raise TrackerFailure, 'Invalid IP address'
!       end
! 
!       peer = {
!         'ip'   => ip,
!         'key'  => key,
!         'nat'  => 0,
!         'port' => port.to_i,
!         'left' => left.to_i,
!       }
        
        db = PStore.new(DSTATE_FILE)
        db.transaction do
! 
!         db['peers'][info_hash] ||= {}
!         
!         #if db['peers'][info_hash].has_key? peer_id and
!         #   db['peers'][info_hash][peer_id].has_key 'key'
!         #  unless db['peers'][info_hash][peer_id]['key'] == key
!         #    raise TrackerFailure, 'key did not match'  
!         #  end
!         #end
! 
!         @@times[peer_id] = Time.now
!         @@cache[info_hash] ||= {}
!         @@cache[info_hash][peer_id] = { 'ip' => ip,
!                                        'port' => port.to_i,
!                                        'peer_id' => peer_id }
          db['peers'][info_hash][peer_id] = peer
  
!         p "-" * 50
!         p @@cache
! 
!         case event 
          when 'started'
!           ret['peers'] = @@cache[info_hash].values.dup
!           
          when 'completed'
!           db['completed'][info_hash] ||= 0
!           db['completed'][info_hash] += 1
!           
          when 'stopped'
            raise NotImplementedError
+           
          else
            raise "Not come here"
          end
!       end
! 
! 
!     rescue RuntimeError => e
!       ret['failure reason'] = e.to_s
  
      rescue NotImplementedError 
!       ret['failure reason'] = 'This feature was not implemented, yet'
      
!     rescue TrackerFailure => failure
!       ret['failure reason'] = failure.reason
  
      ## Don't catch while debug.
***************
*** 182,193 ****
  
      ensure
!       res['Server'] = SERVER_NAME
!       res['Connection'] = 'close'
!       res['Content-Type'] = 'text/plain'
!       res.body = ret
!     
!       # Call super for Encode res.body and Set Content-length field.
!       super(req, res)
      end
    end
  
--- 259,265 ----
  
      ensure
!       super(req, res, ret)
      end
+ 
    end
  
***************
*** 335,346 ****
        end
  
-       res.body = ret
- 
      rescue NotImplementedError => err
!       res.body = { 'failure reason' => "#{err}" } 
  
      ensure
!       res['Content-Type'] = 'text/plain'
!       super(req, res)
      end
    end
--- 407,415 ----
        end
  
      rescue NotImplementedError => err
!       ret = { 'failure reason' => "#{err}" } 
  
      ensure
!       super(req, res, ret)
      end
    end



More information about the Aversa-commits mailing list