Exemple #1
0
LPFN_WSARECVMSG GetWSARecvMsgFunctionPointer()
{
    LPFN_WSARECVMSG     lpfnWSARecvMsg = NULL;
    GUID                guidWSARecvMsg = WSAID_WSARECVMSG;
    SOCKET              sock = INVALID_SOCKET;
    DWORD               dwBytes = 0;

    sock = socket(AF_INET6,SOCK_DGRAM,0);

    if(SOCKET_ERROR == WSAIoctl(sock,
                                SIO_GET_EXTENSION_FUNCTION_POINTER,
                                &guidWSARecvMsg,
                                sizeof(guidWSARecvMsg),
                                &lpfnWSARecvMsg,
                                sizeof(lpfnWSARecvMsg),
                                &dwBytes,
                                NULL,
                                NULL
                               ))
    {
        ERR("WSAIoctl SIO_GET_EXTENSION_FUNCTION_POINTER");
        return NULL;
    }

    CLOSESOCK(sock);

    return lpfnWSARecvMsg;
}
Exemple #2
0
int __cdecl main()
{
    WSADATA             wsd;
    INT                 i = 0,
                        nErr = 0,
                        nStartup = 0,
                        rc = 0;
    SOCKET              sock = INVALID_SOCKET;
    SOCKADDR_STORAGE    addr = {0},
                        mcaddr = {0},
                        remoteaddr = {0};
    WSAOVERLAPPED       over = {0};
    WSABUF              wsabuf = {0};
    DWORD               dwBytes = 0,
                        dwFlags = 0,
                        dwRet = 0;
    IPV6_MREQ           mreq = {0};
    WSAMSG              wsamsg = {0};
    LPFN_WSARECVMSG     WSARecvMsg = NULL;


    __try
    {
        //Initialize Winsock

        nErr = WSAStartup(WS_VER,&wsd);
        if (nErr)
        {
            WSASetLastError(nErr);
            ERR("WSAStartup");
            __leave;
        }
        else
            nStartup++;


        // bind socket and register multicast

        mcaddr.ss_family = AF_INET6;

        InitMcastAddr((SOCKADDR*)&mcaddr,sizeof mcaddr);

        if (INVALID_SOCKET == (sock = socket(AF_INET6,SOCK_DGRAM,0)))
        {
            ERR("socket");
            __leave;
        }

        if(!RouteLookup((SOCKADDR*)&mcaddr,
                        sizeof mcaddr,
                        (SOCKADDR*)&addr,
                        sizeof addr
                       ))
        {
            ERR("RouteLookup");
            __leave;
        }

        SET_PORT((SOCKADDR*)&addr,DEFAULT_PORT);

        if (SOCKET_ERROR == bind(sock,(SOCKADDR*)&addr,sizeof addr))
        {
            ERR("bind");
            __leave;
        }

        mreq.ipv6mr_multiaddr = ((SOCKADDR_IN6*)&mcaddr)->sin6_addr;

        if (SOCKET_ERROR == setsockopt(sock,
                                       IPPROTO_IPV6,
                                       IPV6_ADD_MEMBERSHIP,
                                       (char*)&mreq,
                                       sizeof mreq
                                      ))
        {
            ERR("setsockopt IPV6_ADD_MEMBRESHIP");
            __leave;
        }

        // PktInfo

        if (!SetIpv6PktInfoOption(sock))
        {
            ERR("SetIpv6PktInfoOption");
            __leave;
        }

        if(!AllocAndInitIpv6PktInfo(&wsamsg))
        {
            ERR("AllocAndInitIpv6PktInfo");
            __leave;
        }

        // data buffer

        wsabuf.buf = (CHAR*)MALLOC(100);

        if(NULL == wsabuf.buf)
        {
            ERR("HeapAlloc");
            __leave;
        }

        wsabuf.len = (ULONG)MSIZE(wsabuf.buf);
        wsamsg.lpBuffers = &wsabuf;
        wsamsg.dwBufferCount = 1;

        // packet source address
        wsamsg.name = (SOCKADDR*)&remoteaddr;
        wsamsg.namelen = sizeof remoteaddr;

        //Post overlapped WSARecvMsg
        InitOverlap(&over);

        if (NULL == (WSARecvMsg = GetWSARecvMsgFunctionPointer()))
        {
            ERR("GetWSARecvMsgFunctionPointer");
            __leave;
        }

        if (SOCKET_ERROR == WSARecvMsg(sock,
                                       &wsamsg,
                                       &dwBytes,
                                       &over,
                                       NULL
                                      ))
        {
            if (WSA_IO_PENDING != WSAGetLastError())
            {
                ERR("WSARecvMsg");
                __leave;
            }
        }

        //set send interface

        if (SOCKET_ERROR == SetSendInterface(sock,(SOCKADDR*)&addr))
        {
            ERR("SetSendInterface");
            __leave;
        }

        //send msg to multicast


        SET_PORT((SOCKADDR*)&mcaddr,DEFAULT_PORT);

        //send a few packets
        for (i=0; i<5; i++)
        {

            if (SOCKET_ERROR == (rc = sendto(sock,
                                             TST_MSG,
                                             lstrlenA(TST_MSG),
                                             0,
                                             (SOCKADDR*)&mcaddr,
                                             sizeof (mcaddr)
                                            )))
            {
                ERR("sendto");
                __leave;
            }

            printf("Sent %d bytes\n",rc);
        }

        dwRet = WaitForSingleObject(over.hEvent,DEFAULT_WAIT);

        if (dwRet)
        {
            printf("%s\n",gai_strerror(dwRet));
            __leave;
        }

        if (!WSAGetOverlappedResult(sock,
                                    &over,
                                    &dwBytes,
                                    TRUE,
                                    &dwFlags
                                   ))
        {
            ERR("WSAGetOverlappedResult");
            __leave;
        }

        printf("WSARecvMsg completed with %d bytes\n",dwBytes);

        // if multicast packet do further processing
        if (MSG_MCAST & wsamsg.dwFlags)
        {
            if (ProcessIpv6Msg(&wsamsg))
            {
                //do something more interesting here
                printf("Recvd multicast msg.\n");
            }

        }

    }
    __finally
    {


        CLOSESOCK(sock);
        FREE(wsabuf.buf);
        FREE(wsamsg.Control.buf);
        CLOSESOCKEVENT(over.hEvent);
        if(nStartup) WSACleanup();
    }

    return 0;
}
Exemple #3
0
BOOL RouteLookup(SOCKADDR   *destAddr,
                 int         destLen,
                 SOCKADDR   *localAddr,
                 int         localLen
                )
{
    DWORD       dwBytes = 0;
    BOOL        bRet = FALSE;
    CHAR        szAddr[MAX_PATH] = {0};
    SOCKET      s = INVALID_SOCKET;


    __try
    {

        if (INVALID_SOCKET == (s = socket(destAddr->sa_family,SOCK_DGRAM,0)))
        {
            ERR("socket");
            __leave;
        }

        if (SOCKET_ERROR == WSAIoctl(s,
                                     SIO_ROUTING_INTERFACE_QUERY,
                                     destAddr,
                                     destLen,
                                     localAddr,
                                     localLen,
                                     &dwBytes,
                                     NULL,
                                     NULL
                                    ))
        {
            ERR("WSAIoctl");
            __leave;
        }

        dwBytes = sizeof(szAddr);

        ZeroMemory(szAddr,dwBytes);

        WSAAddressToStringA(destAddr,
                            (DWORD)destLen,
                            NULL,
                            szAddr,
                            &dwBytes
                           );

        dwBytes = sizeof(szAddr);

        ZeroMemory(szAddr,dwBytes);

        WSAAddressToStringA(localAddr,
                            (DWORD)localLen,
                            NULL,
                            szAddr,
                            &dwBytes
                           );

        bRet = TRUE;
    }
    __finally
    {
        CLOSESOCK(s);
    }

    return bRet;
}
int __cdecl main(int argc, char **argv)
{

    char *interface = NULL;
    char *Buffer = NULL;
    char *port = DEFAULT_PORT;
    char host[NI_MAXHOST];
    char serv[NI_MAXSERV];
    int hostlen = NI_MAXHOST;
    int servlen = NI_MAXSERV;
    int ai_family = AF_UNSPEC;
    int i = 0;
    int nStartup = 0;
    struct addrinfo hints = {0};
    struct addrinfo *local = NULL;
    WSADATA wsaData;
    SOCKET listen_socket = INVALID_SOCKET;
    SOCKET accept_socket = INVALID_SOCKET;
    WSAOVERLAPPED *Overlap = NULL;
    DWORD bytes = 0;
    DWORD bytes_read = 0;
    DWORD lasterror = 0;

    //
    // Handles is the array that stores the Event Handles
    //
    WSAEVENT Handles[MAX_IO_PEND] ;

    //
    // socklist is a parallel array that keeps state information for
    // each Handle.
    //
    Socklist socklist[MAX_IO_PEND];

    //
    // Pointers to Microsoft specific extensions
    //
    LPFN_ACCEPTEX pfnAcceptEx;
    GUID acceptex_guid = WSAID_ACCEPTEX;

    __try
    {


        if (NULL == (Buffer = (char*)XMALLOC(((2*sizeof(SOCKADDR_STORAGE))+32)*sizeof(char))))
        {
            ERR("HeapAlloc()");
            __leave;

        }

        //
        // Parse arguments
        //
        if ( argc > 1 )
        {
            for ( i = 1;i < argc; i++ )
            {
                if ( (argv[i][0] == '-') || (argv[i][0] == '/') )
                {
                    switch ( tolower(argv[i][1]) )
                    {
                    
                    case 'i':
                        if ( i+1 < argc )
                            interface = argv[++i];
                        break;
                    case 'e':
                        if ( i+1 < argc )
                            port = argv[++i];
                        break;
                    default:
                        {
                            Usage(argv[0]);
                            __leave;
                        }
                        break;
                    }
                }
                else
                {
                    Usage(argv[0]);
                    __leave;
                }
            }
        }

        //
        // Since port 0 would be any available port. 
        // Resetting port back to DEFAULT_PORT to avoid confusion.
        //
        if ( 0 == strncmp(port, "0", 1) )
        {
            port = DEFAULT_PORT;
        }

        if ( 0 != (nStartup = WSAStartup(WS_VER, &wsaData)) )
        {
            WSASetLastError(nStartup); //WSAStartup does not set last error on failure
            ERR("WSAStartup()");
            __leave;

        }
        else
            nStartup++;

        //
        // Resolve the interface
        //
        SecureZeroMemory(&hints,sizeof(hints));
        hints.ai_flags  = ((interface) ? 0 : AI_PASSIVE);
        hints.ai_family = ai_family;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = IPPROTO_TCP;

        if ( 0 != getaddrinfo(interface, port, &hints, &local))
        {
            ERR("getaddrinfo()");
            __leave;
        }

        ai_family = local->ai_family;

        if (NULL == local)
        {
            fprintf(stderr, "getaddrinfo() failed to resolve/convert the interface\n");
            __leave;
        }

        if (INVALID_SOCKET == (listen_socket = WSASocket(local->ai_family, 
                                                         local->ai_socktype, 
                                                         local->ai_protocol, 
                                                         NULL, 
                                                         0,
                                                         WSA_FLAG_OVERLAPPED
                                                        )))
        {
            ERR("WSASocket()");
            __leave;
        }


        if ( SOCKET_ERROR == bind(listen_socket, 
                                  local->ai_addr, 
                                  (int)local->ai_addrlen
                                 ))
        {
            ERR("bind()");
            __leave;
        }


        if ( SOCKET_ERROR == listen(listen_socket, DEFAULT_BACKLOG))
        {
            ERR("listen()");
            __leave;
        }

        //
        // Resolve numeric host name
        //
        if ( 0 != getnameinfo(local->ai_addr, 
                              (int)local->ai_addrlen, 
                              host, 
                              hostlen, 
                              serv, 
                              servlen,
                              NI_NUMERICHOST | NI_NUMERICSERV
                             ))
        {
            ERR("getnameinfo()");
            __leave;
        }

        // Don't need the local interface anymore
        if (NULL != local)
            freeaddrinfo(local);

        printf("Listening on %s:%s\n", host, serv);

        //
        // Add the listening socket to our state information for the handle.
        //
        socklist[0].sock = listen_socket;

        curr_size =1;

        for ( i = 0;i < MAX_IO_PEND;i++ )
            Handles[i] = WSA_INVALID_EVENT;

        //
        // Load the extension functions
        //

        if ( SOCKET_ERROR == WSAIoctl(listen_socket, 
                                      SIO_GET_EXTENSION_FUNCTION_POINTER,
                                      &acceptex_guid,
                                      sizeof(acceptex_guid),
                                      &pfnAcceptEx,
                                      sizeof(pfnAcceptEx), 
                                      &bytes, 
                                      NULL, 
                                      NULL
                                     ))
        {
            fprintf(stderr,"Failed to obtain AcceptEx() pointer: ");
            ERR("WSAIoctl()");
            __leave;
        }

        //
        // The structure of the following loop is very similar to a situation
        // where select() might be used. 
        // We use WSAGetOverlappedResult() to multiplex between incoming/outgoing
        // data on existing connections.
        //
        // We don't queue an AcceptEx() until someone actually connects to 
        // the previous socket. This is to keep the code simple, not a limitation
        // of the API itself.
        //
        for ( ;; )
        {

            // create a socket for AcceptEx()

            if (INVALID_SOCKET == (accept_socket = WSASocket(ai_family, 
                                                             SOCK_STREAM, 
                                                             0, 
                                                             NULL, 
                                                             0,
                                                             WSA_FLAG_OVERLAPPED
                                                            )))
            {
                ERR("WSASocket()");
                __leave;
            }

            //
            // Allocate an overlapped structure.
            // We use the Offset field to keep track of the socket handle
            // we have accepted a connection on, since there is no other
            // way to pass information to GetOverlappedResult()
            //
            Overlap = (WSAOVERLAPPED*)XMALLOC(sizeof(WSAOVERLAPPED));

            //
            // Did the HeapAllocation FAIL??
            //
            if ( Overlap == NULL )
            {
                ERR("HeapAlloc()");
                __leave;
            }

            SecureZeroMemory(Overlap, sizeof(WSAOVERLAPPED));

            if ( WSA_INVALID_EVENT == (Overlap->hEvent = WSACreateEvent() ))
            {
                ERR("WSACreateEvent()");
                __leave;
            }

            //
            // Set the appropriate array members
            //
            Handles[0] = Overlap->hEvent;
            socklist[0].overlap = Overlap;
            socklist[0].SockAccepted = accept_socket;

            //
            // AcceptEx()
            //
            if ( !pfnAcceptEx(listen_socket, 
                              accept_socket, 
                              Buffer,
                              0, // read nothing from the socket
                              sizeof(SOCKADDR_STORAGE)+16, 
                              sizeof(SOCKADDR_STORAGE)+16,
                              &bytes_read, 
                              Overlap
                             ))
            {

                lasterror = WSAGetLastError();
                if ( WSA_IO_PENDING != lasterror)
                {
                    ERR("AcceptEx()");
                    for ( i = 0; i < curr_size; i++ )
                    {
                        shutdown(socklist[i].sock, SD_BOTH);
                        CLOSESOCK(socklist[i].sock);
                        XFREE(socklist[i].overlap);
                        CLOSEEVENT(Handles[i]);
                    }
                    __leave;
                }
            }

            //
            // This loop simple checks the handles to see which one is 
            // signalled. 
            // If error, exit. 
            // If there is a new incoming connection, we break to the outer loop
            // queue another AcceptEx()
            //
            for ( ;; )
            {
                i = DoWait(Handles, socklist);
                if ( i < 0 )
                    break;
                HandleEvent(i, Handles, socklist);
                if ( i == 0 )
                    break;
            };
            if ( i < 0 )
            {
                for ( i = 0; i < curr_size; i++ )
                {
                    shutdown(socklist[i].sock, SD_BOTH);
                    CLOSESOCK(socklist[i].sock);
                    XFREE(socklist[i].overlap);
                    CLOSEEVENT(Handles[i]);
                }
                __leave;
            }
        }
    }
    __finally
    {
        XFREE(Buffer);
        if (NULL != local) freeaddrinfo(local);
        CLOSESOCK(listen_socket); 
        CLOSESOCK(accept_socket);
        CLOSEEVENT(Overlap->hEvent);
        XFREE(Overlap);

    }
}
/*
 * This is the main function that handles all the events occuring on the
 * different handles we are watching.
 *
 * Parameters:
 *          index: Index into the Handles[] array. Returned by DoWait()
 *          Handles: Array of Event Handles we are watching
 *          socklist: Helper parallel array of state information
 *
 */
void HandleEvent(int index, WSAEVENT *Handles, Socklist *socklist)
{

    WSAOVERLAPPED *Overlap;
    SOCKET newsock = INVALID_SOCKET;
    DWORD bytes = 0;
    DWORD    flags    =    0;
    DWORD lasterr = 0;
    int i = 0;

    Overlap = socklist[index].overlap;




    if (!WSAResetEvent(Handles[index]))
    {
        ERR("WSAResetEvent()");
    }

    //
    // Check the specified handle
    //
    // If a socket is closed by the other side, the error returned is
    // WSAECONNRESET
    //
    if ( !WSAGetOverlappedResult(socklist[index].sock, 
                                 Overlap, 
                                 &bytes, 
                                 FALSE, 
                                 &flags))
    {
        ERR("WSAGetOverlappedResult()");
    }

    newsock = socklist[index].SockAccepted;

    //
    // If the other side closed the connection, close our socket and 
    // move the next element of the Handles[] array into our 
    // index.
    //
    // The array compaction is done so that we only pass valid handles
    // in the first "curr_size" elements of the array to
    // WSAWaitForMultipleEvents(). The function will fail otherwise.
    //

    //
    // We should NEVER get this for our listening socket
    //
    if ( (index != 0) && (bytes == 0 ) )
    {
        CLOSESOCK(newsock);
        XFREE(Overlap);
        CLOSEEVENT(Handles[index]);
        for ( i = index; i < curr_size; i++ )
        {
            Handles[i] = Handles[i+1];
            socklist[i] = socklist[i+1];
        }
        curr_size--;
        return;
    }

    if ( (index == 0) )
    {    // listening socket
        if ( curr_size >= MAX_IO_PEND )
        {
            shutdown(newsock, SD_BOTH);
            CLOSESOCK(newsock);
            fprintf(stderr,"Too many pending requests\n");
            return;
        }

        //
        // Get the event handle used to queue the AcceptEx(),
        // and re-use it to queue a WSARecv() on the socket.
        //
        Handles[curr_size] = Overlap->hEvent;

        //
        // Fill in the details of our accepted socket
        //
        socklist[curr_size].sock = newsock;
        SecureZeroMemory(socklist[curr_size].Buffer, 
                         sizeof(socklist[curr_size].Buffer)/sizeof(socklist[curr_size].Buffer[0]
                         ));

        socklist[curr_size].overlap = Overlap;
        socklist[curr_size].DataBuf.len = sizeof(socklist[curr_size].Buffer);
        socklist[curr_size].DataBuf.buf = socklist[curr_size].Buffer;

        //
        // The OffsetHigh field is used to keep track of what we are doing.
        // This enables us to alternate WSARecv() and WSASend() on a 
        // connection
        //
        socklist[curr_size].Op = OP_READ;

        flags = 0;
        if ( SOCKET_ERROR == WSARecv(socklist[curr_size].sock, 
                                     &(socklist[curr_size].DataBuf), 
                                     1, 
                                     &bytes, 
                                     &flags,
                                     socklist[curr_size].overlap, 
                                     NULL
                                     ))
        {

            lasterr = WSAGetLastError();

            if ( WSA_IO_PENDING != lasterr)
            {
                ERR("WSARecv()");
                if ( WSAECONNRESET == lasterr)
                {

                    //
                    // Handle WSAECONNRESET specially
                    // Other errors are not good
                    //
                    shutdown(newsock, SD_BOTH);
                    CLOSESOCK(newsock);
                    XFREE(Overlap);
                    CLOSEEVENT(Handles[index]);
                    for ( i = index; i < curr_size; i++ )
                    {
                        Handles[i] = Handles[i+1];
                        socklist[i] = socklist[i+1];
                    }
                    curr_size--;
                }
                return;
            }
        }

        //
        // Increment the last valid handle location in the Handles
        // array.
        //
        curr_size++;
        return;
    }

    //
    //  If the previous operation was an OP_READ, queue WSASend() on the
    //  socket
    //
    if ( socklist[index].Op == OP_READ )
    { // WSARecv() was queued

        printf("Read buffer [%s]\n", socklist[index].Buffer);
        printf("Echoing back to client\n");

        if ( SOCKET_ERROR == WSASend(socklist[index].sock, 
                                     &(socklist[index].DataBuf), 
                                     1, 
                                     &bytes, 
                                     0,
                                     socklist[index].overlap, 
                                     NULL))
        {

            lasterr = WSAGetLastError();
            if(WSA_IO_PENDING != lasterr)
            {
                ERR("WSASend()");
                if ( WSAECONNRESET == lasterr)
                {
                    shutdown(newsock, SD_BOTH);
                    CLOSESOCK(newsock);
                    XFREE(Overlap);
                    CLOSEEVENT(Handles[index]);
                    for ( i = index; i < curr_size; i++ )
                    {
                        Handles[i] = Handles[i+1];
                        socklist[i] = socklist[i+1];
                    }
                    curr_size--;
                }
                return;
            }
        }

        socklist[index].Op = OP_WRITE;
        return;
    }

    //
    // If we had a WSASend() queued, now do a WSARecv()
    //
    else if ( socklist[index].Op == OP_WRITE )
    { // WSASend() was queued

        printf("Wrote %d bytes\n",bytes);
        printf("Queueing read\n");

        flags = 0;
        if ( SOCKET_ERROR == WSARecv(socklist[index].sock, 
                                     &(socklist[index].DataBuf), 
                                     1, 
                                     &bytes, 
                                     &flags,
                                     socklist[index].overlap, 
                                     NULL
                                     ))
        {

            lasterr = WSAGetLastError();
            if(WSA_IO_PENDING != lasterr)
            {
                ERR("WSARecv()");
                if ( WSAECONNRESET == lasterr)
                {
                    shutdown(newsock, SD_BOTH);          
                    CLOSESOCK(newsock);
                    XFREE(Overlap);
                    CLOSEEVENT(Handles[index]);
                    for ( i = index; i < curr_size; i++ )
                    {
                        Handles[i] = Handles[i+1];
                        socklist[i] = socklist[i+1];
                    }
                    curr_size--;
                }
                return;
            }
        }

        socklist[index].Op = OP_READ;
        return;
    }
    else
    {
        fprintf(stderr,"Unknown operation queued\n");
    }



}
Exemple #6
0
int __cdecl main()
{
	WSADATA wsd;
	INT nStartup = 0, nErr = 0, ret = 0;
	SOCKET lsock = INVALID_SOCKET, asock = INVALID_SOCKET;
	SOCKADDR_STORAGE    addr = {0};
	WSAPOLLFD           fdarray = {0};
	ULONG               uNonBlockingMode = 1;
	CHAR                buf[MAX_PATH] = {0};
	HANDLE              hThread = NULL;
	DWORD               dwThreadId = 0;
	
	nErr = WSAStartup(WS_VER,&wsd);
	if (nErr) {
		WSASetLastError(nErr);
		ERR("WSAStartup");
		exit(0);
	} else {
		nStartup++;
	}
	
	if (NULL == (hCloseSignal = CreateEvent(NULL, TRUE, FALSE, NULL))) {
		ERR("CreateEvent");
		exit(0);
	}
	
	/*
	if (NULL == (hThread = CreateThread(NULL, 0, ConnectThread, NULL, 0, &dwThreadId))) {
		ERR("CreateThread");
		//exit__leave;
	}
	*/
	
	addr.ss_family = AF_INET;
	INETADDR_SETANY((SOCKADDR*)&addr);
	SS_PORT((SOCKADDR*)&addr) = htons(DEFAULT_PORT);
	
	if (INVALID_SOCKET == (lsock = socket(AF_INET, SOCK_STREAM, 0))) {
		ERR("socket");
		exit(0);
	}
	/*
	if (SOCKET_ERROR == ioctlsocket(lsock, FIONBIO, &uNonBlockingMode)) {
		ERR("FIONBIO");
		exit(0);
	}
	*/
	
	if (SOCKET_ERROR == bind(lsock, (SOCKADDR*)&addr, sizeof (addr))) {
		ERR("bind");
		exit(0);
	}
	
	if (SOCKET_ERROR == listen(lsock, 100)) {
		ERR("listen");
		exit(0);
	}
	
	//Call WSAPoll for readability of listener (accepted)
	
	//fdarray.fd = lsock;
	//fdarray.events = POLLRDNORM | POLLWRNORM;

	/*
	if (SOCKET_ERROR == (ret = WSAPoll(&fdarray, 1, DEFAULT_WAIT))) {
		ERR("WSAPoll");
		exit(0);
	}
	*/

while (1) {
	//if (ret) {
		//if ((fdarray.revents & POLLRDNORM) || (fdarray.revents & POLLWRNORM)) {
		//	printf("Main: Connection established.\n");
			
			if (INVALID_SOCKET == (asock = accept(lsock, NULL, NULL))) {
				ERR("accept");
				//__leave;
			}
			
			/*
			if (SOCKET_ERROR == (ret = recv(asock, buf, sizeof(buf), 0))) {
				ERR("recv");
			} else {
				printf("Main: recvd %d bytes\n",ret);
			}
			*/
		//}
	//}
	
	//Call WSAPoll for writeability of accepted
	
	fdarray.fd = asock;
	fdarray.events = POLLWRNORM;
	
	if (SOCKET_ERROR == (ret = WSAPoll(&fdarray, 1, DEFAULT_WAIT))) {
		ERR("WSAPoll");
		// exit
	}
	
	if (ret) {
		if (fdarray.revents & POLLWRNORM) {
			if (SOCKET_ERROR == (ret = send(asock, TST_MSG, sizeof(TST_MSG), 0))) {
				ERR("send");
				// exit
			} else {
				printf("Main: sent %d bytes\n",ret);
				closesocket(asock);
			}
		}
	}

}

	//SetEvent(hCloseSignal);
	
	//WaitForSingleObject(hThread,DEFAULT_WAIT);
	
	/* clean up before exit */
	
	CloseHandle(hCloseSignal);
	CloseHandle(hThread);
	CLOSESOCK(asock);
	CLOSESOCK(lsock);
	
	if (nStartup) {
		WSACleanup();
	}
	
	return 0;
	
}