Feat: 代码提交
This commit is contained in:
@@ -0,0 +1,265 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"computer-network/admin"
|
||||
"computer-network/config"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
listener net.Listener
|
||||
config *config.Config
|
||||
handler *Handler
|
||||
mu sync.RWMutex
|
||||
running bool
|
||||
stopChan chan struct{}
|
||||
}
|
||||
|
||||
func NewServer(cfg *config.Config) *Server {
|
||||
return &Server{
|
||||
config: cfg,
|
||||
handler: NewHandler(cfg.GetRootDir()),
|
||||
stopChan: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) Start() error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
if s.running {
|
||||
return fmt.Errorf("server is already running")
|
||||
}
|
||||
|
||||
var err error
|
||||
addr := fmt.Sprintf(":%d", s.config.GetPort())
|
||||
s.listener, err = net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to listen on port %d: %v", s.config.GetPort(), err)
|
||||
}
|
||||
|
||||
s.running = true
|
||||
fmt.Printf("Web Server started on port %d\n", s.config.GetPort())
|
||||
fmt.Printf("Root directory: %s\n", s.config.GetRootDir())
|
||||
fmt.Printf("Admin console: http://localhost:%d\n", s.config.GetAdminPort())
|
||||
|
||||
go s.acceptConnections()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) acceptConnections() {
|
||||
for {
|
||||
select {
|
||||
case <-s.stopChan:
|
||||
return
|
||||
default:
|
||||
conn, err := s.listener.Accept()
|
||||
if err != nil {
|
||||
select {
|
||||
case <-s.stopChan:
|
||||
return
|
||||
default:
|
||||
fmt.Printf("Error accepting connection: %v\n", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
go s.handler.HandleConnection(conn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) Stop() error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
if !s.running {
|
||||
return fmt.Errorf("server is not running")
|
||||
}
|
||||
|
||||
close(s.stopChan)
|
||||
s.running = false
|
||||
|
||||
if s.listener != nil {
|
||||
err := s.listener.Close()
|
||||
if err != nil {
|
||||
fmt.Printf("Error closing listener: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("Web Server stopped")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) IsRunning() bool {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
return s.running
|
||||
}
|
||||
|
||||
func (s *Server) GetPort() int {
|
||||
return s.config.GetPort()
|
||||
}
|
||||
|
||||
func (s *Server) UpdateConfig(cfg *config.Config) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.config = cfg
|
||||
s.handler = NewHandler(cfg.GetRootDir())
|
||||
}
|
||||
|
||||
type AdminServer struct {
|
||||
listener net.Listener
|
||||
config *config.Config
|
||||
adminHandler *admin.AdminHandler
|
||||
webServer *Server
|
||||
mu sync.RWMutex
|
||||
running bool
|
||||
stopChan chan struct{}
|
||||
}
|
||||
|
||||
func NewAdminServer(cfg *config.Config) *AdminServer {
|
||||
return &AdminServer{
|
||||
config: cfg,
|
||||
adminHandler: admin.NewAdminHandler(),
|
||||
stopChan: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
func (as *AdminServer) SetWebServer(ws *Server) {
|
||||
as.mu.Lock()
|
||||
defer as.mu.Unlock()
|
||||
as.webServer = ws
|
||||
}
|
||||
|
||||
func (as *AdminServer) Start() error {
|
||||
as.mu.Lock()
|
||||
defer as.mu.Unlock()
|
||||
|
||||
if as.running {
|
||||
return fmt.Errorf("admin server is already running")
|
||||
}
|
||||
|
||||
var err error
|
||||
addr := fmt.Sprintf(":%d", as.config.GetAdminPort())
|
||||
as.listener, err = net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to listen on admin port %d: %v", as.config.GetAdminPort(), err)
|
||||
}
|
||||
|
||||
as.running = true
|
||||
fmt.Printf("Admin server started on port %d\n", as.config.GetAdminPort())
|
||||
|
||||
go as.acceptConnections()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (as *AdminServer) acceptConnections() {
|
||||
for {
|
||||
select {
|
||||
case <-as.stopChan:
|
||||
return
|
||||
default:
|
||||
conn, err := as.listener.Accept()
|
||||
if err != nil {
|
||||
select {
|
||||
case <-as.stopChan:
|
||||
return
|
||||
default:
|
||||
fmt.Printf("Error accepting admin connection: %v\n", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
go as.handleAdminConnection(conn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (as *AdminServer) handleAdminConnection(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
|
||||
reader := bufio.NewReader(conn)
|
||||
req, err := ParseRequest(reader)
|
||||
if err != nil {
|
||||
response := BuildErrorResponse(StatusBadRequest, "", as.config.GetRootDir())
|
||||
SendResponse(conn, response)
|
||||
return
|
||||
}
|
||||
|
||||
if !req.IsGET() && req.Method != "DELETE" {
|
||||
response := BuildErrorResponse(StatusNotImplemented, "", as.config.GetRootDir())
|
||||
SendResponse(conn, response)
|
||||
return
|
||||
}
|
||||
|
||||
path := req.GetPath()
|
||||
var response *Response
|
||||
|
||||
switch path {
|
||||
case "/", "/index.html":
|
||||
httpResp := as.adminHandler.GetIndexPage()
|
||||
response = convertAdminResponse(httpResp)
|
||||
case "/api/logs":
|
||||
if req.IsGET() {
|
||||
httpResp := as.adminHandler.GetLogsJSON()
|
||||
response = convertAdminResponse(httpResp)
|
||||
} else if req.Method == "DELETE" {
|
||||
httpResp := as.adminHandler.ClearLogs()
|
||||
response = convertAdminResponse(httpResp)
|
||||
} else {
|
||||
response = BuildErrorResponse(StatusNotImplemented, "", as.config.GetRootDir())
|
||||
}
|
||||
case "/logs":
|
||||
httpResp := as.adminHandler.GetLogsPage()
|
||||
response = convertAdminResponse(httpResp)
|
||||
case "/api/status":
|
||||
webServerRunning := as.webServer != nil && as.webServer.IsRunning()
|
||||
webServerPort := 9000
|
||||
if as.webServer != nil {
|
||||
webServerPort = as.webServer.GetPort()
|
||||
}
|
||||
|
||||
statusBody := fmt.Sprintf(`{"running":%t,"port":%d}`, webServerRunning, webServerPort)
|
||||
response = NewResponse("200 OK", statusBody, "application/json")
|
||||
default:
|
||||
response = BuildErrorResponse(StatusNotFound, "", as.config.GetRootDir())
|
||||
}
|
||||
|
||||
SendResponse(conn, response)
|
||||
}
|
||||
|
||||
func (as *AdminServer) Stop() error {
|
||||
as.mu.Lock()
|
||||
defer as.mu.Unlock()
|
||||
|
||||
if !as.running {
|
||||
return fmt.Errorf("admin server is not running")
|
||||
}
|
||||
|
||||
close(as.stopChan)
|
||||
as.running = false
|
||||
|
||||
if as.listener != nil {
|
||||
err := as.listener.Close()
|
||||
if err != nil {
|
||||
fmt.Printf("Error closing admin listener: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("Admin server stopped")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (as *AdminServer) IsRunning() bool {
|
||||
as.mu.RLock()
|
||||
defer as.mu.RUnlock()
|
||||
return as.running
|
||||
}
|
||||
|
||||
func convertAdminResponse(resp *admin.HTTPResponse) *Response {
|
||||
return NewResponse(resp.StatusCode, resp.Body, resp.ContentType)
|
||||
}
|
||||
Reference in New Issue
Block a user