1 /***************************************************************************
2 casyncdns.cpp - description
3 -------------------
4 begin : Mon Jun 10 2002
5 copyright : (C) 2002-2004 by Mathias Küster
6 email : mathen@users.berlios.de
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 #include "casyncdns.h"
19 #include "cnetaddr.h"
20
21 #include <string.h>
22
23 #define HOST_LIST_TIMEOUT 60
24 #define HOST_CACHE_TIMEOUT 60
25
26 /** */
CAsyncDns()27 CAsyncDns::CAsyncDns()
28 {
29 m_pHostCache = new CStringList<CAsyncDnsEntry>(4);
30 m_pHostList = new CStringList<CAsyncDnsEntry>(4);
31
32 // start new thread
33 Start();
34 }
35
36 /** */
~CAsyncDns()37 CAsyncDns::~CAsyncDns()
38 {
39 SetInstance(0);
40
41 // stop thread
42 Stop(true);
43
44 Lock();
45
46 delete m_pHostCache;
47 m_pHostCache = 0;
48
49 delete m_pHostList;
50 m_pHostList = 0;
51
52 UnLock();
53 }
54
55 /** call from application */
GetHostI4(CString stringHost,struct sockaddr_in * sin,CString * errmsg)56 eAsyncDns CAsyncDns::GetHostI4( CString stringHost, struct sockaddr_in * sin, CString * errmsg )
57 {
58 CAsyncDnsEntry * AsyncDnsEntry;
59 eAsyncDns err;
60
61 // return if lock failed
62 if ( TryLock() == false )
63 {
64 return eadAGAIN;
65 }
66
67 err = eadERROR;
68
69 // sanity check
70 if ( m_pHostCache && m_pHostList && (stringHost.NotEmpty()) && sin )
71 {
72 if ( m_pHostCache->Get( stringHost, &AsyncDnsEntry ) != -1 )
73 {
74 // host found in the m_pHostCache list, return first resolved ip
75 memcpy( sin, &AsyncDnsEntry->m_sin, sizeof(struct sockaddr_in) );
76 m_pHostCache->Del(stringHost);
77 err = eadSUCCESS;
78 }
79
80 if ( err == eadERROR )
81 {
82 if ( m_pHostList->Get( stringHost, &AsyncDnsEntry ) == -1 )
83 {
84 // host not found in the m_pHostList, add it
85 AsyncDnsEntry = new CAsyncDnsEntry();
86
87 AsyncDnsEntry->m_sHost = stringHost;
88 AsyncDnsEntry->m_bError = false;
89 // set initial timeout
90 AsyncDnsEntry->m_tTimeout = time(0);
91
92 m_pHostList->Add( stringHost, AsyncDnsEntry );
93
94 err = eadAGAIN;
95 }
96 else if ( AsyncDnsEntry->m_bError == false )
97 {
98 // dns query not finished
99 err = eadAGAIN;
100 }
101 else
102 {
103 if ( errmsg != 0 )
104 {
105 // return error message
106 *errmsg = AsyncDnsEntry->m_sErrMsg;
107 }
108
109 // remove from hostlist
110 m_pHostList->Del(AsyncDnsEntry->m_sHost);
111 }
112 }
113 }
114
115 UnLock();
116
117 return err;
118 }
119
120 /** */
Thread()121 void CAsyncDns::Thread()
122 {
123 CAsyncDnsEntry * AsyncDnsEntry = 0;
124
125 Lock();
126
127 if ( m_pHostCache->Count() > 0 )
128 {
129 // check cache timeout to avoid possible list overflows
130 while ( m_pHostCache->Next( &AsyncDnsEntry ) != 0 )
131 {
132 if ( (time(0)-AsyncDnsEntry->m_tTimeout) >= HOST_CACHE_TIMEOUT )
133 {
134 // remove entry from m_pHostCache list
135 m_pHostCache->Del(AsyncDnsEntry->m_sHost);
136 AsyncDnsEntry = 0;
137 break;
138 }
139 }
140 }
141
142 AsyncDnsEntry = 0;
143
144 if ( m_pHostList->Count() > 0 )
145 {
146 while ( m_pHostList->Next( &AsyncDnsEntry ) != 0 )
147 {
148 if ( AsyncDnsEntry->m_bError == false )
149 {
150 // no error
151 break;
152 }
153 else if ( (time(0)-AsyncDnsEntry->m_tTimeout) >= HOST_LIST_TIMEOUT )
154 {
155 // timeout, remove host from m_pHostList
156 m_pHostList->Del(AsyncDnsEntry->m_sHost);
157 AsyncDnsEntry = 0;
158 break;
159 }
160 }
161 }
162
163 if ( AsyncDnsEntry != 0 )
164 {
165 // no error, no timeout -> update entry
166 CString s = AsyncDnsEntry->m_sHost;
167 UnLock();
168 UpdateEntry(s);
169 }
170 else
171 {
172 UnLock();
173 }
174
175 NanoSleep(50);
176 }
177
178 /** */
UpdateEntry(CString stringHost)179 void CAsyncDns::UpdateEntry( CString stringHost )
180 {
181 CAsyncDnsEntry * AsyncDnsEntry = 0;
182 struct sockaddr_in sin;
183 bool res;
184 CString errmsg;
185
186 // ask dns for ip
187 res = CNetAddr::GetHostI4( stringHost.Data(), &sin, &errmsg );
188
189 Lock();
190
191 if ( m_pHostList->Get( stringHost, &AsyncDnsEntry ) == 0 )
192 {
193 if ( !res )
194 {
195 // error, update entry
196 AsyncDnsEntry->m_bError = true;
197 // update timeout to avoid list overflow
198 AsyncDnsEntry->m_tTimeout = time(0);
199 AsyncDnsEntry->m_sErrMsg = errmsg;
200 }
201 else
202 {
203 // no error, remove from m_pHostList and update m_pHostCache
204 AsyncDnsEntry = new CAsyncDnsEntry();
205
206 AsyncDnsEntry->m_sHost = stringHost;
207 AsyncDnsEntry->m_bError = false;
208 // update timeout to avoid list overflow
209 AsyncDnsEntry->m_tTimeout = time(0);
210 memcpy( &AsyncDnsEntry->m_sin, &sin, sizeof(struct sockaddr_in) );
211
212 m_pHostList->Del(stringHost);
213 m_pHostCache->Add(stringHost,AsyncDnsEntry);
214 }
215 }
216
217 UnLock();
218 }
219