Ejemplo n.º 1
0
Archivo: ssdp.cpp Proyecto: baz/upnpx
int SSDP::Start(){
	int ret = 0;
	u32 optval = 0;
	
	if(mMulticastSocket != INVALID_SOCKET || mUnicastSocket != INVALID_SOCKET){
		ret = -9;
		goto EXIT;
	}
    
    //
	//Setup the Multicast Socket
    //
	mMulticastSocket = socket(PF_INET, SOCK_DGRAM, 0);
	STATNVAL(mMulticastSocket, INVALID_SOCKET, EXIT);
	
	//Set nonblocking
	optval = fcntl( mMulticastSocket, F_GETFL, 0 );
	STATNVAL(optval, -1,  CLEAN_AND_EXIT);
	ret = fcntl(mMulticastSocket, F_SETFL, optval | O_NONBLOCK);
	STATNVAL(ret, -1,  CLEAN_AND_EXIT);
	
	//Source address
	mSrcaddr.sin_family = PF_INET;
	mSrcaddr.sin_port = 0; //Let the IP stack decide 
	mSrcaddr.sin_addr.s_addr = INADDR_ANY; //Default multicast nic 

	//Reuse port
	optval = 1;
	ret = setsockopt(mMulticastSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, 4);
	STATVAL(ret, 0, CLEAN_AND_EXIT);
	optval = 1;
	ret = setsockopt(mMulticastSocket, SOL_SOCKET, SO_REUSEPORT, (char*)&optval, 4);
	STATVAL(ret, 0, CLEAN_AND_EXIT);
	

	//Disable loopback
	optval = 0;
	ret = setsockopt(mMulticastSocket, IPPROTO_IP, IP_MULTICAST_LOOP, (char*)&optval, sizeof(int));
	STATNVAL(ret, SOCKET_ERROR, CLEAN_AND_EXIT);	
	
	//TTL
	optval = mTTL;
	ret = setsockopt(mMulticastSocket, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&optval, sizeof(int));
	STATNVAL(ret, SOCKET_ERROR, CLEAN_AND_EXIT);	
	
	
	//Add membership
	mMreq.imr_multiaddr.s_addr = inet_addr(SSDP_MCAST_ADDRESS);
	mMreq.imr_interface.s_addr = INADDR_ANY;
	ret = setsockopt(mMulticastSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mMreq, sizeof(struct ip_mreq));
	STATNVAL(ret, SOCKET_ERROR, CLEAN_AND_EXIT);	
	
	
	//Bind to all interface(s)
	ret = bind(mMulticastSocket, (struct sockaddr*)&mSrcaddr, sizeof(struct sockaddr));
	if(ret < 0 && (errno == EACCES || errno == EADDRINUSE))
		printf("address in use\n");
	STATVAL(ret, 0, CLEAN_AND_EXIT);
	
	
	//Destination address
	mDstaddr.sin_family = PF_INET;
	mDstaddr.sin_addr.s_addr = inet_addr(SSDP_MCAST_ADDRESS);
	mDstaddr.sin_port = htons(SSDP_MCAST_PORT);
	
    
    //
    // Setup the Unicast Socket (We listen for Advertisements)
    //
	mUnicastSocket = socket(PF_INET, SOCK_DGRAM, 0);
	STATNVAL(mUnicastSocket, INVALID_SOCKET, EXIT);
	
	//Set nonblocking
	optval = fcntl( mUnicastSocket, F_GETFL, 0 );
	STATNVAL(optval, -1,  CLEAN_AND_EXIT);
	ret = fcntl(mUnicastSocket, F_SETFL, optval | O_NONBLOCK);
	STATNVAL(ret, -1,  CLEAN_AND_EXIT);

    //Source address
	mUnicastSrcaddr.sin_family = PF_INET;
	mUnicastSrcaddr.sin_port = htons(SSDP_MCAST_PORT); 
	mUnicastSrcaddr.sin_addr.s_addr = INADDR_ANY; //Default nic 
    
	//Reuse port
	optval = 1;
	ret = setsockopt(mUnicastSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, 4);
	STATVAL(ret, 0, CLEAN_AND_EXIT);
	optval = 1;
	ret = setsockopt(mUnicastSocket, SOL_SOCKET, SO_REUSEPORT, (char*)&optval, 4);
	STATVAL(ret, 0, CLEAN_AND_EXIT);

    //Join Multicast group
    mMreqU.imr_multiaddr.s_addr = inet_addr(SSDP_MCAST_ADDRESS);
	mMreqU.imr_interface.s_addr = INADDR_ANY;
	ret = setsockopt(mUnicastSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mMreqU, sizeof(struct ip_mreq));
	STATNVAL(ret, SOCKET_ERROR, CLEAN_AND_EXIT);	

    
    
	//Bind to all interface(s)
	ret = bind(mUnicastSocket, (struct sockaddr*)&mUnicastSrcaddr, sizeof(struct sockaddr));
	if(ret < 0 && (errno == EACCES || errno == EADDRINUSE))
		printf("address in use\n");
	STATVAL(ret, 0, CLEAN_AND_EXIT);
    
    

	//Start the read thread
	pthread_attr_t  attr;
	ret = pthread_attr_init(&attr);
	if(ret != 0){
		goto CLEAN_AND_EXIT;
	}
	ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
	if(ret != 0){
		pthread_attr_destroy(&attr);
		goto CLEAN_AND_EXIT;
	}
	
	ret = pthread_create(&mReadThread, &attr, SSDP::sReadLoop, (void*)this);
	
	pthread_attr_destroy(&attr);
	
	
	goto EXIT;
	
	
CLEAN_AND_EXIT:	
	close(mMulticastSocket);
	mMulticastSocket = INVALID_SOCKET;
	close(mUnicastSocket);
	mUnicastSocket = INVALID_SOCKET;

EXIT:	
	return ret;
}
Ejemplo n.º 2
0
int SocketServer::Start(){
    int ret = 0;
    u32 optval = 0;
    int cnt = 0;

    //Get the IP Address
    ret = getLocalIPAddress(ipAddress, 10);
    if(ret != 0){
        return -1;
    }

    mServerSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (mServerSocket < 0){
        return -1;
    }

    //Set nonblocking
    optval = fcntl( mServerSocket, F_GETFL, 0 );
    STATNVAL(optval, -1,  CLEAN_AND_EXIT);
    ret = fcntl(mServerSocket, F_SETFL, optval | O_NONBLOCK);
    STATNVAL(ret, -1,  CLEAN_AND_EXIT);

    memset((char*)&mServerAddr, 0, sizeof(struct sockaddr_in));

    //Bind to port (try 500 numbers if needed)
    cnt = 0;
    do{
        mServerAddr.sin_family = AF_INET;
        mServerAddr.sin_addr.s_addr = INADDR_ANY;
        mServerAddr.sin_port = htons(mPort);

        if (bind(mServerSocket, (struct sockaddr *) &mServerAddr, sizeof(struct sockaddr_in)) == 0){
            break;
        }
        mPort++;
        cnt++;
    }while(cnt < 500);

    if(cnt == 500){
        return -2;
    }

    //Start the read thread
    pthread_attr_t  attr;
    ret = pthread_attr_init(&attr);
    if(ret != 0){
        goto CLEAN_AND_EXIT;
    }
    ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    if(ret != 0){
        pthread_attr_destroy(&attr);
        goto CLEAN_AND_EXIT;
    }

    ret = pthread_create(&mReadThread, &attr, SocketServer::sReadLoop, (void*)this);

    pthread_attr_destroy(&attr);

    goto EXIT;

CLEAN_AND_EXIT:
    close(mServerSocket);
    mServerSocket = INVALID_SOCKET;

EXIT:
    return ret;
}