Merge branch 'master' into udp

This commit is contained in:
Jimmy Zelinskie 2015-03-27 22:05:48 -04:00
commit f25464a02b
7 changed files with 178 additions and 42 deletions

120
CONFIGURATION.md Normal file
View file

@ -0,0 +1,120 @@
# Configuration
Chihaya's behaviour is customized by setting up a JSON configuration file.
Available keys are as follows:
##### `http_listen_addr`
type: string
default: ":6881"
The listen address for the HTTP server. If only a port is specified, the tracker will listen on all interfaces.
##### `private_enabled`
type: bool
default: true
Whether this is a public or private tracker.
##### `create_on_announce`
type: bool
default: true
Whether to register new torrents with the tracker when any client announces (`true`), or to return an error if the torrent doesn't exist (`false`). This should be set to `false` for private trackers in most cases.
##### `purge_inactive_torrents`
type: bool
default: true
If torrents should be forgotten when there are no active peers. This should be set to `false` for private trackers.
##### `announce`
type: duration
default: "30m"
The announce `interval` value sent to clients. This specifies how long clients should wait between regular announces.
##### `min_announce`
type: duration
default: "30m"
The announce `min_interval` value sent to clients. This theoretically specifies the minimum allowed time between announces, but most clients don't really respect it.
##### `default_num_want`
type: integer
default: 50
The default maximum number of peers to return if the client has not requested a specific number.
##### `allow_ip_spoofing`
type: bool
default: true
Whether peers are allowed to set their own IP via the various supported methods or if these are ignored. This must be enabled for dual-stack IP support, since there is no other way to determine both IPs of a peer otherwise.
##### `dual_stacked_peers`
type: bool
default: true
True if peers may have both an IPv4 and IPv6 address, otherwise only one IP per peer will be used.
##### `real_ip_header`
type: string
default: blank
An optional HTTP header indicating the upstream IP, for example `X-Forwarded-For` or `X-Real-IP`. Use this when running the tracker behind a reverse proxy.
##### `respect_af`
type: bool
default: false
Whether responses should only include peers of the same address family as the announcing peer, or if peers of any family may be returned (i.e. both IPv4 and IPv6).
##### `client_whitelist_enabled`
type: bool
default: false
Enables the peer ID whitelist.
##### `client_whitelist`
type: array of strings
default: []
List of peer ID prefixes to allow if `client_whitelist_enabled` is set to true.
##### `freeleech_enabled`
type: bool
default: false
For private trackers only, whether download stats should be counted or ignored for users.
##### `torrent_map_shards`
type: integer
default: 1
Number of internal torrent maps to use. Leave this at 1 in general, however it can potentially improve performance when there are many unique torrents and few peers per torrent.
- `http_request_timeout: "10s"`
- `http_read_timeout: "10s"`
- `http_write_timeout: "10s"`
- `http_listen_limit: 0`
- `driver: "noop"`
- `stats_buffer_size: 0`
- `include_mem_stats: true`
- `verbose_mem_stats: false`
- `mem_stats_interval: "5s"`

24
Dockerfile Normal file
View file

@ -0,0 +1,24 @@
# vim: ft=dockerfile
FROM golang
MAINTAINER Jimmy Zelinskie <jimmyzelinskie@gmail.com>
# Add files
WORKDIR /go/src/github.com/chihaya/chihaya/
RUN mkdir -p /go/src/github.com/chihaya/chihaya/
ADD chihaya.go /go/src/github.com/chihaya/chihaya/
ADD backend /go/src/github.com/chihaya/chihaya/backend
ADD cmd /go/src/github.com/chihaya/chihaya/cmd
ADD config /go/src/github.com/chihaya/chihaya/config
ADD http /go/src/github.com/chihaya/chihaya/http
ADD stats /go/src/github.com/chihaya/chihaya/stats
ADD tracker /go/src/github.com/chihaya/chihaya/tracker
ADD Godeps /go/src/github.com/chihaya/chihaya/Godeps
# Install
RUN go get ./...
RUN go install
# docker run -p 6881:6881 -v $PATH_TO_DIR_WITH_CONF_FILE:/config quay.io/jzelinskie/chihaya
VOLUME ["/config"]
EXPOSE 6881
CMD ["chihaya", "-config=/config/config.json", "-logtostderr=true"]

View file

@ -1,4 +1,8 @@
# Chihaya [![Build Status](https://api.travis-ci.org/chihaya/chihaya.svg?branch=master)](https://travis-ci.org/chihaya/chihaya)
# Chihaya
[![GoDoc](https://godoc.org/github.com/chihaya/chihaya?status.svg)](https://godoc.org/github.com/chihaya/chihaya)
[![Build Status](https://api.travis-ci.org/chihaya/chihaya.svg?branch=master)](https://travis-ci.org/chihaya/chihaya)
[![Docker Repository on Quay.io](https://quay.io/repository/jzelinskie/chihaya/status "Docker Repository on Quay.io")](https://quay.io/repository/jzelinskie/chihaya)
Chihaya is a high-performance [BitTorrent tracker] written in the Go
programming language. It is still heavily under development and the current
@ -32,7 +36,7 @@ use-cases).
## Building & Installing
Chihaya requires Go 1.4, [Godep], and a [Go environment] previously setup.
Chihaya requires 64-bit Go 1.4, [Godep], and a [Go environment] previously set up.
[Godep]: https://github.com/tools/godep
[Go environment]: https://golang.org/doc/code.html
@ -65,30 +69,5 @@ $ godep go test -v ./... -bench .
Copy [`example_config.json`](https://github.com/chihaya/chihaya/blob/master/example_config.json)
to your choice of location, and update the values as required.
The available keys and their default values are as follows:
An explanation of the available keys can be found in [CONFIGURATION.md](https://github.com/chihaya/chihaya/blob/master/CONFIGURATION.md).
- `private_enabled: false` if this is a private tracker
- `freeleech_enabled: false` for private trackers, whether download stats should be counted for users
- `purge_inactive_torrents: true` if torrents should be forgotten after some time
- `announce: "30m"` the announce "interval" value sent to clients
- `min_announce: "15m"` the announce "min_interval" value sent to clients
- `default_num_want: 50` the default number of peers to return if the client has not specified
- `torrent_map_shards: 1` number of torrent maps to use (leave this at 1 in general)
- `allow_ip_spoofing: true` if peers are allowed to set their own IP, this must be enabled for dual-stack IP support
- `dual_stacked_peers: true` if peers may have both an IPv4 and IPv6 address, otherwise only one IP per peer will be used
- `real_ip_header: ""` optionally an HTTP header where the upstream IP is stored, for example `X-Forwarded-For` or `X-Real-IP`
- `respect_af: false` if responses should only include peers of the same address family as the announcing peer
- `client_whitelist_enabled: false` if peer IDs should be matched against the whitelist
- `client_whitelist: []` list of peer ID prefixes to allow
- `http_listen_addr: ""` listen address for the HTTP server
- `http_request_timeout: "10s"`
- `http_read_timeout: "10s"`
- `http_write_timeout: "10s"`
- `http_listen_limit: 0`
- `udp_listen_addr: ""` listen address for the UDP server
- `udp_read_buffer_size: undefined` size of the UDP socket's kernel read buffer
- `driver: "noop"`
- `stats_buffer_size: 0`
- `include_mem_stats: true`
- `verbose_mem_stats: false`
- `mem_stats_interval: "5s"`

View file

@ -75,6 +75,7 @@ type WhitelistConfig struct {
// TrackerConfig is the configuration for tracker functionality.
type TrackerConfig struct {
CreateOnAnnounce bool `json:"create_on_announce"`
PrivateEnabled bool `json:"private_enabled"`
FreeleechEnabled bool `json:"freeleech_enabled"`
PurgeInactiveTorrents bool `json:"purge_inactive_torrents"`
@ -114,6 +115,7 @@ type Config struct {
// DefaultConfig is a configuration that can be used as a fallback value.
var DefaultConfig = Config{
TrackerConfig: TrackerConfig{
CreateOnAnnounce: true,
PrivateEnabled: false,
FreeleechEnabled: false,
PurgeInactiveTorrents: true,
@ -134,14 +136,14 @@ var DefaultConfig = Config{
},
HTTPConfig: HTTPConfig{
HTTPListenAddr: "",
HTTPListenAddr: ":6881",
HTTPRequestTimeout: Duration{10 * time.Second},
HTTPReadTimeout: Duration{10 * time.Second},
HTTPWriteTimeout: Duration{10 * time.Second},
},
UDPConfig: UDPConfig{
UDPListenAddr: "",
UDPListenAddr: ":6882",
},
DriverConfig: DriverConfig{

View file

@ -1,4 +1,5 @@
{
"create_on_announce": true,
"private_enabled": false,
"freeleech_enabled": false,
"purge_inactive_torrents": true,

View file

@ -27,7 +27,7 @@ func (tkr *Tracker) HandleAnnounce(ann *models.Announce, w Writer) (err error) {
torrent, err := tkr.FindTorrent(ann.Infohash)
if err == models.ErrTorrentDNE && !tkr.Config.PrivateEnabled {
if err == models.ErrTorrentDNE && tkr.Config.CreateOnAnnounce {
torrent = &models.Torrent{
Infohash: ann.Infohash,
Seeders: models.NewPeerMap(true, tkr.Config),
@ -231,20 +231,13 @@ func (tkr *Tracker) handlePeerEvent(ann *models.Announce, p *models.Peer) (snatc
}
case ann.Event == "completed":
v4seed := t.Seeders.Contains(p.Key())
v6seed := t.Seeders.Contains(p.Key())
if t.Leechers.Contains(p.Key()) {
err = tkr.leecherFinished(t, p)
} else {
err = models.ErrBadRequest
}
// If one of the dual-stacked peers is already a seeder, they have
// already snatched.
if !(v4seed || v6seed) {
snatched = true
}
snatched = true
case t.Leechers.Contains(p.Key()) && ann.Left == 0:
// A leecher completed but the event was never received.

View file

@ -8,6 +8,7 @@ package models
import (
"net"
"strconv"
"strings"
"time"
@ -52,13 +53,18 @@ func IsPublicError(err error) bool {
return cl || nf || pc
}
// PeerList represents a list of peers: either seeders or leechers.
type PeerList []Peer
// PeerKey is the key used to uniquely identify a peer in a swarm.
type PeerKey string
func NewPeerKey(peerID string, ip net.IP) PeerKey {
return PeerKey(peerID + "//" + ip.String())
// NewPeerKey creates a properly formatted PeerKey.
func NewPeerKey(peerID string, ip net.IP, port string) PeerKey {
return PeerKey(peerID + "//" + ip.String() + ":" + port)
}
// IP parses and returns the IP address for a given PeerKey.
func (pk PeerKey) IP() net.IP {
ip := net.ParseIP(strings.Split(string(pk), "//")[1])
if rval := ip.To4(); rval != nil {
@ -67,10 +73,16 @@ func (pk PeerKey) IP() net.IP {
return ip
}
// PeerID returns the PeerID section of a PeerKey.
func (pk PeerKey) PeerID() string {
return strings.Split(string(pk), "//")[0]
}
// Port returns the port section of the PeerKey.
func (pk PeerKey) Port() string {
return strings.Split(string(pk), "//")[2]
}
// Peer is a participant in a swarm.
type Peer struct {
ID string `json:"id"`
@ -88,16 +100,21 @@ type Peer struct {
LastAnnounce int64 `json:"last_announce"`
}
// HasIPv4 determines if a peer's IP address can be represented as an IPv4
// address.
func (p *Peer) HasIPv4() bool {
return !p.HasIPv6()
}
// HasIPv6 determines if a peer's IP address can be represented as an IPv6
// address.
func (p *Peer) HasIPv6() bool {
return len(p.IP) == net.IPv6len
}
// Key returns a PeerKey for the given peer.
func (p *Peer) Key() PeerKey {
return NewPeerKey(p.ID, p.IP)
return NewPeerKey(p.ID, p.IP, strconv.FormatUint(p.Port, 10))
}
// Torrent is a swarm for a given torrent file.