77 lines
1.5 KiB
Go
77 lines
1.5 KiB
Go
/*
|
|
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
|
*/
|
|
package handler
|
|
|
|
import (
|
|
"io"
|
|
"net"
|
|
"net/http"
|
|
"strings"
|
|
"sync"
|
|
|
|
"mproxy/app/router"
|
|
)
|
|
|
|
func (hand *Handler) ConnectTo(rctx *router.Context) {
|
|
hostaddr := rctx.GetHost()
|
|
hand.logg.Debugf("Hostaddr: [%s]", hostaddr)
|
|
|
|
if strings.Contains(hostaddr, "https://") {
|
|
hand.logg.Errorf("Wrong request, found schema definition in Host")
|
|
rctx.SetStatus(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
destConn, err := net.Dial("tcp", hostaddr)
|
|
if err != nil {
|
|
hand.logg.Errorf("ConnectTo error: %v", err)
|
|
rctx.SetStatus(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
hand.logg.Errorf("ConnectTo error: %v", err)
|
|
rctx.SetStatus(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
defer destConn.Close()
|
|
hijacker, hijackerOk := rctx.Writer.(http.Hijacker)
|
|
if !hijackerOk {
|
|
hand.logg.Errorf("Hijacking not OK")
|
|
rctx.SetStatus(http.StatusInternalServerError)
|
|
return
|
|
|
|
}
|
|
rctx.SetStatus(http.StatusOK)
|
|
clientConn, _, err := hijacker.Hijack()
|
|
if err != nil {
|
|
hand.logg.Errorf("Hijacking error: %v", err)
|
|
rctx.SetStatus(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
var wg sync.WaitGroup
|
|
copyTo := func() {
|
|
defer wg.Done()
|
|
_, err = io.Copy(clientConn, destConn)
|
|
if err != nil {
|
|
hand.logg.Errorf("CopyTo error: %v", err)
|
|
return
|
|
}
|
|
}
|
|
copyFrom := func() {
|
|
defer wg.Done()
|
|
_, err = io.Copy(destConn, clientConn)
|
|
if err != nil {
|
|
hand.logg.Errorf("CopyFrom error: %v", err)
|
|
return
|
|
}
|
|
}
|
|
wg.Add(1)
|
|
go copyTo()
|
|
wg.Add(1)
|
|
go copyFrom()
|
|
wg.Wait()
|
|
return
|
|
}
|