+2004-11-11 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ ==== TAG tclresolver-0-4-0 ====
+
+ * tclresolver3.c: Renamed to tclresolver. This is the thread
+ version.
+ * tclresolver2.c, resolvchk.c: Removed.
+
2004-08-26 Pat Thoyts <patthoyts@users.sourceforge.net>
* all: Initial checkin
INC =-Ic:\opt\tcl\include
LIBS =c:\opt\tcl\lib\tclstub84.lib ws2_32.lib
-all: resolver.exe resolvchk.exe tclresolver.dll tclresolver2.dll tclresolver3.dll
+all: resolver.exe tclresolver.dll
resolver.exe: resolver.c
$(CC) $(CFLAGS) -o $@ $**
-resolvchk.exe: resolvchk.c
- $(CC) $(CFLAGS) -o $@ $**
-
tclresolver.dll: tclresolver.obj
$(LD) $(LDFLAGS) -out:$@ $(LIBS) $**
-
-tclresolver2.dll: tclresolver2.obj
- $(LD) $(LDFLAGS) -out:$@ $(LIBS) $**
-
-tclresolver3.dll: tclresolver3.obj
- $(LD) $(LDFLAGS) -out:$@ $(LIBS) $**
-
.c.obj::
$(CC) $(CFLAGS) $(DEFS) $(INC) -c @<<
$<
clean:
@if exist tclresolver.obj del tclresolver.obj
- @if exist tclresolver2.obj del tclresolver2.obj
- @if exist tclresolver3.obj del tclresolver3.obj
realclean: clean
@if exist tclresolver.dll del tclresolver.dll
@if exist tclresolver.exp del tclresolver.exp
@if exist tclresolver.lib del tclresolver.lib
- @if exist tclresolver2.dll del tclresolver2.dll
- @if exist tclresolver2.exp del tclresolver2.exp
- @if exist tclresolver2.lib del tclresolver2.lib
- @if exist tclresolver3.dll del tclresolver3.dll
- @if exist tclresolver3.exp del tclresolver3.exp
- @if exist tclresolver3.lib del tclresolver3.lib
@if exist resolver.exe del resolver.exe
- @if exist resolvchk.exe del resolvchk.exe
-if {[file exists tclresolver3.dll]} {
- load tclresolver3.dll Tclresolver
+if {[file exists tclresolver.dll]} {
+ load tclresolver.dll Tclresolver
} else {
package require Tclresolver
}
--- /dev/null
+# pkgIndex.tcl - Copyright (C) 2004 Pat Thoyts <patthoyts@users.sf.net>
+#
+package ifneeded Tclresolver 0.4.0 [list load [file join $dir tclresolver.dll]]
+++ /dev/null
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <tchar.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#define BUFSIZE 4096
-
-typedef struct {
- HANDLE hReady;
- HANDLE hDone;
- HANDLE hIn;
- HANDLE hOut;
- LPBYTE pData;
- BOOL bRunning;
-} LookupInfo;
-
-static LPCTSTR LookupHostname(LookupInfo * pLookupInfo, LPCTSTR szHostname);
-static DWORD WINAPI Reader(LPVOID clientData);
-static BOOL CreateChildProcess(HANDLE hChildStdoutWr, HANDLE hChildStdinRd);
-static void ErrorExit(LPTSTR);
-static void Win32Error(FILE *fp, LPCTSTR szMessage, HRESULT hr);
-
-DWORD
-_tmain(int argc, LPCTSTR argv[])
-{
- HANDLE hChildStdinWr, hChildStdinWrDup, hChildStdoutRd, hChildStdoutRdDup;
- HANDLE hChildStdinRd, hChildStdoutWr;
- LookupInfo lookupinfo;
- HANDLE hReaderThread = INVALID_HANDLE_VALUE;
- DWORD idReaderThread = 0;
- SECURITY_ATTRIBUTES saAttr;
- BOOL fSuccess;
- LPCTSTR szAddress;
- int n;
-
- if (argc < 2) {
- ErrorExit(_T("usage: resolvchk hostname ?hostname ...?"));
- }
-
- // Set the bInheritHandle flag so pipe handles are inherited.
- saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
- saAttr.bInheritHandle = TRUE;
- saAttr.lpSecurityDescriptor = NULL;
-
- // Create a pipe for the child process's STDOUT.
- if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
- ErrorExit("Stdout pipe creation failed\n");
-
- // Create noninheritable read handle and close the inheritable read
- // handle.
- fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
- GetCurrentProcess(), &hChildStdoutRdDup,
- 0, FALSE,
- DUPLICATE_SAME_ACCESS);
- if( !fSuccess )
- ErrorExit("DuplicateHandle failed");
- CloseHandle(hChildStdoutRd);
-
- // Create a pipe for the child process's STDIN.
- if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
- ErrorExit("Stdin pipe creation failed\n");
-
- // Duplicate the write handle to the pipe so it is not inherited.
- fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
- GetCurrentProcess(), &hChildStdinWrDup,
- 0, FALSE, // not inherited
- DUPLICATE_SAME_ACCESS);
- if (! fSuccess)
- ErrorExit("DuplicateHandle failed");
-
- CloseHandle(hChildStdinWr);
-
- // Create an event for lookup synch.
- lookupinfo.hReady = CreateEvent(NULL, FALSE, FALSE, NULL);
- lookupinfo.hDone = CreateEvent(NULL, FALSE, FALSE, NULL);
- lookupinfo.hIn = hChildStdoutRdDup;
- lookupinfo.hOut = hChildStdinWrDup;
- lookupinfo.bRunning = TRUE;
- lookupinfo.pData = (LPBYTE)malloc(BUFSIZE);
-
- // Create reader thread.
- hReaderThread = CreateThread(NULL, 0, Reader, &lookupinfo,
- 0, &idReaderThread);
-
- // Now create the child process.
- fSuccess = CreateChildProcess(hChildStdoutWr, hChildStdinRd);
- if (! fSuccess)
- ErrorExit("Create process failed");
-
- // Perform the address lookup.
- for (n = 1; n < argc; n++) {
- szAddress = LookupHostname(&lookupinfo, argv[n]);
- _ftprintf(stdout, _T("'%s'\n"), szAddress);
- }
-
- lookupinfo.bRunning = FALSE;
- free((LPBYTE)lookupinfo.pData);
-
- // Close the pipe handle so the child process stops reading and exits.
- if (! CloseHandle(hChildStdinWrDup))
- ErrorExit("Close pipe failed");
- if (!CloseHandle(hChildStdoutWr))
- ErrorExit("CloseHandle failed");
-
- return 0;
-}
-
-static LPCTSTR
-LookupHostname(LookupInfo *pLookupInfo, LPCTSTR szHostname)
-{
- DWORD dwWrote;
- BOOL br;
-
- ZeroMemory(pLookupInfo->pData, BUFSIZE);
- lstrcpy((LPTSTR)pLookupInfo->pData, szHostname);
- lstrcat((LPTSTR)pLookupInfo->pData, _T("\n"));
- br = WriteFile(pLookupInfo->hOut, pLookupInfo->pData,
- lstrlen((LPTSTR)pLookupInfo->pData) * sizeof(TCHAR),
- &dwWrote, NULL);
- if (br)
- br = FlushFileBuffers(pLookupInfo->hOut);
- if (br) {
- ZeroMemory(pLookupInfo->pData, BUFSIZE);
- SetEvent(pLookupInfo->hReady);
- WaitForSingleObject(pLookupInfo->hDone, INFINITE);
- }
- if (!br) {
- Win32Error(stderr, _T("lookup hostname"), GetLastError());
- }
- return (LPCTSTR)pLookupInfo->pData;
-}
-
-static DWORD WINAPI
-Reader(LPVOID clientData)
-{
- LookupInfo *pLookupInfo = (LookupInfo *)clientData;
- DWORD dwErr = 0, dwRead = 0;
- BOOL br;
-
- while (pLookupInfo->bRunning) {
- dwErr = WaitForSingleObject(pLookupInfo->hReady, 500);
- if (dwErr == WAIT_OBJECT_0) {
- br = ReadFile(pLookupInfo->hIn, pLookupInfo->pData,
- BUFSIZE, &dwRead, NULL);
-
- if (dwRead > 0) {
- LPTSTR p = (LPTSTR)pLookupInfo->pData;
- for (p = p + lstrlen(p) - 1;
- p > pLookupInfo->pData && _istspace(*p);
- p--)
- ;
- *++p = 0;
- }
- SetEvent(pLookupInfo->hDone);
- } else {
- Win32Error(stderr, _T("reader wait"), dwErr);
- }
- }
- return 0;
-}
-
-static BOOL
-CreateChildProcess(HANDLE hChildStdoutWr, HANDLE hChildStdinRd)
-{
- PROCESS_INFORMATION piProcInfo;
- STARTUPINFO siStartInfo;
- BOOL bFuncRetn = FALSE;
-
- // Set up members of the PROCESS_INFORMATION structure.
- ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
-
- // Set up members of the STARTUPINFO structure.
- ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
- siStartInfo.cb = sizeof(STARTUPINFO);
- siStartInfo.hStdError = hChildStdoutWr;
- siStartInfo.hStdOutput = hChildStdoutWr;
- siStartInfo.hStdInput = hChildStdinRd;
- siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
-
- // Create the child process.
- bFuncRetn = CreateProcess(NULL,
- "resolver", // command line
- NULL, // process security attributes
- NULL, // primary thread security attributes
- TRUE, // handles are inherited
- 0, // creation flags
- NULL, // use parent's environment
- NULL, // use parent's current directory
- &siStartInfo, // STARTUPINFO pointer
- &piProcInfo); // receives PROCESS_INFORMATION
-
- if (bFuncRetn == 0) {
- ErrorExit("CreateProcess failed");
- return FALSE;
- } else {
- CloseHandle(piProcInfo.hProcess);
- CloseHandle(piProcInfo.hThread);
- return bFuncRetn;
- }
-}
-
-static void
-ErrorExit (LPTSTR lpszMessage)
-{
- _ftprintf(stderr, _T("%s\n"), lpszMessage);
- ExitProcess(0);
-}
-
-static void
-Win32Error(FILE *fp, LPCTSTR szMessage, HRESULT hr)
-{
- LPTSTR lpBuffer = NULL;
- DWORD dwLen = 0;
-
- dwLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
- | FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, (DWORD)hr, LANG_NEUTRAL,
- (LPTSTR)&lpBuffer, 0, NULL);
- if (dwLen < 1) {
- dwLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
- | FORMAT_MESSAGE_FROM_STRING
- | FORMAT_MESSAGE_ARGUMENT_ARRAY,
- _T("code 0x%1!08X!%n"), 0, LANG_NEUTRAL,
- (LPTSTR)&lpBuffer, 0, (va_list *)&hr);
- }
- _ftprintf(fp, _T("%s"), szMessage);
- if (dwLen > 0) {
- _ftprintf(fp, _T(": "));
- _ftprintf(fp, lpBuffer);
- }
- LocalFree((HLOCAL)lpBuffer);
-}
+++ /dev/null
-/* tclresolver.c - Copyright (C) 2004 Pat Thoyts <patthoyts@users.sf.net>
- *
- *
- *
- * $Id$
- */
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <tchar.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
-
-#include <tcl.h>
-
-#if _MSC_VER >= 1000
-#pragma comment(lib, "ws2_32")
-#endif
-
-#define BUFSIZE 4096
-#undef TCL_STORAGE_CLASS
-#define TCL_STORAGE_CLASS DLLEXPORT
-
-static const char ASSOC_KEY[] = "tclresolver_key";
-
-EXTERN int Tclresolver_Init(Tcl_Interp *interp);
-EXTERN int Tclresolver_Unload(Tcl_Interp *interp);
-EXTERN int TclGetHostByName(LPSOCKADDR_IN saddrPtr,
- const char *hostname, int port);
-
-typedef struct {
- HANDLE hReader;
- DWORD idReader;
- HANDLE hReady;
- HANDLE hDone;
- LPBYTE pData;
- BOOL bRunning;
- Tcl_ThreadId tclid;
- Tcl_Command command;
-} LOOKUPINFO, *LPLOOKUPINFO;
-
-typedef struct {
- Tcl_Event header;
- LPLOOKUPINFO info;
-} RESOLVEREVENT, *LPRESOLVEREVENT;
-
-static Tcl_ObjCmdProc TclresolverObjCmd;
-static Tcl_ExitProc Terminate;
-static int Initialize(Tcl_Interp *interp, LPLOOKUPINFO pLookupInfo);
-static LPCTSTR LookupHostname(LPLOOKUPINFO pLookupInfo, LPCTSTR szHostname);
-static DWORD WINAPI Reader(LPVOID clientData);
-static void QueueEvent(LPLOOKUPINFO pLookupInfo);
-static int ResolverEventProc(Tcl_Event *evPtr, int flags);
-static int GetAddress(char *query);
-static Tcl_Obj *Win32Error(const char * szPrefix, HRESULT hr);
-
-/* ---------------------------------------------------------------------- */
-
-int
-Tclresolver_Init(Tcl_Interp *interp)
-{
- int initialized = 0;
- LPLOOKUPINFO pLookupInfo = NULL;
-
-#ifdef USE_TCL_STUBS
- if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
- return TCL_ERROR;
- }
-#endif
-
- pLookupInfo = (LPLOOKUPINFO)Tcl_Alloc(sizeof(LOOKUPINFO));
- if (pLookupInfo == NULL) {
- Tcl_SetResult(interp, "out of memory", TCL_STATIC);
- return TCL_ERROR;
- }
- ZeroMemory(pLookupInfo, sizeof(LOOKUPINFO));
-
- if (Initialize(interp, pLookupInfo) != TCL_OK) {
- Tcl_Free((char*)pLookupInfo);
- return TCL_ERROR;
- }
- pLookupInfo->tclid = Tcl_GetCurrentThread();
- pLookupInfo->command = Tcl_CreateObjCommand(interp, "resolve",
- TclresolverObjCmd,
- (ClientData)pLookupInfo,
- (Tcl_CmdDeleteProc *)NULL);
- Tcl_CreateExitHandler(Terminate, (ClientData)pLookupInfo);
- Tcl_SetAssocData(interp, ASSOC_KEY, NULL, (ClientData)pLookupInfo);
- return Tcl_PkgProvide(interp, "Tclresolver", "1.2.0");
-}
-
-EXTERN int
-Tclresolver_SafeInit(Tcl_Interp *interp)
-{
- return Tclresolver_Init(interp);
-}
-
-int
-Tclresolver_Unload(Tcl_Interp *interp)
-{
- LPLOOKUPINFO pLookupInfo = NULL;
- pLookupInfo = (LPLOOKUPINFO)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
- Tcl_DeleteCommandFromToken(interp, pLookupInfo->command);
- Terminate((ClientData)pLookupInfo);
- Tcl_SetAssocData(interp, ASSOC_KEY, NULL, (ClientData)NULL);
- return TCL_OK;
-}
-
-static int
-TclresolverObjCmd(ClientData clientData, Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[])
-{
- LPLOOKUPINFO pLookupInfo = (LPLOOKUPINFO)clientData;
- Tcl_Obj *resObj = NULL;
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, objc, objv, "hostname");
- return TCL_ERROR;
- }
- resObj = Tcl_NewStringObj(LookupHostname(pLookupInfo,
- Tcl_GetString(objv[1])), -1);
- Tcl_SetObjResult(interp, resObj);
- return TCL_OK;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int
-Initialize(Tcl_Interp *interp, LPLOOKUPINFO pLookupInfo)
-{
- WSADATA wsd;
-
- OutputDebugString(_T("Initialize\n"));
-
- /* Initialize windows sockets. */
- if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) {
- Tcl_Obj *errObj = Win32Error("WSAStartup error", GetLastError());
- Tcl_SetObjResult(interp, errObj);
- return TCL_ERROR;
- }
-
- if (LOBYTE(wsd.wVersion) != 2 ||
- HIBYTE(wsd.wVersion) != 2) {
- Tcl_SetResult(interp,
- "error: failed to load a compatible winsock version", TCL_STATIC);
- WSACleanup();
- return TCL_ERROR;
- }
-
- /* Create synchronization events */
- pLookupInfo->hReady = CreateEvent(NULL, FALSE, FALSE, NULL);
- pLookupInfo->hDone = CreateEvent(NULL, FALSE, FALSE, NULL);
- pLookupInfo->bRunning = TRUE;
- pLookupInfo->pData = (LPBYTE)Tcl_Alloc(BUFSIZE);
-
- /* Create the reader thread */
- pLookupInfo->hReader = CreateThread(NULL, 0, Reader, pLookupInfo,
- 0, &pLookupInfo->idReader);
-
- return TCL_OK;
-}
-
-static void
-Terminate(ClientData clientData)
-{
- LPLOOKUPINFO pLookupInfo = (LPLOOKUPINFO)clientData;
- OutputDebugString(_T("Terminate\n"));
- pLookupInfo->bRunning = FALSE;
- Tcl_DeleteExitHandler(Terminate, clientData);
- WaitForSingleObject(pLookupInfo->hReader, 400);
- CloseHandle(pLookupInfo->hReader);
- CloseHandle(pLookupInfo->hReady);
- CloseHandle(pLookupInfo->hDone);
- Tcl_Free(pLookupInfo->pData);
- Tcl_Free((LPBYTE)pLookupInfo);
- WSACleanup();
-}
-
-static LPCTSTR
-LookupHostname(LPLOOKUPINFO pLookupInfo, LPCTSTR szHostname)
-{
- DWORD dwWait;
-
- /* copy the hostname into out buffer */
- ZeroMemory(pLookupInfo->pData, BUFSIZE);
- lstrcpy((LPTSTR)pLookupInfo->pData, szHostname);
-
- /* notify the reader thread that it should begin reading */
- SetEvent(pLookupInfo->hReady);
-
- /* Run a tcl event loop while we wait for the answer */
- while (1) {
- Tcl_DoOneEvent(0); /* when tk loaded */
- //Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT);
- OutputDebugString("done one event\n");
- dwWait = WaitForSingleObject(pLookupInfo->hDone, 0);
- if (dwWait == WAIT_OBJECT_0)
- break;
- }
-
- return (LPCTSTR)pLookupInfo->pData;
-}
-
-static DWORD WINAPI
-Reader(LPVOID clientData)
-{
- LPLOOKUPINFO pLookupInfo = (LPLOOKUPINFO)clientData;
- DWORD dwErr = 0, dwRead = 0;
-
- while (pLookupInfo->bRunning) {
- dwErr = WaitForSingleObject(pLookupInfo->hReady, 500);
- if (dwErr == WAIT_OBJECT_0) {
- GetAddress((char *)pLookupInfo->pData);
- QueueEvent(pLookupInfo);
- }
- }
- return 0;
-}
-
-static void
-QueueEvent(LPLOOKUPINFO pLookupInfo)
-{
- LPRESOLVEREVENT evPtr;
- OutputDebugString(_T("QueueEvent\n"));
- evPtr = (LPRESOLVEREVENT)Tcl_Alloc(sizeof(RESOLVEREVENT));
- evPtr->header.proc = ResolverEventProc;
- evPtr->header.nextPtr = NULL;
- evPtr->info = pLookupInfo;
- Tcl_ThreadQueueEvent(pLookupInfo->tclid,
- (Tcl_Event *)evPtr, TCL_QUEUE_TAIL);
-}
-
-static int
-ResolverEventProc(Tcl_Event *evPtr, int flags)
-{
- LPRESOLVEREVENT revPtr = (LPRESOLVEREVENT)evPtr;
- OutputDebugString(_T("ResolverEventProc\n"));
- SetEvent(revPtr->info->hDone);
- return 1;
-}
-
-static Tcl_Obj *
-Win32Error(const char * szPrefix, HRESULT hr)
-{
- Tcl_Obj *msgObj = NULL;
- char * lpBuffer = NULL;
- DWORD dwLen = 0;
-
- dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
- | FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, (DWORD)hr, LANG_NEUTRAL,
- (LPTSTR)&lpBuffer, 0, NULL);
- if (dwLen < 1) {
- dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
- | FORMAT_MESSAGE_FROM_STRING
- | FORMAT_MESSAGE_ARGUMENT_ARRAY,
- "code 0x%1!08X!%n", 0, LANG_NEUTRAL,
- (LPTSTR)&lpBuffer, 0, (va_list *)&hr);
- }
-
- msgObj = Tcl_NewStringObj(szPrefix, -1);
- if (dwLen > 0) {
- char *p = lpBuffer + dwLen - 1; /* remove cr-lf at end */
- for ( ; p && *p && isspace(*p); p--)
- ;
- *++p = 0;
- Tcl_AppendToObj(msgObj, ": ", 2);
- Tcl_AppendToObj(msgObj, lpBuffer, -1);
- }
- LocalFree((HLOCAL)lpBuffer);
- return msgObj;
-}
-
-static int
-GetAddress(char *query)
-{
- struct addrinfo hints = {0};
- struct addrinfo *res = NULL;
- char *hostname, *p, *q;
- int r = 0, nc = 0;
-
- /* trim whitespace */
- for (p = query; *p && isspace(*p); p++)
- ;
- for (q = p + strlen(p) - 1; q > p && *q && isspace(*q); q--)
- ;
- *++q = 0;
- hostname = p;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_flags = AI_CANONNAME;
- hints.ai_socktype = SOCK_STREAM;
- r = getaddrinfo(hostname, "", &hints, &res);
- *query = 0;
-
- if (r != 0) {
- Tcl_Obj *o = Win32Error("error", WSAGetLastError());
- strcpy(query, Tcl_GetString(o));
- Tcl_DecrRefCount(o);
- } else {
- struct addrinfo *resPtr = res;
- for (resPtr = res; resPtr != NULL; resPtr = resPtr->ai_next) {
- char name[NI_MAXHOST];
-
- getnameinfo(resPtr->ai_addr, resPtr->ai_addrlen,
- name, NI_MAXHOST,
- NULL, 0,
- NI_NUMERICHOST | NI_NUMERICSERV);
-
- if (resPtr != res)
- strcat(query, " ");
- strcat(query, name);
- }
- freeaddrinfo(res);
- }
- return r;
-}
-
-
+++ /dev/null
-/* tclresolver.c - Copyright (C) 2004 Pat Thoyts <patthoyts@users.sf.net>
- *
- * Non-blocking name resolution.
- *
- * $Id$
- */
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
-
-#include <tcl.h>
-
-#if _MSC_VER >= 1000
-#pragma comment(lib, "ws2_32")
-#pragma comment(lib, "user32")
-#endif
-
-#define BUFSIZE 4096
-#define XWM_RESOLVE WM_APP + 1
-
-#undef TCL_STORAGE_CLASS
-#define TCL_STORAGE_CLASS DLLEXPORT
-
-static const char ASSOC_KEY[] = "tclresolver_key";
-
-EXTERN int Tclresolver_Init(Tcl_Interp *interp);
-EXTERN int Tclresolver_Unload(Tcl_Interp *interp);
-EXTERN int TclGetHostByName(LPSOCKADDR_IN saddrPtr,
- const char *hostname, int port);
-
-typedef struct {
- HANDLE hReader;
- DWORD idReader;
- Tcl_ThreadId tclid;
- Tcl_Command command;
-} PKGINFO, *LPPKGINFO;
-
-typedef struct {
- HANDLE lock;
- LONG cookie;
- char data[BUFSIZE];
-} QUERYINFO, *LPQUERYINFO;
-
-typedef struct {
- Tcl_Event header;
- LPQUERYINFO query;
-} RESOLVEREVENT, *LPRESOLVEREVENT;
-
-static Tcl_ObjCmdProc TclresolverObjCmd;
-static Tcl_ExitProc Terminate;
-static int Initialize(Tcl_Interp *interp, LPPKGINFO pkgPtr);
-static Tcl_Obj *LookupHostname(LPPKGINFO pkgPtr, const char *hostname);
-static DWORD WINAPI Reader(LPVOID clientData);
-static void QueueEvent(Tcl_ThreadId id, LPQUERYINFO pQuery);
-static int ResolverEventProc(Tcl_Event *evPtr, int flags);
-static int GetAddress(char *query);
-static Tcl_Obj *Win32Error(const char * szPrefix, HRESULT hr);
-
-/* ---------------------------------------------------------------------- */
-
-int
-Tclresolver_Init(Tcl_Interp *interp)
-{
- int initialized = 0;
- LPPKGINFO pkgPtr = NULL;
-
-#ifdef USE_TCL_STUBS
- if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
- return TCL_ERROR;
- }
-#endif
-
- pkgPtr = (LPPKGINFO)Tcl_Alloc(sizeof(PKGINFO));
- if (pkgPtr == NULL) {
- Tcl_SetResult(interp, "out of memory", TCL_STATIC);
- return TCL_ERROR;
- }
- ZeroMemory(pkgPtr, sizeof(PKGINFO));
-
- if (Initialize(interp, pkgPtr) != TCL_OK) {
- Tcl_Free((char*)pkgPtr);
- return TCL_ERROR;
- }
- pkgPtr->tclid = Tcl_GetCurrentThread();
- pkgPtr->command = Tcl_CreateObjCommand(interp, "resolve",
- TclresolverObjCmd,
- (ClientData)pkgPtr,
- (Tcl_CmdDeleteProc *)NULL);
- Tcl_CreateExitHandler(Terminate, (ClientData)pkgPtr);
- Tcl_SetAssocData(interp, ASSOC_KEY, NULL, (ClientData)pkgPtr);
- return Tcl_PkgProvide(interp, "Tclresolver", "1.3.0");
-}
-
-EXTERN int
-Tclresolver_SafeInit(Tcl_Interp *interp)
-{
- return Tclresolver_Init(interp);
-}
-
-int
-Tclresolver_Unload(Tcl_Interp *interp)
-{
- LPPKGINFO pkgPtr = NULL;
- pkgPtr = (LPPKGINFO)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
- Tcl_DeleteCommandFromToken(interp, pkgPtr->command);
- Terminate((ClientData)pkgPtr);
- Tcl_SetAssocData(interp, ASSOC_KEY, NULL, (ClientData)NULL);
- return TCL_OK;
-}
-
-static int
-TclresolverObjCmd(ClientData clientData, Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[])
-{
- LPPKGINFO pkgPtr = (LPPKGINFO)clientData;
- Tcl_Obj *resObj = NULL;
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, objc, objv, "hostname");
- return TCL_ERROR;
- }
- resObj = LookupHostname(pkgPtr, Tcl_GetString(objv[1]));
- Tcl_SetObjResult(interp, resObj);
- return TCL_OK;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int
-Initialize(Tcl_Interp *interp, LPPKGINFO pkgPtr)
-{
- WSADATA wsd;
-
- OutputDebugStringA("Initialize\n");
-
- /* Initialize windows sockets. */
- if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) {
- Tcl_Obj *errObj = Win32Error("WSAStartup error", GetLastError());
- Tcl_SetObjResult(interp, errObj);
- return TCL_ERROR;
- }
-
- if (LOBYTE(wsd.wVersion) != 2 ||
- HIBYTE(wsd.wVersion) != 2) {
- Tcl_SetResult(interp,
- "error: failed to load a compatible winsock version", TCL_STATIC);
- WSACleanup();
- return TCL_ERROR;
- }
-
- /* Create the reader thread */
- pkgPtr->hReader = CreateThread(NULL, 0, Reader, pkgPtr,
- 0, &pkgPtr->idReader);
-
- return TCL_OK;
-}
-
-static void
-Terminate(ClientData clientData)
-{
- LPPKGINFO pkgPtr = (LPPKGINFO)clientData;
- OutputDebugStringA("Terminate\n");
- PostThreadMessage(pkgPtr->idReader, WM_QUIT, 0, 0L);
- Tcl_DeleteExitHandler(Terminate, clientData);
- WaitForSingleObject(pkgPtr->hReader, 400);
- CloseHandle(pkgPtr->hReader);
- Tcl_Free((LPBYTE)pkgPtr);
- WSACleanup();
-}
-
-static Tcl_Obj *
-LookupHostname(LPPKGINFO pkgPtr, const char * hostname)
-{
- Tcl_Obj *resObj = NULL;
- DWORD dwWait;
- LPQUERYINFO queryPtr;
- static LONG cookie;
- char sz[128];
-
- /* copy the hostname into out buffer */
- queryPtr = (LPQUERYINFO)Tcl_Alloc(sizeof(QUERYINFO));
- memset(queryPtr, 0, sizeof(QUERYINFO));
- queryPtr->lock = CreateEvent(NULL, FALSE, FALSE, NULL);
- queryPtr->cookie = InterlockedIncrement(&cookie);
- strcpy(queryPtr->data, hostname);
-
- sprintf(sz, "query %d begin\n", queryPtr->cookie);
- OutputDebugString(sz);
-
- /* notify the reader thread that it should begin reading */
- PostThreadMessage(pkgPtr->idReader, XWM_RESOLVE, 0, (LPARAM)queryPtr);
-
- /* Run a tcl event loop while we wait for the answer */
- while (1) {
- Tcl_DoOneEvent(0); /* when tk loaded */
- //Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT);
- dwWait = WaitForSingleObject(queryPtr->lock, 0);
- if (dwWait == WAIT_OBJECT_0) {
- sprintf(sz, "query %d complete\n", queryPtr->cookie);
- OutputDebugString(sz);
- break;
- }
- }
-
- resObj = Tcl_NewStringObj(queryPtr->data, -1);
- CloseHandle(queryPtr->lock);
- Tcl_Free((char *)queryPtr);
- return resObj;
-}
-
-static DWORD WINAPI
-Reader(LPVOID clientData)
-{
- LPPKGINFO pkgPtr = (LPPKGINFO)clientData;
- LPQUERYINFO queryPtr = NULL;
- MSG msg;
- DWORD dwErr = 0, dwRead = 0;
-
- while(GetMessage(&msg, 0, 0, 0)) {
- if (msg.hwnd == NULL) {
- switch (msg.message) {
- case XWM_RESOLVE:
- queryPtr = (LPQUERYINFO)msg.lParam;
- GetAddress(queryPtr->data);
- QueueEvent(pkgPtr->tclid, queryPtr);
- break;
- }
- }
- DispatchMessage(&msg);
- }
-
- OutputDebugStringA("Reader exiting.\n");
- return 0;
-}
-
-static void
-QueueEvent(Tcl_ThreadId id, LPQUERYINFO queryPtr)
-{
- LPRESOLVEREVENT evPtr;
- OutputDebugStringA("QueueEvent\n");
- evPtr = (LPRESOLVEREVENT)Tcl_Alloc(sizeof(RESOLVEREVENT));
- evPtr->header.proc = ResolverEventProc;
- evPtr->header.nextPtr = NULL;
- evPtr->query = queryPtr;
- Tcl_ThreadQueueEvent(id, (Tcl_Event *)evPtr, TCL_QUEUE_TAIL);
-}
-
-static int
-ResolverEventProc(Tcl_Event *evPtr, int flags)
-{
- LPRESOLVEREVENT revPtr = (LPRESOLVEREVENT)evPtr;
- OutputDebugStringA("ResolverEventProc\n");
- SetEvent(revPtr->query->lock);
- return 1;
-}
-
-static Tcl_Obj *
-Win32Error(const char * szPrefix, HRESULT hr)
-{
- Tcl_Obj *msgObj = NULL;
- char * lpBuffer = NULL;
- DWORD dwLen = 0;
-
- dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
- | FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, (DWORD)hr, LANG_NEUTRAL,
- (LPTSTR)&lpBuffer, 0, NULL);
- if (dwLen < 1) {
- dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
- | FORMAT_MESSAGE_FROM_STRING
- | FORMAT_MESSAGE_ARGUMENT_ARRAY,
- "code 0x%1!08X!%n", 0, LANG_NEUTRAL,
- (LPTSTR)&lpBuffer, 0, (va_list *)&hr);
- }
-
- msgObj = Tcl_NewStringObj(szPrefix, -1);
- if (dwLen > 0) {
- char *p = lpBuffer + dwLen - 1; /* remove cr-lf at end */
- for ( ; p && *p && isspace(*p); p--)
- ;
- *++p = 0;
- Tcl_AppendToObj(msgObj, ": ", 2);
- Tcl_AppendToObj(msgObj, lpBuffer, -1);
- }
- LocalFree((HLOCAL)lpBuffer);
- return msgObj;
-}
-
-static int
-GetAddress(char *query)
-{
- struct addrinfo hints = {0};
- struct addrinfo *res = NULL;
- char *hostname, *p, *q;
- int r = 0, nc = 0;
-
- /* trim whitespace */
- for (p = query; *p && isspace(*p); p++)
- ;
- for (q = p + strlen(p) - 1; q > p && *q && isspace(*q); q--)
- ;
- *++q = 0;
- hostname = p;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_INET; /* use PF_UNSPEC if we want IPv6 too */
- hints.ai_flags = AI_CANONNAME;
- hints.ai_socktype = SOCK_STREAM;
- r = getaddrinfo(hostname, "", &hints, &res);
- *query = 0;
-
- if (r != 0) {
- Tcl_Obj *o = Win32Error("error", WSAGetLastError());
- strcpy(query, Tcl_GetString(o));
- Tcl_DecrRefCount(o);
- } else {
- struct addrinfo *resPtr = res;
- for (resPtr = res; resPtr != NULL; resPtr = resPtr->ai_next) {
- char name[NI_MAXHOST];
-
- getnameinfo(resPtr->ai_addr, resPtr->ai_addrlen,
- name, NI_MAXHOST,
- NULL, 0,
- NI_NUMERICHOST | NI_NUMERICSERV);
-
- if (resPtr != res)
- strcat(query, " ");
- strcat(query, name);
- }
- freeaddrinfo(res);
- }
- return r;
-}
-
-
+++ /dev/null
-/* w32cat.c - Copyright (C) 2004 Pat Thoyts <patthoyts@users.sourceforge.net>
- *
- * This illustrates a line-oriented cat program. Each line read from the
- * console is echoed to the output.
- *
- * NB: only reads from the CONSOLE though. Not piped input.
- *
- * $Id$
- */
-
-#if defined(_UNICODE) && !defined(UNICODE)
-#define UNICODE
-#endif
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <tchar.h>
-
-void Win32Error(HANDLE hFile, LPCTSTR sz, HRESULT hr);
-
-int
-_tmain(int argc, LPCTSTR argv[])
-{
- HANDLE hStdin, hStdout, hStderr;
- DWORD dwMode;
-
- if ((hStderr = GetStdHandle(STD_ERROR_HANDLE)) == INVALID_HANDLE_VALUE) {
- return -2;
- }
-
- if ((hStdout = GetStdHandle(STD_OUTPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
- Win32Error(hStderr, _T("get stdout handle"), GetLastError());
- return -1;
- }
-
- if ((hStdin = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
- Win32Error(hStderr, _T("get stdin handle"), GetLastError());
- return -1;
- }
-
- /*
- * By default the console input is processed line oriented so we
- * don't need to do anything special.
- */
-
- GetConsoleMode(hStdin, &dwMode);
- dwMode &= ~ENABLE_LINE_INPUT;
- SetConsoleMode(hStdin, dwMode);
- GetConsoleMode(hStdout, &dwMode);
- dwMode &= ~ENABLE_LINE_INPUT;
- SetConsoleMode(hStdout, dwMode);
-
- while (1) {
- DWORD cbRead = 0;
- TCHAR buffer[1024];
-
- if (! ReadFile(hStdin, buffer, 1023, &cbRead, NULL))
- break;
- if (CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE,
- _T("quit"), 4, buffer, 4) == CSTR_EQUAL)
- break;
-
- WriteFile(hStdout, buffer, cbRead, NULL, NULL);
- }
-
- return 0;
-}
-
-void
-Win32Error(HANDLE hFile, LPCTSTR sz, HRESULT hr)
-{
- LPTSTR lpBuffer = NULL;
- DWORD dwLen = 0;
-
- dwLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
- | FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, (DWORD)hr, LANG_NEUTRAL,
- (LPTSTR)&lpBuffer, 0, NULL);
- if (dwLen < 1) {
- HRESULT ahr[1] = {hr};
- dwLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
- | FORMAT_MESSAGE_FROM_STRING
- | FORMAT_MESSAGE_ARGUMENT_ARRAY,
- _T("code: 0x%1!08X!%n"), 0, LANG_NEUTRAL,
- (LPTSTR)&lpBuffer, 0, (va_list *)ahr);
- }
- WriteConsole(hFile, sz, lstrlen(sz), NULL, NULL);
- if (dwLen > 0) {
- WriteConsole(hFile, _T(": "), 3, NULL, NULL);
- WriteConsole(hFile, lpBuffer, dwLen, NULL, NULL);
- }
- LocalFree((HLOCAL)lpBuffer);
-}
/* tclresolver.c - Copyright (C) 2004 Pat Thoyts <patthoyts@users.sf.net>
*
- *
+ * Non-blocking name resolution.
*
* $Id$
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
-#include <tchar.h>
#include <winsock2.h>
+#include <ws2tcpip.h>
#include <tcl.h>
+#if _MSC_VER >= 1000
+#pragma comment(lib, "ws2_32")
+#pragma comment(lib, "user32")
+#endif
+
#define BUFSIZE 4096
+#define XWM_RESOLVE WM_APP + 1
+
#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLEXPORT
typedef struct {
HANDLE hReader;
DWORD idReader;
- HANDLE hReady;
- HANDLE hDone;
- HANDLE hIn;
- HANDLE hOut;
- LPBYTE pData;
- BOOL bRunning;
Tcl_ThreadId tclid;
Tcl_Command command;
-} LOOKUPINFO, *LPLOOKUPINFO;
+} PKGINFO, *LPPKGINFO;
+
+typedef struct {
+ HANDLE lock;
+ LONG cookie;
+ char data[BUFSIZE];
+} QUERYINFO, *LPQUERYINFO;
typedef struct {
Tcl_Event header;
- LPLOOKUPINFO info;
+ LPQUERYINFO query;
} RESOLVEREVENT, *LPRESOLVEREVENT;
-//static int TclResolverObjCmd(ClientData clientData, Tcl_Interp *interp,
-// int objc, Tcl_Obj *CONST objv[]);
static Tcl_ObjCmdProc TclresolverObjCmd;
static Tcl_ExitProc Terminate;
-static int Initialize(Tcl_Interp *interp, LPLOOKUPINFO pLookupInfo);
-static BOOL CreateChildProcess(HANDLE hChildStdoutWr, HANDLE hChildStdinRd);
-static LPCTSTR LookupHostname(LPLOOKUPINFO pLookupInfo, LPCTSTR szHostname);
+static int Initialize(Tcl_Interp *interp, LPPKGINFO pkgPtr);
+static Tcl_Obj *LookupHostname(LPPKGINFO pkgPtr, const char *hostname);
static DWORD WINAPI Reader(LPVOID clientData);
-static void QueueEvent(LPLOOKUPINFO pLookupInfo);
+static void QueueEvent(Tcl_ThreadId id, LPQUERYINFO pQuery);
static int ResolverEventProc(Tcl_Event *evPtr, int flags);
-
+static int GetAddress(char *query);
+static Tcl_Obj *Win32Error(const char * szPrefix, HRESULT hr);
/* ---------------------------------------------------------------------- */
Tclresolver_Init(Tcl_Interp *interp)
{
int initialized = 0;
- LPLOOKUPINFO pLookupInfo = NULL;
+ LPPKGINFO pkgPtr = NULL;
#ifdef USE_TCL_STUBS
if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
}
#endif
- pLookupInfo = (LPLOOKUPINFO)Tcl_Alloc(sizeof(LOOKUPINFO));
- if (pLookupInfo == NULL) {
+ pkgPtr = (LPPKGINFO)Tcl_Alloc(sizeof(PKGINFO));
+ if (pkgPtr == NULL) {
Tcl_SetResult(interp, "out of memory", TCL_STATIC);
return TCL_ERROR;
}
- ZeroMemory(pLookupInfo, sizeof(LOOKUPINFO));
+ ZeroMemory(pkgPtr, sizeof(PKGINFO));
- if (Initialize(interp, pLookupInfo) != TCL_OK) {
- Tcl_Free((char*)pLookupInfo);
- //Tcl_SetResult(interp, "failed to initialize package", TCL_STATIC);
+ if (Initialize(interp, pkgPtr) != TCL_OK) {
+ Tcl_Free((char*)pkgPtr);
return TCL_ERROR;
}
- pLookupInfo->tclid = Tcl_GetCurrentThread();
- pLookupInfo->command = Tcl_CreateObjCommand(interp, "resolve",
+ pkgPtr->tclid = Tcl_GetCurrentThread();
+ pkgPtr->command = Tcl_CreateObjCommand(interp, "resolve",
TclresolverObjCmd,
- (ClientData)pLookupInfo,
+ (ClientData)pkgPtr,
(Tcl_CmdDeleteProc *)NULL);
- Tcl_CreateExitHandler(Terminate, (ClientData)pLookupInfo);
- Tcl_SetAssocData(interp, ASSOC_KEY, NULL, (ClientData)pLookupInfo);
- return Tcl_PkgProvide(interp, "Tclresolver", "1.0.0");
+ Tcl_CreateExitHandler(Terminate, (ClientData)pkgPtr);
+ Tcl_SetAssocData(interp, ASSOC_KEY, NULL, (ClientData)pkgPtr);
+ return Tcl_PkgProvide(interp, "Tclresolver", "0.4.0");
}
EXTERN int
int
Tclresolver_Unload(Tcl_Interp *interp)
{
- LPLOOKUPINFO pLookupInfo = NULL;
- pLookupInfo = (LPLOOKUPINFO)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
- Tcl_DeleteCommandFromToken(interp, pLookupInfo->command);
- Terminate((ClientData)pLookupInfo);
+ LPPKGINFO pkgPtr = NULL;
+ pkgPtr = (LPPKGINFO)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
+ Tcl_DeleteCommandFromToken(interp, pkgPtr->command);
+ Terminate((ClientData)pkgPtr);
Tcl_SetAssocData(interp, ASSOC_KEY, NULL, (ClientData)NULL);
return TCL_OK;
}
TclresolverObjCmd(ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[])
{
- LPLOOKUPINFO pLookupInfo = (LPLOOKUPINFO)clientData;
+ LPPKGINFO pkgPtr = (LPPKGINFO)clientData;
Tcl_Obj *resObj = NULL;
if (objc != 2) {
Tcl_WrongNumArgs(interp, objc, objv, "hostname");
return TCL_ERROR;
}
- resObj = Tcl_NewStringObj(LookupHostname(pLookupInfo,
- Tcl_GetString(objv[1])), -1);
+ resObj = LookupHostname(pkgPtr, Tcl_GetString(objv[1]));
Tcl_SetObjResult(interp, resObj);
return TCL_OK;
}
/* ---------------------------------------------------------------------- */
static int
-Initialize(Tcl_Interp *interp, LPLOOKUPINFO pLookupInfo)
-{
- SECURITY_ATTRIBUTES saAttr;
- BOOL fSuccess;
- HANDLE hChildStdinRd, hChildStdinWr, hChildStdoutRd, hChildStdoutWr;
- HANDLE hChildStdoutRdDup, hChildStdinWrDup;
-
- // Set the bInheritHandle flag so pipe handles are inherited.
- saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
- saAttr.bInheritHandle = TRUE;
- saAttr.lpSecurityDescriptor = NULL;
-
- // Create a pipe for the child process's STDOUT.
- if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) {
- Tcl_SetResult(interp, "Stdout pipe creation failed", TCL_STATIC);
- return TCL_ERROR;
- }
-
- // Create noninheritable read handle and close the inheritable read
- // handle.
- fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
- GetCurrentProcess(), &hChildStdoutRdDup , 0,
- FALSE,
- DUPLICATE_SAME_ACCESS);
- if( !fSuccess ) {
- Tcl_SetResult(interp, "DuplicateHandle failed", TCL_STATIC);
- return TCL_ERROR;
- }
- CloseHandle(hChildStdoutRd);
-
- // Create a pipe for the child process's STDIN.
- if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) {
- Tcl_SetResult(interp, "Stdin pipe creation failed", TCL_STATIC);
+Initialize(Tcl_Interp *interp, LPPKGINFO pkgPtr)
+{
+ WSADATA wsd;
+
+ OutputDebugStringA("Initialize\n");
+
+ /* Initialize windows sockets. */
+ if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) {
+ Tcl_Obj *errObj = Win32Error("WSAStartup error", GetLastError());
+ Tcl_SetObjResult(interp, errObj);
return TCL_ERROR;
}
-
- // Duplicate the write handle to the pipe so it is not inherited.
- fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
- GetCurrentProcess(), &hChildStdinWrDup, 0,
- FALSE, // not inherited
- DUPLICATE_SAME_ACCESS);
- if (! fSuccess) {
- Tcl_SetResult(interp, "DuplicateHandle failed", TCL_STATIC);
+
+ if (LOBYTE(wsd.wVersion) != 2 ||
+ HIBYTE(wsd.wVersion) != 2) {
+ Tcl_SetResult(interp,
+ "error: failed to load a compatible winsock version", TCL_STATIC);
+ WSACleanup();
return TCL_ERROR;
}
- CloseHandle(hChildStdinWr);
-
- /* Create synchronization events */
- pLookupInfo->hReady = CreateEvent(NULL, FALSE, FALSE, NULL);
- pLookupInfo->hDone = CreateEvent(NULL, FALSE, FALSE, NULL);
- pLookupInfo->hIn = hChildStdoutRdDup;
- pLookupInfo->hOut = hChildStdinWrDup;
- pLookupInfo->bRunning = TRUE;
- pLookupInfo->pData = (LPBYTE)Tcl_Alloc(BUFSIZE);
/* Create the reader thread */
- pLookupInfo->hReader = CreateThread(NULL, 0, Reader, pLookupInfo,
- 0, &pLookupInfo->idReader);
+ pkgPtr->hReader = CreateThread(NULL, 0, Reader, pkgPtr,
+ 0, &pkgPtr->idReader);
- /* Now create the child process. */
- fSuccess = CreateChildProcess(hChildStdoutWr, hChildStdinRd);
- if (! fSuccess) {
- Tcl_SetResult(interp, "Create process failed", TCL_STATIC);
- return TCL_ERROR;
- }
-
return TCL_OK;
}
static void
Terminate(ClientData clientData)
{
- LPLOOKUPINFO pLookupInfo = (LPLOOKUPINFO)clientData;
- OutputDebugString("Pkgdeleteproc\n");
- pLookupInfo->bRunning = FALSE;
- WaitForSingleObject(pLookupInfo->hReader, 400);
- CloseHandle(pLookupInfo->hReader);
- CloseHandle(pLookupInfo->hReady);
- CloseHandle(pLookupInfo->hDone);
- CloseHandle(pLookupInfo->hIn);
- CloseHandle(pLookupInfo->hOut);
- Tcl_Free(pLookupInfo->pData);
- Tcl_Free((LPBYTE)pLookupInfo);
+ LPPKGINFO pkgPtr = (LPPKGINFO)clientData;
+ OutputDebugStringA("Terminate\n");
+ PostThreadMessage(pkgPtr->idReader, WM_QUIT, 0, 0L);
+ Tcl_DeleteExitHandler(Terminate, clientData);
+ WaitForSingleObject(pkgPtr->hReader, 400);
+ CloseHandle(pkgPtr->hReader);
+ Tcl_Free((LPBYTE)pkgPtr);
+ WSACleanup();
}
-static LPCTSTR
-LookupHostname(LPLOOKUPINFO pLookupInfo, LPCTSTR szHostname)
+static Tcl_Obj *
+LookupHostname(LPPKGINFO pkgPtr, const char * hostname)
{
- DWORD dwWrote, dwWait;
- BOOL br;
+ Tcl_Obj *resObj = NULL;
+ DWORD dwWait;
+ LPQUERYINFO queryPtr;
+ static LONG cookie;
+ char sz[128];
+
+ /* copy the hostname into out buffer */
+ queryPtr = (LPQUERYINFO)Tcl_Alloc(sizeof(QUERYINFO));
+ memset(queryPtr, 0, sizeof(QUERYINFO));
+ queryPtr->lock = CreateEvent(NULL, FALSE, FALSE, NULL);
+ queryPtr->cookie = InterlockedIncrement(&cookie);
+ strcpy(queryPtr->data, hostname);
+
+ sprintf(sz, "query %d begin\n", queryPtr->cookie);
+ OutputDebugString(sz);
- ZeroMemory(pLookupInfo->pData, BUFSIZE);
- lstrcpy((LPTSTR)pLookupInfo->pData, szHostname);
- lstrcat((LPTSTR)pLookupInfo->pData, _T("\n"));
- br = WriteFile(pLookupInfo->hOut, pLookupInfo->pData,
- lstrlen((LPTSTR)pLookupInfo->pData) * sizeof(TCHAR),
- &dwWrote, NULL);
- if (br)
- br = FlushFileBuffers(pLookupInfo->hOut);
- if (br) {
- /* clear out the buffer ready for reading */
- ZeroMemory(pLookupInfo->pData, BUFSIZE);
- /* notify the reader thread that it should begin reading */
- SetEvent(pLookupInfo->hReady);
-#ifdef USE_WIN32_EVENTS
- /* Doing this will block Tcl event processing */
- dwWait = WaitForSingleObject(pLookupInfo->hDone, INFINITE);
-#else
- /* Run a tcl event loop while we wait for the answer */
- while (1) {
- Tcl_DoOneEvent(0); /* when tk loaded */
- //Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT);
- OutputDebugString("done one event\n");
- dwWait = WaitForSingleObject(pLookupInfo->hDone, 0);
- if (dwWait == WAIT_OBJECT_0)
- break;
- }
-#endif
- }
- if (!br) {
- return _T("");
- }
- return (LPCTSTR)pLookupInfo->pData;
-}
-
-static BOOL
-CreateChildProcess(HANDLE hChildStdoutWr, HANDLE hChildStdinRd)
-{
- PROCESS_INFORMATION piProcInfo;
- STARTUPINFO siStartInfo;
- BOOL bFuncRetn = FALSE;
-
- /* Set up members of the PROCESS_INFORMATION structure.*/
- ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
-
- /* Set up members of the STARTUPINFO structure.*/
- ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
- siStartInfo.cb = sizeof(STARTUPINFO);
- siStartInfo.hStdError = hChildStdoutWr;
- siStartInfo.hStdOutput = hChildStdoutWr;
- siStartInfo.hStdInput = hChildStdinRd;
- siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
-
- /* Create the child process.*/
- bFuncRetn = CreateProcess(NULL,
- "resolver", // command line
- NULL, // process security attributes
- NULL, // primary thread security attributes
- TRUE, // handles are inherited
- DETACHED_PROCESS, // no console
- NULL, // use parent's environment
- NULL, // use parent's current directory
- &siStartInfo, // STARTUPINFO pointer
- &piProcInfo); // receives PROCESS_INFORMATION
-
- if (bFuncRetn == 0)
- return bFuncRetn; /*ErrorExit("CreateProcess failed");*/
- else
- {
- CloseHandle(piProcInfo.hProcess);
- CloseHandle(piProcInfo.hThread);
- return bFuncRetn;
+ /* notify the reader thread that it should begin reading */
+ PostThreadMessage(pkgPtr->idReader, XWM_RESOLVE, 0, (LPARAM)queryPtr);
+
+ /* Run a tcl event loop while we wait for the answer */
+ while (1) {
+ Tcl_DoOneEvent(0); /* when tk loaded */
+ //Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT);
+ dwWait = WaitForSingleObject(queryPtr->lock, 0);
+ if (dwWait == WAIT_OBJECT_0) {
+ sprintf(sz, "query %d complete\n", queryPtr->cookie);
+ OutputDebugString(sz);
+ break;
+ }
}
+
+ resObj = Tcl_NewStringObj(queryPtr->data, -1);
+ CloseHandle(queryPtr->lock);
+ Tcl_Free((char *)queryPtr);
+ return resObj;
}
static DWORD WINAPI
Reader(LPVOID clientData)
{
- LPLOOKUPINFO pLookupInfo = (LPLOOKUPINFO)clientData;
+ LPPKGINFO pkgPtr = (LPPKGINFO)clientData;
+ LPQUERYINFO queryPtr = NULL;
+ MSG msg;
DWORD dwErr = 0, dwRead = 0;
- BOOL br;
-
- while (pLookupInfo->bRunning) {
- dwErr = WaitForSingleObject(pLookupInfo->hReady, 500);
- if (dwErr == WAIT_OBJECT_0) {
- br = ReadFile(pLookupInfo->hIn, pLookupInfo->pData,
- BUFSIZE, &dwRead, NULL);
-
- if (dwRead > 0) {
- LPTSTR p = (LPTSTR)pLookupInfo->pData;
- for (p = p + lstrlen(p) - 1;
- p > pLookupInfo->pData && _istspace(*p);
- p--)
- ;
- *++p = 0;
- }
-#ifdef USE_WIN32_EVENTS
- SetEvent(pLookupInfo->hDone);
-#else
- QueueEvent(pLookupInfo);
-#endif
- }
+
+ while(GetMessage(&msg, 0, 0, 0)) {
+ if (msg.hwnd == NULL) {
+ switch (msg.message) {
+ case XWM_RESOLVE:
+ queryPtr = (LPQUERYINFO)msg.lParam;
+ GetAddress(queryPtr->data);
+ QueueEvent(pkgPtr->tclid, queryPtr);
+ break;
+ }
+ }
+ DispatchMessage(&msg);
}
+
+ OutputDebugStringA("Reader exiting.\n");
return 0;
}
static void
-QueueEvent(LPLOOKUPINFO pLookupInfo)
+QueueEvent(Tcl_ThreadId id, LPQUERYINFO queryPtr)
{
LPRESOLVEREVENT evPtr;
- OutputDebugString("queueevent\n");
+ OutputDebugStringA("QueueEvent\n");
evPtr = (LPRESOLVEREVENT)Tcl_Alloc(sizeof(RESOLVEREVENT));
evPtr->header.proc = ResolverEventProc;
evPtr->header.nextPtr = NULL;
- evPtr->info = pLookupInfo;
- Tcl_ThreadQueueEvent(pLookupInfo->tclid,
- (Tcl_Event *)evPtr, TCL_QUEUE_TAIL);
+ evPtr->query = queryPtr;
+ Tcl_ThreadQueueEvent(id, (Tcl_Event *)evPtr, TCL_QUEUE_TAIL);
}
static int
ResolverEventProc(Tcl_Event *evPtr, int flags)
{
LPRESOLVEREVENT revPtr = (LPRESOLVEREVENT)evPtr;
- OutputDebugString("resolvereventproc\n");
- SetEvent(revPtr->info->hDone);
+ OutputDebugStringA("ResolverEventProc\n");
+ SetEvent(revPtr->query->lock);
return 1;
}
-#if 0
-int
-TclGetHostByName(LPSOCKADDR_IN saddrPtr, const char *hostname, int port)
+static Tcl_Obj *
+Win32Error(const char * szPrefix, HRESULT hr)
+{
+ Tcl_Obj *msgObj = NULL;
+ char * lpBuffer = NULL;
+ DWORD dwLen = 0;
+
+ dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, (DWORD)hr, LANG_NEUTRAL,
+ (LPTSTR)&lpBuffer, 0, NULL);
+ if (dwLen < 1) {
+ dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_FROM_STRING
+ | FORMAT_MESSAGE_ARGUMENT_ARRAY,
+ "code 0x%1!08X!%n", 0, LANG_NEUTRAL,
+ (LPTSTR)&lpBuffer, 0, (va_list *)&hr);
+ }
+
+ msgObj = Tcl_NewStringObj(szPrefix, -1);
+ if (dwLen > 0) {
+ char *p = lpBuffer + dwLen - 1; /* remove cr-lf at end */
+ for ( ; p && *p && isspace(*p); p--)
+ ;
+ *++p = 0;
+ Tcl_AppendToObj(msgObj, ": ", 2);
+ Tcl_AppendToObj(msgObj, lpBuffer, -1);
+ }
+ LocalFree((HLOCAL)lpBuffer);
+ return msgObj;
+}
+
+static int
+GetAddress(char *query)
{
- struct in_addr addr;
-
- ZeroMemory(saddrPtr, sizeof(SOCKADDR_IN));
- saddrPtr->sin_family = AF_INET;
- saddrPtr->sin_port = htons((unsigned short)port);
- /* if no hostname then the answer is any host */
- if (hostname == NULL || *hostname == 0) {
- addr.s_addr = INADDR_ANY;
+ struct addrinfo hints = {0};
+ struct addrinfo *res = NULL;
+ char *hostname, *p, *q;
+ int r = 0, nc = 0;
+
+ /* trim whitespace */
+ for (p = query; *p && isspace(*p); p++)
+ ;
+ for (q = p + strlen(p) - 1; q > p && *q && isspace(*q); q--)
+ ;
+ *++q = 0;
+ hostname = p;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_INET; /* use PF_UNSPEC if we want IPv6 too */
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_socktype = SOCK_STREAM;
+ r = getaddrinfo(hostname, "", &hints, &res);
+ *query = 0;
+
+ if (r != 0) {
+ Tcl_Obj *o = Win32Error("error", WSAGetLastError());
+ strcpy(query, Tcl_GetString(o));
+ Tcl_DecrRefCount(o);
} else {
- /* see if we have been given an ip number already */
- addr.s_addr = inet_addr(hostname);
- if (addr.s_addr == INADDR_NONE) {
- /* Perform the address lookup via our subprocess */
- addr.s_addr = inet_addr(LookupHostname(hostname));
- if (addr.s_addr == INADDR_NONE) {
-#ifdef EHOSTUNREACH
- Tcl_SetErrno(EHOSTUNREACH);
-#endif
- return 0; /* error */
- }
- }
+ struct addrinfo *resPtr = res;
+ for (resPtr = res; resPtr != NULL; resPtr = resPtr->ai_next) {
+ char name[NI_MAXHOST];
+
+ getnameinfo(resPtr->ai_addr, resPtr->ai_addrlen,
+ name, NI_MAXHOST,
+ NULL, 0,
+ NI_NUMERICHOST | NI_NUMERICSERV);
+
+ if (resPtr != res)
+ strcat(query, " ");
+ strcat(query, name);
+ }
+ freeaddrinfo(res);
}
- saddrPtr->sin_addr.s_addr = addr.s_addr;
- return 1;
+ return r;
}
-#endif
+
+