Ejemplo n.º 1
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;
}
//
// Function: main
// 
// Description:
//    Parse the command line arguments, load the Winsock library, 
//    create a socket and join the multicast group. If set as a
//    sender then begin sending messages to the multicast group;
//    otherwise, call recvfrom() to read messages send to the 
//    group.
//    
int _cdecl main(int argc, char **argv)
{
    WSADATA             wsd;
    SOCKET              s,
                        sc;
    SOCKADDR_STORAGE    remote;
    struct addrinfo    *resmulti=NULL,
                       *resif=NULL,
                       *resbind=NULL;
    char               *buf=NULL;
    int                 remotelen,
                        err,
                        rc,
                        i=0;

    // Parse the command line
    ValidateArgs(argc, argv);

    // Load Winsock
    if (WSAStartup(MAKEWORD(1, 1), &wsd) != 0)
    {
        printf("WSAStartup failed\n");
        return -1;
    }

    // Resolve the multicast address
    resmulti = ResolveAddress(gMulticast, gPort, AF_INET, 0, 0);
    if (resmulti == NULL)
    {
        fprintf(stderr, "Unable to convert multicast address '%s': %d\n",
                gMulticast, WSAGetLastError());
        return -1;
    }

    // 
    // Create the socket. In Winsock 1 you don't need any special
    // flags to indicate multicasting.
    //
    s = socket(resmulti->ai_family, gSocketType, gProtocol);
    if (s == INVALID_SOCKET)
    {
        printf("socket failed with: %d\n", WSAGetLastError());
        return -1;
    }
    printf("socket handle = 0x%p\n", s);

    // Allocate the send/receive buffer
    buf = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, gBufferSize);
    if (buf == NULL)
    {
        fprintf(stderr, "HeapAlloc failed: %d\n", GetLastError());
        return -1;
    }

    if (bSender)
    {
        // Bind to the wildcard address
        resbind = ResolveAddress(NULL, gPort, AF_INET, 0, 0);
        if (resbind == NULL)
        {
            fprintf(stderr, "Unable to obtain bind address!\n");
            return -1;
        }

        // Bind the socket
        rc = bind(s, resbind->ai_addr, resbind->ai_addrlen);
        if (rc == SOCKET_ERROR)
        {
            fprintf(stderr, "bind failed: %d\n", WSAGetLastError());
            return -1;
        }
        freeaddrinfo(resbind);

        // If sepcified, set the send interface
        if (gInterfaceCount == 1)
        {
            resif = ResolveAddress(gListenInterface[0], gPort, AF_INET, 0, 0);
            if (resif == NULL)
            {
                return -1;
            }
            rc = SetSendInterface(s, resif);

            freeaddrinfo(resif);

            // Set the TTL to something else. The default TTL is one.
            rc = SetMulticastTtl(s, resmulti->ai_family, gTtl);
            if (rc == SOCKET_ERROR)
            {
                return -1;
            }
        }
        
        // If specified set the late joiner option
        if (gLateJoin != -1)
        {
            SetLateJoin(s, gLateJoin);
        }

        // If specified set the window paramters
        if (bSetSendWindow)
        {
            SetWindowSize(s, gWindowSizeBytes, gWindowSizeMSec, gWindowRateKbitsSec);
        }

        // If specified set the FEC paramters
        if (bUseFec == TRUE)
        {
            SetFecParameters(s, gFecBlockSize, gFecGroupSize, bFecOnDemand, gFecProActive);
        }

        // Connect the socket to the multicast group the session is to be on
        rc = connect(s, resmulti->ai_addr, resmulti->ai_addrlen);
        if (rc == SOCKET_ERROR)
        {
            printf("connect failed: %d\n", WSAGetLastError());
            return -1;
        }

        memset(buf, '^', gBufferSize);

        // Send some data
        for(i=0; i < gCount ; i++)
        {
            rc = send(
                    s, 
                    buf, 
                    gBufferSize,
                    0
                    );
            if (rc == SOCKET_ERROR)
            {
                fprintf(stderr, "send failed with: %d\n", WSAGetLastError());
                return -1;
            }

            printf("SENT %d bytes\n", rc);
        }
    }
    else
    {
        // Bind the socket to the multicast address on which the session will take place
        rc = bind(s, resmulti->ai_addr, resmulti->ai_addrlen);
        if (rc == SOCKET_ERROR)
        {
            fprintf(stderr, "bind failed: %d\n", WSAGetLastError());
            return -1;
        }
        printf("Binding to ");
        PrintAddress(resmulti->ai_addr, resmulti->ai_addrlen);
        printf("\n");

        // Add each supplied interface as a receive interface
        if (gInterfaceCount > 0)
        {
            for(i=0; i < gInterfaceCount ;i++)
            {
                resif = ResolveAddress(gListenInterface[i], "0", AF_INET, 0, 0);
                if (resif == NULL)
                {
                    return -1;
                }
                rc = AddReceiveInterface(s, resif);

                freeaddrinfo(resif);
            }
        }

        // Listen for sessions
        rc = listen(s, 1);
        if (rc == SOCKET_ERROR)
        {
            fprintf(stderr, "listen failed: %d\n", WSAGetLastError());
            return -1;
        }

        // Wait for a session to become available
        remotelen = sizeof(remote);
        sc = accept(s, (SOCKADDR *)&remote, &remotelen);
        if (sc == INVALID_SOCKET)
        {
            fprintf(stderr, "accept failed: %d\n", WSAGetLastError());
            return -1;
        }

        printf("Join multicast session from: ");
        PrintAddress((SOCKADDR *)&remote, remotelen);
        printf("\n");

        while (1)
        {
            // Receive data until an error or until the session is closed
            rc = recv(sc, buf, gBufferSize, 0);
            if (rc == SOCKET_ERROR)
            {
                if ((err = WSAGetLastError()) != WSAEDISCON)
                {
                    fprintf(stderr, "recv failed: %d\n", err);
                }
                break;
            }
            else 
            {
                printf("received %d bytes\n", rc);
            }
        }

        // Close the session socket
        closesocket(sc);
    }

    // Clean up
    freeaddrinfo(resmulti);

    closesocket(s);

    WSACleanup();
    return 0;
}