MCPcopy Create free account
hub / github.com/Invisv-Privacy/masque / CreateUDPStream

Method CreateUDPStream

http2/client.go:540–609  ·  view source on GitHub ↗

CreateUDPStream creates a UDP stream to the given address using the client. This function should ONLY be called after calling |ConnectToProxy| successfully. If it succeeds, return a Conn struct that provides a pair of I/O interfaces. Users can then use the provided I/O interfaces to communicate wit

(addr string)

Source from the content-addressed store, hash-verified

538// Otherwise, it returns nil and indicates the error. It refills the connection for
539// the next call.
540func (c *Client) CreateUDPStream(addr string) (*Conn, error) {
541 if c.tlsConn == nil {
542 newTr, err := c.dialProxyViaTLS()
543 if err == nil {
544 c.tlsConn = newTr
545 } else {
546 return nil, fmt.Errorf("TLS. Failed to start a new tls conn to proxy. %v", err)
547 }
548 }
549
550 ipPort, err := netaddr.ParseIPPort(addr)
551 if err != nil {
552 return nil, errors.New("an invalid destination addr: not a IPPort")
553 }
554
555 // Note: do not reuse a TLS connection. otherwise, the response is likely to be an error response.
556 tr := c.tlsConn
557 c.tlsConn = nil
558
559 // Craft a HTTP/1.1 CONNECT-UDP request
560 req := fmt.Sprintf("CONNECT-UDP masque://%s/ HTTP/1.1\r\nHost: %s\r\nProxy-Authorization: PrivacyToken token=%s\r\n\r\n",
561 ipPort.String(), ipPort.String(), c.authToken)
562
563 // Send the request and receive the CONNECT-UDP response
564 if _, err = tr.Write([]byte(req)); err != nil {
565 return nil, fmt.Errorf("failed to send a CONNECT-UDP request. %v", err)
566 }
567
568 br := bufio.NewReader(tr)
569 resp, err := http.ReadResponse(br, nil)
570
571 if err != nil {
572 if err := tr.Close(); err != nil {
573 c.logger.Error("Error from tr.Close", "err", err)
574 }
575 return nil, fmt.Errorf("reading HTTP response from CONNECT-UDP to %s via proxy %s failed: %v",
576 addr, c.proxyAddr, err)
577 }
578 if resp.StatusCode != 200 {
579 return nil, fmt.Errorf("proxy error from %s while dialing %s: %v",
580 c.proxyAddr, addr, resp.Status)
581 }
582
583 c.mu.Lock()
584 // We have to use two pairs of I/O pipe here because of encoding/decoding.
585 // TODO: switch to use buffered writer for the input channel
586 inR, inW := io.Pipe()
587 outR, outW := io.Pipe()
588 ctx, cancel := context.WithCancel(context.Background())
589 udp := &Conn{
590 sid: getNextUdpStreamID(),
591 IoInc: inW,
592 IoOut: outR,
593 transport: tr,
594 alive: true,
595 connCtx: ctx,
596 connCancel: cancel,
597 isTcp: false,

Callers 2

TestCreateUDPStreamFunction · 0.95
HandleConnectMasqueFunction · 0.45

Calls 7

dialProxyViaTLSMethod · 0.95
connCleanupMethod · 0.95
encodeLoopUDPMethod · 0.95
decodeLoopUDPMethod · 0.95
getNextUdpStreamIDFunction · 0.85
WriteMethod · 0.45
CloseMethod · 0.45

Tested by 1

TestCreateUDPStreamFunction · 0.76