@@ -3,6 +3,7 @@ package tworeqresp
3
3
import (
4
4
"bytes"
5
5
"fmt"
6
+ "sync"
6
7
"time"
7
8
8
9
pb "github.com/refraction-networking/conjure/proto"
@@ -19,33 +20,44 @@ type oneresponder interface {
19
20
type Responder struct {
20
21
parent oneresponder
21
22
parts map [[idLen ]byte ]* timedData
23
+ mutex sync.Mutex
22
24
}
23
25
24
26
func NewResponder (parent oneresponder ) (* Responder , error ) {
25
- return & Responder {
27
+ r := & Responder {
26
28
parent : parent ,
27
29
parts : make (map [[idLen ]byte ]* timedData ),
28
- }, nil
29
- }
30
-
31
- type timedData struct {
32
- data [][]byte
33
- expiry time.Time
30
+ mutex : sync.Mutex {},
31
+ }
32
+ go r .gc ()
33
+ return r , nil
34
34
}
35
35
36
- func (r * Responder ) RecvAndRespond ( parentGetResponse func ([] byte ) ([] byte , error )) error {
36
+ func (r * Responder ) gc () {
37
37
ticker := time .NewTicker (interval )
38
- getResponse := func (data []byte ) ([]byte , error ) {
39
- select {
40
- case <- ticker .C :
38
+
39
+ for range ticker .C {
40
+ func () {
41
+ r .mutex .Lock ()
42
+ defer r .mutex .Unlock ()
41
43
for key , data := range r .parts {
42
44
if time .Now ().After (data .expiry ) {
43
45
delete (r .parts , key )
44
46
}
45
47
}
46
- default :
47
- }
48
+ }()
49
+ }
50
+
51
+ }
48
52
53
+ type timedData struct {
54
+ data [][]byte
55
+ expiry time.Time
56
+ mutex sync.Mutex
57
+ }
58
+
59
+ func (r * Responder ) RecvAndRespond (parentGetResponse func ([]byte ) ([]byte , error )) error {
60
+ getResponse := func (data []byte ) ([]byte , error ) {
49
61
partIn := & pb.DnsPartReq {}
50
62
err := proto .Unmarshal (data , partIn )
51
63
if err != nil {
@@ -58,29 +70,53 @@ func (r *Responder) RecvAndRespond(parentGetResponse func([]byte) ([]byte, error
58
70
59
71
partId := (* [idLen ]byte )(partIn .GetId ())
60
72
61
- if _ , ok := r .parts [* partId ]; ! ok {
73
+ r .mutex .Lock ()
74
+ regData , ok := r .parts [* partId ]
75
+
76
+ if ! ok {
62
77
r .parts [* partId ] = & timedData {
63
78
data : make ([][]byte , partIn .GetTotalParts ()),
64
79
expiry : time .Now ().Add (interval ),
80
+ mutex : sync.Mutex {},
65
81
}
82
+ regData = r .parts [* partId ]
66
83
}
84
+ r .mutex .Unlock ()
67
85
68
- if int (partIn .GetTotalParts ()) != len (r .parts [* partId ].data ) {
69
- return nil , fmt .Errorf ("invalid total parts" )
70
- }
86
+ buf , waiting , err := func () ([]byte , bool , error ) {
87
+ regData .mutex .Lock ()
88
+ defer regData .mutex .Unlock ()
89
+ if int (partIn .GetTotalParts ()) != len (regData .data ) {
90
+ return nil , false , fmt .Errorf ("invalid total parts" )
91
+ }
71
92
72
- if int (partIn .GetPartNum ()) >= len (r . parts [ * partId ] .data ) {
73
- return nil , fmt .Errorf ("part number out of bound" )
74
- }
93
+ if int (partIn .GetPartNum ()) >= len (regData .data ) {
94
+ return nil , false , fmt .Errorf ("part number out of bound" )
95
+ }
75
96
76
- r . parts [ * partId ] .data [partIn .GetPartNum ()] = partIn .GetData ()
97
+ regData .data [partIn .GetPartNum ()] = partIn .GetData ()
77
98
78
- waiting := false
79
- for _ , part := range r .parts [* partId ].data {
80
- if part == nil {
81
- waiting = true
82
- break
99
+ waiting := false
100
+ for _ , part := range regData .data {
101
+ if part == nil {
102
+ waiting = true
103
+ break
104
+ }
105
+ }
106
+ if waiting {
107
+ return nil , true , nil
108
+ }
109
+
110
+ var buffer bytes.Buffer
111
+ for _ , part := range regData .data {
112
+ buffer .Write (part )
83
113
}
114
+
115
+ return buffer .Bytes (), false , nil
116
+ }()
117
+
118
+ if err != nil {
119
+ return nil , err
84
120
}
85
121
86
122
if waiting {
@@ -93,11 +129,7 @@ func (r *Responder) RecvAndRespond(parentGetResponse func([]byte) ([]byte, error
93
129
return respBytes , nil
94
130
}
95
131
96
- var buffer bytes.Buffer
97
- for _ , part := range r .parts [* partId ].data {
98
- buffer .Write (part )
99
- }
100
- res , err := parentGetResponse (buffer .Bytes ())
132
+ res , err := parentGetResponse (buf )
101
133
if err != nil {
102
134
return nil , fmt .Errorf ("error from parent getResponse: %v" , err )
103
135
}
0 commit comments