glider/service/dhcpd/pool.go

72 lines
1.2 KiB
Go
Raw Normal View History

2020-09-28 00:49:58 +08:00
package dhcpd
import (
"bytes"
"errors"
2020-09-29 00:38:35 +08:00
"math/rand"
2020-09-28 00:49:58 +08:00
"net"
"time"
)
type Pool struct {
items []*item
}
func NewPool(lease time.Duration, ipStart, ipEnd net.IP) (*Pool, error) {
items := make([]*item, 0)
2020-09-29 00:38:35 +08:00
curip := ipStart.To4()
for bytes.Compare(curip, ipEnd.To4()) <= 0 {
2020-09-28 00:49:58 +08:00
ip := make([]byte, 4)
2020-09-29 00:38:35 +08:00
copy(ip, curip)
items = append(items, &item{lease: lease, ip: ip})
curip[3]++
2020-09-28 00:49:58 +08:00
}
2020-09-29 00:38:35 +08:00
rand.Seed(time.Now().Unix())
return &Pool{items: items}, nil
2020-09-28 00:49:58 +08:00
}
func (p *Pool) AssignIP(mac net.HardwareAddr) (net.IP, error) {
var ip net.IP
for _, item := range p.items {
2020-09-29 00:38:35 +08:00
if bytes.Equal(mac, item.mac) {
2020-09-28 00:49:58 +08:00
return item.ip, nil
}
}
2020-09-29 00:38:35 +08:00
idx := rand.Intn(len(p.items))
for _, item := range p.items[idx:] {
if ip = item.take(mac); ip != nil {
return ip, nil
}
}
2020-09-28 00:49:58 +08:00
for _, item := range p.items {
if ip = item.take(mac); ip != nil {
return ip, nil
}
}
return nil, errors.New("no more ip can be assigned")
}
type item struct {
2020-09-29 00:38:35 +08:00
taken bool
ip net.IP
lease time.Duration
mac net.HardwareAddr
2020-09-28 00:49:58 +08:00
}
func (i *item) take(addr net.HardwareAddr) net.IP {
2020-09-29 00:38:35 +08:00
if !i.taken {
2020-09-28 00:49:58 +08:00
i.taken = true
go func() {
timer := time.NewTimer(i.lease)
<-timer.C
2020-09-29 00:38:35 +08:00
i.mac = nil
2020-09-28 00:49:58 +08:00
i.taken = false
}()
2020-09-29 00:38:35 +08:00
i.mac = addr
2020-09-28 00:49:58 +08:00
return i.ip
}
2020-09-29 00:38:35 +08:00
return nil
2020-09-28 00:49:58 +08:00
}