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. err = binary.Write(conn, binary.BigEndian, uint8(CommandCloseConnection))
  18. if err != nil {
  19. return err
  20. }
  21. writer := bufio.NewWriter(conn)
  22. err = varbin.Write(writer, binary.BigEndian, connId)
  23. if err != nil {
  24. return err
  25. }
  26. err = writer.Flush()
  27. if err != nil {
  28. return err
  29. }
  30. return readError(conn)
  31. }
  32. func (s *CommandServer) handleCloseConnection(conn net.Conn) error {
  33. reader := bufio.NewReader(conn)
  34. var connId string
  35. err := varbin.Read(reader, binary.BigEndian, &connId)
  36. if err != nil {
  37. return E.Cause(err, "read connection id")
  38. }
  39. service := s.service
  40. if service == nil {
  41. return writeError(conn, E.New("service not ready"))
  42. }
  43. targetConn := service.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. }