Author: cgutman Date: Wed Jan 11 22:24:49 2012 New Revision: 54912
URL: http://svn.reactos.org/svn/reactos?rev=54912&view=rev Log: [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
Modified: branches/wlan-bringup/dll/win32/dhcpcsvc/dhcp/adapter.c branches/wlan-bringup/dll/win32/dhcpcsvc/dhcp/api.c branches/wlan-bringup/dll/win32/dhcpcsvc/dhcp/dispatch.c
Modified: branches/wlan-bringup/dll/win32/dhcpcsvc/dhcp/adapter.c URL: http://svn.reactos.org/svn/reactos/branches/wlan-bringup/dll/win32/dhcpcsvc/... ============================================================================== --- branches/wlan-bringup/dll/win32/dhcpcsvc/dhcp/adapter.c [iso-8859-1] (original) +++ branches/wlan-bringup/dll/win32/dhcpcsvc/dhcp/adapter.c [iso-8859-1] Wed Jan 11 22:24:49 2012 @@ -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 @@ 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 @@ /* 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 @@ Adapter->DhclientInfo.rfdesc, got_one, &Adapter->DhclientInfo);
- state_init(&Adapter->DhclientInfo); + state_init(&Adapter->DhclientInfo); }
ApiLock();
Modified: branches/wlan-bringup/dll/win32/dhcpcsvc/dhcp/api.c URL: http://svn.reactos.org/svn/reactos/branches/wlan-bringup/dll/win32/dhcpcsvc/... ============================================================================== --- branches/wlan-bringup/dll/win32/dhcpcsvc/dhcp/api.c [iso-8859-1] (original) +++ branches/wlan-bringup/dll/win32/dhcpcsvc/dhcp/api.c [iso-8859-1] Wed Jan 11 22:24:49 2012 @@ -14,6 +14,8 @@
static CRITICAL_SECTION ApiCriticalSection;
+extern HANDLE AdapterStateChangedEvent; + VOID ApiInit() { InitializeCriticalSection( &ApiCriticalSection ); } @@ -35,19 +37,28 @@ DWORD DSLeaseIpAddress( PipeSendFunc Send, COMM_DHCP_REQ *Req ) { COMM_DHCP_REPLY Reply; PDHCP_ADAPTER Adapter; - - ApiLock(); - - Adapter = AdapterFindIndex( Req->AdapterIndex ); - - Reply.Reply = Adapter ? 1 : 0; - - if( Adapter ) { + struct protocol* proto; + + ApiLock(); + + Adapter = AdapterFindIndex( Req->AdapterIndex ); + + 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 @@ 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 DSRenewIpAddressLease( PipeSendFunc Send, COMM_DHCP_REQ *Req ) { COMM_DHCP_REPLY Reply; PDHCP_ADAPTER Adapter; + struct protocol* proto;
ApiLock();
@@ -118,11 +136,19 @@
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();
@@ -154,6 +180,9 @@ &Adapter->NteContext, &Adapter->NteInstance ); Reply.Reply = NT_SUCCESS(Status); + + if (AdapterStateChangedEvent != NULL) + SetEvent(AdapterStateChangedEvent); }
ApiUnlock();
Modified: branches/wlan-bringup/dll/win32/dhcpcsvc/dhcp/dispatch.c URL: http://svn.reactos.org/svn/reactos/branches/wlan-bringup/dll/win32/dhcpcsvc/... ============================================================================== --- branches/wlan-bringup/dll/win32/dhcpcsvc/dhcp/dispatch.c [iso-8859-1] (original) +++ branches/wlan-bringup/dll/win32/dhcpcsvc/dhcp/dispatch.c [iso-8859-1] Wed Jan 11 22:24:49 2012 @@ -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 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; - - AdapterStateChangedEvent = StartAdapterDiscovery(); - if (!AdapterStateChangedEvent) + HANDLE Events[2]; + int EventCount = 1; + + Events[0] = StartAdapterDiscovery(); + if (!Events[0]) return; - + AdapterStateChangedEvent = Events[0]; + + Events[1] = WSA_INVALID_EVENT; + ApiLock();
do { @@ -83,7 +87,8 @@ */ time(&cur_time);
- if (timeouts) { + if (timeouts) + { struct timeout *t;
if (timeouts->when <= cur_time) { @@ -105,55 +110,75 @@ 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(); - + to_msec = INFINITE; + } + + 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; + + EventCount = 1; + } + + ApiUnlock(); + count = WaitForMultipleObjects(EventCount, + Events, + FALSE, + to_msec); + ApiLock(); + if (count == WAIT_OBJECT_0) + { + /* Adapter state change */ continue; } - - DH_DbgPrint(MID_TRACE,("Select: %d\n", count)); - - /* Not likely to be transitory... */ - if (count == SOCKET_ERROR) { - err = WSAGetLastError(); - error("poll: %d", err); - break; + 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(); }