]> Sergey Matveev's repositories - btrtrc.git/blob - tracker/udp/dispatcher.go
Handle torrentfs failure in test.sh
[btrtrc.git] / tracker / udp / dispatcher.go
1 package udp
2
3 import (
4         "bytes"
5         "fmt"
6         "net"
7         "sync"
8 )
9
10 // Maintains a mapping of transaction IDs to handlers.
11 type Dispatcher struct {
12         mu           sync.RWMutex
13         transactions map[TransactionId]Transaction
14 }
15
16 // The caller owns b.
17 func (me *Dispatcher) Dispatch(b []byte, addr net.Addr) error {
18         buf := bytes.NewBuffer(b)
19         var rh ResponseHeader
20         err := Read(buf, &rh)
21         if err != nil {
22                 return err
23         }
24         me.mu.RLock()
25         defer me.mu.RUnlock()
26         if t, ok := me.transactions[rh.TransactionId]; ok {
27                 t.h(DispatchedResponse{
28                         Header: rh,
29                         Body:   append([]byte(nil), buf.Bytes()...),
30                         Addr:   addr,
31                 })
32                 return nil
33         } else {
34                 return fmt.Errorf("unknown transaction id %v", rh.TransactionId)
35         }
36 }
37
38 func (me *Dispatcher) forgetTransaction(id TransactionId) {
39         me.mu.Lock()
40         defer me.mu.Unlock()
41         delete(me.transactions, id)
42 }
43
44 func (me *Dispatcher) NewTransaction(h TransactionResponseHandler) Transaction {
45         me.mu.Lock()
46         defer me.mu.Unlock()
47         for {
48                 id := RandomTransactionId()
49                 if _, ok := me.transactions[id]; ok {
50                         continue
51                 }
52                 t := Transaction{
53                         d:  me,
54                         h:  h,
55                         id: id,
56                 }
57                 if me.transactions == nil {
58                         me.transactions = make(map[TransactionId]Transaction)
59                 }
60                 me.transactions[id] = t
61                 return t
62         }
63 }
64
65 type DispatchedResponse struct {
66         Header ResponseHeader
67         // Response payload, after the header.
68         Body []byte
69         // Response source address
70         Addr net.Addr
71 }