mirror of
https://github.com/mumble-voip/grumble.git
synced 2025-12-20 06:10:00 -08:00
Server-side crypt resync. Properly store ping stats.
This commit is contained in:
parent
0b086d6f57
commit
a2c9a15386
4 changed files with 131 additions and 59 deletions
32
client.go
32
client.go
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"grumble/blobstore"
|
"grumble/blobstore"
|
||||||
"io"
|
"io"
|
||||||
"packetdatastream"
|
"packetdatastream"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A client connection
|
// A client connection
|
||||||
|
|
@ -39,9 +40,18 @@ type Client struct {
|
||||||
|
|
||||||
disconnected bool
|
disconnected bool
|
||||||
|
|
||||||
crypt *cryptstate.CryptState
|
lastResync int64
|
||||||
codecs []int32
|
crypt *cryptstate.CryptState
|
||||||
udp bool
|
codecs []int32
|
||||||
|
udp bool
|
||||||
|
|
||||||
|
// Ping stats
|
||||||
|
UdpPingAvg float32
|
||||||
|
UdpPingVar float32
|
||||||
|
UdpPackets uint32
|
||||||
|
TcpPingAvg float32
|
||||||
|
TcpPingVar float32
|
||||||
|
TcpPackets uint32
|
||||||
|
|
||||||
// If the client is a registered user on the server,
|
// If the client is a registered user on the server,
|
||||||
// the user field will point to the registration record.
|
// the user field will point to the registration record.
|
||||||
|
|
@ -573,3 +583,19 @@ func (client *Client) sendChannelTree(channel *Channel) {
|
||||||
client.sendChannelTree(subchannel)
|
client.sendChannelTree(subchannel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try to do a crypto resync
|
||||||
|
func (client *Client) cryptResync() {
|
||||||
|
goodElapsed := time.Seconds() - client.crypt.LastGoodTime
|
||||||
|
if goodElapsed > 5 {
|
||||||
|
requestElapsed := time.Seconds() - client.lastResync
|
||||||
|
if requestElapsed > 5 {
|
||||||
|
client.lastResync = time.Seconds()
|
||||||
|
cryptsetup := &mumbleproto.CryptSetup{}
|
||||||
|
err := client.sendProtoMessage(MessageCryptSetup, cryptsetup)
|
||||||
|
if err != nil {
|
||||||
|
client.Panicf("%v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
35
message.go
35
message.go
|
|
@ -113,8 +113,39 @@ func (server *Server) handlePingMessage(client *Client, msg *Message) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Phony response for ping messages. We don't keep stats
|
if ping.Good != nil {
|
||||||
// for this yet.
|
client.crypt.RemoteGood = uint32(*ping.Good)
|
||||||
|
}
|
||||||
|
if ping.Late != nil {
|
||||||
|
client.crypt.RemoteLate = *ping.Late
|
||||||
|
}
|
||||||
|
if ping.Lost != nil {
|
||||||
|
client.crypt.RemoteLost = *ping.Lost
|
||||||
|
}
|
||||||
|
if ping.Resync != nil {
|
||||||
|
client.crypt.RemoteResync = *ping.Resync
|
||||||
|
}
|
||||||
|
|
||||||
|
if ping.UdpPingAvg != nil {
|
||||||
|
client.UdpPingAvg = *ping.UdpPingAvg
|
||||||
|
}
|
||||||
|
if ping.UdpPingVar != nil {
|
||||||
|
client.UdpPingVar = *ping.UdpPingVar
|
||||||
|
}
|
||||||
|
if ping.UdpPackets != nil {
|
||||||
|
client.UdpPackets = *ping.UdpPackets
|
||||||
|
}
|
||||||
|
|
||||||
|
if ping.TcpPingAvg != nil {
|
||||||
|
client.TcpPingAvg = *ping.TcpPingAvg
|
||||||
|
}
|
||||||
|
if ping.TcpPingVar != nil {
|
||||||
|
client.TcpPingVar = *ping.TcpPingVar
|
||||||
|
}
|
||||||
|
if ping.TcpPackets != nil {
|
||||||
|
client.TcpPackets = *ping.TcpPackets
|
||||||
|
}
|
||||||
|
|
||||||
client.sendProtoMessage(MessagePing, &mumbleproto.Ping{
|
client.sendProtoMessage(MessagePing, &mumbleproto.Ping{
|
||||||
Timestamp: ping.Timestamp,
|
Timestamp: ping.Timestamp,
|
||||||
Good: proto.Uint32(uint32(client.crypt.Good)),
|
Good: proto.Uint32(uint32(client.crypt.Good)),
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"os"
|
"os"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const AESBlockSize = 16
|
const AESBlockSize = 16
|
||||||
|
|
@ -20,15 +21,16 @@ type CryptState struct {
|
||||||
DecryptIV [AESBlockSize]byte
|
DecryptIV [AESBlockSize]byte
|
||||||
decryptHistory [DecryptHistorySize]byte
|
decryptHistory [DecryptHistorySize]byte
|
||||||
|
|
||||||
Good int
|
LastGoodTime int64
|
||||||
Late int
|
|
||||||
Lost int
|
|
||||||
Resync int
|
|
||||||
|
|
||||||
RemoteGood int
|
Good uint32
|
||||||
RemoteLate int
|
Late uint32
|
||||||
RemoteLost int
|
Lost uint32
|
||||||
RemoteResync int
|
Resync uint32
|
||||||
|
RemoteGood uint32
|
||||||
|
RemoteLate uint32
|
||||||
|
RemoteLost uint32
|
||||||
|
RemoteResync uint32
|
||||||
|
|
||||||
cipher *aes.Cipher
|
cipher *aes.Cipher
|
||||||
}
|
}
|
||||||
|
|
@ -196,10 +198,18 @@ func (cs *CryptState) Decrypt(dst, src []byte) (err os.Error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
cs.Good += 1
|
cs.Good += 1
|
||||||
cs.Late += late
|
if late > 0 {
|
||||||
cs.Lost += lost
|
cs.Late += uint32(late)
|
||||||
|
} else {
|
||||||
|
cs.Late -= uint32(-late)
|
||||||
|
}
|
||||||
|
if lost > 0 {
|
||||||
|
cs.Lost = uint32(lost)
|
||||||
|
} else {
|
||||||
|
cs.Lost = uint32(-lost)
|
||||||
|
}
|
||||||
|
|
||||||
// restart timer
|
cs.LastGoodTime = time.Seconds()
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
91
server.go
91
server.go
|
|
@ -492,6 +492,7 @@ func (server *Server) handleAuthenticate(client *Client, msg *Message) {
|
||||||
|
|
||||||
// Send CryptState information to the client so it can establish an UDP connection,
|
// Send CryptState information to the client so it can establish an UDP connection,
|
||||||
// if it wishes.
|
// if it wishes.
|
||||||
|
client.lastResync = time.Seconds()
|
||||||
err = client.sendProtoMessage(MessageCryptSetup, &mumbleproto.CryptSetup{
|
err = client.sendProtoMessage(MessageCryptSetup, &mumbleproto.CryptSetup{
|
||||||
Key: client.crypt.RawKey[0:],
|
Key: client.crypt.RawKey[0:],
|
||||||
ClientNonce: client.crypt.DecryptIV[0:],
|
ClientNonce: client.crypt.DecryptIV[0:],
|
||||||
|
|
@ -923,53 +924,57 @@ func (server *Server) ListenUDP() {
|
||||||
address: udpaddr,
|
address: udpaddr,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var match *Client
|
server.handleUdpPacket(udpaddr, buf, nread)
|
||||||
plain := make([]byte, nread-4)
|
|
||||||
|
|
||||||
// Determine which client sent the the packet. First, we
|
|
||||||
// check the map 'hpclients' in the server struct. It maps
|
|
||||||
// a hort-post combination to a client.
|
|
||||||
//
|
|
||||||
// If we don't find any matches, we look in the 'hclients',
|
|
||||||
// which maps a host address to a slice of clients.
|
|
||||||
server.hmutex.Lock()
|
|
||||||
client, ok := server.hpclients[udpaddr.String()]
|
|
||||||
if ok {
|
|
||||||
err = client.crypt.Decrypt(plain[0:], buf[0:nread])
|
|
||||||
if err != nil {
|
|
||||||
server.Panicf("Unable to decrypt incoming packet for client %v (host-port matched)", client)
|
|
||||||
}
|
|
||||||
match = client
|
|
||||||
} else {
|
|
||||||
host := udpaddr.IP.String()
|
|
||||||
hostclients := server.hclients[host]
|
|
||||||
for _, client := range hostclients {
|
|
||||||
err = client.crypt.Decrypt(plain[0:], buf[0:nread])
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
match = client
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if match != nil {
|
|
||||||
match.udpaddr = udpaddr
|
|
||||||
server.hpclients[udpaddr.String()] = match
|
|
||||||
}
|
|
||||||
}
|
|
||||||
server.hmutex.Unlock()
|
|
||||||
|
|
||||||
// No client found.
|
|
||||||
if match == nil {
|
|
||||||
server.Printf("Sender of UDP packet could not be determined. Packet dropped.")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
match.udp = true
|
|
||||||
match.udprecv <- plain
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (server *Server) handleUdpPacket(udpaddr *net.UDPAddr, buf []byte, nread int) {
|
||||||
|
var match *Client
|
||||||
|
plain := make([]byte, nread-4)
|
||||||
|
|
||||||
|
// Determine which client sent the the packet. First, we
|
||||||
|
// check the map 'hpclients' in the server struct. It maps
|
||||||
|
// a hort-post combination to a client.
|
||||||
|
//
|
||||||
|
// If we don't find any matches, we look in the 'hclients',
|
||||||
|
// which maps a host address to a slice of clients.
|
||||||
|
server.hmutex.Lock()
|
||||||
|
defer server.hmutex.Unlock()
|
||||||
|
client, ok := server.hpclients[udpaddr.String()]
|
||||||
|
if ok {
|
||||||
|
err := client.crypt.Decrypt(plain[0:], buf[0:nread])
|
||||||
|
if err != nil {
|
||||||
|
client.cryptResync()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
match = client
|
||||||
|
} else {
|
||||||
|
host := udpaddr.IP.String()
|
||||||
|
hostclients := server.hclients[host]
|
||||||
|
for _, client := range hostclients {
|
||||||
|
err := client.crypt.Decrypt(plain[0:], buf[0:nread])
|
||||||
|
if err != nil {
|
||||||
|
client.cryptResync()
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
match = client
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if match != nil {
|
||||||
|
match.udpaddr = udpaddr
|
||||||
|
server.hpclients[udpaddr.String()] = match
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if match == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
match.udp = true
|
||||||
|
match.udprecv <- plain
|
||||||
|
}
|
||||||
|
|
||||||
// Clear the ACL cache
|
// Clear the ACL cache
|
||||||
func (s *Server) ClearACLCache() {
|
func (s *Server) ClearACLCache() {
|
||||||
s.aclcache = NewACLCache()
|
s.aclcache = NewACLCache()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue