aboutsummaryrefslogtreecommitdiff
path: root/main.go
blob: 69ea5fecd5f0064b7733de9fe481b5212e7a9078 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// +build ignore

package dhtsearch

import (
	"fmt"
	"net"
	"net/http"
	"os"
	"time"

	"github.com/felix/logger"
)

func uptime() interface{} {
	return int64(time.Since(start).Seconds())
}

func main() {
	//defer profile.Start(profile.CPUProfile).Stop()
	expvar.Publish("uptime", expvar.Func(uptime))

	log := logger.New(&logger.Options{
		Name:  "dht",
		Level: logger.Info,
	})

	// Slice of channels for DHT node output
	torrents := make(chan Torrent)
	peers := make(chan peer)

	// Close upstreams channels
	done := make(chan struct{})
	defer close(done)

	// Persistence
	var err error
	DB, err = newDB(Config.Dsn)
	if err != nil {
		os.Exit(1)
	}
	defer DB.Close()

	// Initialise tags
	for tag := range tags {
		_, err := createTag(tag)
		if err != nil {
			fmt.Printf("Error creating tag %s: %q\n", tag, err)
		}
	}

	// Create DHT nodes
	if Config.Debug {
		fmt.Printf("Starting %d instance(s)\n", Config.NumNodes)
	}
	for i := 0; i < Config.NumNodes; i++ {
		// Consecutive port numbers
		port := Config.BasePort + i
		dht := newDHTNode("", port, peers)
		err = dht.run(done)
		if err != nil {
			os.Exit(1)
		}
	}

	// Create BT node
	bt := &btClient{}
	bt.log = log.Named("bt")
	err = btClient.run(torrents)
	if err != nil {
		os.Exit(1)
	}

	// HTTP Server
	if !Config.NoHttp {
		http.HandleFunc("/", indexHandler)
		http.HandleFunc("/stats", statsHandler)
		http.HandleFunc("/search", searchHandler)
		sock, _ := net.Listen("tcp", Config.HttpAddress)
		go func() {
			if !Config.Quiet {
				fmt.Printf("HTTP now available at %s\n", Config.HttpAddress)
			}
			http.Serve(sock, nil)
		}()
	}

	// Simple cache of most recent
	var p peer
	var t Torrent

	for {
		select {
		case t = <-torrents:
			length := t.Size

			// Add tags
			tagTorrent(&t)

			// Not sure if I like continue labels, so this
			var notWanted = false
			for _, tag := range Config.SkipTags {
				if hasTag(t, tag) {
					if !Config.Quiet {
						fmt.Printf("Skipping torrent tagged '%s': %q\n", tag, t.Name)
					}
					notWanted = true
					break
				}
			}
			if notWanted {
				torrentsSkipped.Add(1)
				continue
			}

			err := t.save()
			if err != nil {
				fmt.Printf("Error saving torrent: %q\n", err)
				continue
			}
			if !Config.Quiet {
				fmt.Printf("Torrrent added, length: %d, name: %q, tags: %s, url: magnet:?xt=urn:btih:%s\n", length, t.Name, t.Tags, t.Infohash)
			}
			torrentsSaved.Add(1)
			torrentsTotal.Add(1)
		}
	}
}