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

📄 sipclient.cpp

📁 kphone-4.2,SHELL协议的VOIP电话
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#include <pwd.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/time.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/nameser.h>#include <resolv.h>#include <qdatetime.h>#include <fcntl.h>#include <errno.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include "siputil.h"#include "sipuser.h"#include "sipvia.h"#include "sipcall.h"#include "tcpmessagesocket.h"#include "sipmessage.h"#include "mimecontenttype.h"#include "sipstatus.h"#include "siptransaction.h"#include "sipclient.h"typedef unsigned int u_int;typedef unsigned short u_short;typedef unsigned char u_char;struct s_SOA{	char *mname;	char *rname;	u_int serial;	u_int refresh;	u_int retry;	u_int expire;	u_int minimum;};struct s_NULL{	char *anything;	u_short length;         /* Length of valid data */};struct s_WKS{	struct in_addr address;	char *bitmap;	u_int maplength;	u_char protocol;};struct s_HINFO{	char *cpu;	char *os;};struct s_MINFO{	char *rmailbx;	char *emailbx;};struct s_MX{	char *exchange;	u_short preference;};struct s_TXT{	char *text;	struct s_TXT *next;	u_short len;};struct s_SRV{	u_short priority;	u_short weight;	u_short port;	char *target;};struct s_NAPTR{	u_short order;	u_short pref;	char *flags;	char *service;	char *regexp;	char *replacement;};/* AFS servers */struct s_AFSDB{	u_short subtype;	char *hostname;};/* Responsible Person */struct s_RP{	char *mbox_dname;	char *txt_dname;};/* ISDN Address */struct s_ISDN{	char *address;	char *sa;    /* optional */};/* Route Through */struct s_RT{	u_short preference;	char *int_host;};/* Generic RDATA RR structure */union u_rdata{	char *string;            /* Any simple string record */	u_int number;            /* Any simple numeric record */	struct in_addr address; /* Simple address (A record) *//* other structured RR types */	struct s_SOA soa;	struct s_NULL null;	struct s_WKS wks;	struct s_HINFO hinfo;	struct s_MINFO minfo;	struct s_MX mx;	struct s_TXT txt;	struct s_SRV srv;	struct s_NAPTR naptr;/* RFC 1183 RR types */	struct s_AFSDB afsdb;	struct s_RP rp;	struct s_ISDN isdn;	struct s_RT rt;};/* Full RR structure */typedef struct s_rr{	char *name;	u_short type;	u_short xclass;	u_int ttl;	u_int dlen;	union u_rdata rdata;} s_rr;/* DNS Question sctructure */typedef struct s_question{	char *qname;	u_short qtype;	u_short qclass;} s_question;/* Full DNS message structure */typedef struct s_res_response{	HEADER header;	s_question **question;	s_rr **answer;	s_rr **authority;	s_rr **additional;} res_response;bool const traceMessageSending = true;bool const traceMessageReceived = true;SipClient::SipClient( QObject *parent, const char *name, unsigned int newListenport,			bool newLooseRoute, bool newStrictRoute, QString socketStr )	: QObject( parent, name ){	if( !setupSocketStuff( newListenport, socketStr ) ) {		printf("SipClient::setupSocketStuff() Failed.\n");		exit( 1 );	}	setupContactUri();	useProxyDial = false;	useExplicitProxy = false;	proxyport = 5060;	calls.setAutoDelete( false );	tcpSockets.setAutoDelete( true );	fwmode = false;	busymode = false;	user = 0;	hidemode = DontHideVia;	symmetricmode = false;	maxforwards = 0;	looseRoute = newLooseRoute;	strictRoute = newStrictRoute;	testOn = false;	useStunProxy = false;	tcpSocket = 0;}SipClient::~SipClient( void ){}void SipClient::setupContactUri( SipUser *user ){	if( user ) {		contacturi.setFullname( user->getUri().getFullname() );		contacturi.setUsername( user->getUri().getUsername() );	}	contacturi.setHostname( Sip::getLocalAddress() );	if( isTcpSocket() ) {		contacturi.setPortNumber( TCP_listener.getPortNumber() );		contacturi.setTransportParam( SipUri::TCP );	} else {		contacturi.setPortNumber( listener.getPortNumber() );		contacturi.setTransportParam( SipUri::UDP );	}}bool SipClient::setupSocketStuff( unsigned int newListenport, QString socketStr ){	unsigned int listenport;	if( socketStr == "UDP" ) {		SocketMode = UDP;	} else {		SocketMode = TCP;	}		listenport = QString::fromUtf8( getenv( "DISSIPATE_PORT" ) ).toUInt();	if( newListenport ) {		listenport = newListenport;	}	if( listenport == 0 ) {		listenport = 5060;	}	if( isTcpSocket() ) {		listenport = TCP_listener.listen( listenport );		if( !listenport ) { return false; }		TCP_listener.forcePortNumber( listenport );		printf( "SipClient: Listening TCP on port: %d\n", TCP_listener.getPortNumber() );	}	listenport = listener.listen( listenport );	if( !listenport ) { return false; }	listener.forcePortNumber( listenport );	printf( "SipClient: Listening UDP on port: %d\n", listener.getPortNumber() );	printf( "SipClient: Our address: %s\n", Sip::getLocalAddress().latin1() );	return true;}void SipClient::doSelect( bool block ){	struct timeval timeout;	fd_set read_fds;	int highest_fd;	timeout.tv_sec = 0;	timeout.tv_usec = 0;	FD_ZERO( &read_fds );	FD_SET( listener.getFileDescriptor(), &read_fds );	highest_fd = listener.getFileDescriptor() + 1;retry:	if( select( highest_fd, &read_fds, NULL, NULL, block ? NULL : &timeout ) == -1 ) {		if( errno == EINTR ) goto retry;		perror( "SipClient::doSelect(): select() punted" );		exit( 1 );	}	if( FD_ISSET( listener.getFileDescriptor(), &read_fds ) ) {		incomingMessage( listener.getFileDescriptor() );	}	if( isTcpSocket() ) {		FD_ZERO( &read_fds );		FD_SET( TCP_listener.getFileDescriptor(), &read_fds );		highest_fd = TCP_listener.getFileDescriptor() + 1;retry2:		if( select( highest_fd, &read_fds, NULL, NULL, block ? NULL : &timeout ) == -1 ) {			if( errno == EINTR ) goto retry2;			perror( "SipClient::doSelect(): select() punted" );			exit( 1 );		}		if( FD_ISSET( TCP_listener.getFileDescriptor(), &read_fds ) ) {			clilen = sizeof(cli_addr);			newsockfd = ::accept( TCP_listener.getFileDescriptor(), (struct sockaddr *) &cli_addr, (socklen_t*)&clilen);			incomingMessage( newsockfd );			::close( newsockfd );		}		TCPMessageSocketIterator it( getTcpSocketList() );		for (it.toFirst(); it.current(); ++it) {			tcpSocket = it.current();			if( tcpSocket != 0 ) {				FD_ZERO( &read_fds );				FD_SET( tcpSocket->getFileDescriptor(), &read_fds );				highest_fd = tcpSocket->getFileDescriptor() + 1;retry3:				if( select( highest_fd, &read_fds, NULL, NULL, block ? NULL : &timeout ) == -1 ) {					if( errno == EINTR ) goto retry3;					perror( "SipClient::doSelect(): select() punted" );					exit( 1 );				}				if( FD_ISSET( tcpSocket->getFileDescriptor(), &read_fds ) ) {					incomingMessage( tcpSocket->getFileDescriptor() );				}			}		}	} else {		auditPending();	}}void SipClient::auditPending( void ){	SipCall *curcall;	SipTransaction *curtrans;	for( curcall = calls.first(); curcall != 0; curcall = calls.next() ) {		for( curtrans = curcall->getTransactionList().first(); curtrans != 0;		     curtrans = curcall->getTransactionList().next() ) {			if( curtrans->auditPending() ) {				return;			}		}	}}void SipClient::incomingMessage( int socketfd ){	QString fullmessage;	char inputbuf[ 8000 ];	int bytesread;	int i1,i2,i3,i4;	unsigned int port;	char ip[16];	unsigned int contentLength = 0;	// Receive the message	printf( tr("SipClient: Receiving message...") + "\n" );	for(;;) {		bytesread = read( socketfd, inputbuf, 8000 - 1 );		StunMsgHdr* hdr = reinterpret_cast<StunMsgHdr*>( inputbuf );		if( hdr->msgType == BindResponseMsg ) {					// check that the size of the header isn't larger than what we've read			if ((signed int)sizeof(StunMsgHdr) > bytesread)			{				printf("Malformed packet (sizeof(StunMsgHdr) > bytesread)\n");				return;			}			printf( "SipClient: STUN response\n" );			char* body = inputbuf + sizeof( StunMsgHdr );			unsigned int size = ntohs( hdr->msgLength );			port = listener.getPortNumber();			while( size > 0 ) {				StunAtrHdr* attr = reinterpret_cast<StunAtrHdr*>( body );				unsigned int hdrLen = ntohs( attr->length );				// check that our attribute length is not larger than the remaining size				if (hdrLen+4 > size)				{					printf("Malformed packet (hdrLen+4 > size)\n");					return;				}				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 );							printf( "   address_port:   %d\n", 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( "   address:        %s\n", ip );						}					}				}				body += hdrLen+4;				size -= hdrLen+4;			}			SipRegister *current;			if( !QString(ip).contains( Sip::getLocalAddress() ) ||					listener.getPortNumber() != port ) {				Sip::setLocalAddress( ip );				listener.forcePortNumber( port );				setupContactUri();				QPtrListIterator<SipRegister> reg = user->getSipRegisterList();				for( ; reg.current(); ++reg ) {					current = reg.current();					if( current->getRegisterState() == SipRegister::Connected ||					    current->getAutoRegister() ) {						current->setAutoRegister( false );						current->requestRegister();					}				}			} else {				QPtrListIterator<SipRegister> reg = user->getSipRegisterList();				for( ; reg.current(); ++reg ) {					current = reg.current();					if( current->getAutoRegister() ) {						current->setAutoRegister( false );						current->requestRegister();					}				}			}			return;		} else {			fullmessage.append( QString::fromUtf8( inputbuf, bytesread ) );		}		if( bytesread < 0 ) {			perror( "SipClient::incomingMessage(): read failed" );			tcpSockets.remove( tcpSocket );			tcpSocket = 0;			return;		}		QString s;		if( isTcpSocket() ) {			if( fullmessage.contains( "\r\n\r\n" ) > 0 ) {				if( fullmessage.findRev( "Content-Length: " ) < fullmessage.findRev( "\r\n\r\n" ) ) {					s = fullmessage.mid( fullmessage.findRev( "Content-Length: " ) + 16 );					s = s.left( s.find( '\r' ) );					if( s.toInt() == 0 ) {						if( fullmessage.right( 4 ) == "\r\n\r\n" ) {							break;						}					} else {						contentLength = s.toInt();						s = fullmessage.mid( fullmessage.findRev( QString( "\r\n\r\n" ) ) + 4 );						if( s.utf8().length() == contentLength ) {							break;						}					}				} else if( fullmessage.right( 4 ) == "\r\n\r\n" ) {					break;				}			}		} else {			break;		}		// Socket closed (so we're done) WRONG		if( bytesread == 0 ) {			tcpSockets.remove( tcpSocket );			tcpSocket = 0;			break;		}	}	// Parse input	if( isTcpSocket() ) {		int contentLength;		QString s;		while( !fullmessage.isEmpty() ) {			contentLength = 0;			if( fullmessage.contains( "Content-Length: " ) > 0 ) {				if( fullmessage.find( "Content-Length: " ) < fullmessage.find( QString( "\r\n\r\n" ) ) ) {					s = fullmessage.mid( fullmessage.find( "Content-Length: " ) + 16 );					s = s.left( s.find( '\r' ) );					contentLength = s.toInt();				}			}			s = fullmessage.left( fullmessage.find( QString( "\r\n\r\n" ) ) + 4 + contentLength );			parseMessage( s );			fullmessage.remove( 0, s.length() );		}	} else {		parseMessage( fullmessage );	}}void SipClient::parseMessage( QString fullmessage ){	SipMessage *curmessage = new SipMessage( fullmessage );	if( traceMessageReceived ) {		printf( "\nSipClient: Received: %s.%03d\n---------------------------------\n%s\n",			QTime::currentTime().toString().latin1(), QTime::currentTime().msec(), fullmessage.latin1() );	}	if( !curmessage->isValid() ) {		delete curmessage;		return;	}//#test	if( testOn ) {		incomingTestMessage();		delete curmessage;		return;	}	QString callid = curmessage->getHeaderData( SipHeader::Call_ID );	// Grab address in To: header	SipUri touri( curmessage->getHeaderData( SipHeader::To ) );	// Grab address in From: header	SipUri fromuri( curmessage->getHeaderData( SipHeader::From ) );	if( curmessage->getStatus().getCode() == 487 ) {		sendAck( curmessage );		delete curmessage;		return;	}	QString cseq = curmessage->getHeaderData( SipHeader::CSeq );	if( curmessage->getMethod() == Sip::MESSAGE ) {		if( callid == messageCID && cseq == messageCSeq ) {			printf( "SipCient: Received what was likely a retransmission, badly ignoring...\n" );			delete curmessage;			return;		}		messageCID = callid;		messageCSeq = cseq;		sendQuickResponse( curmessage, SipStatus( 200 ) );		incomingInstantMessage( curmessage );		delete curmessage;		return;	}	if( curmessage->getMethod() == Sip::INFO ) {		sendQuickResponse( curmessage, SipStatus( 200 ) );	}	if( curmessage->getMethod() == Sip::SUBSCRIBE ) {		if( callid == subscribeCID && cseq == subscribeCSeq ) {			printf( "SipCient: Received what was likely a retransmission, badly ignoring...\n" );			delete curmessage;			return;		}		subscribeCID = callid;		subscribeCSeq = cseq;		bool found = false;		for( SipCall *curcall = calls.first(); curcall != 0; curcall = calls.next() ) {			if( callid == curcall->getCallId() && curcall->getCallType() == SipCall::inSubscribeCall ) {				curcall->incomingMessage( curmessage );				QString expires = curmessage->getHeaderData( SipHeader::Expires );				SipUri incominguri( curmessage->getHeaderData( SipHeader::From ) );				if( curcall->getMember( incominguri ) ) {					if( expires == "0" ) {						curcall->setCallStatus( SipCall::callUnconnected );						incomingSubscribe( 0, false );						delete curcall;						for( SipCall *c = calls.first(); c != 0; c = calls.next() ) {							if( c->getCallType() == SipCall::outSubscribeCall ) {								if( c->getMember( incominguri ) ) {									if( c->getCallStatus() != SipCall::callDead ) {										c->setCallStatus(											SipCall::callUnconnected );									}								}							}						}					} else {						curcall->getMember( incominguri )->timerStart( expires.toInt() * 1000 );						curcall->setCallStatus( SipCall::callInProgress );						incomingSubscribe( curcall->getMember( incominguri ), false );

⌨️ 快捷键说明

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