|
|
|
@ -211,40 +211,43 @@ func (m *Client) fetchOutput() {
|
|
|
|
|
defer m.cancel()
|
|
|
|
|
|
|
|
|
|
reader := NewReader(m.inboundRay.InboundOutput())
|
|
|
|
|
L:
|
|
|
|
|
for {
|
|
|
|
|
meta, err := reader.ReadMetadata()
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Trace(newError("failed to read metadata").Base(err))
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
if meta.SessionStatus == SessionStatusKeepAlive {
|
|
|
|
|
if meta.Option.Has(OptionData) {
|
|
|
|
|
if err := drain(reader); err != nil {
|
|
|
|
|
log.Trace(newError("failed to read data").Base(err))
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
var drainData bool
|
|
|
|
|
switch meta.SessionStatus {
|
|
|
|
|
case SessionStatusKeepAlive:
|
|
|
|
|
drainData = true
|
|
|
|
|
case SessionStatusEnd:
|
|
|
|
|
if s, found := m.sessionManager.Get(meta.SessionID); found {
|
|
|
|
|
s.CloseDownlink()
|
|
|
|
|
s.output.Close()
|
|
|
|
|
}
|
|
|
|
|
drainData = true
|
|
|
|
|
case SessionStatusNew:
|
|
|
|
|
drainData = true
|
|
|
|
|
case SessionStatusKeep:
|
|
|
|
|
if !meta.Option.Has(OptionData) {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
if s, found := m.sessionManager.Get(meta.SessionID); found {
|
|
|
|
|
if err := pipe(reader, s.output); err != nil {
|
|
|
|
|
log.Trace(newError("failed to pipe data").Base(err))
|
|
|
|
|
break L
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s, found := m.sessionManager.Get(meta.SessionID)
|
|
|
|
|
if found && meta.SessionStatus == SessionStatusEnd {
|
|
|
|
|
s.CloseDownlink()
|
|
|
|
|
s.output.Close()
|
|
|
|
|
}
|
|
|
|
|
if !meta.Option.Has(OptionData) {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if found {
|
|
|
|
|
err = pipe(reader, s.output)
|
|
|
|
|
} else {
|
|
|
|
|
err = drain(reader)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Trace(newError("failed to read data").Base(err))
|
|
|
|
|
break
|
|
|
|
|
if drainData && meta.Option.Has(OptionData) {
|
|
|
|
|
if err := drain(reader); err != nil {
|
|
|
|
|
log.Trace(newError("failed to drain data").Base(err))
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -300,6 +303,7 @@ func handle(ctx context.Context, s *Session, output buf.Writer) {
|
|
|
|
|
func (w *ServerWorker) run(ctx context.Context) {
|
|
|
|
|
input := w.outboundRay.OutboundInput()
|
|
|
|
|
reader := NewReader(input)
|
|
|
|
|
L:
|
|
|
|
|
for {
|
|
|
|
|
select {
|
|
|
|
|
case <-ctx.Done():
|
|
|
|
@ -313,30 +317,25 @@ func (w *ServerWorker) run(ctx context.Context) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if meta.SessionStatus == SessionStatusKeepAlive {
|
|
|
|
|
if meta.Option.Has(OptionData) {
|
|
|
|
|
if err := drain(reader); err != nil {
|
|
|
|
|
log.Trace(newError("failed to read data").Base(err))
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
var drainData bool
|
|
|
|
|
switch meta.SessionStatus {
|
|
|
|
|
case SessionStatusKeepAlive:
|
|
|
|
|
drainData = true
|
|
|
|
|
case SessionStatusEnd:
|
|
|
|
|
if s, found := w.sessionManager.Get(meta.SessionID); found {
|
|
|
|
|
s.CloseUplink()
|
|
|
|
|
s.output.Close()
|
|
|
|
|
}
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s, found := w.sessionManager.Get(meta.SessionID)
|
|
|
|
|
if found && meta.SessionStatus == SessionStatusEnd {
|
|
|
|
|
s.CloseUplink()
|
|
|
|
|
s.output.Close()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if meta.SessionStatus == SessionStatusNew {
|
|
|
|
|
drainData = true
|
|
|
|
|
case SessionStatusNew:
|
|
|
|
|
log.Trace(newError("received request for ", meta.Target))
|
|
|
|
|
inboundRay, err := w.dispatcher.Dispatch(ctx, meta.Target)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Trace(newError("failed to dispatch request.").Base(err))
|
|
|
|
|
continue
|
|
|
|
|
drainData = true
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
s = &Session{
|
|
|
|
|
s := &Session{
|
|
|
|
|
input: inboundRay.InboundOutput(),
|
|
|
|
|
output: inboundRay.InboundInput(),
|
|
|
|
|
parent: w.sessionManager,
|
|
|
|
@ -344,21 +343,30 @@ func (w *ServerWorker) run(ctx context.Context) {
|
|
|
|
|
}
|
|
|
|
|
w.sessionManager.Add(s)
|
|
|
|
|
go handle(ctx, s, w.outboundRay.OutboundOutput())
|
|
|
|
|
if !meta.Option.Has(OptionData) {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
if err := pipe(reader, s.output); err != nil {
|
|
|
|
|
log.Trace(newError("failed to read data").Base(err))
|
|
|
|
|
break L
|
|
|
|
|
}
|
|
|
|
|
case SessionStatusKeep:
|
|
|
|
|
if !meta.Option.Has(OptionData) {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
if s, found := w.sessionManager.Get(meta.SessionID); found {
|
|
|
|
|
if err := pipe(reader, s.output); err != nil {
|
|
|
|
|
log.Trace(newError("failed to read data").Base(err))
|
|
|
|
|
break L
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !meta.Option.Has(OptionData) {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if s != nil {
|
|
|
|
|
err = pipe(reader, s.output)
|
|
|
|
|
} else {
|
|
|
|
|
err = drain(reader)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Trace(newError("failed to read data").Base(err))
|
|
|
|
|
break
|
|
|
|
|
if meta.Option.Has(OptionData) && drainData {
|
|
|
|
|
if err := drain(reader); err != nil {
|
|
|
|
|
log.Trace(newError("failed to drain data").Base(err))
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|