github.com/xraypb/xray-core@v1.6.6/common/mux/server.go (about) 1 package mux 2 3 import ( 4 "context" 5 "io" 6 7 "github.com/xraypb/xray-core/common" 8 "github.com/xraypb/xray-core/common/buf" 9 "github.com/xraypb/xray-core/common/errors" 10 "github.com/xraypb/xray-core/common/log" 11 "github.com/xraypb/xray-core/common/net" 12 "github.com/xraypb/xray-core/common/protocol" 13 "github.com/xraypb/xray-core/common/session" 14 "github.com/xraypb/xray-core/core" 15 "github.com/xraypb/xray-core/features/routing" 16 "github.com/xraypb/xray-core/transport" 17 "github.com/xraypb/xray-core/transport/pipe" 18 ) 19 20 type Server struct { 21 dispatcher routing.Dispatcher 22 } 23 24 // NewServer creates a new mux.Server. 25 func NewServer(ctx context.Context) *Server { 26 s := &Server{} 27 core.RequireFeatures(ctx, func(d routing.Dispatcher) { 28 s.dispatcher = d 29 }) 30 return s 31 } 32 33 // Type implements common.HasType. 34 func (s *Server) Type() interface{} { 35 return s.dispatcher.Type() 36 } 37 38 // Dispatch implements routing.Dispatcher 39 func (s *Server) Dispatch(ctx context.Context, dest net.Destination) (*transport.Link, error) { 40 if dest.Address != muxCoolAddress { 41 return s.dispatcher.Dispatch(ctx, dest) 42 } 43 44 opts := pipe.OptionsFromContext(ctx) 45 uplinkReader, uplinkWriter := pipe.New(opts...) 46 downlinkReader, downlinkWriter := pipe.New(opts...) 47 48 _, err := NewServerWorker(ctx, s.dispatcher, &transport.Link{ 49 Reader: uplinkReader, 50 Writer: downlinkWriter, 51 }) 52 if err != nil { 53 return nil, err 54 } 55 56 return &transport.Link{Reader: downlinkReader, Writer: uplinkWriter}, nil 57 } 58 59 // DispatchLink implements routing.Dispatcher 60 func (s *Server) DispatchLink(ctx context.Context, dest net.Destination, link *transport.Link) error { 61 if dest.Address != muxCoolAddress { 62 return s.dispatcher.DispatchLink(ctx, dest, link) 63 } 64 _, err := NewServerWorker(ctx, s.dispatcher, link) 65 return err 66 } 67 68 // Start implements common.Runnable. 69 func (s *Server) Start() error { 70 return nil 71 } 72 73 // Close implements common.Closable. 74 func (s *Server) Close() error { 75 return nil 76 } 77 78 type ServerWorker struct { 79 dispatcher routing.Dispatcher 80 link *transport.Link 81 sessionManager *SessionManager 82 } 83 84 func NewServerWorker(ctx context.Context, d routing.Dispatcher, link *transport.Link) (*ServerWorker, error) { 85 worker := &ServerWorker{ 86 dispatcher: d, 87 link: link, 88 sessionManager: NewSessionManager(), 89 } 90 go worker.run(ctx) 91 return worker, nil 92 } 93 94 func handle(ctx context.Context, s *Session, output buf.Writer) { 95 writer := NewResponseWriter(s.ID, output, s.transferType) 96 if err := buf.Copy(s.input, writer); err != nil { 97 newError("session ", s.ID, " ends.").Base(err).WriteToLog(session.ExportIDToError(ctx)) 98 writer.hasError = true 99 } 100 101 writer.Close() 102 s.Close() 103 } 104 105 func (w *ServerWorker) ActiveConnections() uint32 { 106 return uint32(w.sessionManager.Size()) 107 } 108 109 func (w *ServerWorker) Closed() bool { 110 return w.sessionManager.Closed() 111 } 112 113 func (w *ServerWorker) handleStatusKeepAlive(meta *FrameMetadata, reader *buf.BufferedReader) error { 114 if meta.Option.Has(OptionData) { 115 return buf.Copy(NewStreamReader(reader), buf.Discard) 116 } 117 return nil 118 } 119 120 func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata, reader *buf.BufferedReader) error { 121 newError("received request for ", meta.Target).WriteToLog(session.ExportIDToError(ctx)) 122 { 123 msg := &log.AccessMessage{ 124 To: meta.Target, 125 Status: log.AccessAccepted, 126 Reason: "", 127 } 128 if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Source.IsValid() { 129 msg.From = inbound.Source 130 msg.Email = inbound.User.Email 131 } 132 ctx = log.ContextWithAccessMessage(ctx, msg) 133 } 134 link, err := w.dispatcher.Dispatch(ctx, meta.Target) 135 if err != nil { 136 if meta.Option.Has(OptionData) { 137 buf.Copy(NewStreamReader(reader), buf.Discard) 138 } 139 return newError("failed to dispatch request.").Base(err) 140 } 141 s := &Session{ 142 input: link.Reader, 143 output: link.Writer, 144 parent: w.sessionManager, 145 ID: meta.SessionID, 146 transferType: protocol.TransferTypeStream, 147 } 148 if meta.Target.Network == net.Network_UDP { 149 s.transferType = protocol.TransferTypePacket 150 } 151 w.sessionManager.Add(s) 152 go handle(ctx, s, w.link.Writer) 153 if !meta.Option.Has(OptionData) { 154 return nil 155 } 156 157 rr := s.NewReader(reader, &meta.Target) 158 if err := buf.Copy(rr, s.output); err != nil { 159 buf.Copy(rr, buf.Discard) 160 common.Interrupt(s.input) 161 return s.Close() 162 } 163 return nil 164 } 165 166 func (w *ServerWorker) handleStatusKeep(meta *FrameMetadata, reader *buf.BufferedReader) error { 167 if !meta.Option.Has(OptionData) { 168 return nil 169 } 170 171 s, found := w.sessionManager.Get(meta.SessionID) 172 if !found { 173 // Notify remote peer to close this session. 174 closingWriter := NewResponseWriter(meta.SessionID, w.link.Writer, protocol.TransferTypeStream) 175 closingWriter.Close() 176 177 return buf.Copy(NewStreamReader(reader), buf.Discard) 178 } 179 180 rr := s.NewReader(reader, &meta.Target) 181 err := buf.Copy(rr, s.output) 182 183 if err != nil && buf.IsWriteError(err) { 184 newError("failed to write to downstream writer. closing session ", s.ID).Base(err).WriteToLog() 185 186 // Notify remote peer to close this session. 187 closingWriter := NewResponseWriter(meta.SessionID, w.link.Writer, protocol.TransferTypeStream) 188 closingWriter.Close() 189 190 drainErr := buf.Copy(rr, buf.Discard) 191 common.Interrupt(s.input) 192 s.Close() 193 return drainErr 194 } 195 196 return err 197 } 198 199 func (w *ServerWorker) handleStatusEnd(meta *FrameMetadata, reader *buf.BufferedReader) error { 200 if s, found := w.sessionManager.Get(meta.SessionID); found { 201 if meta.Option.Has(OptionError) { 202 common.Interrupt(s.input) 203 common.Interrupt(s.output) 204 } 205 s.Close() 206 } 207 if meta.Option.Has(OptionData) { 208 return buf.Copy(NewStreamReader(reader), buf.Discard) 209 } 210 return nil 211 } 212 213 func (w *ServerWorker) handleFrame(ctx context.Context, reader *buf.BufferedReader) error { 214 var meta FrameMetadata 215 err := meta.Unmarshal(reader) 216 if err != nil { 217 return newError("failed to read metadata").Base(err) 218 } 219 220 switch meta.SessionStatus { 221 case SessionStatusKeepAlive: 222 err = w.handleStatusKeepAlive(&meta, reader) 223 case SessionStatusEnd: 224 err = w.handleStatusEnd(&meta, reader) 225 case SessionStatusNew: 226 err = w.handleStatusNew(ctx, &meta, reader) 227 case SessionStatusKeep: 228 err = w.handleStatusKeep(&meta, reader) 229 default: 230 status := meta.SessionStatus 231 return newError("unknown status: ", status).AtError() 232 } 233 234 if err != nil { 235 return newError("failed to process data").Base(err) 236 } 237 return nil 238 } 239 240 func (w *ServerWorker) run(ctx context.Context) { 241 input := w.link.Reader 242 reader := &buf.BufferedReader{Reader: input} 243 244 defer w.sessionManager.Close() 245 246 for { 247 select { 248 case <-ctx.Done(): 249 return 250 default: 251 err := w.handleFrame(ctx, reader) 252 if err != nil { 253 if errors.Cause(err) != io.EOF { 254 newError("unexpected EOF").Base(err).WriteToLog(session.ExportIDToError(ctx)) 255 common.Interrupt(input) 256 } 257 return 258 } 259 } 260 } 261 }