2016-06-14 16:54:08 -04:00
|
|
|
package kcp
|
|
|
|
|
|
|
|
import (
|
2016-09-30 10:53:40 -04:00
|
|
|
"crypto/tls"
|
2016-06-14 18:30:11 -04:00
|
|
|
"net"
|
2016-11-27 02:58:31 -05:00
|
|
|
"sync"
|
2016-07-12 12:54:16 -04:00
|
|
|
"sync/atomic"
|
2016-12-08 10:27:41 -05:00
|
|
|
|
|
|
|
"crypto/cipher"
|
|
|
|
|
2016-11-27 02:58:31 -05:00
|
|
|
"v2ray.com/core/common/alloc"
|
2016-08-20 14:55:45 -04:00
|
|
|
"v2ray.com/core/common/dice"
|
2016-12-08 10:27:41 -05:00
|
|
|
"v2ray.com/core/common/errors"
|
2016-08-20 14:55:45 -04:00
|
|
|
"v2ray.com/core/common/log"
|
|
|
|
v2net "v2ray.com/core/common/net"
|
|
|
|
"v2ray.com/core/transport/internet"
|
2016-11-27 02:58:31 -05:00
|
|
|
"v2ray.com/core/transport/internet/internal"
|
2016-09-30 10:53:40 -04:00
|
|
|
v2tls "v2ray.com/core/transport/internet/tls"
|
2016-06-14 16:54:08 -04:00
|
|
|
)
|
|
|
|
|
2016-07-12 12:54:16 -04:00
|
|
|
var (
|
|
|
|
globalConv = uint32(dice.Roll(65536))
|
2016-11-27 02:58:31 -05:00
|
|
|
globalPool = internal.NewConnectionPool()
|
2016-07-12 12:54:16 -04:00
|
|
|
)
|
|
|
|
|
2016-11-27 02:58:31 -05:00
|
|
|
type ClientConnection struct {
|
2016-12-08 10:27:41 -05:00
|
|
|
sync.RWMutex
|
2016-11-27 02:58:31 -05:00
|
|
|
net.Conn
|
2016-12-08 10:27:41 -05:00
|
|
|
id internal.ConnectionId
|
|
|
|
input func([]Segment)
|
|
|
|
reader PacketReader
|
|
|
|
writer PacketWriter
|
|
|
|
}
|
|
|
|
|
|
|
|
func (o *ClientConnection) Overhead() int {
|
|
|
|
o.RLock()
|
|
|
|
defer o.RUnlock()
|
|
|
|
if o.writer == nil {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
return o.writer.Overhead()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (o *ClientConnection) Write(b []byte) (int, error) {
|
|
|
|
o.RLock()
|
|
|
|
defer o.RUnlock()
|
|
|
|
|
|
|
|
if o.writer == nil {
|
|
|
|
return len(b), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return o.writer.Write(b)
|
2016-11-27 02:58:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func (o *ClientConnection) Read([]byte) (int, error) {
|
|
|
|
panic("KCP|ClientConnection: Read should not be called.")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (o *ClientConnection) Id() internal.ConnectionId {
|
|
|
|
return o.id
|
|
|
|
}
|
|
|
|
|
|
|
|
func (o *ClientConnection) Close() error {
|
|
|
|
return o.Conn.Close()
|
|
|
|
}
|
|
|
|
|
2016-12-08 10:27:41 -05:00
|
|
|
func (o *ClientConnection) Reset(inputCallback func([]Segment)) {
|
2016-11-27 02:58:31 -05:00
|
|
|
o.Lock()
|
|
|
|
o.input = inputCallback
|
2016-12-08 10:27:41 -05:00
|
|
|
o.Unlock()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (o *ClientConnection) ResetSecurity(header internet.PacketHeader, security cipher.AEAD) {
|
|
|
|
o.Lock()
|
|
|
|
if o.reader == nil {
|
|
|
|
o.reader = new(KCPPacketReader)
|
|
|
|
}
|
|
|
|
o.reader.(*KCPPacketReader).Header = header
|
|
|
|
o.reader.(*KCPPacketReader).Security = security
|
|
|
|
if o.writer == nil {
|
|
|
|
o.writer = new(KCPPacketWriter)
|
|
|
|
}
|
|
|
|
o.writer.(*KCPPacketWriter).Header = header
|
|
|
|
o.writer.(*KCPPacketWriter).Security = security
|
|
|
|
o.writer.(*KCPPacketWriter).Writer = o.Conn
|
|
|
|
|
2016-11-27 02:58:31 -05:00
|
|
|
o.Unlock()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (o *ClientConnection) Run() {
|
|
|
|
payload := alloc.NewSmallBuffer()
|
|
|
|
defer payload.Release()
|
|
|
|
|
|
|
|
for {
|
2016-12-06 05:03:42 -05:00
|
|
|
payload.Clear()
|
|
|
|
_, err := payload.FillFrom(o.Conn)
|
2016-11-27 02:58:31 -05:00
|
|
|
if err != nil {
|
|
|
|
payload.Release()
|
|
|
|
return
|
|
|
|
}
|
2016-12-08 10:27:41 -05:00
|
|
|
o.RLock()
|
|
|
|
if o.input != nil {
|
|
|
|
segments := o.reader.Read(payload.Bytes())
|
|
|
|
if len(segments) > 0 {
|
|
|
|
o.input(segments)
|
|
|
|
}
|
2016-11-27 02:58:31 -05:00
|
|
|
}
|
2016-12-08 10:27:41 -05:00
|
|
|
o.RUnlock()
|
2016-11-27 02:58:31 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-30 10:53:40 -04:00
|
|
|
func DialKCP(src v2net.Address, dest v2net.Destination, options internet.DialerOptions) (internet.Connection, error) {
|
2016-09-20 05:53:05 -04:00
|
|
|
dest.Network = v2net.Network_UDP
|
|
|
|
log.Info("KCP|Dialer: Dialing KCP to ", dest)
|
2016-11-27 02:58:31 -05:00
|
|
|
|
|
|
|
id := internal.NewConnectionId(src, dest)
|
|
|
|
conn := globalPool.Get(id)
|
|
|
|
if conn == nil {
|
|
|
|
rawConn, err := internet.DialToDest(src, dest)
|
|
|
|
if err != nil {
|
|
|
|
log.Error("KCP|Dialer: Failed to dial to dest: ", err)
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
c := &ClientConnection{
|
|
|
|
Conn: rawConn,
|
|
|
|
id: id,
|
|
|
|
}
|
|
|
|
go c.Run()
|
|
|
|
conn = c
|
2016-06-14 16:54:08 -04:00
|
|
|
}
|
2016-06-14 18:30:11 -04:00
|
|
|
|
2016-10-02 17:43:58 -04:00
|
|
|
networkSettings, err := options.Stream.GetEffectiveNetworkSettings()
|
|
|
|
if err != nil {
|
|
|
|
log.Error("KCP|Dialer: Failed to get KCP settings: ", err)
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
kcpSettings := networkSettings.(*Config)
|
|
|
|
|
2016-12-08 10:27:41 -05:00
|
|
|
clientConn := conn.(*ClientConnection)
|
|
|
|
header, err := kcpSettings.GetPackerHeader()
|
2016-08-06 15:59:22 -04:00
|
|
|
if err != nil {
|
2016-12-08 10:27:41 -05:00
|
|
|
return nil, errors.Base(err).Message("KCP|Dialer: Failed to create packet header.")
|
|
|
|
}
|
|
|
|
security, err := kcpSettings.GetSecurity()
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Base(err).Message("KCP|Dialer: Failed to create security.")
|
2016-08-06 15:59:22 -04:00
|
|
|
}
|
2016-12-08 10:27:41 -05:00
|
|
|
clientConn.ResetSecurity(header, security)
|
2016-07-12 12:54:16 -04:00
|
|
|
conv := uint16(atomic.AddUint32(&globalConv, 1))
|
2016-12-08 10:27:41 -05:00
|
|
|
session := NewConnection(conv, clientConn, globalPool, kcpSettings)
|
2016-06-17 10:51:41 -04:00
|
|
|
|
2016-09-30 10:53:40 -04:00
|
|
|
var iConn internet.Connection
|
|
|
|
iConn = session
|
|
|
|
|
2016-10-16 08:22:21 -04:00
|
|
|
if options.Stream != nil && options.Stream.HasSecuritySettings() {
|
2016-10-02 17:43:58 -04:00
|
|
|
securitySettings, err := options.Stream.GetEffectiveSecuritySettings()
|
|
|
|
if err != nil {
|
2016-10-16 08:22:21 -04:00
|
|
|
log.Error("KCP|Dialer: Failed to get security settings: ", err)
|
2016-10-02 17:43:58 -04:00
|
|
|
return nil, err
|
|
|
|
}
|
2016-10-16 08:22:21 -04:00
|
|
|
switch securitySettings := securitySettings.(type) {
|
|
|
|
case *v2tls.Config:
|
|
|
|
config := securitySettings.GetTLSConfig()
|
|
|
|
if dest.Address.Family().IsDomain() {
|
|
|
|
config.ServerName = dest.Address.Domain()
|
|
|
|
}
|
|
|
|
tlsConn := tls.Client(conn, config)
|
|
|
|
iConn = v2tls.NewConnection(tlsConn)
|
2016-09-30 10:53:40 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return iConn, nil
|
2016-06-14 16:54:08 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
internet.KCPDialer = DialKCP
|
|
|
|
}
|