glider/service/dhcpd/pool.go

68 lines
1.2 KiB
Go
Raw Normal View History

2020-09-28 00:49:58 +08:00
package dhcpd
import (
"bytes"
"errors"
"net"
"time"
)
type Pool struct {
lease time.Duration
items []*item
}
func NewPool(lease time.Duration, ipStart, ipEnd net.IP) (*Pool, error) {
items := make([]*item, 0)
var currentIp = ipStart.To4()
for bytes.Compare(currentIp, ipEnd.To4()) <= 0 {
ip := make([]byte, 4)
copy(ip, currentIp)
i := &item{
lease: lease,
ip: ip,
}
items = append(items, i)
currentIp[3]++
}
return &Pool{lease: lease, items: items}, nil
}
func (p *Pool) AssignIP(mac net.HardwareAddr) (net.IP, error) {
var ip net.IP
for _, item := range p.items {
if mac.String() == item.hardwareAddr.String() {
return item.ip, nil
}
}
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 {
ip net.IP
lease time.Duration
taken bool
hardwareAddr net.HardwareAddr
}
func (i *item) take(addr net.HardwareAddr) net.IP {
if i.taken {
return nil
} else {
i.taken = true
go func() {
timer := time.NewTimer(i.lease)
<-timer.C
i.hardwareAddr = nil
i.taken = false
}()
i.hardwareAddr = addr
return i.ip
}
}