//
// Copyright (c) 2016, Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
// 4 Oct 2016 Andy Frank Creation
//
using inet
using concurrent
**
** DhcpClient
**
class DhcpClient
{
Void discover()
{
socket := MulticastSocket()
socket.loopbackMode = true
socket.bind(null, 68)
socket.joinGroup(IpAddr("224.0.0.1"), null, null)
while (true)
{
try
{
p := socket.receive
echo("# got it!")
}
catch (Err e)
{
echo("# ERR $e.msg")
Actor.sleep(1sec)
}
}
/*
// socket := UdpSocket()
// socket.options.broadcast = true
socket := MulticastSocket()
socket.timeToLive = 10
socket.options.receiveTimeout = 10sec
// send request
socket.send(UdpPacket(baddr, port, DhcpPacket {
//socket.send(UdpPacket(maddr, port, DhcpPacket {
it.op = DhcpPacket.opBootRequest
it.chaddr = IpInterface.findByName("en0").hardwareAddr
}.encode))
// wait for response
res := UdpPacket(null, null, Buf(65536))
while (true)
{
// receive message or on timeout break
res.data.clear
try
{
socket.receive(res)
echo("### RECV ###")
echo(res.data.toHex)
}
catch (IOErr e)
{
e.trace
break
}
}
*/
}
private static const IpAddr baddr := IpAddr("255.255.255.255")
private static const IpAddr maddr := IpAddr("224.0.0.1")
private static const Int port := 67
// Grid discover()
// {
// // create socket
// socket := MulticastSocket()
// socket.timeToLive = 4
// socket.options.receiveTimeout = 300ms
// packet := UdpPacket(null, null, Buf(65536))
//
// // request data
// reqGrid := Etc.makeMapGrid(null, ["host":IpAddr.local.hostname])
// reqData := ZincWriter.gridToStr(reqGrid).toBuf
//
// // keep track of unique URI endpoints
// acc := Uri:Dict[:]
//
// // send out request three times and wait for responses
// 3.times
// {
// // send request
// socket.send(UdpPacket(multicastGroup, multicastPort, reqData.seek(0)))
//
// // look receiving messages until we have timeout
// while (true)
// {
// // receive message or on timeout break
// packet.data.clear
// try
// socket.receive(packet)
// catch (IOErr e)
// break
//
// // process the packet
// try
// {
// grid := ZincReader(packet.data.flip.in).readGrid
// grid.each |row|
// {
// uri := row["uri"] as Uri
// if (uri == null || uri.scheme == null) return
// acc[uri] = row
// }
// }
// catch (Err e) e.trace
// }
// }
//
// // now build up response of unique URI endpoints
// rows := acc.vals.sort |a, b| { a.dis <=> b.dis }
// return Etc.makeDictsGrid(null, rows)
// }
}
**************************************************************************
** DhcpPacket
**************************************************************************
**
** DhcpPacket models a DHCP UDP Packet. See RFC 2131
** for documentation on fields.
**
@NoDoc const class DhcpPacket
{
** It-block ctor.
new make(|This| f) { f(this) }
static const Int opBootRequest := 1
static const Int opBootReply := 2
const Int op
const Int htype := 1 // eth=1
const Int hlen := 6 // always 6 for eth/802
const Int hops := 0
const Int xid := Int.random(0..0xffff_ffff)
const Int secs := 0
const Int flags := 0
const Int ciaddr := 0
const Int yiaddr := 0
const Int siaddr := 0
const Int giaddr := 0
const Buf chaddr
const Str? sname := null
const Buf? options := null
** Encode this packet into a Buf.
Buf encode()
{
buf := Buf()
buf.write(op)
buf.write(htype)
buf.write(hlen)
buf.write(hops)
buf.writeI4(xid)
buf.writeI2(secs)
buf.writeI2(flags)
buf.writeI4(ciaddr)
buf.writeI4(yiaddr)
buf.writeI4(siaddr)
buf.writeI4(giaddr)
// chaddr
hlen.times |i| { buf.write(chaddr[i]) }
(16-hlen).times { buf.write(0) }
// TODO: sname
64.times { buf.write(0) }
// TODO: file
128.times { buf.write(0) }
// TODO: options
// padding
while (buf.size < 300) buf.write(0)
echo("$buf.toHex [$buf.size]")
return buf.flip
}
}