Hello all, it's a long time since I wrote to this list but I'm still reading 
and using ICS.
I implemented a built-in option for async DNS lookups. Initially I did this in 
my TWSocket descendant class but that have lead to some troubles (more bloated 
code, inability to use existing timeout mechanism etc) so I decided to improve 
ICS sources instead.
In short, there's new wsoAsyncDnsLookup option and private flag 
FInternalDnsActive; some new code in Connect and TriggerDNSLookupDone. Backward 
compatibility is kept (no change for existing code).

Here's diff with SVN r1301

Source/OverbyteIcsWSocket.pas | 78 +++++++++++++++++++++++++++++++++++++------
1 file changed, 68 insertions(+), 10 deletions(-)

diff --git a/Source/OverbyteIcsWSocket.pas b/Source/OverbyteIcsWSocket.pas
index 588ff11..e77ed5f 100644
--- a/Source/OverbyteIcsWSocket.pas
+++ b/Source/OverbyteIcsWSocket.pas
@@ -1639,7 +1639,8 @@ type
                         { is set HTTP/1.0 responses are treated as errors.  }
                          wsoNoHttp10Tunnel,
                          wsoNotifyAddressListChange,
-                          wsoNotifyRoutingInterfaceChange);
+                          wsoNotifyRoutingInterfaceChange,
+                          wsoAsyncDnsLookup);
  TWSocketOptions      = set of TWSocketOption;

  TTcpKeepAlive = packed record
@@ -1707,6 +1708,7 @@ type  { <== Required to make D7 code explorer happy, AG 
05/24/2007 }
  {$IFDEF MSWINDOWS}
    FDnsLookupBuffer    : array [0..MAXGETHOSTSTRUCT] of AnsiChar;
  {$ENDIF}
+    FInternalDnsActive  : Boolean;
    FDnsLookupCheckMsg  : Boolean;
    FDnsLookupTempMsg   : TMessage;
    // FHandle             : HWND;
@@ -7072,6 +7074,7 @@ begin
{   FReadCount          := 0;  V7.24 only reset when connection opened, not 
closed }
    FCloseInvoked       := FALSE;
    FFlushTimeout       := 60;
+    FInternalDnsActive  := FALSE;
end;


@@ -9112,6 +9115,7 @@ var
begin
    if FDnsLookupHandle = 0 then
        Exit;
+    FInternalDnsActive := FALSE;
  {$IFDEF MSWINDOWS}
    if FSocketFamily = sfIPv4 then
        RetVal := WSocket_Synchronized_WSACancelAsyncRequest(FDnsLookupHandle)
@@ -9172,6 +9176,7 @@ begin
    {$ENDIF}
            IcsCancelAsyncRequest(FDnsLookupHandle);
        FDnsLookupHandle := 0;
+        FInternalDnsActive := FALSE;
    end;

    FDnsResult := '';
@@ -9274,6 +9279,7 @@ begin
      {$ENDIF}
            IcsCancelAsyncRequest(FDnsLookupHandle);
        FDnsLookupHandle := 0;
+        FInternalDnsActive := FALSE;
    end;

    FDnsResult := '';
@@ -9342,6 +9348,8 @@ begin
        else
      {$ENDIF}
            IcsCancelAsyncRequest(FDnsLookupHandle);
+      FDnsLookupHandle := 0;
+      FInternalDnsActive := FALSE;
    end;
    FDnsResult := '';
    if FSocketFamily = sfIPv4 then
@@ -9593,8 +9601,9 @@ var
    optval  : Integer;
    optlen  : Integer;
    lAddr   : TSockAddrIn6;
+    TmpOnError: TNotifyEvent;
begin
-    if (FHSocket <> INVALID_SOCKET) and (FState <> wsClosed) then begin
+    if ((FHSocket <> INVALID_SOCKET) and (FState <> wsClosed)) or 
FInternalDnsActive then begin
        RaiseException('Connect: Socket already in use');
        Exit;
    end;
@@ -9642,15 +9651,29 @@ begin
        end;

        if not FAddrResolved then begin
-            { The next line will trigger an exception in case of failure }
-            if FSocketFamily = sfIPv4 then
-            begin
-                Fsin.sin6_family := AF_INET;
-                PSockAddrIn(@Fsin).sin_addr.S_addr := 
WSocket_Synchronized_ResolveHost(AnsiString(FAddrStr)).s_addr;
+            if (wsoAsyncDnsLookup in ComponentOptions) and not 
WSocketIsDottedIP(AnsiString(FAddrStr)) then begin
+                  { If Socket.OnError is assigned, any raised exception will 
be transferred to }
+                  { the handler silently. So clear the handler temporarily to 
catch exception. }
+                  TmpOnError := OnError;
+                  OnError := nil;
+                  try
+                      DnsLookup(FAddrStr);
+                      FInternalDnsActive := TRUE;
+                      Exit; { Actual connect will happen on DNS lookup done }
+                  finally
+                      OnError := TmpOnError;
+                  end;
            end
-            else
-                WSocket_Synchronized_ResolveHost(FAddrStr, Fsin, 
FSocketFamily, FProto);
-
+            else begin
+              { The next line will trigger an exception in case of failure }
+              if FSocketFamily = sfIPv4 then
+              begin
+                  Fsin.sin6_family := AF_INET;
+                  PSockAddrIn(@Fsin).sin_addr.S_addr := 
WSocket_Synchronized_ResolveHost(AnsiString(FAddrStr)).s_addr;
+              end
+              else
+                  WSocket_Synchronized_ResolveHost(FAddrStr, Fsin, 
FSocketFamily, FProto);
+            end;
            FAddrResolved := TRUE;
            FAddrFormat := Fsin.sin6_family;
        end;
@@ -10840,7 +10863,42 @@ end;

{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TCustomWSocket.TriggerDNSLookupDone(Error : Word);
+var
+    TmpOnError: TNotifyEvent;
begin
+    { Actions if it was internal DNS call.           }
+    { In case of error call TriggerSessionConnected  }
+    if FInternalDnsActive then
+    begin
+        FInternalDnsActive := FALSE;
+        if Error = 0 then
+            try
+                { The next line will trigger an exception in case of failure }
+                if FSocketFamily = sfIPv4 then
+                begin
+                    Fsin.sin6_family := AF_INET;
+                    PSockAddrIn(@Fsin).sin_addr.S_addr := 
WSocket_Synchronized_ResolveHost(AnsiString(DnsResult)).s_addr;
+                end
+                else
+                    WSocket_Synchronized_ResolveHost(DnsResult, Fsin, 
FSocketFamily, FProto);
+                FAddrResolved := TRUE;
+                { If Socket.OnError is assigned, any raised exception will be 
transferred to }
+                { the handler silently. So clear the handler temporarily to 
catch exception. }
+                TmpOnError := OnError;
+                OnError := nil;
+                try
+                    Connect;
+                finally
+                    OnError := TmpOnError;
+                end;
+            except on E: Exception do
+                HandleBackGroundException(E);
+            end
+        else
+            TriggerSessionConnected(Error);
+        Exit;
+    end;
+
    if Assigned(FOnDNSLookupDone) then
        FOnDNSLookupDone(Self, Error);
end;

If someone's interested, I also added an option to use internal ICS DNS lookup 
mechanism for IPv4 on Windows

--
A.S.
--
To unsubscribe or change your settings for TWSocket mailing list
please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket
Visit our website at http://www.overbyte.be

Reply via email to