|
|
@@ -70,7 +70,6 @@ type UDPSession struct {
|
|
|
wd time.Time // write deadline
|
|
|
chReadEvent chan struct{}
|
|
|
chWriteEvent chan struct{}
|
|
|
- ackNoDelay bool
|
|
|
writer io.WriteCloser
|
|
|
since int64
|
|
|
}
|
|
|
@@ -88,7 +87,6 @@ func newUDPSession(conv uint32, writerCloser io.WriteCloser, local *net.UDPAddr,
|
|
|
|
|
|
mtu := uint32(effectiveConfig.Mtu - block.HeaderSize() - headerSize)
|
|
|
sess.kcp = NewKCP(conv, mtu, func(buf []byte, size int) {
|
|
|
- log.Info(sess.local, " kcp output: ", buf[:size])
|
|
|
if size >= IKCP_OVERHEAD {
|
|
|
ext := alloc.NewBuffer().Clear().Append(buf[:size])
|
|
|
cmd := cmdData
|
|
|
@@ -102,12 +100,10 @@ func newUDPSession(conv uint32, writerCloser io.WriteCloser, local *net.UDPAddr,
|
|
|
})
|
|
|
sess.kcp.WndSize(effectiveConfig.Sndwnd, effectiveConfig.Rcvwnd)
|
|
|
sess.kcp.NoDelay(1, 20, 2, 1)
|
|
|
- sess.ackNoDelay = effectiveConfig.Acknodelay
|
|
|
sess.kcp.current = sess.Elapsed()
|
|
|
|
|
|
go sess.updateTask()
|
|
|
|
|
|
- log.Info("Created KCP conn to ", sess.RemoteAddr())
|
|
|
return sess
|
|
|
}
|
|
|
|
|
|
@@ -158,7 +154,6 @@ func (s *UDPSession) Read(b []byte) (int, error) {
|
|
|
|
|
|
// Write implements the Conn Write method.
|
|
|
func (s *UDPSession) Write(b []byte) (int, error) {
|
|
|
- log.Info("Trying to write ", len(b), " bytes. ", s.local)
|
|
|
if s.state == ConnStateReadyToClose ||
|
|
|
s.state == ConnStatePeerClosed ||
|
|
|
s.state == ConnStateClosed {
|
|
|
@@ -166,44 +161,28 @@ func (s *UDPSession) Write(b []byte) (int, error) {
|
|
|
}
|
|
|
|
|
|
for {
|
|
|
- s.Lock()
|
|
|
if s.state == ConnStateReadyToClose ||
|
|
|
s.state == ConnStatePeerClosed ||
|
|
|
s.state == ConnStateClosed {
|
|
|
- s.Unlock()
|
|
|
return 0, io.ErrClosedPipe
|
|
|
}
|
|
|
|
|
|
- if !s.wd.IsZero() {
|
|
|
- if time.Now().After(s.wd) { // timeout
|
|
|
- s.Unlock()
|
|
|
- return 0, errTimeout
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
+ s.kcpAccess.Lock()
|
|
|
if s.kcp.WaitSnd() < int(s.kcp.snd_wnd) {
|
|
|
nBytes := len(b)
|
|
|
- log.Info("Writing ", nBytes, " bytes.", s.local)
|
|
|
s.kcp.Send(b)
|
|
|
s.kcp.current = s.Elapsed()
|
|
|
s.kcp.flush()
|
|
|
- s.Unlock()
|
|
|
+ s.kcpAccess.Unlock()
|
|
|
return nBytes, nil
|
|
|
}
|
|
|
+ s.kcpAccess.Unlock()
|
|
|
|
|
|
- var timeout <-chan time.Time
|
|
|
- if !s.wd.IsZero() {
|
|
|
- delay := s.wd.Sub(time.Now())
|
|
|
- timeout = time.After(delay)
|
|
|
- }
|
|
|
- s.Unlock()
|
|
|
-
|
|
|
- // wait for write event or timeout
|
|
|
- select {
|
|
|
- case <-s.chWriteEvent:
|
|
|
- case <-timeout:
|
|
|
+ if !s.wd.IsZero() && s.wd.Before(time.Now()) {
|
|
|
return 0, errTimeout
|
|
|
}
|
|
|
+
|
|
|
+ time.Sleep(time.Duration(s.kcp.WaitSnd()*5) * time.Millisecond)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -213,6 +192,9 @@ func (this *UDPSession) Terminate() {
|
|
|
}
|
|
|
this.Lock()
|
|
|
defer this.Unlock()
|
|
|
+ if this.state == ConnStateClosed {
|
|
|
+ return
|
|
|
+ }
|
|
|
|
|
|
this.state = ConnStateClosed
|
|
|
this.writer.Close()
|
|
|
@@ -223,7 +205,7 @@ func (this *UDPSession) NotifyTermination() {
|
|
|
this.Lock()
|
|
|
if this.state == ConnStateClosed {
|
|
|
this.Unlock()
|
|
|
- return
|
|
|
+ break
|
|
|
}
|
|
|
buffer := alloc.NewSmallBuffer().Clear()
|
|
|
buffer.AppendBytes(byte(CommandTerminate), byte(OptionClose), byte(0), byte(0), byte(0), byte(0))
|
|
|
@@ -236,7 +218,7 @@ func (this *UDPSession) NotifyTermination() {
|
|
|
|
|
|
// Close closes the connection.
|
|
|
func (s *UDPSession) Close() error {
|
|
|
- log.Info("Closed ", s.local)
|
|
|
+ log.Debug("KCP|Connection: Closing connection to ", s.remote)
|
|
|
s.Lock()
|
|
|
defer s.Unlock()
|
|
|
|
|
|
@@ -300,31 +282,11 @@ func (s *UDPSession) output(payload *alloc.Buffer) {
|
|
|
|
|
|
// kcp update, input loop
|
|
|
func (s *UDPSession) updateTask() {
|
|
|
- ticker := time.NewTicker(20 * time.Millisecond)
|
|
|
- defer ticker.Stop()
|
|
|
-
|
|
|
- var nextupdate uint32 = 0
|
|
|
- for range ticker.C {
|
|
|
- s.Lock()
|
|
|
- if s.state == ConnStateClosed {
|
|
|
- s.Unlock()
|
|
|
- return
|
|
|
- }
|
|
|
+ for s.state != ConnStateClosed {
|
|
|
current := s.Elapsed()
|
|
|
- if !s.needUpdate && nextupdate == 0 {
|
|
|
- nextupdate = s.kcp.Check(current)
|
|
|
- }
|
|
|
- current = s.Elapsed()
|
|
|
- if s.needUpdate || current >= nextupdate {
|
|
|
- log.Info("Updating KCP: ", current, " addr ", s.LocalAddr())
|
|
|
- s.kcp.Update(current)
|
|
|
- nextupdate = s.kcp.Check(current)
|
|
|
- s.needUpdate = false
|
|
|
- }
|
|
|
- if s.kcp.WaitSnd() < int(s.kcp.snd_wnd) {
|
|
|
- s.notifyWriteEvent()
|
|
|
- }
|
|
|
- s.Unlock()
|
|
|
+ s.kcp.Update(current)
|
|
|
+ interval := s.kcp.Check(s.Elapsed())
|
|
|
+ time.Sleep(time.Duration(interval) * time.Millisecond)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -367,16 +329,8 @@ func (s *UDPSession) kcpInput(data []byte) {
|
|
|
}
|
|
|
s.kcpAccess.Lock()
|
|
|
s.kcp.current = s.Elapsed()
|
|
|
- log.Info(s.local, " kcp input: ", data[2:])
|
|
|
- ret := s.kcp.Input(data[2:])
|
|
|
- log.Info("kcp input returns ", ret)
|
|
|
-
|
|
|
- if s.ackNoDelay {
|
|
|
- s.kcp.current = s.Elapsed()
|
|
|
- s.kcp.flush()
|
|
|
- } else {
|
|
|
- s.needUpdate = true
|
|
|
- }
|
|
|
+ s.kcp.Input(data[2:])
|
|
|
+
|
|
|
s.kcpAccess.Unlock()
|
|
|
s.notifyReadEvent()
|
|
|
}
|
|
|
@@ -391,8 +345,9 @@ func (this *UDPSession) FetchInputFrom(conn net.Conn) {
|
|
|
}
|
|
|
payload.Slice(0, nBytes)
|
|
|
if this.block.Open(payload) {
|
|
|
- log.Info("Client fetching ", payload.Len(), " bytes.")
|
|
|
this.kcpInput(payload.Value)
|
|
|
+ } else {
|
|
|
+ log.Info("KCP|Connection: Invalid response from ", conn.RemoteAddr())
|
|
|
}
|
|
|
payload.Release()
|
|
|
}
|