Merge branch 'master' into udp
This commit is contained in:
commit
f25464a02b
7 changed files with 178 additions and 42 deletions
120
CONFIGURATION.md
Normal file
120
CONFIGURATION.md
Normal 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
24
Dockerfile
Normal 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"]
|
35
README.md
35
README.md
|
@ -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"`
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"create_on_announce": true,
|
||||
"private_enabled": false,
|
||||
"freeleech_enabled": false,
|
||||
"purge_inactive_torrents": true,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue