MCPcopy Create free account
hub / github.com/Hidden-Node/GooseRelayVPN-AndroidClient / handleTunnel

Method handleTunnel

internal/exit/exit.go:314–453  ·  view source on GitHub ↗
(w http.ResponseWriter, r *http.Request)

Source from the content-addressed store, hash-verified

312}
313
314func (s *Server) handleTunnel(w http.ResponseWriter, r *http.Request) {
315 if r.Method != http.MethodPost {
316 w.WriteHeader(http.StatusMethodNotAllowed)
317 return
318 }
319 s.stats.requests.Add(1)
320 body, err := readTunnelRequestBody(r.Body, r.ContentLength, maxRequestBodyBytes)
321 if err != nil {
322 log.Printf("[exit] read body: %v", err)
323 if errors.Is(err, errRequestTooLarge) {
324 w.WriteHeader(http.StatusRequestEntityTooLarge)
325 } else {
326 w.WriteHeader(http.StatusBadRequest)
327 }
328 return
329 }
330
331 clientID, rxFrames, err := frame.DecodeBatch(s.aead, body)
332 if err != nil {
333 s.stats.decodeFailures.Add(1)
334 // Decode failure on the very first batch from a client almost always
335 // means the AES key on the client does not match this server's key.
336 log.Printf("[exit] decode batch failed: %v (likely tunnel_key mismatch — confirm client config matches this server's tunnel_key)", err)
337 w.WriteHeader(http.StatusNoContent)
338 return
339 }
340
341 if len(rxFrames) > 0 {
342 var bytesIn uint64
343 for _, f := range rxFrames {
344 bytesIn += uint64(len(f.Payload))
345 }
346 s.stats.framesIn.Add(uint64(len(rxFrames)))
347 s.stats.bytesIn.Add(bytesIn)
348 }
349
350 // Process SYN frames in parallel — each routeIncoming on a SYN may dial
351 // upstream synchronously, and a single bad target (typo'd / stale DNS /
352 // unroutable IP) used to block every other SYN behind it for the full
353 // dial timeout. Non-SYN frames are still routed sequentially after the
354 // SYN goroutines finish so a DATA frame that lands in the same batch as
355 // its own SYN doesn't race the openSession registration.
356 var synWG sync.WaitGroup
357 for _, f := range rxFrames {
358 if f.HasFlag(frame.FlagSYN) {
359 synWG.Add(1)
360 go func(f *frame.Frame) {
361 defer synWG.Done()
362 s.routeIncoming(f, clientID)
363 }(f)
364 }
365 }
366 synWG.Wait()
367 for _, f := range rxFrames {
368 if !f.HasFlag(frame.FlagSYN) {
369 s.routeIncoming(f, clientID)
370 }
371 }

Callers 3

invokeExitTunnelFunction · 0.80
invokeAsClientFunction · 0.80

Calls 11

routeIncomingMethod · 0.95
activityForMethod · 0.95
drainWindowMethod · 0.95
drainAllMethod · 0.95
coalesceDurationMethod · 0.95
gcDoneSessionsMethod · 0.95
DecodeBatchFunction · 0.92
EncodeBatchFunction · 0.92
readTunnelRequestBodyFunction · 0.85
HasFlagMethod · 0.80
WriteMethod · 0.45

Tested by 3

invokeExitTunnelFunction · 0.64
invokeAsClientFunction · 0.64