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