[DHCPCSVC]

- Fix ipconfig hang with ipconfig /renew and ipconfig /release
- Fix duplicate protocol entries being added for the same adapter
- Use WSAEventSelect and WaitForMultipleObjects to manage waiting between timeouts, adapter state changes, and incoming packets

svn path=/branches/wlan-bringup/; revision=54912
This commit is contained in:
Cameron Gutman 2012-01-11 22:24:49 +00:00
parent 83a2fb2da4
commit 12f1e92c72
3 changed files with 105 additions and 46 deletions

View file

@ -1,6 +1,6 @@
#include "rosdhcp.h"
static SOCKET DhcpSocket = INVALID_SOCKET;
SOCKET DhcpSocket = INVALID_SOCKET;
static LIST_ENTRY AdapterList;
static WSADATA wsd;
@ -209,6 +209,7 @@ DWORD WINAPI AdapterDiscoveryThread(LPVOID Context) {
PDHCP_ADAPTER Adapter = NULL;
HANDLE AdapterStateChangedEvent = (HANDLE)Context;
struct interface_info *ifi = NULL;
struct protocol *proto;
int i, AdapterCount = 0, Broadcast;
/* FIXME: Kill this thread when the service is stopped */
@ -245,6 +246,10 @@ DWORD WINAPI AdapterDiscoveryThread(LPVOID Context) {
/* We're still active so we stay in the list */
ifi = &Adapter->DhclientInfo;
} else {
proto = find_protocol_by_adapter(&Adapter->DhclientInfo);
if (proto)
remove_protocol(proto);
/* We've lost our link so out we go */
RemoveEntryList(&Adapter->ListEntry);
free(Adapter);
@ -330,7 +335,7 @@ DWORD WINAPI AdapterDiscoveryThread(LPVOID Context) {
Adapter->DhclientInfo.rfdesc,
got_one, &Adapter->DhclientInfo);
state_init(&Adapter->DhclientInfo);
state_init(&Adapter->DhclientInfo);
}
ApiLock();

View file

@ -14,6 +14,8 @@
static CRITICAL_SECTION ApiCriticalSection;
extern HANDLE AdapterStateChangedEvent;
VOID ApiInit() {
InitializeCriticalSection( &ApiCriticalSection );
}
@ -35,6 +37,7 @@ VOID ApiFree() {
DWORD DSLeaseIpAddress( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
COMM_DHCP_REPLY Reply;
PDHCP_ADAPTER Adapter;
struct protocol* proto;
ApiLock();
@ -43,11 +46,19 @@ DWORD DSLeaseIpAddress( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
Reply.Reply = Adapter ? 1 : 0;
if( Adapter ) {
proto = find_protocol_by_adapter( &Adapter->DhclientInfo );
if (proto)
remove_protocol(proto);
add_protocol( Adapter->DhclientInfo.name,
Adapter->DhclientInfo.rfdesc, got_one,
&Adapter->DhclientInfo );
Adapter->DhclientInfo.client->state = S_INIT;
state_reboot(&Adapter->DhclientInfo);
Adapter->DhclientInfo.client->state = S_INIT;
state_reboot(&Adapter->DhclientInfo);
if (AdapterStateChangedEvent != NULL)
SetEvent(AdapterStateChangedEvent);
}
ApiUnlock();
@ -95,6 +106,12 @@ DWORD DSReleaseIpAddressLease( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
proto = find_protocol_by_adapter( &Adapter->DhclientInfo );
if (proto)
remove_protocol(proto);
Adapter->DhclientInfo.client->active = NULL;
Adapter->DhclientInfo.client->state = S_INIT;
if (AdapterStateChangedEvent != NULL)
SetEvent(AdapterStateChangedEvent);
}
ApiUnlock();
@ -105,6 +122,7 @@ DWORD DSReleaseIpAddressLease( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
DWORD DSRenewIpAddressLease( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
COMM_DHCP_REPLY Reply;
PDHCP_ADAPTER Adapter;
struct protocol* proto;
ApiLock();
@ -118,12 +136,20 @@ DWORD DSRenewIpAddressLease( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
Reply.Reply = 1;
proto = find_protocol_by_adapter( &Adapter->DhclientInfo );
if (proto)
remove_protocol(proto);
add_protocol( Adapter->DhclientInfo.name,
Adapter->DhclientInfo.rfdesc, got_one,
&Adapter->DhclientInfo );
Adapter->DhclientInfo.client->state = S_INIT;
state_reboot(&Adapter->DhclientInfo);
if (AdapterStateChangedEvent != NULL)
SetEvent(AdapterStateChangedEvent);
ApiUnlock();
return Send( &Reply );
@ -154,6 +180,9 @@ DWORD DSStaticRefreshParams( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
&Adapter->NteContext,
&Adapter->NteInstance );
Reply.Reply = NT_SUCCESS(Status);
if (AdapterStateChangedEvent != NULL)
SetEvent(AdapterStateChangedEvent);
}
ApiUnlock();

View file

@ -47,6 +47,8 @@
//#include <ifaddrs.h>
//#include <poll.h>
extern SOCKET DhcpSocket;
HANDLE AdapterStateChangedEvent = NULL;
struct protocol *protocols = NULL;
struct timeout *timeouts = NULL;
static struct timeout *free_timeouts = NULL;
@ -63,17 +65,19 @@ void (*bootp_packet_handler)(struct interface_info *,
void
dispatch(void)
{
int count, to_msec, err;
int count, to_msec;
struct protocol *l;
fd_set fds;
time_t howlong, cur_time;
struct timeval timeval;
HANDLE AdapterStateChangedEvent;
HANDLE Events[2];
int EventCount = 1;
AdapterStateChangedEvent = StartAdapterDiscovery();
if (!AdapterStateChangedEvent)
Events[0] = StartAdapterDiscovery();
if (!Events[0])
return;
AdapterStateChangedEvent = Events[0];
Events[1] = WSA_INVALID_EVENT;
ApiLock();
do {
@ -83,7 +87,8 @@ dispatch(void)
*/
time(&cur_time);
if (timeouts) {
if (timeouts)
{
struct timeout *t;
if (timeouts->when <= cur_time) {
@ -105,55 +110,75 @@ dispatch(void)
if (howlong > INT_MAX / 1000)
howlong = INT_MAX / 1000;
to_msec = howlong * 1000;
/* Set up the descriptors to be polled. */
FD_ZERO(&fds);
for (l = protocols; l; l = l->next)
FD_SET(l->fd, &fds);
/* Wait for a packet or a timeout... XXX */
timeval.tv_sec = to_msec / 1000;
timeval.tv_usec = to_msec % 1000;
ApiUnlock();
count = select(0, &fds, NULL, NULL, &timeval);
ApiLock();
}
else
{
ApiUnlock();
WaitForSingleObject(AdapterStateChangedEvent, INFINITE);
ApiLock();
continue;
to_msec = INFINITE;
}
DH_DbgPrint(MID_TRACE,("Select: %d\n", count));
if (Events[1] == WSA_INVALID_EVENT && DhcpSocket != INVALID_SOCKET)
{
Events[1] = WSACreateEvent();
if (Events[1] != WSA_INVALID_EVENT)
{
count = WSAEventSelect(DhcpSocket, Events[1], FD_READ | FD_CLOSE);
if (count != NO_ERROR)
{
WSACloseEvent(Events[1]);
Events[1] = WSA_INVALID_EVENT;
}
else
{
EventCount = 2;
}
}
}
else if (Events[1] != WSA_INVALID_EVENT && DhcpSocket == INVALID_SOCKET)
{
WSACloseEvent(Events[1]);
Events[1] = WSA_INVALID_EVENT;
/* Not likely to be transitory... */
if (count == SOCKET_ERROR) {
err = WSAGetLastError();
error("poll: %d", err);
break;
EventCount = 1;
}
ApiUnlock();
count = WaitForMultipleObjects(EventCount,
Events,
FALSE,
to_msec);
ApiLock();
if (count == WAIT_OBJECT_0)
{
/* Adapter state change */
continue;
}
else if (count == WAIT_OBJECT_0 + 1)
{
/* Packet received */
/* WSA events are manual reset events */
WSAResetEvent(Events[1]);
}
else
{
/* Timeout */
continue;
}
for (l = protocols; l; l = l->next) {
struct interface_info *ip;
ip = l->local;
if (FD_ISSET(l->fd, &fds)) {
if (ip && (l->handler != got_one ||
!ip->dead)) {
DH_DbgPrint(MID_TRACE,("Handling %x\n", l));
(*(l->handler))(l);
}
if (ip && (l->handler != got_one ||
!ip->dead)) {
DH_DbgPrint(MID_TRACE,("Handling %x\n", l));
(*(l->handler))(l);
}
}
} while (1);
CloseHandle(AdapterStateChangedEvent);
AdapterStateChangedEvent = NULL;
CloseHandle(Events[0]);
WSACloseEvent(Events[1]);
ApiUnlock();
}