next up previous contents
Nächste Seite: Vergleich SIP und H.323 Aufwärts: Session Initiation Protocol Vorherige Seite: Aendern einer existierenden Sitzung   Inhalt

Beispiel Rufaufbau bei SIP

Wir nehmen an, der Anrufer sendet eine INVITE-Anforderung an den Angerufenen. Dann benoetigen wir fuer den Rufaufbau folgende C++-Funktionen:

Als erstes muss sich der Client an einem Registrierungsserver anmelden:

void SipTransaction::sendRegister( QString registerserver, bool clear,
                           const QString &body, MimeContentType *bodytype )
{
        if ( requestmessage == NULL ) {
                direction = LocalRequest;
        }

        // Create message
        requestmessage = new SipMessage;
        requestmessage->setType( SipMessage::Request );
        requestmessage->setMethod( Sip::REGISTER );

        // Set request URI
        SipUri requri;
        requri.setHostname( registerserver );
        requestmessage->setRequestUri( requri );

        requestmessage->insertHeader( SipHeader::CSeq, getCSeq() );
        requestmessage->insertHeader( SipHeader::To, remote.nameAddr() );

        if ( bodytype ) {
                requestmessage->insertHeader( SipHeader::Content_Type, bodytype->type() );
        }
        requestmessage->setBody( body );

        if( clear ) {
                requestmessage->insertHeader( SipHeader::Expires, "0" );
                requestmessage->insertHeader( SipHeader::Contact, "*" );
                parent->sendRequest( requestmessage, false );
        } else {
                parent->sendRequest( requestmessage, true );
        }
}

Wie man sieht wird zuerst eine neue Instanz der Klasse SipMessage erstellt, anschliessend der Typ und die Methode, ``Sip::REGISTER'' gesetzt. Nachdem die Header der Nachricht korrekt gesetzt wurden und der body mit ``setBody( body )'' wird die Nachricht schliesslich gesendet.

Eine erhaltene INVITE-Nachricht wird auf Seite des Angerufenen in der folgenden Funktion gehandhabt:

void SipTransaction::incommingRequest( SipMessage *message )
{
        printf( "SipTransaction: Incomming Request\n" );
        if( ( message->getMethod() == Sip::ACK ) ||
                                   ( message->getMethod() == Sip::CANCEL ) ) {
                printf( "SipTransaction: Message is ACK or CANCEL\n" );
        } else {
                direction = RemoteRequest;
                requestmessage = message;
                switch( message->getMethod() ) {
                        case Sip::INVITE:
                                parent->setCallType( SipCall::StandardCall );
                                sendResponse( SipStatus( 180 ) );
                                break;
                        case Sip::BYE:
                                if( parent->getCallType() == SipCall::UnknownCall ) {
                                        parent->setCallType( SipCall::BrokenCall );
                                }
                                sendResponse( SipStatus( 200 ) );
                                break;
                        case Sip::OPTIONS:
                                if( parent->getCallType() == SipCall::UnknownCall ) {
                                        parent->setCallType( SipCall::OptionsCall );
                                }
                                sendResponse( SipStatus( 200 ) );
                                break;
                        case Sip::MSG:
                                parent->setCallType( SipCall::MsgCall );
                                if( message->hasHeader( SipHeader::Subject ) ) {                                        parent->setSubject( message->getHeaderData( SipHeader::Subject ) );
                                }
                                sendResponse( SipStatus( 200 ) );
                                break;
                        default:
                                break;
                }
        }
}

Die Funktion behandelt eine eingehende Anfrage. Der Code erklaert sich weitestgehend selbst, es wird eine Behandlung fuer die verschiedenen SIP-Messagetypen bereitgestellt.

Die hierfuer wichtige Funktion in der SipStatus-Klasse und gleichzeitig eine Aufstellung aller SIP-Response-Codes ist hier:

QString SipStatus::codeString( unsigned int code )
{
        switch ( code ) {
                case 0: return "No Response";

                case 100: return "Trying";
                case 180: return "Ringing";
                case 181: return "Call is Being Forwarded";
                case 182: return "Queued";

                case 200: return "OK";

                case 300: return "Multiple Choices";
                case 301: return "Moved Permanently";
                case 302: return "Moved Temporarily";
                case 303: return "See Other";
                case 305: return "Use Proxy";
                case 380: return "Alternative Service";

                case 400: return "Bad Request";
                case 401: return "Unauthorized";
                case 402: return "Payment Required";
                case 403: return "Forbidden";
                case 404: return "Not Found";
                case 405: return "Method Not Allowed";
                case 406: return "Not Acceptable";
                case 407: return "Proxy Authentication Required";
                case 408: return "Request Timeout";
                case 409: return "Conflict";
                case 410: return "Gone";
                case 411: return "Length Required";
                case 413: return "Request Entity Too Large";
                case 414: return "Request-URI Too Large";
                case 415: return "Unsupported Media Type";
                case 420: return "Bad Extension";
                case 480: return "Temporarily not available";
                case 481: return "Call Leg/Transaction Does Not Exist";
                case 482: return "Loop Detected";
                case 483: return "Too Many Hops";
                case 484: return "Address Incomplete";
                case 485: return "Ambiguous";
                case 486: return "Busy Here";

                case 500: return "Internal Server Error";
                case 501: return "Not Implemented";
                case 502: return "Bad Gateway";
                case 503: return "Service Unavailable";
                case 504: return "Gateway Time-out";
                case 505: return "SIP Version not supported";

                case 600: return "Busy Everywhere";
                case 603: return "Decline";
                case 604: return "Does not exist anywhere";
                case 606: return "Not Acceptable";
        }
        return "Unknown";
}

Nach Erhalt der INVITE-Nachricht schickt also der Angerufene mit folgendem Code-Fragment die SIP-Antwort ``Ringing'' (180):

void SipTransaction::sendResponse( const SipStatus &status,
                               const QString &body, MimeContentType *bodytype )
{
        SipMessage *response = new SipMessage;
        unsigned int i;

        setStatus( status ); // Update our status
        responses.append( response ); // Save this response

        response->setType( SipMessage::Response );
        response->setStatus( status );

        // Copy via list exactly
        for( i = 0; i < requestmessage->getViaListLength(); i++ ) {
                response->addVia( requestmessage->getVia( i ) );
        }

        response->insertHeader( SipHeader::From, remote.nameAddr() );
        response->insertHeader( SipHeader::CSeq,
                          requestmessage->getHeaderData(SipHeader::CSeq ) );
        if( bodytype ) {
                response->insertHeader( SipHeader::Content_Type, bodytype->type() );
        }
        response->setBody( body );

        parent->sendResponse( response );
}

Zum Senden von SIP-Anforderungen wird hingegen folgender Code verwendet:

void SipTransaction::sendRequest( Sip::Method meth, const QString &body,
                                                    MimeContentType *bodytype )
{
        if( meth == Sip::INVITE ) {
                parent->setCallType( SipCall::StandardCall );
        }

        if ( requestmessage == NULL ) {
                direction = LocalRequest;
        }

        // Construct message
        requestmessage = new SipMessage;
        requestmessage->setType( SipMessage::Request );
        requestmessage->setMethod( meth );

        // Set Request Uri
        SipUri requri;
        requri.setUsername( remote.getUsername() );
        requri.setHostname( remote.getHostname() );
        requestmessage->setRequestUri( requri );
        requestmessage->setDestinationHost( remote.getHostname() );

        requestmessage->insertHeader( SipHeader::CSeq, getCSeq() );
        requestmessage->insertHeader( SipHeader::To, remote.nameAddr() );

        if ( bodytype ) {
                requestmessage->insertHeader( SipHeader::Content_Type, bodytype->type() );
        }
        requestmessage->setBody( body );

        parent->sendRequest( requestmessage );
}

Anfangs wird die Unterscheidung getroffen, in welche Richtung der Request gesendet werden soll. Anschliessend wird eine neue SipMessage sowie eine SipUri erzeugt, die SipMessage konfiguriert und schlieslich an den entfernten Server gesandt.


next up previous contents
Nächste Seite: Vergleich SIP und H.323 Aufwärts: Session Initiation Protocol Vorherige Seite: Aendern einer existierenden Sitzung   Inhalt
Robert Hoehndorf 2002-06-18