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; }
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; }