コード例 #1
0
ファイル: proxy.c プロジェクト: Gastlag/Opentracker
static void livesync_handle_peersync( ssize_t datalen ) {
  int off = sizeof( g_tracker_id ) + sizeof( uint32_t );

  fprintf( stderr, "." );

  while( off + (ssize_t)sizeof( ot_hash ) + (ssize_t)sizeof( ot_peer ) <= datalen ) {
    ot_peer *peer = (ot_peer*)(g_inbuffer + off + sizeof(ot_hash));
    ot_hash *hash = (ot_hash*)(g_inbuffer + off);

    if( OT_PEERFLAG(peer) & PEER_FLAG_STOPPED )
      remove_peer_from_torrent_proxy( *hash, peer );
    else
      add_peer_to_torrent_proxy( *hash, peer );

    off += sizeof( ot_hash ) + sizeof( ot_peer );
  }
}
コード例 #2
0
ファイル: proxy.c プロジェクト: Gastlag/Opentracker
size_t add_peer_to_torrent_proxy( ot_hash hash, ot_peer *peer ) {
  int         exactmatch;
  ot_torrent *torrent;
  ot_peer    *peer_dest;
  ot_vector  *torrents_list = mutex_bucket_lock_by_hash( hash );

  torrent = vector_find_or_insert( torrents_list, (void*)hash, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch );
  if( !torrent )
    return -1;

  if( !exactmatch ) {
    /* Create a new torrent entry, then */
    memcpy( torrent->hash, hash, sizeof(ot_hash) );

    if( !( torrent->peer_list = malloc( sizeof (ot_peerlist) ) ) ) {
      vector_remove_torrent( torrents_list, torrent );
      mutex_bucket_unlock_by_hash( hash, 0 );
      return -1;
    }

    byte_zero( torrent->peer_list, sizeof( ot_peerlist ) );
  }

  /* Check for peer in torrent */
  peer_dest = vector_find_or_insert_peer( &(torrent->peer_list->peers), peer, &exactmatch );
  if( !peer_dest ) {
    mutex_bucket_unlock_by_hash( hash, 0 );
    return -1;
  }
  /* Tell peer that it's fresh */
  OT_PEERTIME( peer ) = 0;

  /* If we hadn't had a match create peer there */
  if( !exactmatch ) {
    torrent->peer_list->peer_count++;
    if( OT_PEERFLAG(peer) & PEER_FLAG_SEEDING )
      torrent->peer_list->seed_count++;
  }
  memcpy( peer_dest, peer, sizeof(ot_peer) );
  mutex_bucket_unlock_by_hash( hash, 0 );
  return 0;
}
コード例 #3
0
ファイル: ot_vector.c プロジェクト: donatus/opentracker
/* This is the non-generic delete from vector-operation specialized for peers in pools.
   It returns 0 if no peer was found (and thus not removed)
              1 if a non-seeding peer was removed
              2 if a seeding peer was removed
*/
int vector_remove_peer( ot_vector *vector, ot_peer *peer ) {
  int      exactmatch;
  ot_peer *match, *end;

  if( !vector->size ) return 0;

  /* If space is zero but size is set, we're dealing with a list of vector->size buckets */
  if( vector->space < vector->size )
    vector = ((ot_vector*)vector->data) + vector_hash_peer(peer, vector->size );

  end = ((ot_peer*)vector->data) + vector->size;
  match = (ot_peer*)binary_search( peer, vector->data, vector->size, sizeof(ot_peer), OT_PEER_COMPARE_SIZE, &exactmatch );
  if( !exactmatch ) return 0;

  exactmatch = ( OT_PEERFLAG( match ) & PEER_FLAG_SEEDING ) ? 2 : 1;
  memmove( match, match + 1, sizeof(ot_peer) * ( end - match - 1 ) );

  vector->size--;
  vector_fixup_peers( vector );
  return exactmatch;
}
コード例 #4
0
ファイル: ot_livesync.c プロジェクト: cjmalloy/opentracker
static void livesync_handle_peersync( struct ot_workstruct *ws ) {
  int off = sizeof( g_tracker_id ) + sizeof( uint32_t );

  /* Now basic sanity checks have been done on the live sync packet
     We might add more testing and logging. */
  while( off + (ssize_t)sizeof( ot_hash ) + (ssize_t)sizeof( ot_peer ) <= ws->request_size ) {
    memcpy( &ws->peer, ws->request + off + sizeof(ot_hash), sizeof( ot_peer ) );
    ws->hash = (ot_hash*)(ws->request + off);

    if( !g_opentracker_running ) return;

    if( OT_PEERFLAG(&ws->peer) & PEER_FLAG_STOPPED )
      remove_peer_from_torrent( FLAG_MCA, ws );
    else
      add_peer_to_torrent_and_return_peers( FLAG_MCA, ws, /* amount = */ 0 );

    off += sizeof( ot_hash ) + sizeof( ot_peer );
  }

  stats_issue_event(EVENT_SYNC, 0,
                    (ws->request_size - sizeof( g_tracker_id ) - sizeof( uint32_t ) ) /
                    ((ssize_t)sizeof( ot_hash ) + (ssize_t)sizeof( ot_peer )));
}
コード例 #5
0
ファイル: ot_clean.c プロジェクト: SpiderX/opentracker
/* Returns amount of removed peers */
static ssize_t clean_single_bucket( ot_peer *peers, size_t peer_count, time_t timedout, int *removed_seeders ) {
  ot_peer *last_peer = peers + peer_count, *insert_point;
  time_t timediff;

  /* Two scan modes: unless there is one peer removed, just increase ot_peertime */
  while( peers < last_peer ) {
    if( ( timediff = timedout + OT_PEERTIME( peers ) ) >= OT_PEER_TIMEOUT )
      break;
    OT_PEERTIME( peers++ ) = timediff;
  }

  /* If we at least remove one peer, we have to copy  */
  insert_point = peers;
  while( peers < last_peer )
    if( ( timediff = timedout + OT_PEERTIME( peers ) ) < OT_PEER_TIMEOUT ) {
      OT_PEERTIME( peers ) = timediff;
      memcpy( insert_point++, peers++, sizeof(ot_peer));
    } else
      if( OT_PEERFLAG( peers++ ) & PEER_FLAG_SEEDING )
        (*removed_seeders)++;

  return peers - insert_point;
}
コード例 #6
0
ファイル: ot_udp.c プロジェクト: biiiep/opentracker
/* UDP implementation according to http://xbtt.sourceforge.net/udp_tracker_protocol.html */
int handle_udp6( int64 serversocket, struct ot_workstruct *ws ) {
  ot_ip6      remoteip;
  uint32_t   *inpacket = (uint32_t*)ws->inbuf;
  uint32_t   *outpacket = (uint32_t*)ws->outbuf;
  uint32_t    numwant, left, event, scopeid;
  uint32_t    connid[2];
  uint16_t    port, remoteport;
  size_t      byte_count, scrape_count;

  byte_count = socket_recv6( serversocket, ws->inbuf, G_INBUF_SIZE, remoteip, &remoteport, &scopeid );
  if( !byte_count ) return 0;

  stats_issue_event( EVENT_ACCEPT, FLAG_UDP, (uintptr_t)remoteip );
  stats_issue_event( EVENT_READ, FLAG_UDP, byte_count );

  /* Minimum udp tracker packet size, also catches error */
  if( byte_count < 16 )
    return 1;

  /* Generate the connection id we give out and expect to and from
     the requesting ip address, this prevents udp spoofing */
  udp_make_connectionid( connid, remoteip, 0 );

  /* Initialise hash pointer */
  ws->hash = NULL;
  ws->peer_id = NULL;

  /* If action is not a ntohl(a) == a == 0, then we
     expect the derived connection id in first 64 bit */
  if( inpacket[2] && ( inpacket[0] != connid[0] || inpacket[1] != connid[1] ) ) {
    /* If connection id does not match, try the one that was
       valid in the previous hour. Only if this also does not
       match, return an error packet */
    udp_make_connectionid( connid, remoteip, 1 );
    if( inpacket[0] != connid[0] || inpacket[1] != connid[1] ) {
      const size_t s = sizeof( "Connection ID missmatch." );
      outpacket[0] = 3; outpacket[1] = inpacket[3];
      memcpy( &outpacket[2], "Connection ID missmatch.", s );
      socket_send6( serversocket, ws->outbuf, 8 + s, remoteip, remoteport, 0 );
      stats_issue_event( EVENT_CONNID_MISSMATCH, FLAG_UDP, 8 + s );
      return 1;
    }
  }

  switch( ntohl( inpacket[2] ) ) {
    case 0: /* This is a connect action */
      /* look for udp bittorrent magic id */
      if( (ntohl(inpacket[0]) != 0x00000417) || (ntohl(inpacket[1]) != 0x27101980) )
        return 1;

      outpacket[0] = 0;
      outpacket[1] = inpacket[3];
      outpacket[2] = connid[0];
      outpacket[3] = connid[1];

      socket_send6( serversocket, ws->outbuf, 16, remoteip, remoteport, 0 );
      stats_issue_event( EVENT_CONNECT, FLAG_UDP, 16 );
      break;
    case 1: /* This is an announce action */
      /* Minimum udp announce packet size */
      if( byte_count < 98 )
        return 1;

      /* We do only want to know, if it is zero */
      left  = inpacket[64/4] | inpacket[68/4];

      numwant = ntohl( inpacket[92/4] );
      if (numwant > 200) numwant = 200;

      event    = ntohl( inpacket[80/4] );
      port     = *(uint16_t*)( ((char*)inpacket) + 96 );
      ws->hash = (ot_hash*)( ((char*)inpacket) + 16 );

      OT_SETIP( &ws->peer, remoteip );
      OT_SETPORT( &ws->peer, &port );
      OT_PEERFLAG( &ws->peer ) = 0;

      switch( event ) {
        case 1: OT_PEERFLAG( &ws->peer ) |= PEER_FLAG_COMPLETED; break;
        case 3: OT_PEERFLAG( &ws->peer ) |= PEER_FLAG_STOPPED; break;
        default: break;
      }

      if( !left )
        OT_PEERFLAG( &ws->peer )         |= PEER_FLAG_SEEDING;

      outpacket[0] = htonl( 1 );    /* announce action */
      outpacket[1] = inpacket[12/4];

      if( OT_PEERFLAG( &ws->peer ) & PEER_FLAG_STOPPED ) { /* Peer is gone. */
        ws->reply      = ws->outbuf;
        ws->reply_size = remove_peer_from_torrent( FLAG_UDP, ws );
      } else {
        ws->reply      = ws->outbuf + 8;
        ws->reply_size = 8 + add_peer_to_torrent_and_return_peers( FLAG_UDP, ws, numwant );
      }

      socket_send6( serversocket, ws->outbuf, ws->reply_size, remoteip, remoteport, 0 );
      stats_issue_event( EVENT_ANNOUNCE, FLAG_UDP, ws->reply_size );
      break;

    case 2: /* This is a scrape action */
      outpacket[0] = htonl( 2 );    /* scrape action */
      outpacket[1] = inpacket[12/4];

      for( scrape_count = 0; ( scrape_count * 20 < byte_count - 16) && ( scrape_count <= 74 ); scrape_count++ )
        return_udp_scrape_for_torrent( *(ot_hash*)( ((char*)inpacket) + 16 + 20 * scrape_count ), ((char*)outpacket) + 8 + 12 * scrape_count );

      socket_send6( serversocket, ws->outbuf, 8 + 12 * scrape_count, remoteip, remoteport, 0 );
      stats_issue_event( EVENT_SCRAPE, FLAG_UDP, scrape_count );
      break;
  }
  return 1;
}
コード例 #7
0
ファイル: ot_persist.c プロジェクト: SpiderX/opentracker
static int persist_add_peer(ot_hash *hash, ot_peerlist *peer_list, ot_peer *peer) {
  int         exactmatch, delta_torrentcount = 0;
  ot_torrent *torrent;
  ot_peer    *peer_dest;

  /* eliminate compiler warnings */
  (void)peer_list;

  ot_vector  *torrents_list = mutex_bucket_lock_by_hash(*hash);

  if( !accesslist_hashisvalid( hash ) ) {
    mutex_bucket_unlock_by_hash( *hash, 0 );
    return 0;
  }

  torrent = vector_find_or_insert( torrents_list, (void*)hash, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch );
  if( !torrent ) {
    mutex_bucket_unlock_by_hash( *hash, 0 );
    return 0;
  }

  if( !exactmatch ) {
    /* Create a new torrent entry, then */
    memcpy( torrent->hash, hash, sizeof(ot_hash) );

    if( !( torrent->peer_list = malloc( sizeof (ot_peerlist) ) ) ) {
      vector_remove_torrent( torrents_list, torrent );
      mutex_bucket_unlock_by_hash( *hash, 0 );
      return 0;
    }

    byte_zero( torrent->peer_list, sizeof( ot_peerlist ) );
    delta_torrentcount = 1;
  }

  /* Ignore torrent base in odb file, just use current clock. */
  torrent->peer_list->base = g_now_minutes;

  /* Check for peer in torrent */
  peer_dest = vector_find_or_insert_peer( &(torrent->peer_list->peers), peer, &exactmatch );
  if( !peer_dest ) {
    mutex_bucket_unlock_by_hash( *hash, delta_torrentcount );
    return 0;
  }

  /* If we hadn't had a match, create peer there */
  if( !exactmatch ) {
    torrent->peer_list->peer_count++;
    if( OT_PEERFLAG(peer) & PEER_FLAG_COMPLETED )
      torrent->peer_list->down_count++;
    if( OT_PEERFLAG(peer) & PEER_FLAG_SEEDING )
      torrent->peer_list->seed_count++;
  } else {
    LOG_ERR("Repeat peer in a same torrent\n");
    assert(0);
  }

  memcpy( peer_dest, peer, sizeof(ot_peer) );

  mutex_bucket_unlock_by_hash( *hash, delta_torrentcount );
  return 0;
}
コード例 #8
0
ファイル: ot_http.c プロジェクト: Moscarda/opentracker
static ssize_t http_handle_announce( const int64 sock, struct ot_workstruct *ws, char *read_ptr ) {
  int               numwant, tmp, scanon;
  unsigned short    port = 0;
  char             *write_ptr;
  ssize_t           len;
  struct http_data *cookie = io_getcookie( sock );

  /* This is to hack around stupid clients that send "announce ?info_hash" */
  if( read_ptr[-1] != '?' ) {
    while( ( *read_ptr != '?' ) && ( *read_ptr != '\n' ) ) ++read_ptr;
    if( *read_ptr == '\n' ) HTTPERROR_400_PARAM;
    ++read_ptr;
  }

#ifdef WANT_IP_FROM_PROXY
  if( accesslist_isblessed( cookie->ip, OT_PERMISSION_MAY_PROXY ) ) {
    ot_ip6 proxied_ip;
    char *fwd = http_header( ws->request, ws->header_size, "x-forwarded-for" );
    if( fwd && scan_ip6( fwd, proxied_ip ) )
      OT_SETIP( &ws->peer, proxied_ip );
    else
      OT_SETIP( &ws->peer, cookie->ip );
  } else
#endif
  OT_SETIP( &ws->peer, cookie->ip );

  ws->peer_id = NULL;
  ws->hash = NULL;

  OT_SETPORT( &ws->peer, &port );
  OT_PEERFLAG( &ws->peer ) = 0;
  numwant = 50;
  scanon = 1;

  while( scanon ) {
    switch( scan_find_keywords(keywords_announce, &read_ptr, SCAN_SEARCHPATH_PARAM ) ) {
    case -2: scanon = 0; break;   /* TERMINATOR */
    case -1: HTTPERROR_400_PARAM; /* PARSE ERROR */
    case -3: scan_urlencoded_skipvalue( &read_ptr ); break;
    case 1: /* matched "port" */
      len = scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE );
      if( ( len <= 0 ) || scan_fixed_int( write_ptr, len, &tmp ) || ( tmp > 0xffff ) ) HTTPERROR_400_PARAM;
      port = htons( tmp ); OT_SETPORT( &ws->peer, &port );
      break;
    case 2: /* matched "left" */
      if( ( len = scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE ) ) <= 0 ) HTTPERROR_400_PARAM;
      if( scan_fixed_int( write_ptr, len, &tmp ) ) tmp = 0;
      if( !tmp ) OT_PEERFLAG( &ws->peer ) |= PEER_FLAG_SEEDING;
      break;
    case 3: /* matched "event" */
      switch( scan_find_keywords( keywords_announce_event, &read_ptr, SCAN_SEARCHPATH_VALUE ) ) {
        case -1: HTTPERROR_400_PARAM;
        case  1: /* matched "completed" */
          OT_PEERFLAG( &ws->peer ) |= PEER_FLAG_COMPLETED;
          break;
        case  2: /* matched "stopped" */
          OT_PEERFLAG( &ws->peer ) |= PEER_FLAG_STOPPED;
          break;
        default:
          break;
      }
      break;
    case 4: /* matched "numwant" */
      len = scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE );
      if( ( len <= 0 ) || scan_fixed_int( write_ptr, len, &numwant ) ) HTTPERROR_400_PARAM;
      if( numwant < 0 ) numwant = 50;
      if( numwant > 200 ) numwant = 200;
      break;
    case 5: /* matched "compact" */
      len = scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE );
      if( ( len <= 0 ) || scan_fixed_int( write_ptr, len, &tmp ) ) HTTPERROR_400_PARAM;
      if( !tmp ) HTTPERROR_400_COMPACT;
      break;
    case 6: /* matched "info_hash" */
      if( ws->hash ) HTTPERROR_400_DOUBLEHASH;
      /* ignore this, when we have less than 20 bytes */
      if( scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE ) != 20 ) HTTPERROR_400_PARAM;
        ws->hash = (ot_hash*)write_ptr;
      break;
#ifdef WANT_IP_FROM_QUERY_STRING
    case  7: /* matched "ip" */
      {
        char *tmp_buf1 = ws->reply, *tmp_buf2 = ws->reply+16;
        len = scan_urlencoded_query( &read_ptr, tmp_buf2, SCAN_SEARCHPATH_VALUE );
        tmp_buf2[len] = 0;
        if( ( len <= 0 ) || !scan_ip6( tmp_buf2, tmp_buf1 ) ) HTTPERROR_400_PARAM;
        OT_SETIP( &ws->peer, tmp_buf1 );
      }
      break;
#endif
#ifdef WANT_FULLLOG_NETWORKS
      case 8: /* matched "lognet" */
      {
        //if( accesslist_isblessed( cookie->ip, OT_PERMISSION_MAY_STAT ) ) {
          char *tmp_buf = ws->reply;
          ot_net net;
          signed short parsed, bits;

          len = scan_urlencoded_query( &read_ptr, tmp_buf, SCAN_SEARCHPATH_VALUE );
          tmp_buf[len] = 0;
          if( len <= 0 ) HTTPERROR_400_PARAM;
          if( *tmp_buf == '-' ) {
            loglist_reset( );
            return ws->reply_size = sprintf( ws->reply, "Successfully removed.\n" );
          }
          parsed = scan_ip6( tmp_buf, net.address );
          if( !parsed ) HTTPERROR_400_PARAM;
          if( tmp_buf[parsed++] != '/' )
            bits = 128;
          else {
            parsed = scan_short( tmp_buf + parsed, &bits );
            if( !parsed ) HTTPERROR_400_PARAM; 
            if( ip6_isv4mapped( net.address ) )
              bits += 96;
          }
          net.bits = bits;
          loglist_add_network( &net );
          return ws->reply_size = sprintf( ws->reply, "Successfully added.\n" );
        //}
      }
#endif
        break;
      case 9: /* matched "peer_id" */
        /* ignore this, when we have less than 20 bytes */
        if( scan_urlencoded_query( &read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE ) != 20 ) HTTPERROR_400_PARAM;
        ws->peer_id = write_ptr;
        break;
    }
  }

#ifdef WANT_LOG_NUMWANT
  numwants[numwant]++;
#endif

  /* XXX DEBUG
  stats_issue_event( EVENT_ACCEPT, FLAG_TCP, (uintptr_t)ws->reply );
  */

  /* Scanned whole query string */
  if( !ws->hash )
    return ws->reply_size = sprintf( ws->reply, "d14:failure reason80:Your client forgot to send your torrent's info_hash. Please upgrade your client.e" );

  if( OT_PEERFLAG( &ws->peer ) & PEER_FLAG_STOPPED )
    ws->reply_size = remove_peer_from_torrent( FLAG_TCP, ws );
  else
    ws->reply_size = add_peer_to_torrent_and_return_peers( FLAG_TCP, ws, numwant );

  stats_issue_event( EVENT_ANNOUNCE, FLAG_TCP, ws->reply_size);
  return ws->reply_size;
}