command_close_connection.go 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  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/gofrs/uuid/v5"
  9. )
  10. func (c *CommandClient) CloseConnection(connId string) error {
  11. conn, err := c.directConnect()
  12. if err != nil {
  13. return err
  14. }
  15. defer conn.Close()
  16. writer := bufio.NewWriter(conn)
  17. err = binary.WriteData(writer, binary.BigEndian, connId)
  18. if err != nil {
  19. return err
  20. }
  21. err = writer.Flush()
  22. if err != nil {
  23. return err
  24. }
  25. return readError(conn)
  26. }
  27. func (s *CommandServer) handleCloseConnection(conn net.Conn) error {
  28. reader := bufio.NewReader(conn)
  29. var connId string
  30. err := binary.ReadData(reader, binary.BigEndian, &connId)
  31. if err != nil {
  32. return E.Cause(err, "read connection id")
  33. }
  34. service := s.service
  35. if service == nil {
  36. return writeError(conn, E.New("service not ready"))
  37. }
  38. clashServer := service.instance.Router().ClashServer()
  39. if clashServer == nil {
  40. return writeError(conn, E.New("Clash API disabled"))
  41. }
  42. targetConn := clashServer.(*clashapi.Server).TrafficManager().Connection(uuid.FromStringOrNil(connId))
  43. if targetConn == nil {
  44. return writeError(conn, E.New("connection already closed"))
  45. }
  46. targetConn.Close()
  47. return writeError(conn, nil)
  48. }