- int rec = -1;\r
- int rc;\r
- char *buf;\r
-\r
- DEBUGLOG ("GNUNET_W32NSP_LookupServiceEnd\n");\r
- //EnterCriticalSection (&records_cs);\r
- for (i = 0; i < records_len; i++)\r
- {\r
- if (records[i].s == (SOCKET) hLookup)\r
- {\r
- rec = i;\r
- break;\r
- }\r
- }\r
- if (rec == -1)\r
- {\r
- SetLastError (WSA_INVALID_HANDLE);\r
- //LeaveCriticalSection (&records_cs);\r
- DEBUGLOG ("GNUNET_W32NSP_LookupServiceEnd: invalid handle\n");\r
- return SOCKET_ERROR;\r
- }\r
- records[rec].state |= 2;\r
- closesocket (records[rec].s);\r
- while (records[rec].state & 8)\r
- {\r
- //LeaveCriticalSection (&records_cs);\r
- Sleep (10);\r
- //EnterCriticalSection (&records_cs);\r
- }\r
- if (records[rec].buf)\r
- free (records[rec].buf);\r
- records[rec].buf = NULL;\r
- records[rec].state = 0;\r
- if (records[rec].name)\r
- free (records[rec].name);\r
- //LeaveCriticalSection (&records_cs);\r
- DEBUGLOG ("GNUNET_W32NSP_LookupServiceEnd: OK\n");\r
- return NO_ERROR;\r
-}\r
-\r
-int WSAAPI\r
-GNUNET_W32NSP_SetService (LPGUID lpProviderId,\r
- LPWSASERVICECLASSINFOW lpServiceClassInfo, LPWSAQUERYSETW lpqsRegInfo,\r
- WSAESETSERVICEOP essOperation, DWORD dwControlFlags)\r
-{\r
- DEBUGLOG ("GNUNET_W32NSP_SetService\n");\r
- SetLastError (WSAEOPNOTSUPP);\r
- return SOCKET_ERROR;\r
-}\r
-\r
-int WSAAPI\r
-GNUNET_W32NSP_InstallServiceClass (LPGUID lpProviderId,\r
- LPWSASERVICECLASSINFOW lpServiceClassInfo)\r
-{\r
- DEBUGLOG ("GNUNET_W32NSP_InstallServiceClass\n");\r
- SetLastError (WSAEOPNOTSUPP);\r
- return SOCKET_ERROR;\r
-}\r
-\r
-\r
-int WSAAPI\r
-GNUNET_W32NSP_RemoveServiceClass (LPGUID lpProviderId, LPGUID lpServiceClassId)\r
-{\r
- DEBUGLOG ("GNUNET_W32NSP_RemoveServiceClass\n");\r
- SetLastError (WSAEOPNOTSUPP);\r
- return SOCKET_ERROR;\r
-}\r
-\r
-int WSAAPI\r
-GNUNET_W32NSP_GetServiceClassInfo (LPGUID lpProviderId, LPDWORD lpdwBufSize,\r
- LPWSASERVICECLASSINFOW lpServiceClassInfo)\r
-{\r
- DEBUGLOG ("GNUNET_W32NSP_GetServiceClassInfo\n");\r
- SetLastError (WSAEOPNOTSUPP);\r
- return SOCKET_ERROR;\r
-}\r
-\r
-int WSAAPI\r
-GNUNET_W32NSP_Ioctl (HANDLE hLookup, DWORD dwControlCode, LPVOID lpvInBuffer,\r
- DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer,\r
- LPDWORD lpcbBytesReturned, LPWSACOMPLETION lpCompletion,\r
- LPWSATHREADID lpThreadId)\r
-{\r
- DEBUGLOG ("GNUNET_W32NSP_Ioctl\n");\r
- SetLastError (WSAEOPNOTSUPP);\r
- return SOCKET_ERROR;\r
-}\r
-\r
-/**\r
- * This function is called by Winsock to hook up our provider.\r
- * It is the only function that [should be/is] exported by the\r
- * provider. All other routines are passed as pointers in lpnspRoutines.\r
- */\r
-int WSPAPI\r
-NSPStartup (LPGUID lpProviderId, LPNSP_ROUTINE lpnspRoutines)\r
-{\r
- if (IsEqualGUID (lpProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS))\r
- {\r
- if (!connect_to_dns_resolver ())\r
- {\r
- return SOCKET_ERROR;\r
- }\r
- /* This assumes that NSP_ROUTINE struct doesn't have a NSPIoctl member.\r
- * If it does, you need to use FIELD_OFFSET() macro to get offset of NSPIoctl\r
- * and use that offset as cbSize.\r
- */\r
- lpnspRoutines->cbSize = sizeof(NSP_ROUTINE_XP);\r
-\r
- lpnspRoutines->dwMajorVersion = NSPAPI_VERSION_MAJOR;\r
- lpnspRoutines->dwMinorVersion = NSPAPI_VERSION_MINOR;\r
- lpnspRoutines->NSPCleanup = NSPCleanup;\r
- lpnspRoutines->NSPLookupServiceBegin = GNUNET_W32NSP_LookupServiceBegin;\r
- lpnspRoutines->NSPLookupServiceNext = GNUNET_W32NSP_LookupServiceNext;\r
- lpnspRoutines->NSPLookupServiceEnd = GNUNET_W32NSP_LookupServiceEnd;\r
- lpnspRoutines->NSPSetService = GNUNET_W32NSP_SetService;\r
- lpnspRoutines->NSPInstallServiceClass = GNUNET_W32NSP_InstallServiceClass;\r
- lpnspRoutines->NSPRemoveServiceClass = GNUNET_W32NSP_RemoveServiceClass;\r
- lpnspRoutines->NSPGetServiceClassInfo = GNUNET_W32NSP_GetServiceClassInfo;\r
- ((NSP_ROUTINE_XP *) lpnspRoutines)->NSPIoctl = GNUNET_W32NSP_Ioctl;\r
- return NO_ERROR;\r
- }\r
- SetLastError (WSAEINVALIDPROVIDER);\r
- return SOCKET_ERROR;\r
-}\r
-\r
+ int rec = -1;
+ int rc;
+ int to_receive;
+ int t;
+ char *buf;
+
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext\n");
+ //EnterCriticalSection (&records_cs);
+ for (i = 0; i < records_len; i++)
+ {
+ if (records[i].s == (SOCKET) hLookup)
+ {
+ rec = i;
+ break;
+ }
+ }
+ if (rec == -1)
+ {
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: invalid handle\n");
+ SetLastError (WSA_INVALID_HANDLE);
+ //LeaveCriticalSection (&records_cs);
+ return SOCKET_ERROR;
+ }
+ if (records[rec].state & 4)
+ {
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: session is closed\n");
+ SetLastError (WSA_E_NO_MORE);
+ //LeaveCriticalSection (&records_cs);
+ return SOCKET_ERROR;
+ }
+ /*effective_flags = dwControlFlags & records[rec].flags;*/
+ if (records[rec].buf)
+ {
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: checking buffer\n");
+ header = *((struct GNUNET_MessageHeader *) records[rec].buf);
+ if (*lpdwBufferLength < header.size - sizeof (struct GNUNET_W32RESOLVER_GetMessage))
+ {
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: client buffer is too small\n");
+ SetLastError (WSAEFAULT);
+ //LeaveCriticalSection (&records_cs);
+ return SOCKET_ERROR;
+ }
+ GNUNET_memcpy (lpqsResults, &((struct GNUNET_W32RESOLVER_GetMessage *)records[rec].buf)[1], header.size - sizeof (struct GNUNET_W32RESOLVER_GetMessage));
+ free (records[rec].buf);
+ records[rec].buf = NULL;
+ //LeaveCriticalSection (&records_cs);
+ UnmarshallWSAQUERYSETW ((LPWSAQUERYSETW) lpqsResults);
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: OK (from buffer)\n");
+ return NO_ERROR;
+ }
+ records[rec].state |= 8;
+ //LeaveCriticalSection (&records_cs);
+ to_receive = sizeof (header);
+ rc = 0;
+#if VERBOSE
+ {
+ unsigned long have;
+ int ior = ioctlsocket ((SOCKET) hLookup, FIONREAD, &have);
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: reading %d bytes as a header from %p, %lu bytes available\n", to_receive, hLookup, have);
+ }
+#endif
+ while (to_receive > 0)
+ {
+ t = recv ((SOCKET) hLookup, &((char *) &header)[rc], to_receive, 0);
+ if (t > 0)
+ {
+ rc += t;
+ to_receive -= t;
+ }
+ else
+ break;
+ }
+#if VERBOSE
+ {
+ unsigned long have;
+ int ior = ioctlsocket ((SOCKET) hLookup, FIONREAD, &have);
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: read %d bytes as a header from %p, %lu bytes available\n", rc, hLookup, have);
+ }
+#endif
+ //EnterCriticalSection (&records_cs);
+ records[rec].state &= ~8;
+ if (rc != sizeof (header))
+ {
+ if (records[rec].state & 2)
+ {
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: call cancelled\n");
+ SetLastError (WSA_E_CANCELLED);
+ }
+ else
+ {
+ 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);
+ SetLastError (WSA_E_NO_MORE);
+ }
+ records[rec].state |= 4;
+ //LeaveCriticalSection (&records_cs);
+ return SOCKET_ERROR;
+ }
+ records[rec].state &= ~8;
+ header.type = ntohs (header.type);
+ header.size = ntohs (header.size);
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: header type %d, header size %u\n", header.type, header.size);
+ if (header.type != GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE ||
+ (header.type == GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE &&
+ header.size == sizeof (header)))
+ {
+ records[rec].state |= 4;
+ if (header.type != GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE)
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: header type is wrong\n");
+ else
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: empty header - no data\n");
+ //LeaveCriticalSection (&records_cs);
+ SetLastError (WSA_E_NO_MORE);
+ return SOCKET_ERROR;
+ }
+ buf = malloc (header.size);
+ if (buf == NULL)
+ {
+ records[rec].state |= 4;
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: malloc() failed\n");
+ //LeaveCriticalSection (&records_cs);
+ SetLastError (WSA_E_NO_MORE);
+ return SOCKET_ERROR;
+ }
+ records[rec].state |= 8;
+ //LeaveCriticalSection (&records_cs);
+ GNUNET_memcpy (buf, &header, sizeof (header));
+ to_receive = header.size - sizeof (header);
+ rc = 0;
+#if VERBOSE
+ {
+ unsigned long have;
+ int ior = ioctlsocket ((SOCKET) hLookup, FIONREAD, &have);
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: reading %d bytes as a body from %p, %lu bytes available\n", to_receive, hLookup, have);
+ }
+#endif
+ while (to_receive > 0)
+ {
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: recv (%d)\n", to_receive);
+ t = recv ((SOCKET) hLookup, &((char *) &((struct GNUNET_MessageHeader *) buf)[1])[rc], to_receive, 0);
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: recv returned %d\n", t);
+ if (t > 0)
+ {
+ rc += t;
+ to_receive -= t;
+ }
+ else
+ break;
+ }
+#if VERBOSE
+ {
+ unsigned long have;
+ int ior = ioctlsocket ((SOCKET) hLookup, FIONREAD, &have);
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: read %d bytes as a body from %p, %lu bytes available\n", rc, hLookup, have);
+ }
+#endif
+ //EnterCriticalSection (&records_cs);
+ records[rec].state &= ~8;
+ if (rc != header.size - sizeof (header))
+ {
+ free (buf);
+ if (records[rec].state & 2)
+ {
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: call cancelled\n");
+ SetLastError (WSA_E_CANCELLED);
+ }
+ else
+ {
+ 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);
+ SetLastError (WSA_E_NO_MORE);
+ }
+ records[rec].state |= 4;
+ //LeaveCriticalSection (&records_cs);
+ return SOCKET_ERROR;
+ }
+ if (*lpdwBufferLength < header.size - sizeof (struct GNUNET_W32RESOLVER_GetMessage))
+ {
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: client buffer is too small\n");
+ SetLastError (WSAEFAULT);
+ records[rec].buf = buf;
+ //LeaveCriticalSection (&records_cs);
+ return SOCKET_ERROR;
+ }
+ //LeaveCriticalSection (&records_cs);
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: writing %d bytes into result buffer\n", header.size - sizeof (struct GNUNET_W32RESOLVER_GetMessage));
+ GNUNET_memcpy (lpqsResults, &((struct GNUNET_W32RESOLVER_GetMessage *)buf)[1], header.size - sizeof (struct GNUNET_W32RESOLVER_GetMessage));
+ free (buf);
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: OK\n");
+ UnmarshallWSAQUERYSETW ((LPWSAQUERYSETW) lpqsResults);
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: returning (%lu)\n", GetLastError ());
+ return NO_ERROR;
+}
+
+static int WSPAPI
+GNUNET_W32NSP_LookupServiceEnd (HANDLE hLookup)
+{
+ int i;
+ int rec = -1;
+
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceEnd\n");
+ //EnterCriticalSection (&records_cs);
+ for (i = 0; i < records_len; i++)
+ {
+ if (records[i].s == (SOCKET) hLookup)
+ {
+ rec = i;
+ break;
+ }
+ }
+ if (rec == -1)
+ {
+ SetLastError (WSA_INVALID_HANDLE);
+ //LeaveCriticalSection (&records_cs);
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceEnd: invalid handle\n");
+ return SOCKET_ERROR;
+ }
+ records[rec].state |= 2;
+ closesocket (records[rec].s);
+ while (records[rec].state & 8)
+ {
+ //LeaveCriticalSection (&records_cs);
+ Sleep (10);
+ //EnterCriticalSection (&records_cs);
+ }
+ if (records[rec].buf)
+ free (records[rec].buf);
+ records[rec].buf = NULL;
+ records[rec].state = 0;
+ if (records[rec].name)
+ free (records[rec].name);
+ //LeaveCriticalSection (&records_cs);
+ DEBUGLOG ("GNUNET_W32NSP_LookupServiceEnd: OK\n");
+ return NO_ERROR;
+}
+
+static int WSAAPI
+GNUNET_W32NSP_SetService (LPGUID lpProviderId,
+ LPWSASERVICECLASSINFOW lpServiceClassInfo, LPWSAQUERYSETW lpqsRegInfo,
+ WSAESETSERVICEOP essOperation, DWORD dwControlFlags)
+{
+ DEBUGLOG ("GNUNET_W32NSP_SetService\n");
+ SetLastError (WSAEOPNOTSUPP);
+ return SOCKET_ERROR;
+}
+
+static int WSAAPI
+GNUNET_W32NSP_InstallServiceClass (LPGUID lpProviderId,
+ LPWSASERVICECLASSINFOW lpServiceClassInfo)
+{
+ DEBUGLOG ("GNUNET_W32NSP_InstallServiceClass\n");
+ SetLastError (WSAEOPNOTSUPP);
+ return SOCKET_ERROR;
+}
+
+
+static int WSAAPI
+GNUNET_W32NSP_RemoveServiceClass (LPGUID lpProviderId, LPGUID lpServiceClassId)
+{
+ DEBUGLOG ("GNUNET_W32NSP_RemoveServiceClass\n");
+ SetLastError (WSAEOPNOTSUPP);
+ return SOCKET_ERROR;
+}
+
+static int WSAAPI
+GNUNET_W32NSP_GetServiceClassInfo (LPGUID lpProviderId, LPDWORD lpdwBufSize,
+ LPWSASERVICECLASSINFOW lpServiceClassInfo)
+{
+ DEBUGLOG ("GNUNET_W32NSP_GetServiceClassInfo\n");
+ SetLastError (WSAEOPNOTSUPP);
+ return SOCKET_ERROR;
+}
+
+static int WSAAPI
+GNUNET_W32NSP_Ioctl (HANDLE hLookup, DWORD dwControlCode, LPVOID lpvInBuffer,
+ DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer,
+ LPDWORD lpcbBytesReturned, LPWSACOMPLETION lpCompletion,
+ LPWSATHREADID lpThreadId)
+{
+ DEBUGLOG ("GNUNET_W32NSP_Ioctl\n");
+ SetLastError (WSAEOPNOTSUPP);
+ return SOCKET_ERROR;
+}
+
+/**
+ * This function is called by Winsock to hook up our provider.
+ * It is the only function that [should be/is] exported by the
+ * provider. All other routines are passed as pointers in lpnspRoutines.
+ */
+int WSAAPI
+GNUNET_W32NSP_NSPStartup (LPGUID lpProviderId, LPNSP_ROUTINE lpnspRoutines)
+{
+ if (IsEqualGUID (lpProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS))
+ {
+ if (!connect_to_dns_resolver ())
+ {
+ return SOCKET_ERROR;
+ }
+ /* This assumes that NSP_ROUTINE struct doesn't have a NSPIoctl member.
+ * If it does, you need to use FIELD_OFFSET() macro to get offset of NSPIoctl
+ * and use that offset as cbSize.
+ */
+ lpnspRoutines->cbSize = sizeof(NSP_ROUTINE);
+
+ lpnspRoutines->dwMajorVersion = NSPAPI_VERSION_MAJOR;
+ lpnspRoutines->dwMinorVersion = NSPAPI_VERSION_MINOR;
+ lpnspRoutines->NSPCleanup = NSPCleanup;
+ lpnspRoutines->NSPLookupServiceBegin = GNUNET_W32NSP_LookupServiceBegin;
+ lpnspRoutines->NSPLookupServiceNext = GNUNET_W32NSP_LookupServiceNext;
+ lpnspRoutines->NSPLookupServiceEnd = GNUNET_W32NSP_LookupServiceEnd;
+ lpnspRoutines->NSPSetService = GNUNET_W32NSP_SetService;
+ lpnspRoutines->NSPInstallServiceClass = GNUNET_W32NSP_InstallServiceClass;
+ lpnspRoutines->NSPRemoveServiceClass = GNUNET_W32NSP_RemoveServiceClass;
+ lpnspRoutines->NSPGetServiceClassInfo = GNUNET_W32NSP_GetServiceClassInfo;
+ /*((NSP_ROUTINE_XP *) lpnspRoutines)->NSPIoctl = GNUNET_W32NSP_Ioctl;*/
+ lpnspRoutines->NSPIoctl = GNUNET_W32NSP_Ioctl;
+ return NO_ERROR;
+ }
+ SetLastError (WSAEINVALIDPROVIDER);
+ return SOCKET_ERROR;
+}
+