@@ -51,7 +51,7 @@ type configExt struct {
51
51
52
52
// NewWithConfig calls New with the given config. For documentation, see New.
53
53
func NewWithConfig (ctx context.Context , logger slog.Logger , cfg Config ) (* Tunnel , <- chan error , error ) {
54
- err := startUpdateRoutine (ctx , logger , cfg )
54
+ routineEnd , err := startUpdateRoutine (ctx , logger , cfg )
55
55
if err != nil {
56
56
return nil , nil , xerrors .Errorf ("start update routine: %w" , err )
57
57
}
@@ -101,6 +101,7 @@ allowed_ip=%s/128`,
101
101
case <- ctx .Done ():
102
102
_ = wgListen .Close ()
103
103
dev .Close ()
104
+ <- routineEnd
104
105
close (ch )
105
106
106
107
case <- dev .Wait ():
@@ -128,21 +129,24 @@ func New(ctx context.Context, logger slog.Logger) (*Tunnel, <-chan error, error)
128
129
return NewWithConfig (ctx , logger , cfg )
129
130
}
130
131
131
- func startUpdateRoutine (ctx context.Context , logger slog.Logger , cfg Config ) error {
132
+ func startUpdateRoutine (ctx context.Context , logger slog.Logger , cfg Config ) ( <- chan struct {}, error ) {
132
133
// Ensure we send the first config before spawning in the background.
133
134
_ , err := sendConfigToServer (ctx , cfg )
134
135
if err != nil {
135
- return xerrors .Errorf ("send config to server: %w" , err )
136
+ return nil , xerrors .Errorf ("send config to server: %w" , err )
136
137
}
137
138
139
+ endCh := make (chan struct {})
138
140
go func () {
141
+ defer close (endCh )
139
142
ticker := time .NewTicker (30 * time .Second )
140
143
defer ticker .Stop ()
141
144
142
145
for {
143
146
select {
144
147
case <- ctx .Done ():
145
- break
148
+ return
149
+
146
150
case <- ticker .C :
147
151
}
148
152
@@ -152,19 +156,25 @@ func startUpdateRoutine(ctx context.Context, logger slog.Logger, cfg Config) err
152
156
}
153
157
}
154
158
}()
155
- return nil
159
+ return endCh , nil
156
160
}
157
161
158
- func sendConfigToServer (_ context.Context , cfg Config ) (created bool , err error ) {
162
+ func sendConfigToServer (ctx context.Context , cfg Config ) (created bool , err error ) {
159
163
raw , err := json .Marshal (configExt (cfg ))
160
164
if err != nil {
161
165
return false , xerrors .Errorf ("marshal config: %w" , err )
162
166
}
163
167
164
- res , err := http .Post ("https://" + EndpointHTTPS + "/tun" , "application/json" , bytes .NewReader (raw ))
168
+ req , err := http .NewRequestWithContext (ctx , "POST" , "https://" + EndpointHTTPS + "/tun" , bytes .NewReader (raw ))
169
+ if err != nil {
170
+ return false , xerrors .Errorf ("new request: %w" , err )
171
+ }
172
+
173
+ res , err := http .DefaultClient .Do (req )
165
174
if err != nil {
166
- return false , xerrors .Errorf ("send request: %w" , err )
175
+ return false , xerrors .Errorf ("do request: %w" , err )
167
176
}
177
+
168
178
_ , _ = io .Copy (io .Discard , res .Body )
169
179
_ = res .Body .Close ()
170
180
@@ -177,7 +187,13 @@ func cfgPath() (string, error) {
177
187
return "" , xerrors .Errorf ("get user config dir: %w" , err )
178
188
}
179
189
180
- return filepath .Join (cfgDir , "coderv2" , "devtunnel" ), nil
190
+ cfgDir = filepath .Join (cfgDir , "coderv2" )
191
+ err = os .MkdirAll (cfgDir , 0750 )
192
+ if err != nil {
193
+ return "" , xerrors .Errorf ("mkdirall config dir %q: %w" , cfgDir , err )
194
+ }
195
+
196
+ return filepath .Join (cfgDir , "devtunnel" ), nil
181
197
}
182
198
183
199
func readOrGenerateConfig () (Config , error ) {
0 commit comments