package dtls
import (
"sync"
"github.com/pion/dtls/v2/pkg/crypto/prf"
"github.com/pion/dtls/v2/pkg/protocol/handshake"
)
type handshakeCacheItem struct {
typ handshake .Type
isClient bool
epoch uint16
messageSequence uint16
data []byte
}
type handshakeCachePullRule struct {
typ handshake .Type
epoch uint16
isClient bool
optional bool
}
type handshakeCache struct {
cache []*handshakeCacheItem
mu sync .Mutex
}
func newHandshakeCache() *handshakeCache {
return &handshakeCache {}
}
func (h *handshakeCache ) push (data []byte , epoch , messageSequence uint16 , typ handshake .Type , isClient bool ) {
h .mu .Lock ()
defer h .mu .Unlock ()
h .cache = append (h .cache , &handshakeCacheItem {
data : append ([]byte {}, data ...),
epoch : epoch ,
messageSequence : messageSequence ,
typ : typ ,
isClient : isClient ,
})
}
func (h *handshakeCache ) pull (rules ...handshakeCachePullRule ) []*handshakeCacheItem {
h .mu .Lock ()
defer h .mu .Unlock ()
out := make ([]*handshakeCacheItem , len (rules ))
for i , r := range rules {
for _ , c := range h .cache {
if c .typ == r .typ && c .isClient == r .isClient && c .epoch == r .epoch {
switch {
case out [i ] == nil :
out [i ] = c
case out [i ].messageSequence < c .messageSequence :
out [i ] = c
}
}
}
}
return out
}
func (h *handshakeCache ) fullPullMap (startSeq int , cipherSuite CipherSuite , rules ...handshakeCachePullRule ) (int , map [handshake .Type ]handshake .Message , bool ) {
h .mu .Lock ()
defer h .mu .Unlock ()
ci := make (map [handshake .Type ]*handshakeCacheItem )
for _ , r := range rules {
var item *handshakeCacheItem
for _ , c := range h .cache {
if c .typ == r .typ && c .isClient == r .isClient && c .epoch == r .epoch {
switch {
case item == nil :
item = c
case item .messageSequence < c .messageSequence :
item = c
}
}
}
if !r .optional && item == nil {
return startSeq , nil , false
}
ci [r .typ ] = item
}
out := make (map [handshake .Type ]handshake .Message )
seq := startSeq
for _ , r := range rules {
t := r .typ
i := ci [t ]
if i == nil {
continue
}
var keyExchangeAlgorithm CipherSuiteKeyExchangeAlgorithm
if cipherSuite != nil {
keyExchangeAlgorithm = cipherSuite .KeyExchangeAlgorithm ()
}
rawHandshake := &handshake .Handshake {
KeyExchangeAlgorithm : keyExchangeAlgorithm ,
}
if err := rawHandshake .Unmarshal (i .data ); err != nil {
return startSeq , nil , false
}
if uint16 (seq ) != rawHandshake .Header .MessageSequence {
return startSeq , nil , false
}
seq ++
out [t ] = rawHandshake .Message
}
return seq , out , true
}
func (h *handshakeCache ) pullAndMerge (rules ...handshakeCachePullRule ) []byte {
merged := []byte {}
for _ , p := range h .pull (rules ...) {
if p != nil {
merged = append (merged , p .data ...)
}
}
return merged
}
func (h *handshakeCache ) sessionHash (hf prf .HashFunc , epoch uint16 , additional ...[]byte ) ([]byte , error ) {
merged := []byte {}
handshakeBuffer := h .pull (
handshakeCachePullRule {handshake .TypeClientHello , epoch , true , false },
handshakeCachePullRule {handshake .TypeServerHello , epoch , false , false },
handshakeCachePullRule {handshake .TypeCertificate , epoch , false , false },
handshakeCachePullRule {handshake .TypeServerKeyExchange , epoch , false , false },
handshakeCachePullRule {handshake .TypeCertificateRequest , epoch , false , false },
handshakeCachePullRule {handshake .TypeServerHelloDone , epoch , false , false },
handshakeCachePullRule {handshake .TypeCertificate , epoch , true , false },
handshakeCachePullRule {handshake .TypeClientKeyExchange , epoch , true , false },
)
for _ , p := range handshakeBuffer {
if p == nil {
continue
}
merged = append (merged , p .data ...)
}
for _ , a := range additional {
merged = append (merged , a ...)
}
hash := hf ()
if _ , err := hash .Write (merged ); err != nil {
return []byte {}, err
}
return hash .Sum (nil ), nil
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .