diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-07-06 07:39:24 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-07-06 07:39:24 +0000 |
commit | ec59e6a4f56f68916cf8ec8fefca3282a70d16d2 (patch) | |
tree | e9fce0d2f7b8dceb717ba434731bde4db594eb0a /src/gns/w32nsp.c | |
parent | 2dda2c0e3a7c3813fc334d983b65d9f698953143 (diff) | |
download | gnunet-ec59e6a4f56f68916cf8ec8fefca3282a70d16d2.tar.gz gnunet-ec59e6a4f56f68916cf8ec8fefca3282a70d16d2.zip |
-LRN: W32 NS provider for GNS
Also a helper service.
A couple tools for installing/removing the provder.
And a resolver tool that loads the provider directly.
Diffstat (limited to 'src/gns/w32nsp.c')
-rw-r--r-- | src/gns/w32nsp.c | 681 |
1 files changed, 681 insertions, 0 deletions
diff --git a/src/gns/w32nsp.c b/src/gns/w32nsp.c new file mode 100644 index 000000000..b3604271e --- /dev/null +++ b/src/gns/w32nsp.c | |||
@@ -0,0 +1,681 @@ | |||
1 | /* This code is partially based upon samples from the book | ||
2 | * "Network Programming For Microsoft Windows, 2Nd Edition". | ||
3 | */ | ||
4 | |||
5 | #define INITGUID | ||
6 | #include <windows.h> | ||
7 | #include <nspapi.h> | ||
8 | #include <stdint.h> | ||
9 | #include <ws2tcpip.h> | ||
10 | #include <ws2spi.h> | ||
11 | |||
12 | #if 1 | ||
13 | # define DEBUGLOG(s, ...) | ||
14 | #endif | ||
15 | #if 0 | ||
16 | # define DEBUGLOG(s, ...) printf (s, ##__VA_ARGS__) | ||
17 | #endif | ||
18 | |||
19 | #define WINDOWS 1 | ||
20 | #define MINGW 1 | ||
21 | #ifndef __BYTE_ORDER | ||
22 | #ifdef _BYTE_ORDER | ||
23 | #define __BYTE_ORDER _BYTE_ORDER | ||
24 | #else | ||
25 | #ifdef BYTE_ORDER | ||
26 | #define __BYTE_ORDER BYTE_ORDER | ||
27 | #endif | ||
28 | #endif | ||
29 | #endif | ||
30 | #ifndef __BIG_ENDIAN | ||
31 | #ifdef _BIG_ENDIAN | ||
32 | #define __BIG_ENDIAN _BIG_ENDIAN | ||
33 | #else | ||
34 | #ifdef BIG_ENDIAN | ||
35 | #define __BIG_ENDIAN BIG_ENDIAN | ||
36 | #endif | ||
37 | #endif | ||
38 | #endif | ||
39 | #ifndef __LITTLE_ENDIAN | ||
40 | #ifdef _LITTLE_ENDIAN | ||
41 | #define __LITTLE_ENDIAN _LITTLE_ENDIAN | ||
42 | #else | ||
43 | #ifdef LITTLE_ENDIAN | ||
44 | #define __LITTLE_ENDIAN LITTLE_ENDIAN | ||
45 | #endif | ||
46 | #endif | ||
47 | #endif | ||
48 | #include <gnunet_w32nsp_lib.h> | ||
49 | #include <w32resolver.h> | ||
50 | |||
51 | #define NSPAPI_VERSION_MAJOR 4 | ||
52 | #define NSPAPI_VERSION_MINOR 4 | ||
53 | |||
54 | #define REPLY_LIFETIME 60*5 | ||
55 | |||
56 | #define STATE_BEGIN 0x01 | ||
57 | #define STATE_END 0x02 | ||
58 | #define STATE_REPLY 0x04 | ||
59 | #define STATE_GHBN 0x08 | ||
60 | |||
61 | uint64_t | ||
62 | GNUNET_htonll (uint64_t n) | ||
63 | { | ||
64 | #if __BYTE_ORDER == __BIG_ENDIAN | ||
65 | return n; | ||
66 | #elif __BYTE_ORDER == __LITTLE_ENDIAN | ||
67 | return (((uint64_t) htonl (n)) << 32) + htonl (n >> 32); | ||
68 | #else | ||
69 | #error byteorder undefined | ||
70 | #endif | ||
71 | } | ||
72 | |||
73 | CRITICAL_SECTION records_cs; | ||
74 | |||
75 | struct record | ||
76 | { | ||
77 | SOCKET s; | ||
78 | DWORD flags; | ||
79 | uint8_t state; | ||
80 | char *buf; | ||
81 | wchar_t *name; | ||
82 | }; | ||
83 | |||
84 | static struct record *records = NULL; | ||
85 | static size_t records_len = 0; | ||
86 | static size_t records_size = 0; | ||
87 | |||
88 | int | ||
89 | resize_records () | ||
90 | { | ||
91 | size_t new_size = records_len > 0 ? records_len * 2 : 5; | ||
92 | struct record *new_records = malloc (new_size * sizeof (struct record)); | ||
93 | if (new_records == NULL) | ||
94 | { | ||
95 | SetLastError (WSA_NOT_ENOUGH_MEMORY); | ||
96 | return 0; | ||
97 | } | ||
98 | memcpy (new_records, records, records_len * sizeof (struct record)); | ||
99 | memset (&new_records[records_len], 0, sizeof (struct record) * (new_size - records_len)); | ||
100 | records_size = new_size; | ||
101 | free (records); | ||
102 | records = new_records; | ||
103 | return 1; | ||
104 | } | ||
105 | |||
106 | int | ||
107 | add_record (SOCKET s, const wchar_t *name, DWORD flags) | ||
108 | { | ||
109 | int res = 1; | ||
110 | int i; | ||
111 | int empty = -1; | ||
112 | //EnterCriticalSection (&records_cs); | ||
113 | for (i = 0; i < records_len; i++) | ||
114 | if (records[i].state == 0) | ||
115 | break; | ||
116 | empty = i; | ||
117 | if (i == records_len) | ||
118 | { | ||
119 | res = resize_records (); | ||
120 | if (res) | ||
121 | empty = records_len++; | ||
122 | } | ||
123 | if (res) | ||
124 | { | ||
125 | struct record r; | ||
126 | r.s = s; | ||
127 | r.flags = flags; | ||
128 | r.name = (wchar_t *) name; | ||
129 | r.state = 1; | ||
130 | r.buf = NULL; | ||
131 | if (name) | ||
132 | r.name = wcsdup (name); | ||
133 | records[empty] = r; | ||
134 | } | ||
135 | //LeaveCriticalSection (&records_cs); | ||
136 | return res; | ||
137 | } | ||
138 | |||
139 | void | ||
140 | free_record (int i) | ||
141 | { | ||
142 | if (records[i].name) | ||
143 | free (records[i].name); | ||
144 | records[i].state = 0; | ||
145 | } | ||
146 | |||
147 | /* These are not defined by mingw.org headers at the moment*/ | ||
148 | typedef INT (WSPAPI *LPNSPIOCTL) (HANDLE,DWORD,LPVOID,DWORD,LPVOID,DWORD,LPDWORD,LPWSACOMPLETION,LPWSATHREADID); | ||
149 | typedef struct _NSP_ROUTINE_XP { | ||
150 | DWORD cbSize; | ||
151 | DWORD dwMajorVersion; | ||
152 | DWORD dwMinorVersion; | ||
153 | LPNSPCLEANUP NSPCleanup; | ||
154 | LPNSPLOOKUPSERVICEBEGIN NSPLookupServiceBegin; | ||
155 | LPNSPLOOKUPSERVICENEXT NSPLookupServiceNext; | ||
156 | LPNSPLOOKUPSERVICEEND NSPLookupServiceEnd; | ||
157 | LPNSPSETSERVICE NSPSetService; | ||
158 | LPNSPINSTALLSERVICECLASS NSPInstallServiceClass; | ||
159 | LPNSPREMOVESERVICECLASS NSPRemoveServiceClass; | ||
160 | LPNSPGETSERVICECLASSINFO NSPGetServiceClassInfo; | ||
161 | LPNSPIOCTL NSPIoctl; | ||
162 | } NSP_ROUTINE_XP, *PNSP_ROUTINE_XP, *LPNSP_ROUTINE_XP; | ||
163 | |||
164 | static SOCKET | ||
165 | connect_to_dns_resolver () | ||
166 | { | ||
167 | struct sockaddr_in addr; | ||
168 | SOCKET r; | ||
169 | int ret; | ||
170 | |||
171 | r = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); | ||
172 | if (INVALID_SOCKET == r) | ||
173 | { | ||
174 | SetLastError (16004); | ||
175 | return r; | ||
176 | } | ||
177 | |||
178 | addr.sin_family = AF_INET; | ||
179 | addr.sin_port = htons (5353); /* TCP 5353 is not registered; UDP 5353 is */ | ||
180 | addr.sin_addr.s_addr = inet_addr ("127.0.0.1"); | ||
181 | |||
182 | ret = connect (r, (struct sockaddr *) &addr, sizeof (addr)); | ||
183 | if (SOCKET_ERROR == ret) | ||
184 | { | ||
185 | DWORD err = GetLastError (); | ||
186 | closesocket (r); | ||
187 | SetLastError (err); | ||
188 | SetLastError (16005); | ||
189 | r = INVALID_SOCKET; | ||
190 | } | ||
191 | return r; | ||
192 | } | ||
193 | |||
194 | static int | ||
195 | send_name_to_ip_request (LPWSAQUERYSETW lpqsRestrictions, | ||
196 | LPWSASERVICECLASSINFOW lpServiceClassInfo, DWORD dwControlFlags, | ||
197 | SOCKET *resolver) | ||
198 | { | ||
199 | struct GNUNET_W32RESOLVER_GetMessage *msg; | ||
200 | int af4 = 0; | ||
201 | int af6 = 0; | ||
202 | char *buf; | ||
203 | int ret = 1; | ||
204 | int i; | ||
205 | uint32_t id; | ||
206 | size_t size = sizeof (struct GNUNET_W32RESOLVER_GetMessage); | ||
207 | size_t namelen = 0; | ||
208 | if (lpqsRestrictions->lpszServiceInstanceName) | ||
209 | namelen = sizeof (wchar_t) * (wcslen (lpqsRestrictions->lpszServiceInstanceName) + 1); | ||
210 | size += namelen; | ||
211 | buf = malloc (size); | ||
212 | msg = (struct GNUNET_W32RESOLVER_GetMessage *) buf; | ||
213 | msg->header.size = htons (size); | ||
214 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_W32RESOLVER_REQUEST); | ||
215 | if (lpqsRestrictions->dwNumberOfProtocols > 0) | ||
216 | { | ||
217 | int i; | ||
218 | for (i = 0; i < lpqsRestrictions->dwNumberOfProtocols; i++) | ||
219 | { | ||
220 | if (lpqsRestrictions->lpafpProtocols[0].iAddressFamily == AF_INET) | ||
221 | af4 = 1; | ||
222 | if (lpqsRestrictions->lpafpProtocols[0].iAddressFamily == AF_INET6) | ||
223 | af6 = 1; | ||
224 | } | ||
225 | } | ||
226 | if (af4 && !af6) | ||
227 | msg->af = htonl (AF_INET); | ||
228 | else if (af6 && !af4) | ||
229 | msg->af = htonl (AF_INET6); | ||
230 | else | ||
231 | msg->af = htonl (AF_UNSPEC); | ||
232 | if (lpqsRestrictions->lpszServiceInstanceName) | ||
233 | memcpy (&msg[1], lpqsRestrictions->lpszServiceInstanceName, namelen); | ||
234 | msg->sc_data1 = htonl (lpqsRestrictions->lpServiceClassId->Data1); | ||
235 | msg->sc_data2 = htons (lpqsRestrictions->lpServiceClassId->Data2); | ||
236 | msg->sc_data3 = htons (lpqsRestrictions->lpServiceClassId->Data3); | ||
237 | msg->sc_data4 = 0; | ||
238 | for (i = 0; i < 8; i++) | ||
239 | msg->sc_data4 |= ((uint64_t) lpqsRestrictions->lpServiceClassId->Data4[i]) << ((7 - i) * 8); | ||
240 | msg->sc_data4 = GNUNET_htonll (msg->sc_data4); | ||
241 | *resolver = connect_to_dns_resolver (); | ||
242 | if (*resolver != INVALID_SOCKET) | ||
243 | { | ||
244 | if (size != send (*resolver, buf, size, 0)) | ||
245 | { | ||
246 | DWORD err = GetLastError (); | ||
247 | closesocket (*resolver); | ||
248 | *resolver = INVALID_SOCKET; | ||
249 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: failed to send request: %lu\n", err); | ||
250 | SetLastError (WSATRY_AGAIN); | ||
251 | ret = 0; | ||
252 | } | ||
253 | } | ||
254 | else | ||
255 | ret = 0; | ||
256 | free (buf); | ||
257 | return ret; | ||
258 | } | ||
259 | |||
260 | int WSPAPI | ||
261 | NSPCleanup (LPGUID lpProviderId) | ||
262 | { | ||
263 | DEBUGLOG ("NSPCleanup\n"); | ||
264 | if (IsEqualGUID (lpProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS)) | ||
265 | { | ||
266 | return NO_ERROR; | ||
267 | } | ||
268 | SetLastError (WSAEINVALIDPROVIDER); | ||
269 | return SOCKET_ERROR; | ||
270 | } | ||
271 | |||
272 | BOOL WINAPI | ||
273 | DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) | ||
274 | { | ||
275 | switch (fdwReason) | ||
276 | { | ||
277 | case DLL_PROCESS_ATTACH: | ||
278 | if (!InitializeCriticalSectionAndSpinCount (&records_cs, 0x00000400)) | ||
279 | { | ||
280 | return FALSE; | ||
281 | } | ||
282 | break; | ||
283 | case DLL_THREAD_ATTACH: | ||
284 | break; | ||
285 | case DLL_THREAD_DETACH: | ||
286 | break; | ||
287 | case DLL_PROCESS_DETACH: | ||
288 | DeleteCriticalSection (&records_cs); | ||
289 | break; | ||
290 | } | ||
291 | return TRUE; | ||
292 | } | ||
293 | |||
294 | |||
295 | |||
296 | |||
297 | int WSPAPI | ||
298 | GNUNET_W32NSP_LookupServiceBegin (LPGUID lpProviderId, LPWSAQUERYSETW lpqsRestrictions, | ||
299 | LPWSASERVICECLASSINFOW lpServiceClassInfo, DWORD dwControlFlags, | ||
300 | LPHANDLE lphLookup) | ||
301 | { | ||
302 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin\n"); | ||
303 | if (IsEqualGUID (lpProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS)) | ||
304 | { | ||
305 | SOCKET s; | ||
306 | if (lpqsRestrictions->dwNameSpace != NS_DNS && lpqsRestrictions->dwNameSpace != NS_ALL) | ||
307 | { | ||
308 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: wrong namespace\n"); | ||
309 | SetLastError (WSANO_DATA); | ||
310 | return SOCKET_ERROR; | ||
311 | } | ||
312 | if (lpqsRestrictions->lpszServiceInstanceName != NULL) | ||
313 | { | ||
314 | wchar_t *s = lpqsRestrictions->lpszServiceInstanceName; | ||
315 | size_t len = wcslen (s); | ||
316 | if (len >= 4 && wcscmp (&s[len - 4], L"zkey") == 0) | ||
317 | { | ||
318 | } | ||
319 | else if (len >= 6 && wcscmp (&s[len - 6], L"gnunet") == 0) | ||
320 | { | ||
321 | } | ||
322 | else | ||
323 | { | ||
324 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: unsupported TLD\n"); | ||
325 | SetLastError (WSANO_DATA); | ||
326 | return SOCKET_ERROR; | ||
327 | } | ||
328 | } | ||
329 | |||
330 | if (send_name_to_ip_request (lpqsRestrictions, | ||
331 | lpServiceClassInfo, dwControlFlags, &s)) | ||
332 | { | ||
333 | if (!(add_record (s, lpqsRestrictions->lpszServiceInstanceName, dwControlFlags))) | ||
334 | { | ||
335 | DWORD err = GetLastError (); | ||
336 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: failed to add a record\n"); | ||
337 | closesocket (s); | ||
338 | SetLastError (err); | ||
339 | return SOCKET_ERROR; | ||
340 | } | ||
341 | *lphLookup = (HANDLE) s; | ||
342 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: OK (%lu)\n", GetLastError ()); | ||
343 | return NO_ERROR; | ||
344 | } | ||
345 | return SOCKET_ERROR; | ||
346 | } | ||
347 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: wrong provider\n"); | ||
348 | SetLastError (WSAEINVALIDPROVIDER); | ||
349 | return SOCKET_ERROR; | ||
350 | } | ||
351 | |||
352 | #define UnmarshallPtr(ptr, ptrtype, base) \ | ||
353 | if (ptr) \ | ||
354 | ptr = (ptrtype *) (base + (uintptr_t) ptr) | ||
355 | |||
356 | void | ||
357 | UnmarshallWSAQUERYSETW (LPWSAQUERYSETW req) | ||
358 | { | ||
359 | int i; | ||
360 | char *base = (char *) req; | ||
361 | UnmarshallPtr (req->lpszServiceInstanceName, wchar_t, base); | ||
362 | UnmarshallPtr (req->lpServiceClassId, GUID, base); | ||
363 | UnmarshallPtr (req->lpVersion, WSAVERSION, base); | ||
364 | UnmarshallPtr (req->lpszComment, wchar_t, base); | ||
365 | UnmarshallPtr (req->lpNSProviderId, GUID, base); | ||
366 | UnmarshallPtr (req->lpszContext, wchar_t, base); | ||
367 | UnmarshallPtr (req->lpafpProtocols, AFPROTOCOLS, base); | ||
368 | UnmarshallPtr (req->lpszQueryString, wchar_t, base); | ||
369 | UnmarshallPtr (req->lpcsaBuffer, CSADDR_INFO, base); | ||
370 | for (i = 0; i < req->dwNumberOfCsAddrs; i++) | ||
371 | { | ||
372 | UnmarshallPtr (req->lpcsaBuffer[i].LocalAddr.lpSockaddr, SOCKADDR, base); | ||
373 | UnmarshallPtr (req->lpcsaBuffer[i].RemoteAddr.lpSockaddr, SOCKADDR, base); | ||
374 | } | ||
375 | UnmarshallPtr (req->lpBlob, BLOB, base); | ||
376 | if (req->lpBlob) | ||
377 | UnmarshallPtr (req->lpBlob->pBlobData, BYTE, base); | ||
378 | } | ||
379 | |||
380 | int WSAAPI | ||
381 | GNUNET_W32NSP_LookupServiceNext (HANDLE hLookup, DWORD dwControlFlags, | ||
382 | LPDWORD lpdwBufferLength, LPWSAQUERYSET lpqsResults) | ||
383 | { | ||
384 | DWORD effective_flags; | ||
385 | int i; | ||
386 | struct GNUNET_MessageHeader header = {0, 0}; | ||
387 | int rec = -1; | ||
388 | int rc; | ||
389 | int to_receive; | ||
390 | int t; | ||
391 | char *buf; | ||
392 | |||
393 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext\n"); | ||
394 | //EnterCriticalSection (&records_cs); | ||
395 | for (i = 0; i < records_len; i++) | ||
396 | { | ||
397 | if (records[i].s == (SOCKET) hLookup) | ||
398 | { | ||
399 | rec = i; | ||
400 | break; | ||
401 | } | ||
402 | } | ||
403 | if (rec == -1) | ||
404 | { | ||
405 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: invalid handle\n"); | ||
406 | SetLastError (WSA_INVALID_HANDLE); | ||
407 | //LeaveCriticalSection (&records_cs); | ||
408 | return SOCKET_ERROR; | ||
409 | } | ||
410 | if (records[rec].state & 4) | ||
411 | { | ||
412 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: session is closed\n"); | ||
413 | SetLastError (WSA_E_NO_MORE); | ||
414 | //LeaveCriticalSection (&records_cs); | ||
415 | return SOCKET_ERROR; | ||
416 | } | ||
417 | effective_flags = dwControlFlags & records[rec].flags; | ||
418 | if (records[rec].buf) | ||
419 | { | ||
420 | header = *((struct GNUNET_MessageHeader *) records[rec].buf); | ||
421 | if (dwControlFlags & LUP_FLUSHCACHE) | ||
422 | { | ||
423 | free (records[rec].buf); | ||
424 | records[rec].buf = NULL; | ||
425 | } | ||
426 | else | ||
427 | { | ||
428 | if (*lpdwBufferLength < header.size - sizeof (struct GNUNET_W32RESOLVER_GetMessage)) | ||
429 | { | ||
430 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: client buffer is too small\n"); | ||
431 | SetLastError (WSAEFAULT); | ||
432 | //LeaveCriticalSection (&records_cs); | ||
433 | return SOCKET_ERROR; | ||
434 | } | ||
435 | memcpy (lpqsResults, &((struct GNUNET_W32RESOLVER_GetMessage *)records[rec].buf)[1], header.size - sizeof (struct GNUNET_W32RESOLVER_GetMessage)); | ||
436 | free (records[rec].buf); | ||
437 | records[rec].buf = NULL; | ||
438 | //LeaveCriticalSection (&records_cs); | ||
439 | UnmarshallWSAQUERYSETW ((LPWSAQUERYSETW) lpqsResults); | ||
440 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: OK (from buffer)\n"); | ||
441 | return NO_ERROR; | ||
442 | } | ||
443 | } | ||
444 | records[rec].state |= 8; | ||
445 | //LeaveCriticalSection (&records_cs); | ||
446 | to_receive = sizeof (header); | ||
447 | rc = 0; | ||
448 | while (to_receive > 0) | ||
449 | { | ||
450 | t = recv ((SOCKET) hLookup, &((char *) &header)[rc], to_receive, 0); | ||
451 | if (t > 0) | ||
452 | { | ||
453 | rc += t; | ||
454 | to_receive -= t; | ||
455 | } | ||
456 | else | ||
457 | break; | ||
458 | } | ||
459 | //EnterCriticalSection (&records_cs); | ||
460 | records[rec].state &= ~8; | ||
461 | if (rc != sizeof (header)) | ||
462 | { | ||
463 | if (records[rec].state & 2) | ||
464 | { | ||
465 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: call cancelled\n"); | ||
466 | SetLastError (WSA_E_CANCELLED); | ||
467 | } | ||
468 | else | ||
469 | { | ||
470 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: failed to receive enough data\n"); | ||
471 | SetLastError (WSA_E_NO_MORE); | ||
472 | } | ||
473 | records[rec].state |= 4; | ||
474 | //LeaveCriticalSection (&records_cs); | ||
475 | return SOCKET_ERROR; | ||
476 | } | ||
477 | records[rec].state &= ~8; | ||
478 | header.type = ntohs (header.type); | ||
479 | header.size = ntohs (header.size); | ||
480 | if (header.type != GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE || | ||
481 | (header.type == GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE && | ||
482 | header.size == sizeof (header))) | ||
483 | { | ||
484 | records[rec].state |= 4; | ||
485 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: header is wrong or type is wrong or no data\n"); | ||
486 | //LeaveCriticalSection (&records_cs); | ||
487 | SetLastError (WSA_E_NO_MORE); | ||
488 | return SOCKET_ERROR; | ||
489 | } | ||
490 | buf = malloc (header.size); | ||
491 | if (buf == NULL) | ||
492 | { | ||
493 | records[rec].state |= 4; | ||
494 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: malloc() failed\n"); | ||
495 | //LeaveCriticalSection (&records_cs); | ||
496 | SetLastError (WSA_E_NO_MORE); | ||
497 | return SOCKET_ERROR; | ||
498 | } | ||
499 | records[rec].state |= 8; | ||
500 | //LeaveCriticalSection (&records_cs); | ||
501 | memcpy (buf, &header, sizeof (header)); | ||
502 | to_receive = header.size - sizeof (header); | ||
503 | rc = 0; | ||
504 | while (to_receive > 0) | ||
505 | { | ||
506 | t = recv ((SOCKET) hLookup, &((char *) &((struct GNUNET_MessageHeader *) buf)[1])[rc], to_receive, 0); | ||
507 | if (t > 0) | ||
508 | { | ||
509 | rc += t; | ||
510 | to_receive -= t; | ||
511 | } | ||
512 | else | ||
513 | break; | ||
514 | } | ||
515 | //EnterCriticalSection (&records_cs); | ||
516 | records[rec].state &= ~8; | ||
517 | if (rc != header.size - sizeof (header)) | ||
518 | { | ||
519 | free (buf); | ||
520 | if (records[rec].state & 2) | ||
521 | { | ||
522 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: call cancelled\n"); | ||
523 | SetLastError (WSA_E_CANCELLED); | ||
524 | } | ||
525 | else | ||
526 | { | ||
527 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: failed to receive enough data\n"); | ||
528 | SetLastError (WSA_E_NO_MORE); | ||
529 | } | ||
530 | records[rec].state |= 4; | ||
531 | //LeaveCriticalSection (&records_cs); | ||
532 | return SOCKET_ERROR; | ||
533 | } | ||
534 | if (*lpdwBufferLength < header.size - sizeof (struct GNUNET_W32RESOLVER_GetMessage)) | ||
535 | { | ||
536 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: client buffer is too small\n"); | ||
537 | SetLastError (WSAEFAULT); | ||
538 | records[rec].buf = buf; | ||
539 | //LeaveCriticalSection (&records_cs); | ||
540 | return SOCKET_ERROR; | ||
541 | } | ||
542 | //LeaveCriticalSection (&records_cs); | ||
543 | memcpy (lpqsResults, &((struct GNUNET_W32RESOLVER_GetMessage *)buf)[1], header.size - sizeof (struct GNUNET_W32RESOLVER_GetMessage)); | ||
544 | free (buf); | ||
545 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: OK\n"); | ||
546 | UnmarshallWSAQUERYSETW ((LPWSAQUERYSETW) lpqsResults); | ||
547 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: returning (%lu)\n", GetLastError ()); | ||
548 | return NO_ERROR; | ||
549 | } | ||
550 | |||
551 | int WSPAPI | ||
552 | GNUNET_W32NSP_LookupServiceEnd (HANDLE hLookup) | ||
553 | { | ||
554 | DWORD effective_flags; | ||
555 | int i; | ||
556 | struct GNUNET_MessageHeader header = {0, 0}; | ||
557 | int rec = -1; | ||
558 | int rc; | ||
559 | char *buf; | ||
560 | |||
561 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceEnd\n"); | ||
562 | //EnterCriticalSection (&records_cs); | ||
563 | for (i = 0; i < records_len; i++) | ||
564 | { | ||
565 | if (records[i].s == (SOCKET) hLookup) | ||
566 | { | ||
567 | rec = i; | ||
568 | break; | ||
569 | } | ||
570 | } | ||
571 | if (rec == -1) | ||
572 | { | ||
573 | SetLastError (WSA_INVALID_HANDLE); | ||
574 | //LeaveCriticalSection (&records_cs); | ||
575 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceEnd: invalid handle\n"); | ||
576 | return SOCKET_ERROR; | ||
577 | } | ||
578 | records[rec].state |= 2; | ||
579 | closesocket (records[rec].s); | ||
580 | while (records[rec].state & 8) | ||
581 | { | ||
582 | //LeaveCriticalSection (&records_cs); | ||
583 | Sleep (10); | ||
584 | //EnterCriticalSection (&records_cs); | ||
585 | } | ||
586 | if (records[rec].buf) | ||
587 | free (records[rec].buf); | ||
588 | records[rec].buf = NULL; | ||
589 | records[rec].state = 0; | ||
590 | if (records[rec].name) | ||
591 | free (records[rec].name); | ||
592 | //LeaveCriticalSection (&records_cs); | ||
593 | DEBUGLOG ("GNUNET_W32NSP_LookupServiceEnd: OK\n"); | ||
594 | return NO_ERROR; | ||
595 | } | ||
596 | |||
597 | int WSAAPI | ||
598 | GNUNET_W32NSP_SetService (LPGUID lpProviderId, | ||
599 | LPWSASERVICECLASSINFOW lpServiceClassInfo, LPWSAQUERYSETW lpqsRegInfo, | ||
600 | WSAESETSERVICEOP essOperation, DWORD dwControlFlags) | ||
601 | { | ||
602 | DEBUGLOG ("GNUNET_W32NSP_SetService\n"); | ||
603 | SetLastError (WSAEOPNOTSUPP); | ||
604 | return SOCKET_ERROR; | ||
605 | } | ||
606 | |||
607 | int WSAAPI | ||
608 | GNUNET_W32NSP_InstallServiceClass (LPGUID lpProviderId, | ||
609 | LPWSASERVICECLASSINFOW lpServiceClassInfo) | ||
610 | { | ||
611 | DEBUGLOG ("GNUNET_W32NSP_InstallServiceClass\n"); | ||
612 | SetLastError (WSAEOPNOTSUPP); | ||
613 | return SOCKET_ERROR; | ||
614 | } | ||
615 | |||
616 | |||
617 | int WSAAPI | ||
618 | GNUNET_W32NSP_RemoveServiceClass (LPGUID lpProviderId, LPGUID lpServiceClassId) | ||
619 | { | ||
620 | DEBUGLOG ("GNUNET_W32NSP_RemoveServiceClass\n"); | ||
621 | SetLastError (WSAEOPNOTSUPP); | ||
622 | return SOCKET_ERROR; | ||
623 | } | ||
624 | |||
625 | int WSAAPI | ||
626 | GNUNET_W32NSP_GetServiceClassInfo (LPGUID lpProviderId, LPDWORD lpdwBufSize, | ||
627 | LPWSASERVICECLASSINFOW lpServiceClassInfo) | ||
628 | { | ||
629 | DEBUGLOG ("GNUNET_W32NSP_GetServiceClassInfo\n"); | ||
630 | SetLastError (WSAEOPNOTSUPP); | ||
631 | return SOCKET_ERROR; | ||
632 | } | ||
633 | |||
634 | int WSAAPI | ||
635 | GNUNET_W32NSP_Ioctl (HANDLE hLookup, DWORD dwControlCode, LPVOID lpvInBuffer, | ||
636 | DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer, | ||
637 | LPDWORD lpcbBytesReturned, LPWSACOMPLETION lpCompletion, | ||
638 | LPWSATHREADID lpThreadId) | ||
639 | { | ||
640 | DEBUGLOG ("GNUNET_W32NSP_Ioctl\n"); | ||
641 | SetLastError (WSAEOPNOTSUPP); | ||
642 | return SOCKET_ERROR; | ||
643 | } | ||
644 | |||
645 | /** | ||
646 | * This function is called by Winsock to hook up our provider. | ||
647 | * It is the only function that [should be/is] exported by the | ||
648 | * provider. All other routines are passed as pointers in lpnspRoutines. | ||
649 | */ | ||
650 | int WSPAPI | ||
651 | NSPStartup (LPGUID lpProviderId, LPNSP_ROUTINE lpnspRoutines) | ||
652 | { | ||
653 | if (IsEqualGUID (lpProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS)) | ||
654 | { | ||
655 | if (!connect_to_dns_resolver ()) | ||
656 | { | ||
657 | return SOCKET_ERROR; | ||
658 | } | ||
659 | /* This assumes that NSP_ROUTINE struct doesn't have a NSPIoctl member. | ||
660 | * If it does, you need to use FIELD_OFFSET() macro to get offset of NSPIoctl | ||
661 | * and use that offset as cbSize. | ||
662 | */ | ||
663 | lpnspRoutines->cbSize = sizeof(NSP_ROUTINE_XP); | ||
664 | |||
665 | lpnspRoutines->dwMajorVersion = NSPAPI_VERSION_MAJOR; | ||
666 | lpnspRoutines->dwMinorVersion = NSPAPI_VERSION_MINOR; | ||
667 | lpnspRoutines->NSPCleanup = NSPCleanup; | ||
668 | lpnspRoutines->NSPLookupServiceBegin = GNUNET_W32NSP_LookupServiceBegin; | ||
669 | lpnspRoutines->NSPLookupServiceNext = GNUNET_W32NSP_LookupServiceNext; | ||
670 | lpnspRoutines->NSPLookupServiceEnd = GNUNET_W32NSP_LookupServiceEnd; | ||
671 | lpnspRoutines->NSPSetService = GNUNET_W32NSP_SetService; | ||
672 | lpnspRoutines->NSPInstallServiceClass = GNUNET_W32NSP_InstallServiceClass; | ||
673 | lpnspRoutines->NSPRemoveServiceClass = GNUNET_W32NSP_RemoveServiceClass; | ||
674 | lpnspRoutines->NSPGetServiceClassInfo = GNUNET_W32NSP_GetServiceClassInfo; | ||
675 | ((NSP_ROUTINE_XP *) lpnspRoutines)->NSPIoctl = GNUNET_W32NSP_Ioctl; | ||
676 | return NO_ERROR; | ||
677 | } | ||
678 | SetLastError (WSAEINVALIDPROVIDER); | ||
679 | return SOCKET_ERROR; | ||
680 | } | ||
681 | |||