<commit_before>package main

import(
	//"strings"
	//"bytes"
	"log"
	"net"
	"time"

	dhcp "github.com/krolaw/dhcp4"
)

type MAC48 [6]byte;

var zeroMAC = MAC48{0,0,0,0,0,0};

type IPStage byte;
const (
	IP_Removed IPStage = iota;
	IP_Free;
	IP_Reserved;
	IP_Issued;
)

type linkedLease struct{
	stage    IPStage;
	ip       net.IP;
	mac	     MAC48;
	updated  bool;	//need on tLeaseEnd
	pervL   *linkedLease;
	nextL   *linkedLease;
};

func(L *linkedLease) IP() net.IP{
	if L==nil { return nil;
	}else     { return L.ip; }
}

// ServeConn is the bare minimum connection functions required by Serve()
// It allows you to create custom connections for greater control,
// such as ServeIfConn (see serverif.go), which locks to a given interface.
type ServeConn interface {
	ReadFrom(b []byte) (n int, addr net.Addr, err error)
	WriteTo(b []byte, addr net.Addr) (n int, err error)
}

type reqChan struct{
	req dhcp.Packet;
	reqType dhcp.MessageType;
	options dhcp.Options;
	addr net.Addr;
}


type DhcpHandler struct{
	qLastFreeL         *linkedLease; //    Queue-->
	qFirstFreeL        *linkedLease; // -->Queue
	qFirstReserveL     *linkedLease;
	qLastReserveL      *linkedLease;

	iCurrTLeaseEnd int;

	_CONN         *ServeConn;
	_SERVER_IP     net.IP;
	_START_IP      net.IP;
	_OPTIONS       dhcp.Options;
	_T_LEASE_END []int16;

	channelReq <-chan reqChan;/*don't close()*/

	leases            []linkedLease;
	clients map[MAC48] *linkedLease;
}
func(H *DhcpHandler) Init(conn *ServeConn, serverIP, startIP net.IP, rangeIP int, options dhcp.Options, tLeaseEnd []int16, channelReq/*don't close()*/ <-chan reqChan){
	H._CONN        = conn;
	H._SERVER_IP   = serverIP;
	H._START_IP    = startIP;
	H._OPTIONS     = options;
	H._T_LEASE_END = tLeaseEnd;

	H.iCurrTLeaseEnd = 0;

	H.channelReq = channelReq;

	H.leases  = make(          []linkedLease, rangeIP);
	H.clients = make(map[MAC48] *linkedLease, rangeIP);

	{//Init leases
		H.leases[len(H.leases)-1].pervL =  nil;
		H.leases[len(H.leases)-1].nextL = &H.leases[len(H.leases)-2];
		H.leases[len(H.leases)-1].stage =  IP_Free;
		H.leases[len(H.leases)-1].ip    =  dhcp.IPAdd(H._START_IP, len(H.leases)-1);

		for i:=len(H.leases)-2; i>0; i-- {
			H.leases[i].pervL = &H.leases[i+1];
			H.leases[i].nextL = &H.leases[i-1];
			H.leases[i].stage =  IP_Free;
			H.leases[i].ip    =  dhcp.IPAdd(H._START_IP, i);
		}

		H.leases[0].pervL = &H.leases[1];
		H.leases[0].nextL =  nil;
		H.leases[0].stage =  IP_Free;
		H.leases[0].ip    =  H._START_IP;

		H.qLastFreeL    = &H.leases[0];
		H.qFirstFreeL   = &H.leases[len(H.leases)-1];
		H.qFirstReserveL = nil;
		H.qLastReserveL  = nil;
	}//Init leases end
}
func(H *DhcpHandler) GoHandle(){
	var dEmptyReserve    = time.Duration(len(H.leases))*5*time.Millisecond;
	var dNotEmptyReserve =                              5*time.Millisecond;

	var durClearReserve = dEmptyReserve;

	var tNow = time.Now().Local();
	var tNowM = tNow.Hour() * 60 + tNow.Minute();

	H.correctICurrTLeaseEnd(tNowM);

	var durClearIssued = time.Duration(modOneDay(int(H._T_LEASE_END[H.NextTLeaseEnd()])-tNowM))*time.Minute;
	var tClearIssuedStage = -40*time.Second;
	for{
		select{
		// clear old Issued leases on schedule
		case <- time.After(durClearIssued + tClearIssuedStage):
			switch(tClearIssuedStage){
			//set update=false on Issued leases
			case -40*time.Second:
				for _,l := range H.leases{
					if l.stage == IP_Issued {
						l.updated = false;
					}
				}

				durClearIssued = 40*time.Second;
				tClearIssuedStage = 1*time.Minute + 20*time.Second;
			//delete Issued leases if update=false
			case 1*time.Minute + 20*time.Second:
				for _,l := range H.leases{
					if l.stage == IP_Issued && l.updated == false {
						H.DeleteClientL(&l);
					}
				}

				tNow = time.Now().Local();
				tNowM = tNow.Hour() * 60 + tNow.Minute();

				H.correctICurrTLeaseEnd(tNowM);

				durClearIssued = time.Duration(modOneDay(int(H._T_LEASE_END[H.NextTLeaseEnd()])-tNowM))*time.Minute;
				tClearIssuedStage = -40*time.Second;
			}


		//clear old Discover-Offer leases on timeout
		case <- time.After(durClearReserve):
			if H.qLastReserveL != nil { // time to Request lease = 0..durClearReserve
				H.UniPutLease(H.UniRemoveLease(H.qLastReserveL), IP_Free);
				H.DeleteMAC(H.qLastReserveL.mac);<commit_msg>Fix bug: UniRemoveLease change qLastReserveL address<commit_after>package main

import(
	//"strings"
	//"bytes"
	"log"
	"net"
	"time"

	dhcp "github.com/krolaw/dhcp4"
)

type MAC48 [6]byte;

var zeroMAC = MAC48{0,0,0,0,0,0};

type IPStage byte;
const (
	IP_Removed IPStage = iota;
	IP_Free;
	IP_Reserved;
	IP_Issued;
)

type linkedLease struct{
	stage    IPStage;
	ip       net.IP;
	mac	     MAC48;
	updated  bool;	//need on tLeaseEnd
	pervL   *linkedLease;
	nextL   *linkedLease;
};

func(L *linkedLease) IP() net.IP{
	if L==nil { return nil;
	}else     { return L.ip; }
}

// ServeConn is the bare minimum connection functions required by Serve()
// It allows you to create custom connections for greater control,
// such as ServeIfConn (see serverif.go), which locks to a given interface.
type ServeConn interface {
	ReadFrom(b []byte) (n int, addr net.Addr, err error)
	WriteTo(b []byte, addr net.Addr) (n int, err error)
}

type reqChan struct{
	req dhcp.Packet;
	reqType dhcp.MessageType;
	options dhcp.Options;
	addr net.Addr;
}


type DhcpHandler struct{
	qLastFreeL         *linkedLease; //    Queue-->
	qFirstFreeL        *linkedLease; // -->Queue
	qFirstReserveL     *linkedLease;
	qLastReserveL      *linkedLease;

	iCurrTLeaseEnd int;

	_CONN         *ServeConn;
	_SERVER_IP     net.IP;
	_START_IP      net.IP;
	_OPTIONS       dhcp.Options;
	_T_LEASE_END []int16;

	channelReq <-chan reqChan;/*don't close()*/

	leases            []linkedLease;
	clients map[MAC48] *linkedLease;
}
func(H *DhcpHandler) Init(conn *ServeConn, serverIP, startIP net.IP, rangeIP int, options dhcp.Options, tLeaseEnd []int16, channelReq/*don't close()*/ <-chan reqChan){
	H._CONN        = conn;
	H._SERVER_IP   = serverIP;
	H._START_IP    = startIP;
	H._OPTIONS     = options;
	H._T_LEASE_END = tLeaseEnd;

	H.iCurrTLeaseEnd = 0;

	H.channelReq = channelReq;

	H.leases  = make(          []linkedLease, rangeIP);
	H.clients = make(map[MAC48] *linkedLease, rangeIP);

	{//Init leases
		H.leases[len(H.leases)-1].pervL =  nil;
		H.leases[len(H.leases)-1].nextL = &H.leases[len(H.leases)-2];
		H.leases[len(H.leases)-1].stage =  IP_Free;
		H.leases[len(H.leases)-1].ip    =  dhcp.IPAdd(H._START_IP, len(H.leases)-1);

		for i:=len(H.leases)-2; i>0; i-- {
			H.leases[i].pervL = &H.leases[i+1];
			H.leases[i].nextL = &H.leases[i-1];
			H.leases[i].stage =  IP_Free;
			H.leases[i].ip    =  dhcp.IPAdd(H._START_IP, i);
		}

		H.leases[0].pervL = &H.leases[1];
		H.leases[0].nextL =  nil;
		H.leases[0].stage =  IP_Free;
		H.leases[0].ip    =  H._START_IP;

		H.qLastFreeL    = &H.leases[0];
		H.qFirstFreeL   = &H.leases[len(H.leases)-1];
		H.qFirstReserveL = nil;
		H.qLastReserveL  = nil;
	}//Init leases end
}
func(H *DhcpHandler) GoHandle(){
	var dEmptyReserve    = time.Duration(len(H.leases))*5*time.Millisecond;
	var dNotEmptyReserve =                              5*time.Millisecond;

	var durClearReserve = dEmptyReserve;

	var tNow = time.Now().Local();
	var tNowM = tNow.Hour() * 60 + tNow.Minute();

	H.correctICurrTLeaseEnd(tNowM);

	var durClearIssued = time.Duration(modOneDay(int(H._T_LEASE_END[H.NextTLeaseEnd()])-tNowM))*time.Minute;
	var tClearIssuedStage = -40*time.Second;
	for{
		select{
		// clear old Issued leases on schedule
		case <- time.After(durClearIssued + tClearIssuedStage):
			switch(tClearIssuedStage){
			//set update=false on Issued leases
			case -40*time.Second:
				for _,l := range H.leases{
					if l.stage == IP_Issued {
						l.updated = false;
					}
				}

				durClearIssued = 40*time.Second;
				tClearIssuedStage = 1*time.Minute + 20*time.Second;
			//delete Issued leases if update=false
			case 1*time.Minute + 20*time.Second:
				for _,l := range H.leases{
					if l.stage == IP_Issued && l.updated == false {
						H.DeleteClientL(&l);
					}
				}

				tNow = time.Now().Local();
				tNowM = tNow.Hour() * 60 + tNow.Minute();

				H.correctICurrTLeaseEnd(tNowM);

				durClearIssued = time.Duration(modOneDay(int(H._T_LEASE_END[H.NextTLeaseEnd()])-tNowM))*time.Minute;
				tClearIssuedStage = -40*time.Second;
			}


		//clear old Discover-Offer leases on timeout
		case <- time.After(durClearReserve):
			if oldLease:=H.qLastReserveL; oldLease != nil { // time to Request lease = 0..durClearReserve
				H.UniPutLease(H.UniRemoveLease(oldLease), IP_Free);
				H.DeleteMAC(oldLease.mac);
{'fraction_non_alphanumeric': 0.1451631633956567, 'fraction_numerical': 0.014167924747416096, 'mean_word_length': 3.219500244977952, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1001229', 'n_tokens_mistral': 3858, 'n_tokens_neox': 3485, 'n_words': 685}