⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 udpmessagesocket.cpp

📁 KphoneSI (kpsi) is a SIP (Session Initiation Protocol) user agent for Linux, with which you can in
💻 CPP
字号:
#include <sys/types.h>#include <sys/socket.h>#include <netinet/ip.h>#include <netinet/in.h>#include <netdb.h>#include <arpa/nameser.h>#include <sys/ioctl.h>#include <sys/stat.h>#include <sys/time.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <strings.h>#include <errno.h>#include <fcntl.h>#include <resolv.h>#include <qwidget.h>#include "udpmessagesocket.h"#include "sipclient.h"UDPMessageSocket::UDPMessageSocket( void ){	type = SocketUDP;	if ( ( socketfd = socket( AF_INET, SOCK_DGRAM, 0 ) ) == -1 ) {		printf( "UDPMessageSocket::UDPMessageSocket(): socket() failed\n" );	}	didcomplain = false;}UDPMessageSocket::UDPMessageSocket( int newfd ){	type = SocketUDP;	socketfd = newfd;	didcomplain = false;}UDPMessageSocket::~UDPMessageSocket( void ){	close( socketfd );}int UDPMessageSocket::connect( unsigned int portnum ){	socketaddress.sin_family = AF_INET;	socketaddress.sin_port = htons( portnum );	socketaddress.sin_addr = *( (struct in_addr *) he->h_addr );	bzero( &(socketaddress.sin_zero), 8 ); // is this portable?	remoteaddress = socketaddress;	return 0;}int UDPMessageSocket::SetTOS( void ){	unsigned char tos;	socklen_t optlen;	//tos=IPTOS_PREC_CRITIC_ECP;	tos=IPTOS_LOWDELAY;	optlen=1;	if(setsockopt(socketfd,SOL_IP,IP_TOS,&tos,optlen) != 0){		printf("UDPMessageSocket::SetTOS");	}	return 0;}int UDPMessageSocket::send( const char *sendbuffer, unsigned int length ){	int numbytes;	if( ( numbytes = sendto( socketfd, sendbuffer, length, 0,	    (struct sockaddr *) &remoteaddress, sizeof( struct sockaddr ) ) ) == -1 ) {		if( !didcomplain ) {			printf( "UDPMessageSocket::send(): sendto() failed\n" );			didcomplain = true;		}		return -1;	}	return 0;}int UDPMessageSocket::receive( char *recvbuffer, unsigned int maxlength ){	socklen_t addrlength;	int numbytes;	addrlength = sizeof( struct sockaddr );	if( ( numbytes = recvfrom( socketfd, recvbuffer, maxlength, 0, \	    (struct sockaddr *) &remoteaddress, &addrlength ) ) == -1 ) {		printf( "UDPMessageSocket::recieve(): recvfrom() failed\n" );		return -1;	}	return numbytes;}unsigned int UDPMessageSocket::listen( unsigned int portnum ){	struct sockaddr name;	socklen_t namesize;	socketaddress.sin_family = AF_INET;	socketaddress.sin_port = htons( portnum );	socketaddress.sin_addr.s_addr = INADDR_ANY;	bzero( &(socketaddress.sin_zero), 8 ); // is this portable?	/*	 * if already bound then close this one and open	 * a new socket so we can bind it to different port	 * number	 */	if (bound) {		close(socketfd);		bound = false;		if( ( socketfd = socket( AF_INET, SOCK_DGRAM, 0 ) ) == -1 ) {			printf( "UDPMessageSocket::listen: socket() failed\n" );			return 0;		}	}	int count = 0;	while ( bind( socketfd, (struct sockaddr *) &socketaddress, sizeof( struct sockaddr) ) == -1 && count <= 10 ) {		count++;		portnum += 2;		socketaddress.sin_port = htons( portnum );	}	if ( count > 10 ) {		printf( "UDPMessageSocket::listen(): bind() failed\n" );		return 0;	}	bound = true;	namesize = sizeof( struct sockaddr );	bzero( &name, sizeof( struct sockaddr ) );	if ( getsockname( socketfd, &name, &namesize ) == -1 ) {		printf( "UDPMessageSocket::listen(): getsockname() failed\n" );		return 0;	}	ourport = ntohs( ((struct sockaddr_in *) &name)->sin_port );	return ourport;}/* * FIXME: There is no guarantee that the subsequent call * to socket and bind will return previous port number + 1 ! * This function can potentially allocate several file * descriptors and never close them * comment made by jan@iptel.org */int UDPMessageSocket::listenOnEvenPortOS( void ){	struct sockaddr name;	socklen_t namesize;	int oldsocketfd = 0;	int portnum = 0;	/*	 * if already bound then close this one and open	 * a new socket so we can bind it to different port	 * number	 */	if (bound) {		close(socketfd);		bound = false;		if( ( socketfd = socket( AF_INET, SOCK_DGRAM, 0 ) ) == -1 ) {			printf( "UDPMessageSocket::listenOnEvenPortOS: socket() failed\n" );			return -1;		}	}getaddress:	socketaddress.sin_family = AF_INET;	socketaddress.sin_port = htons( portnum );	socketaddress.sin_addr.s_addr = INADDR_ANY;	bzero( &(socketaddress.sin_zero), 8 ); // is this portable?	if ( bind( socketfd, (struct sockaddr *) &socketaddress, sizeof( struct sockaddr) ) == -1 ) {		printf( "UDPMessageSocket::listen(): bind() failed\n" );		return -1;	}	bound = true;	namesize = sizeof( struct sockaddr );	bzero( &name, sizeof( struct sockaddr ) );	if ( getsockname( socketfd, &name, &namesize ) == -1 ) {		printf( "UDPMessageSocket::listen(): getsockname() failed\n" );		return -1;	}	ourport = ntohs( ((struct sockaddr_in *) &name)->sin_port );	if( ( portnum == 0 ) && ( ourport % 2 ) != 0 ) {		oldsocketfd = socketfd;		if( ( socketfd = socket( AF_INET, SOCK_DGRAM, 0 ) ) == -1 ) {			printf( "UDPMessageSocket::UDPMessageSocket(): socket() failed\n" );		}		goto getaddress;	}	if( oldsocketfd != 0 )		close( oldsocketfd );	return 0;}int UDPMessageSocket::listenOnEvenPort(int min, int max){	/* User didn't specify any range, let the OS	 * assign source port number	 */	if ((min == 0) && (max == 0)) {		return listenOnEvenPortOS();	}	/* Only max specified, set min to the lowest limit */	if (min == 0) min = 1024;	/* Only min specified, set max to the highest port number */	if (max == 0) max = 65535;	/* min not odd, increase */	if (min % 2) min++;	/* Out of range ? Signal error */	if (min > max) goto error;	/*	 * if already bound then close this one and open	 * a new socket so we can bind it to different port	 * number	 */	if (bound) {		close(socketfd);		bound = false;		if( ( socketfd = socket( AF_INET, SOCK_DGRAM, 0 ) ) == -1 ) {			printf( "UDPMessageSocket::listenOnEvenPor: socket() failed\n" );			return -1;		}	}loop:	socketaddress.sin_family = AF_INET;	socketaddress.sin_port = htons(min);	socketaddress.sin_addr.s_addr = INADDR_ANY;	bzero(&(socketaddress.sin_zero), 8);	if (bind(socketfd, (struct sockaddr*)&socketaddress, sizeof(struct sockaddr)) == -1) {		min += 2;		if (min <= max) goto loop;		else goto error;	}		bound = true;	/*	 * FIXME: Do some test for even port number here	 */	ourport = min;	return 0;error:	printf("UDPMessageSocket::listen(): Can't find a free port in specified range");	return -1;	}int UDPMessageSocket::listenOnEvenPortForVideo( void ){	struct sockaddr name;	socklen_t namesize;	int oldsocketfd = 0;	int portnum = 0;	if ( ( socketfd = socket( AF_INET, SOCK_DGRAM, 0 ) ) == -1 ) {		printf( "UDPMessageSocket::UDPMessageSocket(): socket() failed\n" );	}getaddress:	socketaddress.sin_family = AF_INET;	socketaddress.sin_port = htons( portnum );	socketaddress.sin_addr.s_addr = INADDR_ANY;	bzero( &(socketaddress.sin_zero), 8 ); // is this portable?	int one = 1;	if ( setsockopt( socketfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof( one ) ) == -1 ) {		printf( "UDPMessageSocket::setsockopt SO_REUSEADDR\n" );	}	if ( bind( socketfd, (struct sockaddr *) &socketaddress, sizeof( struct sockaddr) ) == -1 ) {		printf( "UDPMessageSocket::listen(): bind() failed\n" );		return -1;	}	bound = true;	namesize = sizeof( struct sockaddr );	bzero( &name, sizeof( struct sockaddr ) );	if ( getsockname( socketfd, &name, &namesize ) == -1 ) {		printf( "UDPMessageSocket::listen(): getsockname() failed\n" );		return -1;	}	ourport = ntohs( ((struct sockaddr_in *) &name)->sin_port );	if( portnum == 0 && ( ourport % 4 ) != 0 ) {		oldsocketfd = socketfd;		if( ( socketfd = socket( AF_INET, SOCK_DGRAM, 0 ) ) == -1 ) {			printf( "UDPMessageSocket::UDPMessageSocket(): socket() failed\n" );		}		goto getaddress;	}	if( oldsocketfd != 0 )		close( oldsocketfd );	return 0;}int UDPMessageSocket::accept( void ){	return socketfd;}int UDPMessageSocket::sendStunRequest( QString host, int port ){		setHostname( host);		connect( port);		StunRequestSimple req;		req.msgHdr.msgType = htons(BindRequestMsg);		req.msgHdr.msgLength = htons( sizeof(StunRequestSimple)-sizeof(StunMsgHdr) );		for ( int i=0; i<16; ++i ) {			req.msgHdr.id.octet[i]=0;		}		int id = rand();		req.msgHdr.id.octet[0] = id;		req.msgHdr.id.octet[1] = id>>8;		req.msgHdr.id.octet[2] = id>>16;		req.msgHdr.id.octet[3] = id>>24;		return (send( (char *)&req, sizeof( req ) ) );}unsigned int UDPMessageSocket::receiveStunResponse(void ){	unsigned int port = 0;	int i1,i2,i3,i4;	char ip[17] = { '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0'};	char inputbuf[ 8000 ];	int bytesread;	struct timeval timeout;	fd_set read_fds;	int highest_fd;	timeout.tv_sec = 5;	timeout.tv_usec = 0;	FD_ZERO( &read_fds );	FD_SET( getFileDescriptor(), &read_fds );	highest_fd = getFileDescriptor() + 1;retry:	if( select( highest_fd, &read_fds, NULL, NULL, &timeout ) == -1 ) {		if( errno == EINTR ) goto retry;		perror( "UDPMessageSocket: select() punted" );		exit( 1 );	}	if( FD_ISSET( getFileDescriptor(), &read_fds ) ) {		bytesread = read( getFileDescriptor(), inputbuf, 8000 - 1 );		StunMsgHdr* hdr = reinterpret_cast<StunMsgHdr*>( inputbuf );		if( hdr->msgType == BindResponseMsg ) {			char* body = inputbuf + sizeof( StunMsgHdr );			unsigned int size = ntohs( hdr->msgLength );			while( size > 0 ) {				StunAtrHdr* attr = reinterpret_cast<StunAtrHdr*>( body );				unsigned int hdrLen = ntohs( attr->length );				if( ntohs( attr->type ) == MappedAddress ) {					StunAtrAddress* attribute =						reinterpret_cast<StunAtrAddress*>( body );					if ( attribute->address.addrHdr.family == IPv4Family ) {						StunAtrAddress4* atrAdd4 =							reinterpret_cast<StunAtrAddress4*>( body );						if ( hdrLen == sizeof( StunAtrAddress4 ) - 4 ) {							port = ntohs( atrAdd4->addrHdr.port );							i1 = atrAdd4->v4addr & 0xFF;							i2 = (atrAdd4->v4addr & 0xFF00) >> 8;							i3 = (atrAdd4->v4addr & 0xFF0000) >> 16;							i4 = (atrAdd4->v4addr & 0xFF000000) >> 24;							sprintf( ip, "%d.%d.%d.%d", i1, i2, i3, i4 );							//printf( "UDPMessageSocket::receiveStunResponse %s:%d\n",ip,port);							stunnedHost= QString((char *)&ip[0]);						}					}				}				body += hdrLen+4;				size -= hdrLen+4;			}		}	}	return port;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -