当前位置: 首页 > 工具软件 > dhcp4java > 使用案例 >

android dhcp 服务器,安卓通过DHCP协议获取IP地址的过程

劳星晖
2023-12-01

安卓通过DHCP协议的DORA Discovery发现 Offer提供 Request请求 Ack确认 获取IP地址的过程

安卓N之前 5.0 6.0通过 android_net_utils_runDhcp 方法运行 /system/bin/dhcpcd 获取ip地址

安卓N之后 N不要了runDhcpcd(),而是通过DhcpClient

DhcpClient是通过framework发送dhcpcd协议的UDP请求包直接去拿IP,不再使用开源的dhcpcd

google还用了一个状态机 IpManager 来管理dhcpcd成功还是失败等状态,

将ip赋值给IpConfiguration和LinkProperties传递到上层的framework

/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java

// 当WifiStateMachine状态机进入状态ObtainingIpState时 获取IP地址

class ObtainingIpState extends State {

@Override

public void enter() {

mIpManager.startProvisioning(IpManager.ProvisioningConfiguration prov); //启动获取IP地址

}

}

ObtainingIpState所在状态机

/frameworks/base/services/net/java/android/net/ip/IpManager.java

class StartedState extends State {} IpManager中的三个状态机

class StoppedState extends State {}

class StoppingState extends State {}

public void startProvisioning(ProvisioningConfiguration req) {

getNetworkInterface();

mCallback.setNeighborDiscoveryOffload(true);

// 给初始化的状态机 StoppedState 发送消息CMD_START

sendMessage(CMD_START, new ProvisioningConfiguration(req));

}

1

2

3

4

5

6

7

8

1

2

3

4

5

6

7

8

========================================================================

class StoppedState extends State {

@Override

public boolean processMessage(Message msg) {

switch (msg.what) {

…..

case CMD_START:

mConfiguration = (ProvisioningConfiguration) msg.obj;

// 接收到 CMD_START 会进行状态的切换,调用 StartedState的enter()方法

transitionTo(mStartedState);

break;

…..

}

==========================================

class StartedState extends State {

void enter(){

if(startIPv4()) // 状态 StartedState 的enter 进入方法,调用startIPv4()函数

private boolean startIPv4() {

// If we have a StaticIpConfiguration attempt to apply it and handle the result accordingly.

if (mConfiguration.mStaticIpConfig != null) { // 如果有静态IP

if (setIPv4Address(mConfiguration.mStaticIpConfig.ipAddress)) {

handleIPv4Success(new DhcpResults(mConfiguration.mStaticIpConfig));

} else {

if (VDBG) { Log.d(mTag, "onProvisioningFailure()"); }

recordMetric(IpManagerEvent.PROVISIONING_FAIL);

mCallback.onProvisioningFailure(new LinkProperties(mLinkProperties));

return false;

}

} else {

// Start DHCPv4. 创建DhcpClient

mDhcpClient = DhcpClient.makeDhcpClient(mContext, IpManager.this, mInterfaceName);

mDhcpClient.registerForPreDhcpNotification(); // mRegisteredForPreDhcpNotification = true

//接收前面发过来的mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP);跟着跳转到DhcpInitState:

mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP); // 发送CMD_START_DHCP消息

if (mConfiguration.mProvisioningTimeoutMs > 0) {

final long alarmTime = SystemClock.elapsedRealtime() +

mConfiguration.mProvisioningTimeoutMs;

mProvisioningTimeoutAlarm.schedule(alarmTime); // 在36秒后启动timeout超时操作

}

}

return true;

}

private boolean setIPv4Address(LinkAddress address) {

final InterfaceConfiguration ifcg = new InterfaceConfiguration();

ifcg.setLinkAddress(address);

try {

final INetworkManagementService mNwService.setInterfaceConfig(mInterfaceName, ifcg);

if (VDBG) Log.d(mTag, "IPv4 configuration succeeded");

} catch (IllegalStateException | RemoteException e) {

Log.e(mTag, "IPv4 configuration failed: ", e);

return false;

}

return true;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

==========================================

//接收前面发过来的mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP);跟着跳转到 DhcpInitState:

mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP); // 发送CMD_START_DHCP消息

/frameworks/base/services/net/java/android/net/dhcp/DhcpClient.java

class DhcpInitState extends PacketRetransmittingState {

public DhcpInitState() {

super();

}

1

2

3

4

5

1

2

3

4

5

//进入状态时启动一次startNewTransaction

//DORA Discover发现 Offer提供 Request请求 ACK确认 开始Discovery 发现?

@Override

public void enter() {

super.enter(); // 调用父类的 enter 方法中

startNewTransaction();

}

protected boolean sendPacket() {

return sendDiscoverPacket(); // 发送 DiscoverPacket 发现包

}

protected void receivePacket(DhcpPacket packet) {

if (!isValidPacket(packet)) return;

if (!(packet instanceof DhcpOfferPacket)) return;

mOffer = packet.toDhcpResults();

if (mOffer != null) {

Log.d(TAG, "Got pending lease: " + mOffer);

transitionTo(mDhcpRequestingState); // 接收到了 Offer包 接下来发送 Request 请求包

}

}

}

private void startNewTransaction() {

mTransactionId = mRandom.nextInt(); // 传输包的id号?

mTransactionStartMillis = SystemClock.elapsedRealtime();

}

PacketRetransmittingState

abstract class PacketRetransmittingState extends LoggingState {

private int mTimer;

protected int mTimeout = 0;

@Override

public void enter() {

super.enter();

initTimer();

maybeInitTimeout();

sendMessage(CMD_KICK); // 发送消息 CMD_KICK

}

@Override

public boolean processMessage(Message message) {

super.processMessage(message);

switch (message.what) {

case CMD_KICK:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

// 调用了 sendPacket()抽象方法 所以就是之前的DhcpInitState的具体的实现 sendPacket()

sendPacket();

scheduleKick();

return HANDLED;

case CMD_RECEIVED_PACKET:

receivePacket((DhcpPacket) message.obj);

return HANDLED;

case CMD_TIMEOUT:

timeout();

return HANDLED;

default:

return NOT_HANDLED;

}

}

public void exit() {

mKickAlarm.cancel();

mTimeoutAlarm.cancel();

}

}

abstract protected boolean sendPacket();

1

2

3

4

5

6

7

8

1

2

3

4

5

6

7

8

abstract protected void receivePacket(DhcpPacket packet);

class DhcpInitState extends PacketRetransmittingState {

protected boolean sendPacket() {

return sendDiscoverPacket(); // 发送 DiscoverPacket 发现包

}

private boolean sendDiscoverPacket() {

ByteBuffer packet = DhcpPacket.buildDiscoverPacket(

DhcpPacket.ENCAP_L2, mTransactionId, getSecs(), mHwAddr,

DO_UNICAST, REQUESTED_PARAMS); // 创建 ByteBuffer的UDP包

1

2

3

4

5

6

7

8

9

10

11

12

1

2

3

4

5

6

7

8

9

10

11

12

return transmitPacket(packet, “DHCPDISCOVER”, DhcpPacket.ENCAP_L2, INADDR_BROADCAST); // 发送

}

}

private boolean transmitPacket(ByteBuffer buf, String description, int encap, Inet4Address to) {

try {

if (encap == DhcpPacket.ENCAP_L2) {

if (DBG) Log.d(TAG, "Broadcasting " + description);

// 送这里发送出去

Os.sendto(mPacketSock, buf.array(), 0, buf.limit(), 0, mInterfaceBroadcastAddr);

} else if (encap == DhcpPacket.ENCAP_BOOTP && to.equals(INADDR_BROADCAST)) {

if (DBG) Log.d(TAG, "Broadcasting " + description);

// N.B.: We only need this codepath because DhcpRequestPacket

// hardcodes the source IP address to 0.0.0.0. We could reuse

// the packet socket if this ever changes.

Os.sendto(mUdpSock, buf, 0, to, DhcpPacket.DHCP_SERVER);

} else {

if (DBG) Log.d(TAG, String.format("Unicasting %s to %s",description, Os.getpeername(mUdpSock)));

Os.write(mUdpSock, buf);

}

} catch(ErrnoException|IOException e) {

Log.e(TAG, "Can't send packet: ", e);

return false;

}

return true;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

==================================================================

另外一边有一个接收线程ReceiveThread run(),一直在收dhcp server的的数据包。

class ReceiveThread extends Thread {

private final byte[] mPacket = new byte[DhcpPacket.MAX_LENGTH];

private volatile boolean mStopped = false;

public void halt() {

mStopped = true;

closeSockets(); // Interrupts the read() call the thread is blocked in.

}

@Override

public void run() {

if (DBG) Log.d(TAG, "Receive thread started");

while (!mStopped) {

int length = 0; // Or compiler can't tell it's initialized if a parse error occurs.

try {

//读取DHCP服务发出的OFFER提交包

length = Os.read(mPacketSock 【FileDescriptor】, mPacket, 0, mPacket.length);

DhcpPacket packet = null;

packet = DhcpPacket.decodeFullPacket(mPacket, length, DhcpPacket.ENCAP_L2);

if (DBG) Log.d(TAG, "Received packet: " + packet);

sendMessage(CMD_RECEIVED_PACKET, packet); // 发送接收到消息 CMD_RECEIVED_PACKET

} catch (IOException|ErrnoException e) {

if (!mStopped) {

Log.e(TAG, "Read error", e);

DhcpErrorEvent.logReceiveError(mIfaceName);

}

} catch (DhcpPacket.ParseException e) {

Log.e(TAG, "Can't parse packet: " + e.getMessage());

if (PACKET_DBG) {

Log.d(TAG, HexDump.dumpHexString(mPacket, 0, length));

}

DhcpErrorEvent.logParseError(mIfaceName, e.errorCode);

}

}

if (DBG) Log.d(TAG, "Receive thread stopped");

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

}

abstract class PacketRetransmittingState extends LoggingState {

@Override

public boolean processMessage(Message message) {

super.processMessage(message);

switch (message.what) {

case CMD_RECEIVED_PACKET:

receivePacket((DhcpPacket) message.obj); // 调用子类具体实现的receivePacket 方法

return HANDLED;

default:

return NOT_HANDLED;

}

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

class DhcpInitState extends PacketRetransmittingState {

class DhcpInitState extends PacketRetransmittingState {

protected void receivePacket(DhcpPacket packet) { // 完成 DORA 中的 Offer的阶段

if (!isValidPacket(packet)) return;

if (!(packet instanceof DhcpOfferPacket)) return;

mOffer = packet.toDhcpResults();

if (mOffer != null) {

Log.d(TAG, "Got pending lease: " + mOffer);

// 接收到了来自DHCP服务器的OFFER包,切换状态到 DhcpRequestingState 并进入到 enter() 方法

transitionTo(mDhcpRequestingState);

}

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

1

2

3

4

5

6

7

8

9

10

11

12

13

14

}

===================================================================

class DhcpRequestingState extends PacketRetransmittingState { // 进入到父类的enter 方法

public DhcpRequestingState() {

mTimeout = DHCP_TIMEOUT_MS / 2;

}

public void enter() {// 进入到父类的enter 方法

super.enter();

initTimer();

maybeInitTimeout();

sendMessage(CMD_KICK); // 再次发送 CMD_KICK 消息

}

public boolean processMessage(Message message) {

super.processMessage(message);

switch (message.what) {

case CMD_KICK: // 收到 CMD_KICK 消息

sendPacket(); // 发送包方法,此时调用的是具体子类 DhcpRequestingState的发送方法

scheduleKick();

return HANDLED;

default:

return NOT_HANDLED;

}

}

// 发送请求 完成 DORA中的 Request的阶段

// 此时 继续在接收线程中等待接收来自服务器的ACK DHCP数据包

protected boolean sendPacket() {

return sendRequestPacket(

INADDR_ANY, // ciaddr

(Inet4Address) mOffer.ipAddress.getAddress(), // DHCP_REQUESTED_IP

(Inet4Address) mOffer.serverAddress, // DHCP_SERVER_IDENTIFIER

INADDR_BROADCAST); // packet destination address

}

protected void receivePacket(DhcpPacket packet) {

if (!isValidPacket(packet)) return;

if ((packet instanceof DhcpAckPacket)) {

DhcpResults results = packet.toDhcpResults();

if (results != null) {

setDhcpLeaseExpiry(packet);

acceptDhcpResults(results, "Confirmed");

transitionTo(mConfiguringInterfaceState);

}

} else if (packet instanceof DhcpNakPacket) {

// TODO: Wait a while before returning into INIT state.

Log.d(TAG, "Received NAK, returning to INIT");

mOffer = null;

transitionTo(mDhcpInitState);

}

}

private boolean sendRequestPacket(

Inet4Address clientAddress, Inet4Address requestedAddress,

Inet4Address serverAddress, Inet4Address to) {

// TODO: should we use the transaction ID from the server?

final int encap = INADDR_ANY.equals(clientAddress)

? DhcpPacket.ENCAP_L2 : DhcpPacket.ENCAP_BOOTP;

ByteBuffer packet = DhcpPacket.buildRequestPacket(

encap, mTransactionId, getSecs(), clientAddress,

DO_UNICAST, mHwAddr, requestedAddress,

serverAddress, REQUESTED_PARAMS, null);

String serverStr = (serverAddress != null) ? serverAddress.getHostAddress() : null;

String description = "DHCPREQUEST ciaddr=" + clientAddress.getHostAddress() +

" request=" + requestedAddress.getHostAddress() +

" serverid=" + serverStr;

return transmitPacket(packet, description, encap, to); // 发送数据包

}

return transmitPacket(packet, "DHCPDISCOVER", DhcpPacket.ENCAP_L2, INADDR_BROADCAST); // 发送

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

}

private boolean transmitPacket(ByteBuffer buf, String description, int encap, Inet4Address to) {

try {

if (encap == DhcpPacket.ENCAP_L2) {

if (DBG) Log.d(TAG, "Broadcasting " + description);

// 送这里发送出去 真正发送

Os.sendto(mPacketSock, buf.array(), 0, buf.limit(), 0, mInterfaceBroadcastAddr);

} else if (encap == DhcpPacket.ENCAP_BOOTP && to.equals(INADDR_BROADCAST)) {

if (DBG) Log.d(TAG, "Broadcasting " + description);

// N.B.: We only need this codepath because DhcpRequestPacket

// hardcodes the source IP address to 0.0.0.0. We could reuse

// the packet socket if this ever changes.

Os.sendto(mUdpSock, buf, 0, to, DhcpPacket.DHCP_SERVER);

} else {

if (DBG) Log.d(TAG, String.format("Unicasting %s to %s",description, Os.getpeername(mUdpSock)));

Os.write(mUdpSock, buf);

}

} catch(ErrnoException|IOException e) {

Log.e(TAG, "Can't send packet: ", e);

return false;

}

return true;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

另外一边有一个接收线程ReceiveThread run(),一直在收dhcp server的的数据包。

class ReceiveThread extends Thread {

private final byte[] mPacket = new byte[DhcpPacket.MAX_LENGTH];

private volatile boolean mStopped = false;

public void halt() {

mStopped = true;

closeSockets(); // Interrupts the read() call the thread is blocked in.

}

@Override

public void run() {

if (DBG) Log.d(TAG, "Receive thread started");

while (!mStopped) {

int length = 0; // Or compiler can't tell it's initialized if a parse error occurs.

try {

//读取DHCP服务发出的ACK确认包

length = Os.read(mPacketSock 【FileDescriptor】, mPacket, 0, mPacket.length);

DhcpPacket packet = null;

packet = DhcpPacket.decodeFullPacket(mPacket, length, DhcpPacket.ENCAP_L2);

if (DBG) Log.d(TAG, "Received packet: " + packet);

// 发送接收到消息 CMD_RECEIVED_PACKET 此时处理的状态是 DhcpRequestingState

sendMessage(CMD_RECEIVED_PACKET, packet);

} catch (IOException|ErrnoException e) {

if (!mStopped) {

Log.e(TAG, "Read error", e);

DhcpErrorEvent.logReceiveError(mIfaceName);

}

} catch (DhcpPacket.ParseException e) {

Log.e(TAG, "Can't parse packet: " + e.getMessage());

if (PACKET_DBG) {

Log.d(TAG, HexDump.dumpHexString(mPacket, 0, length));

}

DhcpErrorEvent.logParseError(mIfaceName, e.errorCode);

}

}

if (DBG) Log.d(TAG, "Receive thread stopped");

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

}

// 处理消息 CMD_RECEIVED_PACKET 对应的数据包是 ACK数据包 UDP

class DhcpRequestingState extends PacketRetransmittingState {

public boolean processMessage(Message message) {

super.processMessage(message);

switch (message.what) {

case CMD_RECEIVED_PACKET:

receivePacket((DhcpPacket) message.obj); //DhcpRequestingState处理接收到的数据包

return HANDLED;

default:

return NOT_HANDLED;

}

}

protected void receivePacket(DhcpPacket packet) {

if (!isValidPacket(packet)) return;

if ((packet instanceof DhcpAckPacket)) {

DhcpResults results = packet.toDhcpResults();

if (results != null) {

setDhcpLeaseExpiry(packet);

//这里会调用notifySuccess,发送CMD去通知IpManager说,IP拿到了 分析 acceptDhcpResults

acceptDhcpResults(results, "Confirmed"); // 分叉

//进入新的状态 ConfiguringInterfaceState enter方法

transitionTo(mConfiguringInterfaceState);

}

} else if (packet instanceof DhcpNakPacket) { // 收到的是NACK 解决数据包的话

// TODO: Wait a while before returning into INIT state.

Log.d(TAG, "Received NAK, returning to INIT");

mOffer = null;

transitionTo(mDhcpInitState);

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

}

//这里会调用notifySuccess,发送CMD去通知IpManager说,IP拿到了 分析 acceptDhcpResults

acceptDhcpResults(results, “Confirmed”);

private void acceptDhcpResults(DhcpResults results, String msg) {

mDhcpLease = results;

mOffer = null;

Log.d(TAG, msg + " lease: " + mDhcpLease);

notifySuccess(); // 通知成功拿到IP地址了

}

private void notifySuccess() {

mController【StateMachine】.sendMessage( CMD_POST_DHCP_ACTION, DHCP_SUCCESS, 0, new DhcpResults(mDhcpLease));

}

class StartedState extends State {

@Override

public boolean processMessage(Message msg) {

switch (msg.what) {

case DhcpClient.CMD_POST_DHCP_ACTION:

stopDhcpAction();

switch (msg.arg1) {

case DhcpClient.DHCP_SUCCESS:

handleIPv4Success((DhcpResults) msg.obj); // 处理 handleIPv4Success IPV4地址

break;

case DhcpClient.DHCP_FAILURE:

handleIPv4Failure();

break;

default:

Log.e(mTag, "Unknown CMD_POST_DHCP_ACTION status:" + msg.arg1);

}

break;

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

}

private void handleIPv4Success(DhcpResults dhcpResults) {

mDhcpResults = new DhcpResults(dhcpResults);

final LinkProperties newLp = assembleLinkProperties();

final ProvisioningChange delta = setLinkProperties(newLp);

if (VDBG) {

Log.d(mTag, "onNewDhcpResults(" + Objects.toString(dhcpResults) + ")");

}

mCallback.onNewDhcpResults(dhcpResults);

dispatchCallback(delta, newLp); //这里分发dhcpResults 把IPv4地址发出去

}

private void dispatchCallback(ProvisioningChange delta, LinkProperties newLp) {

switch (delta) {

case GAINED_PROVISIONING:

if (VDBG) { Log.d(mTag, "onProvisioningSuccess()"); }

recordMetric(IpManagerEvent.PROVISIONING_OK);

mCallback.onProvisioningSuccess(newLp); // 回调

break;

}

}

dispatchCallback 的结果最后会作用到 WaitForProvisioningCallback

public static class WaitForProvisioningCallback extends Callback {

private LinkProperties mCallbackLinkProperties;

public LinkProperties waitForProvisioning() {

synchronized (this) {

try {

wait();

} catch (InterruptedException e) {}

return mCallbackLinkProperties;

}

}

@Override

public void onProvisioningSuccess(LinkProperties newLp) { // 回调

synchronized (this) {

mCallbackLinkProperties = newLp; // 把当前的IPv4保存起来

notify();

}

}

@Override

public void onProvisioningFailure(LinkProperties newLp) {

synchronized (this) {

mCallbackLinkProperties = null;

notify();

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

} acceptDhcpResults 分析到此为止 开始分析新的状态

//进入新的状态 ConfiguringInterfaceState enter方法

ConfiguringInterfaceState

@Override

public boolean processMessage(Message message) {

super.processMessage(message);

switch (message.what) {

case EVENT_LINKADDRESS_CONFIGURED:

transitionTo(mDhcpBoundState);

return HANDLED;

default:

return NOT_HANDLED;

}

}

}

========================

class StartedState extends State {

@Override

public boolean processMessage(Message msg) {

switch (msg.what) {

case DhcpClient.CMD_CONFIGURE_LINKADDRESS: {

final LinkAddress ipAddress = (LinkAddress) msg.obj;

if (setIPv4Address(ipAddress)) { // 设置 IPv4地址

mDhcpClient.sendMessage(DhcpClient.EVENT_LINKADDRESS_CONFIGURED);

} else {

Log.e(mTag, "Failed to set IPv4 address!");

dispatchCallback(ProvisioningChange.LOST_PROVISIONING,

new LinkProperties(mLinkProperties));

transitionTo(mStoppingState);

}

break;

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

=========================================

// 回到开头的 setIPv4Address 至此获得了IP地址

private boolean setIPv4Address(LinkAddress address) {

final InterfaceConfiguration ifcg = new InterfaceConfiguration();

ifcg.setLinkAddress(address);

try {

final INetworkManagementService mNwService.setInterfaceConfig(mInterfaceName, ifcg);

if (VDBG) Log.d(mTag, “IPv4 configuration succeeded”);

} catch (IllegalStateException | RemoteException e) {

Log.e(mTag, “IPv4 configuration failed: “, e);

return false;

}

return true;

}

final Command cmd = new Command("interface", "setcfg", iface,

linkAddr.getAddress().getHostAddress(),

linkAddr.getPrefixLength());

for (String flag : cfg.getFlags()) {

cmd.appendArg(flag);

}

try {

mConnector.execute(cmd); // 执行命令

} catch (NativeDaemonConnectorException e) {

throw e.rethrowAsParcelableException();

}

}

 类似资料: