optimise tunnel nat udp module

This commit is contained in:
arraykeys@gmail.com
2018-09-05 11:43:53 +08:00
parent 462ae3deff
commit 6fb3457bd2
6 changed files with 241 additions and 162 deletions

View File

@ -36,6 +36,7 @@ type MuxClientArgs struct {
} }
type ClientUDPConnItem struct { type ClientUDPConnItem struct {
conn *smux.Stream conn *smux.Stream
isActive bool
touchtime int64 touchtime int64
srcAddr *net.UDPAddr srcAddr *net.UDPAddr
localAddr *net.UDPAddr localAddr *net.UDPAddr
@ -292,11 +293,6 @@ func (s *MuxClient) ServeUDP(inConn *smux.Stream, localAddr, ID string) {
} }
(*item).touchtime = time.Now().Unix() (*item).touchtime = time.Now().Unix()
go (*item).udpConn.Write(body) go (*item).udpConn.Write(body)
//_, err = (*item).udpConn.Write(body)
// if err != nil {
// s.log.Printf("send udp packet to %s fail, err : %s", item.localAddr, err)
// return
// }
} }
} }
func (s *MuxClient) UDPRevecive(key, ID string) { func (s *MuxClient) UDPRevecive(key, ID string) {
@ -334,16 +330,11 @@ func (s *MuxClient) UDPRevecive(key, ID string) {
return return
} }
}() }()
// _, err = cui.conn.Write(utils.UDPPacket(cui.srcAddr.String(), buf[:n]))
// if err != nil {
// s.log.Printf("send udp packet to bridge fail, err : %s", err)
// return
// }
} }
}() }()
} }
func (s *MuxClient) UDPGCDeamon() { func (s *MuxClient) UDPGCDeamon() {
gctime := int64(60) gctime := int64(30)
go func() { go func() {
if s.isStop { if s.isStop {
return return

View File

@ -173,6 +173,7 @@ func NewMuxServer() services.Service {
lockChn: make(chan bool, 1), lockChn: make(chan bool, 1),
sessions: mapx.NewConcurrentMap(), sessions: mapx.NewConcurrentMap(),
isStop: false, isStop: false,
udpConns: mapx.NewConcurrentMap(),
} }
} }
@ -181,7 +182,7 @@ type MuxUDPPacketItem struct {
localAddr *net.UDPAddr localAddr *net.UDPAddr
srcAddr *net.UDPAddr srcAddr *net.UDPAddr
} }
type UDPConnItem struct { type MuxUDPConnItem struct {
conn *net.Conn conn *net.Conn
touchtime int64 touchtime int64
srcAddr *net.UDPAddr srcAddr *net.UDPAddr
@ -429,7 +430,7 @@ func (s *MuxServer) getParentConn() (conn net.Conn, err error) {
return return
} }
func (s *MuxServer) UDPGCDeamon() { func (s *MuxServer) UDPGCDeamon() {
gctime := int64(60) gctime := int64(30)
go func() { go func() {
if s.isStop { if s.isStop {
return return
@ -439,10 +440,10 @@ func (s *MuxServer) UDPGCDeamon() {
<-timer.C <-timer.C
gcKeys := []string{} gcKeys := []string{}
s.udpConns.IterCb(func(key string, v interface{}) { s.udpConns.IterCb(func(key string, v interface{}) {
if time.Now().Unix()-v.(*UDPConnItem).touchtime > gctime { if time.Now().Unix()-v.(*MuxUDPConnItem).touchtime > gctime {
(*(v.(*UDPConnItem).conn)).Close() (*(v.(*MuxUDPConnItem).conn)).Close()
gcKeys = append(gcKeys, key) gcKeys = append(gcKeys, key)
s.log.Printf("gc udp conn %s", v.(*UDPConnItem).connid) s.log.Printf("gc udp conn %s", v.(*MuxUDPConnItem).connid)
} }
}) })
for _, k := range gcKeys { for _, k := range gcKeys {
@ -454,7 +455,7 @@ func (s *MuxServer) UDPGCDeamon() {
} }
func (s *MuxServer) UDPSend(data []byte, localAddr, srcAddr *net.UDPAddr) { func (s *MuxServer) UDPSend(data []byte, localAddr, srcAddr *net.UDPAddr) {
var ( var (
uc *UDPConnItem uc *MuxUDPConnItem
key = srcAddr.String() key = srcAddr.String()
ID string ID string
err error err error
@ -475,7 +476,7 @@ func (s *MuxServer) UDPSend(data []byte, localAddr, srcAddr *net.UDPAddr) {
s.log.Printf("connect to %s fail, err: %s", *s.cfg.Parent, err) s.log.Printf("connect to %s fail, err: %s", *s.cfg.Parent, err)
return return
} }
uc = &UDPConnItem{ uc = &MuxUDPConnItem{
conn: &outconn, conn: &outconn,
srcAddr: srcAddr, srcAddr: srcAddr,
localAddr: localAddr, localAddr: localAddr,
@ -484,7 +485,7 @@ func (s *MuxServer) UDPSend(data []byte, localAddr, srcAddr *net.UDPAddr) {
s.udpConns.Set(key, uc) s.udpConns.Set(key, uc)
s.UDPRevecive(key, ID) s.UDPRevecive(key, ID)
} else { } else {
uc = v.(*UDPConnItem) uc = v.(*MuxUDPConnItem)
} }
go func() { go func() {
defer func() { defer func() {
@ -506,7 +507,7 @@ func (s *MuxServer) UDPSend(data []byte, localAddr, srcAddr *net.UDPAddr) {
func (s *MuxServer) UDPRevecive(key, ID string) { func (s *MuxServer) UDPRevecive(key, ID string) {
go func() { go func() {
s.log.Printf("udp conn %s connected", ID) s.log.Printf("udp conn %s connected", ID)
var uc *UDPConnItem var uc *MuxUDPConnItem
defer func() { defer func() {
if uc != nil { if uc != nil {
(*uc.conn).Close() (*uc.conn).Close()
@ -519,7 +520,7 @@ func (s *MuxServer) UDPRevecive(key, ID string) {
s.log.Printf("[warn] udp conn not exists for %s, connid : %s", key, ID) s.log.Printf("[warn] udp conn not exists for %s, connid : %s", key, ID)
return return
} }
uc = v.(*UDPConnItem) uc = v.(*MuxUDPConnItem)
for { for {
_, body, err := utils.ReadUDPPacket(*uc.conn) _, body, err := utils.ReadUDPPacket(*uc.conn)
if err != nil { if err != nil {

View File

@ -141,6 +141,7 @@ func (s *TunnelBridge) callback(inConn net.Conn) {
var buf = make([]byte, 1024) var buf = make([]byte, 1024)
n, _ := inConn.Read(buf) n, _ := inConn.Read(buf)
reader := bytes.NewReader(buf[:n]) reader := bytes.NewReader(buf[:n])
//reader := bufio.NewReader(inConn) //reader := bufio.NewReader(inConn)
var connType uint8 var connType uint8

View File

@ -7,6 +7,7 @@ import (
logger "log" logger "log"
"net" "net"
"os" "os"
"strings"
"time" "time"
"github.com/snail007/goproxy/services" "github.com/snail007/goproxy/services"
@ -28,6 +29,15 @@ type TunnelClientArgs struct {
Timeout *int Timeout *int
Jumper *string Jumper *string
} }
type ClientUDPConnItem struct {
conn *net.Conn
isActive bool
touchtime int64
srcAddr *net.UDPAddr
localAddr *net.UDPAddr
udpConn *net.UDPConn
connid string
}
type TunnelClient struct { type TunnelClient struct {
cfg TunnelClientArgs cfg TunnelClientArgs
ctrlConn net.Conn ctrlConn net.Conn
@ -35,6 +45,7 @@ type TunnelClient struct {
userConns mapx.ConcurrentMap userConns mapx.ConcurrentMap
log *logger.Logger log *logger.Logger
jumper *jumper.Jumper jumper *jumper.Jumper
udpConns mapx.ConcurrentMap
} }
func NewTunnelClient() services.Service { func NewTunnelClient() services.Service {
@ -42,10 +53,12 @@ func NewTunnelClient() services.Service {
cfg: TunnelClientArgs{}, cfg: TunnelClientArgs{},
userConns: mapx.NewConcurrentMap(), userConns: mapx.NewConcurrentMap(),
isStop: false, isStop: false,
udpConns: mapx.NewConcurrentMap(),
} }
} }
func (s *TunnelClient) InitService() (err error) { func (s *TunnelClient) InitService() (err error) {
s.UDPGCDeamon()
return return
} }
@ -133,7 +146,7 @@ func (s *TunnelClient) Start(args interface{}, log *logger.Logger) (err error) {
s.log.Printf("read connection signal err: %s, retrying...", err) s.log.Printf("read connection signal err: %s, retrying...", err)
break break
} }
s.log.Printf("signal revecived:%s %s %s", serverID, ID, clientLocalAddr) //s.log.Printf("signal revecived:%s %s %s", serverID, ID, clientLocalAddr)
protocol := clientLocalAddr[:3] protocol := clientLocalAddr[:3]
localAddr := clientLocalAddr[4:] localAddr := clientLocalAddr[4:]
if protocol == "udp" { if protocol == "udp" {
@ -240,62 +253,119 @@ func (s *TunnelClient) ServeUDP(localAddr, ID, serverID string) {
} }
// s.cm.Add(*s.cfg.Key, ID, &inConn) // s.cm.Add(*s.cfg.Key, ID, &inConn)
s.log.Printf("conn %s created", ID) s.log.Printf("conn %s created", ID)
var item *ClientUDPConnItem
var body []byte
srcAddr := ""
defer func() {
if item != nil {
(*(*item).conn).Close()
(*item).udpConn.Close()
s.udpConns.Remove(srcAddr)
inConn.Close()
}
}()
for { for {
if s.isStop { if s.isStop {
return return
} }
srcAddr, body, err := utils.ReadUDPPacket(inConn) srcAddr, body, err = utils.ReadUDPPacket(inConn)
if err == io.EOF || err == io.ErrUnexpectedEOF { if err != nil {
s.log.Printf("connection %s released", ID) if strings.Contains(err.Error(), "n != int(") {
utils.CloseConn(&inConn) continue
break }
} else if err != nil { if !utils.IsNetDeadlineErr(err) && err != io.EOF {
s.log.Printf("udp packet revecived fail, err: %s", err) s.log.Printf("udp packet revecived from bridge fail, err: %s", err)
}
return
}
if v, ok := s.udpConns.Get(srcAddr); !ok {
_srcAddr, _ := net.ResolveUDPAddr("udp", srcAddr)
zeroAddr, _ := net.ResolveUDPAddr("udp", ":")
_localAddr, _ := net.ResolveUDPAddr("udp", localAddr)
c, err := net.DialUDP("udp", zeroAddr, _localAddr)
if err != nil {
s.log.Printf("create local udp conn fail, err : %s", err)
inConn.Close()
return
}
item = &ClientUDPConnItem{
conn: &inConn,
srcAddr: _srcAddr,
localAddr: _localAddr,
udpConn: c,
connid: ID,
}
s.udpConns.Set(srcAddr, item)
s.UDPRevecive(srcAddr, ID)
} else { } else {
//s.log.Printf("udp packet revecived:%s,%v", srcAddr, body) item = v.(*ClientUDPConnItem)
go s.processUDPPacket(&inConn, srcAddr, localAddr, body)
} }
(*item).touchtime = time.Now().Unix()
go (*item).udpConn.Write(body)
} }
// }
} }
func (s *TunnelClient) processUDPPacket(inConn *net.Conn, srcAddr, localAddr string, body []byte) { func (s *TunnelClient) UDPRevecive(key, ID string) {
dstAddr, err := net.ResolveUDPAddr("udp", localAddr) go func() {
if err != nil { s.log.Printf("udp conn %s connected", ID)
s.log.Printf("can't resolve address: %s", err) v, ok := s.udpConns.Get(key)
utils.CloseConn(inConn) if !ok {
s.log.Printf("[warn] udp conn not exists for %s, connid : %s", key, ID)
return return
} }
clientSrcAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0} cui := v.(*ClientUDPConnItem)
conn, err := net.DialUDP("udp", clientSrcAddr, dstAddr) buf := utils.LeakyBuffer.Get()
defer func() {
utils.LeakyBuffer.Put(buf)
(*cui.conn).Close()
cui.udpConn.Close()
s.udpConns.Remove(key)
s.log.Printf("udp conn %s released", ID)
}()
for {
n, err := cui.udpConn.Read(buf)
if err != nil { if err != nil {
s.log.Printf("connect to udp %s fail,ERR:%s", dstAddr.String(), err) if !utils.IsNetClosedErr(err) {
s.log.Printf("udp conn read udp packet fail , err: %s ", err)
}
return return
} }
conn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout))) cui.touchtime = time.Now().Unix()
_, err = conn.Write(body) go func() {
(*cui.conn).SetWriteDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
_, err = (*cui.conn).Write(utils.UDPPacket(cui.srcAddr.String(), buf[:n]))
(*cui.conn).SetWriteDeadline(time.Time{})
if err != nil { if err != nil {
s.log.Printf("send udp packet to %s fail,ERR:%s", dstAddr.String(), err) cui.udpConn.Close()
return return
} }
//s.log.Printf("send udp packet to %s success", dstAddr.String()) }()
buf := make([]byte, 1024) }
length, _, err := conn.ReadFromUDP(buf) }()
if err != nil { }
s.log.Printf("read udp response from %s fail ,ERR:%s", dstAddr.String(), err) func (s *TunnelClient) UDPGCDeamon() {
gctime := int64(30)
go func() {
if s.isStop {
return return
} }
respBody := buf[0:length] timer := time.NewTicker(time.Second)
//s.log.Printf("revecived udp packet from %s , %v", dstAddr.String(), respBody) for {
bs := utils.UDPPacket(srcAddr, respBody) <-timer.C
_, err = (*inConn).Write(bs) gcKeys := []string{}
if err != nil { s.udpConns.IterCb(func(key string, v interface{}) {
s.log.Printf("send udp response fail ,ERR:%s", err) if time.Now().Unix()-v.(*ClientUDPConnItem).touchtime > gctime {
utils.CloseConn(inConn) (*(v.(*ClientUDPConnItem).conn)).Close()
return (v.(*ClientUDPConnItem).udpConn).Close()
gcKeys = append(gcKeys, key)
s.log.Printf("gc udp conn %s", v.(*ClientUDPConnItem).connid)
} }
//s.log.Printf("send udp response success ,from:%s ,%d ,%v", dstAddr.String(), len(bs), bs) })
for _, k := range gcKeys {
s.udpConns.Remove(k)
}
gcKeys = nil
}
}()
} }
func (s *TunnelClient) ServeConn(localAddr, ID, serverID string) { func (s *TunnelClient) ServeConn(localAddr, ID, serverID string) {
var inConn, outConn net.Conn var inConn, outConn net.Conn

View File

@ -38,18 +38,17 @@ type TunnelServerArgs struct {
} }
type TunnelServer struct { type TunnelServer struct {
cfg TunnelServerArgs cfg TunnelServerArgs
udpChn chan UDPItem
sc utils.ServerChannel sc utils.ServerChannel
isStop bool isStop bool
udpConn *net.Conn udpConn *net.Conn
userConns mapx.ConcurrentMap userConns mapx.ConcurrentMap
log *logger.Logger log *logger.Logger
jumper *jumper.Jumper jumper *jumper.Jumper
udpConns mapx.ConcurrentMap
} }
type TunnelServerManager struct { type TunnelServerManager struct {
cfg TunnelServerArgs cfg TunnelServerArgs
udpChn chan UDPItem
serverID string serverID string
servers []*services.Service servers []*services.Service
log *logger.Logger log *logger.Logger
@ -58,7 +57,6 @@ type TunnelServerManager struct {
func NewTunnelServerManager() services.Service { func NewTunnelServerManager() services.Service {
return &TunnelServerManager{ return &TunnelServerManager{
cfg: TunnelServerArgs{}, cfg: TunnelServerArgs{},
udpChn: make(chan UDPItem, 50000),
serverID: utils.Uniqueid(), serverID: utils.Uniqueid(),
servers: []*services.Service{}, servers: []*services.Service{},
} }
@ -146,17 +144,25 @@ func (s *TunnelServerManager) InitService() (err error) {
func NewTunnelServer() services.Service { func NewTunnelServer() services.Service {
return &TunnelServer{ return &TunnelServer{
cfg: TunnelServerArgs{}, cfg: TunnelServerArgs{},
udpChn: make(chan UDPItem, 50000),
isStop: false, isStop: false,
userConns: mapx.NewConcurrentMap(), userConns: mapx.NewConcurrentMap(),
udpConns: mapx.NewConcurrentMap(),
} }
} }
type UDPItem struct { type TunnelUDPPacketItem struct {
packet *[]byte packet *[]byte
localAddr *net.UDPAddr localAddr *net.UDPAddr
srcAddr *net.UDPAddr srcAddr *net.UDPAddr
} }
type TunnelUDPConnItem struct {
conn *net.Conn
isActive bool
touchtime int64
srcAddr *net.UDPAddr
localAddr *net.UDPAddr
connid string
}
func (s *TunnelServer) StopService() { func (s *TunnelServer) StopService() {
defer func() { defer func() {
@ -183,7 +189,7 @@ func (s *TunnelServer) StopService() {
} }
} }
func (s *TunnelServer) InitService() (err error) { func (s *TunnelServer) InitService() (err error) {
s.UDPConnDeamon() s.UDPGCDeamon()
return return
} }
func (s *TunnelServer) CheckArgs() (err error) { func (s *TunnelServer) CheckArgs() (err error) {
@ -217,11 +223,7 @@ func (s *TunnelServer) Start(args interface{}, log *logger.Logger) (err error) {
s.sc = utils.NewServerChannel(host, p, s.log) s.sc = utils.NewServerChannel(host, p, s.log)
if *s.cfg.IsUDP { if *s.cfg.IsUDP {
err = s.sc.ListenUDP(func(listener *net.UDPConn, packet []byte, localAddr, srcAddr *net.UDPAddr) { err = s.sc.ListenUDP(func(listener *net.UDPConn, packet []byte, localAddr, srcAddr *net.UDPAddr) {
s.udpChn <- UDPItem{ s.UDPSend(packet, localAddr, srcAddr)
packet: &packet,
localAddr: localAddr,
srcAddr: srcAddr,
}
}) })
if err != nil { if err != nil {
return return
@ -348,89 +350,103 @@ func (s *TunnelServer) GetConn() (conn net.Conn, err error) {
} }
return return
} }
func (s *TunnelServer) UDPConnDeamon() { func (s *TunnelServer) UDPGCDeamon() {
gctime := int64(30)
go func() {
if s.isStop {
return
}
timer := time.NewTicker(time.Second)
for {
<-timer.C
gcKeys := []string{}
s.udpConns.IterCb(func(key string, v interface{}) {
if time.Now().Unix()-v.(*TunnelUDPConnItem).touchtime > gctime {
(*(v.(*TunnelUDPConnItem).conn)).Close()
gcKeys = append(gcKeys, key)
s.log.Printf("gc udp conn %s", v.(*TunnelUDPConnItem).connid)
}
})
for _, k := range gcKeys {
s.udpConns.Remove(k)
}
gcKeys = nil
}
}()
}
func (s *TunnelServer) UDPSend(data []byte, localAddr, srcAddr *net.UDPAddr) {
var (
uc *TunnelUDPConnItem
key = srcAddr.String()
ID string
err error
outconn net.Conn
)
v, ok := s.udpConns.Get(key)
if !ok {
outconn, ID, err = s.GetOutConn(CONN_SERVER)
if err != nil {
s.log.Printf("connect to %s fail, err: %s", *s.cfg.Parent, err)
return
}
uc = &TunnelUDPConnItem{
conn: &outconn,
srcAddr: srcAddr,
localAddr: localAddr,
connid: ID,
}
s.udpConns.Set(key, uc)
s.UDPRevecive(key, ID)
} else {
uc = v.(*TunnelUDPConnItem)
}
go func() { go func() {
defer func() { defer func() {
if err := recover(); err != nil { if e := recover(); e != nil {
s.log.Printf("udp conn deamon crashed with err : %s \nstack: %s", err, string(debug.Stack())) (*uc.conn).Close()
s.udpConns.Remove(key)
s.log.Printf("udp sender crashed with error : %s", e)
} }
}() }()
var outConn net.Conn uc.touchtime = time.Now().Unix()
// var hb utils.HeartbeatReadWriter (*uc.conn).SetWriteDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
var ID string _, err = (*uc.conn).Write(utils.UDPPacket(srcAddr.String(), data))
// var cmdChn = make(chan bool, 1000) (*uc.conn).SetWriteDeadline(time.Time{})
var err error
for {
if s.isStop {
return
}
item := <-s.udpChn
RETRY:
if s.isStop {
return
}
if outConn == nil {
for {
if s.isStop {
return
}
outConn, ID, err = s.GetOutConn(CONN_SERVER)
if err != nil { if err != nil {
// cmdChn <- true s.log.Printf("write udp packet to %s fail ,flush err:%s ", *s.cfg.Parent, err)
outConn = nil }
utils.CloseConn(&outConn) }()
s.log.Printf("connect to %s fail, err: %s, retrying...", *s.cfg.Parent, err) }
time.Sleep(time.Second * 3) func (s *TunnelServer) UDPRevecive(key, ID string) {
continue go func() {
} else { s.log.Printf("udp conn %s connected", ID)
go func(outConn net.Conn, ID string) { var uc *TunnelUDPConnItem
if s.udpConn != nil { defer func() {
(*s.udpConn).Close() if uc != nil {
} (*uc.conn).Close()
s.udpConn = &outConn }
for { s.udpConns.Remove(key)
if s.isStop { s.log.Printf("udp conn %s released", ID)
return }()
} v, ok := s.udpConns.Get(key)
srcAddrFromConn, body, err := utils.ReadUDPPacket(outConn) if !ok {
if err == io.EOF || err == io.ErrUnexpectedEOF { s.log.Printf("[warn] udp conn not exists for %s, connid : %s", key, ID)
s.log.Printf("UDP deamon connection %s exited", ID) return
break }
} uc = v.(*TunnelUDPConnItem)
if err != nil { for {
s.log.Printf("parse revecived udp packet fail, err: %s ,%v", err, body) _, body, err := utils.ReadUDPPacket(*uc.conn)
continue if err != nil {
} if strings.Contains(err.Error(), "n != int(") {
//s.log.Printf("udp packet revecived over parent , local:%s", srcAddrFromConn) continue
_srcAddr := strings.Split(srcAddrFromConn, ":") }
if len(_srcAddr) != 2 { if err != io.EOF {
s.log.Printf("parse revecived udp packet fail, addr error : %s", srcAddrFromConn) s.log.Printf("udp conn read udp packet fail , err: %s ", err)
continue }
} return
port, _ := strconv.Atoi(_srcAddr[1]) }
dstAddr := &net.UDPAddr{IP: net.ParseIP(_srcAddr[0]), Port: port} uc.touchtime = time.Now().Unix()
_, err = s.sc.UDPListener.WriteToUDP(body, dstAddr) go s.sc.UDPListener.WriteToUDP(body, uc.srcAddr)
if err != nil {
s.log.Printf("udp response to local %s fail,ERR:%s", srcAddrFromConn, err)
continue
}
//s.log.Printf("udp response to local %s success , %v", srcAddrFromConn, body)
}
}(outConn, ID)
break
}
}
}
outConn.SetWriteDeadline(time.Now().Add(time.Second))
_, err = outConn.Write(utils.UDPPacket(item.srcAddr.String(), *item.packet))
outConn.SetWriteDeadline(time.Time{})
if err != nil {
utils.CloseConn(&outConn)
outConn = nil
s.log.Printf("write udp packet to %s fail ,flush err:%s ,retrying...", *s.cfg.Parent, err)
goto RETRY
}
//s.log.Printf("write packet %v", *item.packet)
} }
}() }()
} }

View File

@ -577,7 +577,7 @@ func BuildPacket(packetType uint8, data ...string) []byte {
binary.Write(pkg, binary.LittleEndian, packetType) binary.Write(pkg, binary.LittleEndian, packetType)
for _, d := range data { for _, d := range data {
bytes := []byte(d) bytes := []byte(d)
binary.Write(pkg, binary.LittleEndian, uint16(len(bytes))) binary.Write(pkg, binary.LittleEndian, uint64(len(bytes)))
binary.Write(pkg, binary.LittleEndian, bytes) binary.Write(pkg, binary.LittleEndian, bytes)
} }
return pkg.Bytes() return pkg.Bytes()