add code and complete first websocket frame
This commit is contained in:
commit
58fdc6c64d
|
@ -0,0 +1,3 @@
|
|||
# go http tunnel
|
||||
|
||||
create tcp tunnel with websocket pipe
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"host":"0.0.0.0",
|
||||
"port":"8080",
|
||||
"log":{
|
||||
"appenders":{
|
||||
"console":{
|
||||
"type":"console"
|
||||
}
|
||||
},
|
||||
"categories":{
|
||||
"default":{
|
||||
"appenders":["console"],
|
||||
"level":"debug"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
module git.pyer.club/kingecg/gotunnelserver
|
||||
|
||||
go 1.23.1
|
||||
|
||||
require (
|
||||
git.pyer.club/kingecg/gologger v1.0.5 // indirect
|
||||
github.com/gorilla/websocket v1.5.3 // indirect
|
||||
)
|
|
@ -0,0 +1,4 @@
|
|||
git.pyer.club/kingecg/gologger v1.0.5 h1:L/N/bleGHhEiaBYBf9U1z2ni0HfhaU71pk8ik/D11oo=
|
||||
git.pyer.club/kingecg/gologger v1.0.5/go.mod h1:SNSl2jRHPzIpHSzdKOoVG798rtYMjPDPFyxUrEgivkY=
|
||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
|
@ -0,0 +1,13 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"git.pyer.club/kingecg/gotunnelserver/server"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := server.New("")
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
s.Start()
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
func (s *Server) HandleAgent(c *websocket.Conn, r *http.Request) {
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
func (s *Server) HandleClient(conn *websocket.Conn, r *http.Request) {
|
||||
conn.WriteMessage(websocket.TextMessage, []byte("hello"))
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
func (s *Server) HandlePipe(conn *websocket.Conn, r *http.Request) {
|
||||
conn.WriteMessage(websocket.TextMessage, []byte("hello"))
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"net/http"
|
||||
|
||||
"git.pyer.club/kingecg/gologger"
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
var upgrader = websocket.Upgrader{
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
Port string `json:"port"`
|
||||
Host string `json:"host"`
|
||||
Cert string `json:"cert"`
|
||||
Key string `json:"key"`
|
||||
Logger *gologger.LoggersConfig `json:"log"`
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
*http.Server
|
||||
mux *http.ServeMux
|
||||
Config *ServerConfig
|
||||
logger *gologger.Logger
|
||||
}
|
||||
|
||||
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
s.logger.Info("request:", r.URL.Path)
|
||||
|
||||
if !s.auth(r) {
|
||||
s.HandleUnAutherized(w, r)
|
||||
} else {
|
||||
s.mux.ServeHTTP(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) auth(r *http.Request) bool {
|
||||
s.logger.Info("auth:", r.RemoteAddr)
|
||||
return true
|
||||
}
|
||||
func (s *Server) Shutdown() {
|
||||
s.logger.Info("shutdown server")
|
||||
s.Close()
|
||||
}
|
||||
|
||||
func (s *Server) HandleHello(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("hello"))
|
||||
}
|
||||
|
||||
func (s *Server) HandleUnAutherized(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
}
|
||||
func (s *Server) HandleWs(w http.ResponseWriter, r *http.Request) {
|
||||
lpath := r.URL.Path
|
||||
lpath = strings.TrimPrefix(lpath, "/ws/")
|
||||
c, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
s.logger.Error("upgrade failed:", err)
|
||||
return
|
||||
}
|
||||
if strings.HasPrefix(lpath, "client") {
|
||||
s.HandleClient(c, r)
|
||||
} else if strings.HasPrefix(lpath, "agent") {
|
||||
s.HandleAgent(c, r)
|
||||
} else if strings.HasPrefix(lpath, "pipe") {
|
||||
s.HandlePipe(c, r)
|
||||
} else {
|
||||
s.logger.Error("unknown path:", lpath)
|
||||
c.Close()
|
||||
}
|
||||
}
|
||||
func (s *Server) registHandler() {
|
||||
if s.mux == nil {
|
||||
s.mux = http.NewServeMux()
|
||||
}
|
||||
s.mux.HandleFunc("/hello", s.HandleHello)
|
||||
s.mux.HandleFunc("/ws", s.HandleWs)
|
||||
}
|
||||
func (s *Server) Start() {
|
||||
addr := s.Config.Host + ":" + s.Config.Port
|
||||
s.Server.Addr = addr
|
||||
|
||||
s.Server.Handler = s
|
||||
s.registHandler()
|
||||
if s.Config.Cert != "" && s.Config.Key != "" {
|
||||
s.logger.Info("start https server")
|
||||
s.ListenAndServeTLS(s.Config.Cert, s.Config.Key)
|
||||
} else {
|
||||
s.logger.Info("start http server")
|
||||
s.ListenAndServe()
|
||||
}
|
||||
}
|
||||
|
||||
func New(configFile string) *Server {
|
||||
// load config from configFile
|
||||
config, err := LoadConfig(configFile)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
gologger.Configure(*config.Logger)
|
||||
logger := gologger.GetLogger("server")
|
||||
logger.Info("create server")
|
||||
server := &Server{
|
||||
Server: &http.Server{},
|
||||
Config: config,
|
||||
logger: logger,
|
||||
}
|
||||
return server
|
||||
}
|
||||
|
||||
func LoadConfig(configFile string) (conf *ServerConfig, err error) {
|
||||
aconfPath := configFile
|
||||
if aconfPath == "" {
|
||||
aconfPath = "conf.json"
|
||||
}
|
||||
if !filepath.IsAbs(aconfPath) {
|
||||
aconfPath, _ = filepath.Abs(aconfPath)
|
||||
}
|
||||
fileConten, err := os.ReadFile(aconfPath)
|
||||
if err != nil {
|
||||
fmt.Printf("read config file failed: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
conf = new(ServerConfig)
|
||||
err = json.Unmarshal(fileConten, conf)
|
||||
if err != nil {
|
||||
fmt.Printf("parse config file failed: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
if conf.Cert != "" && conf.Key != "" {
|
||||
conf.Cert = Abs(filepath.Dir(aconfPath), conf.Cert)
|
||||
conf.Key = Abs(filepath.Dir(aconfPath), conf.Key)
|
||||
} else {
|
||||
conf.Cert = ""
|
||||
conf.Key = ""
|
||||
}
|
||||
return conf, nil
|
||||
}
|
||||
|
||||
func Abs(basePath string, path string) string {
|
||||
if filepath.IsAbs(path) {
|
||||
return path
|
||||
}
|
||||
return filepath.Join(basePath, path)
|
||||
}
|
Loading…
Reference in New Issue