📄 sipclient.cpp
字号:
// #include <pwd.h> #include <sys/types.h>#include <sys/stat.h>#include <sys/time.h>#include <sys/socket.h>#include <sys/ioctl.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 "../kphone/kphone.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"#include "../kphone/kstatics.h"typedef unsigned int u_int;typedef unsigned short u_short;typedef unsigned char u_char;/** @short used by SipClient */struct s_SOA{ char *mname; char *rname; u_int serial; u_int refresh; u_int retry; u_int expire; u_int minimum;};/** @short used by SipClient */struct s_NULL{ char *anything; u_short length; /* Length of valid data */};/** @short used by SipClient */struct s_WKS{ struct in_addr address; char *bitmap; u_int maplength; u_char protocol;};/** @short used by SipClient */struct s_HINFO{ char *cpu; char *os;};/** @short used by SipClient */struct s_MINFO{ char *rmailbx; char *emailbx;};/** @short used by SipClient */struct s_MX{ char *exchange; u_short preference;};/** @short used by SipClient */struct s_TXT{ char *text; struct s_TXT *next; u_short len;};/** @short used by SipClient */struct s_SRV{ u_short priority; u_short weight; u_short port; char *target;};/** @short used by SipClient */struct s_NAPTR{ u_short order; u_short pref; char *flags; char *service; char *regexp; char *replacement;};/** AFS servers used by SipClient */struct s_AFSDB{ u_short subtype; char *hostname;};/** @short Responsible Person */struct s_RP{ char *mbox_dname; char *txt_dname;};/** @short ISDN Address */struct s_ISDN{ char *address; char *sa; /* optional */};/** @short Route Through */struct s_RT{ u_short preference; char *int_host;};/** @short 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) *//** @short other structured RR types */ struct s_SOA soa;/** @short other structured RR types */ struct s_NULL null;/** @short other structured RR types */ struct s_WKS wks;/** @short other structured RR types */ struct s_HINFO hinfo;/** @short other structured RR types */ struct s_MINFO minfo;/** @short other structured RR types */ struct s_MX mx;/** @short other structured RR types */ struct s_TXT txt;/** @short other structured RR types */ struct s_SRV srv;/** @short other structured RR types */ struct s_NAPTR naptr;/** @short other structured RR types */ struct s_AFSDB afsdb;/** @short other structured RR types */ struct s_RP rp;/** @short other structured RR types */ struct s_ISDN isdn;/** @short other structured RR types */ struct s_RT rt;};/** @short 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;/** @short DNS Question sctructure */typedef struct s_question{ char *qname; u_short qtype; u_short qclass;} s_question;/** @short 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;/** Der SipClient*/SipClient::SipClient( QObject *parent, const char *name, unsigned int newListenport, bool newLooseRoute, bool newStrictRoute, QString socketStr ) : QObject( parent, name ){ debug=KStatics::debugLevel; if( !setupSocketStuff( newListenport, socketStr ) ) { printf("=====SipClient::setupSocketStuff() Failed.\n"); exit( 1 ); } nlp=newListenport; setupContactUri(); KStatics::myIP = contacturi.getHostname(); useProxyDial = false; useExplicitProxy = false; proxyport = 5060; calls.setAutoDelete( false ); tcpSockets.setAutoDelete( true ); sndSockets.setAutoDelete( true ); fwmode = false; busymode = false; user = 0; hidemode = DontHideVia; symmetricmode = false; maxforwards = 0; looseRoute = newLooseRoute; strictRoute = newStrictRoute; testOn = false; useStunProxy = false; tcpSocket = 0; stopStun = false; foundStun = false;}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; } if( newListenport ) { listenport = newListenport; } if( listenport == 0 ) { listenport = 5060; } if( isTcpSocket() ) { listenport = TCP_listener.listen( listenport ); if( !listenport ) { return false; } TCP_listener.forcePortNumber( listenport ); if(debug>0) printf( "=====SipClient: Listening TCP on port: %d\n", TCP_listener.getPortNumber() ); } listenport = listener.listen( listenport ); nlp=listenport; if( !listenport ) { return false; } listener.forcePortNumber( listenport ); if(debug>0) printf( "=====SipClient: Listening UDP on port: %d\n", listener.getPortNumber() ); return true;}void SipClient::doSelect( bool block ){ struct timeval timeout; fd_set read_fds; int highest_fd; timeout.tv_sec = 0; timeout.tv_usec = 5; 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; printf( "=====SipClient::doSelect(): select() punted" ); } if( FD_ISSET( listener.getFileDescriptor(), &read_fds ) ) { incomingMessage( listener.getFileDescriptor(),false ); }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; printf( "=====SipClient::doSelect(): select() punted\n" ); } if( FD_ISSET( TCP_listener.getFileDescriptor(), &read_fds ) ) { clilen = sizeof(cli_addr); newsockfd = ::accept( TCP_listener.getFileDescriptor(), (struct sockaddr *) &cli_addr, (socklen_t*)&clilen); //mark socket to be closed immediately after reading incomingMessage( newsockfd,true ); } 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; printf( "=====SipClient::doSelect(): select() punted\n" ); } if( FD_ISSET( tcpSocket->getFileDescriptor(), &read_fds ) ) { incomingMessage( tcpSocket->getFileDescriptor(),false ); } } } } 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,bool closeS ){ QString fullmessage; char inputbuf[ 8000 ]; int bytesread=1; int i1,i2,i3,i4; unsigned int port; char ip[16]; unsigned int contentLength; QString lSearch; int lLen=0; for(;;) { // Receive the message bytesread = read( socketfd, inputbuf, 8000 - 1 ); if( errno == EWOULDBLOCK ) { bytesread=0; break; } 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; } 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 ); 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 ); if(debug >0) printf( "======SipCient (%s:%d) : STUN response %s:%d\n", Sip::getLocalAddress().latin1(),nlp,ip,port ); } } } body += hdrLen+4; size -= hdrLen+4; } SipRegister *current; if( !QString(ip).contains( Sip::getLocalAddress() ) || listener.getPortNumber() != port ) { Sip::setLocalAddress( ip ); foundStun=true; 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 if( haveNoMoreStun() ) { foundStun=false; SipRegister *current; Sip::setLocalAddress( 0 ); int listenport = listener.listen( nlp ); nlp=listenport; listener.forcePortNumber( listenport ); 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(); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -