command_close_connection.go 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. package libbox
  2. import (
  3. "bufio"
  4. "net"
  5. "github.com/sagernet/sing-box/experimental/clashapi"
  6. "github.com/sagernet/sing/common/binary"
  7. E "github.com/sagernet/sing/common/exceptions"
  8. "github.com/sagernet/sing/common/varbin"
  9. "github.com/gofrs/uuid/v5"
  10. )
  11. func (c *CommandClient) CloseConnection(connId string) error {
  12. conn, err := c.directConnect()
  13. if err != nil {
  14. return err
  15. }
  16. defer conn.Close()
  17. writer := bufio.NewWriter(conn)
  18. err = varbin.Write(writer, binary.BigEndian, connId)
  19. if err != nil {
  20. return err
  21. }
  22. err = writer.Flush()
  23. if err != nil {
  24. return err
  25. }
  26. return readError(conn)
  27. }
  28. func (s *CommandServer) handleCloseConnection(conn net.Conn) error {
  29. reader := bufio.NewReader(conn)
  30. var connId string
  31. err := varbin.Read(reader, binary.BigEndian, &connId)
  32. if err != nil {
  33. return E.Cause(err, "read connection id")
  34. }
  35. service := s.service
  36. if service == nil {
  37. return writeError(conn, E.New("service not ready"))
  38. }
  39. clashServer := service.instance.Router().ClashServer()
  40. if clashServer == nil {
  41. return writeError(conn, E.New("Clash API disabled"))
  42. }
  43. targetConn := clashServer.(*clashapi.Server).TrafficManager().Connection(uuid.FromStringOrNil(connId))
  44. if targetConn == nil {
  45. return writeError(conn, E.New("connection already closed"))
  46. }
  47. targetConn.Close()
  48. return writeError(conn, nil)
  49. }