Modularizando o src

Dependencies:   EALib EthernetInterface_vz mbed-rtos mbed

Fork of header_main_colinas_V0-20-09-14 by VZTECH

sip.cpp

Committer:
klauss
Date:
2015-11-24
Revision:
137:32dd35a6dbc9
Parent:
135:2f4290590e51

File content as of revision 137:32dd35a6dbc9:

#include "sip.h"

//*[ begin ] ------------------------------------ Funcoes de uso interno ---------------------------------------------- *//
void Sip::__init_sock__ ( void )
{
    sip_server.set_address ( this->server_ip , this -> server_port );
    sock.bind ( this -> my_port );
    sock.set_blocking ( false, 0 );
}

void Sip::__end_sock__ ( void )
{
    sock.close (); 
}

void Sip::__reconnect__ ( void )
{
    __end_sock__ (); 
    __init_sock__ ();
}
//*[ end ] -------------------------------------- Funcoes de uso interno ---------------------------------------------- *//

  
Sip::Sip ( const int new_ext, const uint16_t my_port )
{
    if ( debug_sip ) vz_debug ("[%d, %d] Building SIP", new_ext, my_port );
    
    this->my_ext = new_ext;
    this->my_port = my_port;
      
    cm -> get_server_ip ( this->server_ip );
    this->server_port = cm -> get_server_port ();
    cm -> get_header_ip ( this->my_ip );
    
    if ( debug_sip ) vz_debug ("[%d] port %d", this->my_ext, this->my_port );
    
    snprintf ( this -> my_display, sizeof ( this -> my_display ), "%i", this -> my_ext );
    
    this->my_rtp_port = 0;
    if ( debug_rtp ) vz_debug ("[%d] rtp port %d ", this->my_ext, this->my_rtp_port );


    this->peer_ext = cm -> get_server_ext ();
    
    strcpy( this->last_invite_tag, "" );
    strcpy( this->last_invite_callid, "");
    strcpy( this->last_branch, "" );
    strcpy( this->SVNREV, "COLA" );
    
    status = sip_idle;
    
    __init_sock__ ();
    
    call = NULL;
    
    waiting = false;
    
    listen_SIP_server_return = 0;
    
    last_cseq = 0;
    
    sip_new_counter++;
}

Sip::~Sip ( void ) 
{
    __end_sock__ ();
    sip_delete_counter++;
}
 
int Sip::registry ( void )
{   
    build_registry_package ();
    
    int send = sock.sendTo ( sip_server, buffer, strlen ( buffer ) ); // > 400
    if ( send not_eq strlen ( buffer ) )
    {
        if ( debug_reconnect ) vz_debug ("[%d] Reconnect SIP -- Registry -- Sent %i of %i bytes", this->my_ext, send, strlen ( buffer ) );
        __reconnect__ ();
        miss_sip_registry_send_pkg ++;
    }

    if ( debug_sip ) vz_debug ("[%d %d] Registry -- Sent %i of %i bytes", 
                    this -> my_ext, this -> my_port, send, strlen ( buffer ) );
    
    return ( send ); 
}

VZ_call * Sip::invite ( void )
{
    if ( status == sip_on_call ) return call;
    
    else if ( status == sip_idle )
    {
        int cseq = 0;

        call = NULL;

        build_invite_package( &cseq );
        
        if ( debug_invite ) vz_debug ("cseq::%d", cseq );
        
        if ( drop_invite_to_ast_pkg )
        {
                vz_debug ("[%d] Droped invite pkg to ast", this->my_ext );
        }
            else
        {
            int send = sock.sendTo ( sip_server, buffer, strlen ( buffer ) );
            
            if ( send not_eq strlen ( buffer ) )
            {
                if ( debug_reconnect ) vz_debug ("[%d] Reconnect SIP -- Invite", this->my_ext );
                __reconnect__ ();
                miss_sip_invite_send_pkg++;
            }
         
            if ( debug_invite || debug_reconnect ) vz_debug ("[%d] Return value for invite pkg %d", this->my_ext, send );
        }
        
        invite_timer.stop ();
        invite_timer.reset ();
        invite_timer.start ();
        
        sip_set_status ( sip_waiting_trying );
        
        waiting = false;
    }
    
    if ( invite_timer.read () > INVITE_MAX_WAITING_TIME )
    {
        if ( debug_invite ) vz_debug ("[%d] Invite call timeout :(", this -> my_ext );
        invite_timer.stop ();
        invite_timer.reset ();
        sip_set_status ( sip_denied );
        send_bye ();
        
        call = NULL;
        return ( NULL );
    }
    
    if ( waiting == true ) { return call; }
    
    else return ( NULL );
}
 
char * Sip::build_registry_package ( void )
{
    char branch [ SIP_MAXMSGSIZE ];
    char tag [ SIP_MAXMSGSIZE ];
    char callid [ SIP_MAXMSGSIZE ];
    fill_random16h ( branch );
    fill_random ( tag, 18 );
    fill_random16h ( callid );
    
    snprintf( buffer, sizeof( buffer ) - 1, 
        "REGISTER sip:%s:%d SIP/2.0\r\nVia: SIP/2.0/UDP %s:%d;branch=%s\r\n"
        "From: %d <sip:%d@%s:%d>;tag=%s\r\n"
        "To: %d <sip:%d@%s:%d>\r\n"
        "Call-ID: %s\r\n"
        "CSeq: %d REGISTER\r\n"
        "Max-Forwards: 70\r\n"
        "Contact: %d <sip:%d@%s:%d>;expires=270\r\n"
        "User-Agent: VZtech/pabxdriver-%s\r\n"
        "Content-Length: 0\r\n"
        "%s\r\n\r\n",        
        server_ip, server_port, my_ip, my_port, branch,
        my_ext, my_ext, server_ip, server_port, tag,
        my_ext, my_ext, server_ip, server_port, 
        callid, 
        get_cseq(), 
        my_ext, my_ext, my_ip, my_port,
        SVNREV,
        SIP_ALLOW
    );
    return ( buffer );
}

char * Sip::build_invite_package ( int * cseq, const bool retry )
{
    char header [ SIP_MAXMSGSIZE ];
    char body [ SIP_MAXMSGSIZE ];
    char branch [ SIP_MAXMSGSIZE ];
    char tag [ SIP_MAXMSGSIZE ];
    char callid [ SIP_MAXMSGSIZE ];
    char callbox_string[ CALLBOX_STRING_SIZE ];
    
    int snprintf_ret = snprintf ( callbox_string, CALLBOX_STRING_SIZE - 1, "%i", this->my_ext );
    
    if ( snprintf_ret == CALLBOX_STRING_SIZE ) callbox_string [ CALLBOX_STRING_SIZE - 1 ] = '\0';
    
    if ( !retry )
    {
        *cseq = get_cseq ();
        last_cseq = *cseq;
        
        fill_random16h ( branch );
        strcpy ( last_branch, branch );
        
        fill_random ( tag, 18 );
        strcpy ( last_invite_tag, tag );
        
        fill_random16h ( callid );
        strcpy ( last_invite_callid, callid );
        
        this->my_rtp_port = fill_random_rtp_port ();
    }
        else
    {
        *cseq = last_cseq;
        
        strcpy ( branch, last_branch  );
        
        strcpy ( tag, last_invite_tag );
        
        strcpy ( callid, last_invite_callid );
    }
    
    if ( debug_invite ) vz_debug ("[%d] branch :: %s -- tag :: %s -- callid :: %s", this->my_ext, branch, tag, callid );
    
    if ( debug_rtp || debug_invite ) vz_debug ( "[%d] Invite PKG rtp port ( %d )", this->my_ext, this->my_rtp_port );

    snprintf( header, sizeof ( header ) -1,
        "INVITE sip:%i@%s:%i SIP/2.0\r\n"
        "Via: SIP/2.0/UDP %s:%i;branch=%s\r\n"
        "From: %s <sip:%i@%s:%i>;tag=%s\r\n"
        "To: <sip:%i@%s:%i>\r\n"
        "Call-ID: %s@%s\r\n"
        "CSeq: %i INVITE\r\n"
        "Contact: %i <sip:%i@%s:%i>\r\n"
        "Max-Forwards: 20\r\n"
        "User-Agent: VZtech/pabxdriver-%s\r\n"
        "Expires: 71\r\n"
        "%s\r\n"
        "Content-Type: application/sdp\r\n",
        this->peer_ext, this->server_ip, this->server_port, 
        this->my_ip, this->my_port, branch, 
        callbox_string, this->my_ext, this->server_ip, this->server_port, tag,
        this->peer_ext, this->server_ip, this->server_port, 
        callid, this->my_ip, 
        *cseq,
        this->my_ext, this->my_ext, this->my_ip, this->my_port, 
        SVNREV, 
        SIP_ALLOW
    );
    
    snprintf( body, sizeof ( body ) - 1,
        "v=0\r\no=- 7377 18176 IN IP4 %s\r\n"
        "s=-\r\n"
        "c=IN IP4 %s\r\n"
        "t=0 0\r\n"
        "i=UDP %i\r\n"
        "m=audio %i RTP/AVP 8 101\r\n"
        "a=rtpmap:8 PCMA/8000/1\r\n"
        "a=rtpmap:101 telephone-event/8000\r\n"
        "a=fmtp: 101 0-11",
        this->my_ip,
        this->my_ip,
        this->my_rtp_port,
        this->my_rtp_port
    );
    
    strcpy( this->buffer, header );
    
    char content_Length_msg [ CONTENT_LENGTH_MSG_SIZE ];
    
    snprintf_ret = snprintf ( content_Length_msg, CONTENT_LENGTH_MSG_SIZE, "Content-Length: %d\r\n\r\n", strlen ( body ) );
    if ( snprintf_ret == CONTENT_LENGTH_MSG_SIZE ) content_Length_msg [ CONTENT_LENGTH_MSG_SIZE - 1 ] = '\0';
    strcat( this->buffer, content_Length_msg );
    
    strcat( this->buffer, body );
    
    if ( debug_invite ) vz_debug ("[%d] strlen( header [%d] ) | strlen( body [%d] ) | ( h + b [%d])", this->my_ext, strlen( header ),strlen( body ), strlen( header ) + strlen( body ) );
    
    return( this->buffer );
}
 
char * Sip::build_bye_package ( void )
{
    char branch [ SIP_MAXMSGSIZE ];
    char tag [ SIP_MAXMSGSIZE ];
    fill_random16h ( branch );
    fill_random (tag,18 );
    
    snprintf(
        this -> buffer, sizeof ( this -> buffer ) - 1,
        "BYE sip:%i@%s:%i SIP/2.0\r\n"
        "Via: SIP/2.0/UDP %s:%i;branch=%s\r\n"
        "From: %i <sip:%i@%s:%i>;tag=%s\r\n"
        "To: <sip:%i@%s:%i>;tag=%s\r\n"    
        "Call-ID: %s@%s\r\n"
        "CSeq: %i BYE\r\n"
        "Max-Forwards: 70\r\n"
        "User-Agent: VZtech/pabxdriver-%s\r\n"
        "Content-Length: 0\r\n\r\n",        
        this->peer_ext, this->server_ip, this->server_port, 
        this->my_ip, this->my_port, branch, 
        this->my_ext, this->my_ext, this->server_ip, this->server_port, last_invite_tag, 
        this->peer_ext, this->server_ip, this->server_port, tag, 
        last_invite_callid, this->my_ip,
        get_cseq(),
        SVNREV
    );
    
    return( buffer );
}
char * Sip::build_ack_package ( void )
{
    if ( this -> buffer not_eq NULL )
    {   
        char to [ SIP_MAXMSGSIZE ];
        char from [ SIP_MAXMSGSIZE ];
        char callid [ SIP_MAXMSGSIZE ];
        char branch [ SIP_MAXMSGSIZE ];
        char cseq [ SIP_MAXMSGSIZE ];
        
        if( decode_gettag( ( const unsigned char * ) this -> buffer, "to: ", to ) == 0) {
            buffer[ 0 ] = 0;
            return NULL;
        }
        if( decode_gettag( ( const unsigned char * ) this -> buffer, "from: ", from ) == 0) {
            buffer[ 0 ] = 0;
            return NULL;
        }
        if( decode_gettag( ( const unsigned char * ) this -> buffer, "call-id: ", callid ) == 0) {
            buffer[ 0 ] = 0;
            return NULL;
        }
        
        decode_branch ( ( const unsigned char * ) this -> buffer, branch );
        decode_cseq ( ( const unsigned char * ) this -> buffer, cseq );
        
        snprintf ( buffer, sizeof ( buffer ) - 1,
            "ACK sip:%i@%s:%i SIP/2.0\r\n"
            "Via: SIP/2.0/UDP %s:%i;branch=%s\r\n"
            "From: %s\r\n"
            "To: %s\r\n"
            "Call-ID: %s\r\n"
            "CSeq: %s ACK\r\n"
            "Max-Forwards: 70\r\n"
            "Contact: %i <sip:%i@%s:%i>\r\n"
            "User-Agent: VZtech/pabxdriver-%s\r\n"
            "Content-Length: 0\r\n\r\n",         
            this -> peer_ext, this -> server_ip, this -> server_port, 
            this -> my_ip, this -> my_port, branch,
            from, 
            to, 
            callid, 
            cseq, 
            this -> my_ext, this -> my_ext, this -> my_ip, this -> my_port,
            SVNREV 
        );
        
        return( buffer );
    }
        else
    {
        return ( NULL );    
    }
}

char * Sip::build_reply_package ( void )
{
    char to [ SIP_MAXMSGSIZE ];
    char from [ SIP_MAXMSGSIZE ];
    char callid [ SIP_MAXMSGSIZE ];
    char cseq [ SIP_MAXMSGSIZE ];
    char via [ SIP_MAXMSGSIZE ];
    char tag [ SIP_MAXMSGSIZE ];
 
    if( decode_gettag( ( const unsigned char * ) buffer, "to: ", to ) == 0) {
        buffer[ 0 ] = 0;
        return NULL;
    }
    if( decode_gettag( ( const unsigned char * ) buffer, "from: ", from ) == 0) {
        buffer[ 0 ] = 0;
        return NULL;
    }
    if( decode_gettag( ( const unsigned char * ) buffer, "call-id: ", callid ) == 0 ) {
        buffer[ 0 ] = 0;
        return NULL;
    }
    if( decode_gettag( ( const unsigned char * ) buffer, "cseq: ", cseq) == 0 ) {
        buffer[ 0 ] = 0;
        return NULL;
    }
    if( decode_gettag( ( const unsigned char * ) buffer, "via: ", via) == 0 ) {
        buffer[ 0 ] = 0;
        return NULL;
    }
 
    if (strlen(via) > 6) {
        if (strcasecmp(";rport",via+strlen(via)-6)==0) {
            via[strlen(via)-6] = 0;
        }
    }
    
    fill_random ( tag, 18 );
    
    snprintf(
        buffer, sizeof ( buffer ) - 1,
        "SIP/2.0 200 OK\r\n"    
        "To: %s;tag=%s\r\n"
        "From: %s\r\n"
        "Call-ID: %s\r\n"
        "CSeq: %s\r\n"
        "Via: %s\r\n"
        "Server: VZtech/pabxdriver-%s\r\n"
        "Content-Length: 0\r\n"
        "%s\r\n\r\n",
        to, tag, 
        from, 
        callid,
        cseq,
        via,
        SVNREV,
        SIP_ALLOW
    );
    
    return( buffer );
}

char * Sip::fill_random16h ( char * buffer )
{
    fill_random( buffer, 16 );
    buffer[ 7 ] = '-';
    return( buffer );
}
 
char * Sip::fill_random ( char * buffer, const int size )
{
    static uint16_t seed = time( NULL );
    seed += 1;
    srand( seed );
 
    for( int i = 0; i < size - 1; i++ )
    {
        buffer[ i ] = fill_random_aux[ rand() & 0x3f ];
    }
    
    buffer[ size - 1 ] = 0;
    return( buffer );
}
 
int Sip::get_cseq ( void )
{
    static unsigned int cseq = 0;
    if( cseq == 0 )
    {
        /* initial value, random number */
        cseq = rand ();
        cseq &= 0x7fff;
    }
    cseq++;
    cseq &= 0x7fff;
    if ( cseq == 0 ) cseq++;
    return cseq;
}
 
char * Sip::decode_cseq ( const unsigned char * package, char * cseq )
{
    char pkg [ SIP_MAXMSGSIZE ];
    
    if( decode_gettag ( package, "cseq: ", pkg ) != 0)
    {
        char cs [ SIP_MAXMSGSIZE ];
        
        int i = 0;
        strcpy ( cs, pkg );
        while ( ( cs [ i ] != 0 ) && ( cs [ i ] != ' ' ) ) i++;
        cs [ i ] = 0;
        strcpy ( cseq, cs );
    } else {
        cseq [ 0 ] = 0;
    }
    return ( cseq );
}
 
char * Sip::decode_branch ( const unsigned char * package, char * branch )
{
    char pkg [ SIP_MAXMSGSIZE ];
    
    if ( decode_gettag ( package, "branch=", pkg ) != 0 )
    {
        int i = 0;
        strcpy ( branch, pkg );
        while ( ( branch [ i ] != 0 ) && ( branch [ i ] != ';' ) ) i++;
        branch [ i ] = 0;
    } else {
        branch [ 0 ] = 0;
    }
    
    return ( branch );
}

int Sip::decode_gettag ( const unsigned char * package, const char * tag, char * out )
{
    int cmpsize = strlen ( tag );
    int size = strlen ( ( char * ) package ) - cmpsize;
    
    for ( int i = 0; i < size; i++ )
    {
        if ( strncasecmp( tag, ( char * ) package + i, cmpsize ) == 0 )
        {
            char * s;
            s = ( char * ) package + i + cmpsize;
            register int j = 0;
            while ( ( s [ j ] != '\r' ) && ( s [ j ] != '\n' ) ) j++;
            strncpy ( out, s, j ); // copy string to output
            out [ j ] = 0; // terminate string
            return 1; // found
        }
    }
    
    return 0; // not found
}

int Sip::fill_random_rtp_port ( void )
{
    static uint16_t port = 0;
    port += 2;
    port &= 0x7fe; // 0 to 2046, always even
    return port + 16384;
}

void Sip::set_server_port ( const int new_server_port ) { this->server_port = new_server_port; }

void Sip::set_server_ext ( const int new_server_ext ) { this->peer_ext = new_server_ext; }

void Sip::set_server_ip ( const char * new_server_ip )
{
    strncpy( this->server_ip, new_server_ip, 20 );
    this->server_ip[19] = 0;
}

/*  Retorna 
    = 0 :: ok
    < 0 :: tive problemas
    > 0 :: devo remover essa call do vetor de calls 
*/
int Sip::listen_SIP_server ( void )
{
    int ret = listen_SIP_server_return;
    listen_SIP_server_return = 0;
    return ret;
}

void Sip::set_port ( const int port ) { my_port = port; }

void Sip::send_bye ( void )
{
    build_bye_package ();
    
    int send = sock.sendTo ( sip_server, this -> buffer, strlen( this -> buffer ) );
    
    // antigo if ( debug_sip ) vz_debug ( "[%d] sizeof( bye pkg ) :: %d", this -> my_ext, strlen ( this -> buffer ) );
    if ( debug_invite ) vz_debug ( "[%d] sizeof( bye pkg ) :: %d", this -> my_ext, strlen ( this -> buffer ) );
    
    if ( send not_eq strlen ( this->buffer ) )
    {
        if ( debug_reconnect ) vz_debug ("[%d] Reconnect SIP -- BYE, %d, %d", this -> my_ext, send, strlen ( this -> buffer ) );
        __reconnect__ ();
        miss_sip_bye_send_pkg ++;
    }
}

int Sip::get_status ( void ) { return this->status; }

void Sip::sip_set_status ( const uint8_t status ) { this->status = status; }

int Sip::get_socket_fd ( void ) { return sock.get_fd (); }

int Sip::udp_incomming_pkg ( void )
{
    Endpoint from;  
    
    int length = sock.receiveFrom ( from, buffer, sizeof( buffer ) );
    
    if ( memcmp( ( ( u8_t * )( &(from._remoteHost) ) ) + 2, ( ( u8_t * )( &(sip_server._remoteHost) ) ) + 2, 6 ) != 0 ) return 0;
    
    if ( length == -1 )
    {
        if ( debug_reconnect ) vz_debug ("[%d] Reconnect SIP -- UDP Incomming", get_ext () );
        __reconnect__ ();
        miss_sip_inc_pkg ++;
    }
    
    if ( length > 0 )
    {
        if ( sizeof( buffer ) > length ) buffer[ length ] = 0;
        
        int sip_response = -1;
        
        // faster than atoi() (: 
        if ( buffer[ 7 ] == ' ' || buffer[ 11 ] == ' ' ){
            sip_response = ( buffer[ 8 ] - '0' ) * 100 + ( buffer[ 9 ] - '0' ) * 10 + ( buffer[ 10 ] - '0' );
        }
        
        if ( ( status == sip_trying ) || ( status == sip_ringing ) || ( status == sip_waiting_trying ) || ( status == sip_on_call ) )
        { 
            if ( sip_response == 200 ){ // Ok    
                char *ref = strstr( buffer, "audio" );
                
                if ( debug_invite ) vz_debug ("[%d] udp_incomming_pkg -- ok", this->my_ext );
                
                if ( ref != NULL )
                {
                    if ( drop_this_amount_of_ack_to_ast ) drop_this_amount_of_ack_to_ast--;
                        
                    if ( drop_this_amount_of_ack_to_ast )
                    {
                        vz_debug ("[%d] Droped ok pkg received from ast (%d)", this->my_ext, drop_this_amount_of_ack_to_ast );
                        return -71;    
                    }
                                        
                    ref += 6; // audio 
                    ref = strtok( ref, " ");
                    if ( call == NULL ){
                        call = new VZ_call ( this->my_ext, this->my_rtp_port, this->peer_ext, atoi( ref ) );
                        if ( debug_alloc_vz_call ) vz_debug ( "VZ_Call :: %p", call );
                        if ( debug_rtp ) vz_debug ("[%d] Ok new call ( %d, %d, %d, %d ( %s ) ) ", this->my_ext, this->my_ext, this->my_rtp_port, this->peer_ext, atoi( ref ), ref );
                        if ( call == NULL ) memory_is_over = true;
                    }
            
                    build_ack_package ();
                    
                    int send = 0;
                    
                    if ( drop_ack_pkg )
                    {
                        vz_debug ("[%d] Droped ack pkt to ast", this->my_ext );
                    }
                        else
                    {
                        send = sock.sendTo ( sip_server, this -> buffer, strlen ( this -> buffer ) );
                    
                        if ( send not_eq strlen( this -> buffer ) )
                        {
                            if ( debug_reconnect ) vz_debug ("[%d] Reconnect SIP -- Ok -- Call mode on", this->my_ext );
                            __reconnect__ ();
                            miss_sip_ok_send_pkg ++;
                        }
                    }
                    
                    if ( debug_invite ) vz_debug ("[%d] Call alocada -- sizeof( ack ) :: %d - strlen( this -> buffer ):: %d", this->my_ext, send, strlen( this -> buffer ) );
                    sip_set_status ( sip_on_call );
                }
            }
        }
        if ( ( status == sip_trying ) || ( status == sip_ringing ) )
        {
            if ( sip_response >= 400 && sip_response < 700 )
            {
                if ( debug_invite ) { 
                    buffer [ 11 ] = 0; 
                    if ( debug_invite ) vz_debug ("[%d] Busy Here :: %s", this -> my_ext, buffer + 8 );
                }
                send_bye ();
                sip_set_status ( sip_busy );
                return ( NULL );  
            }
                else if ( sip_response == 183 ) // Session in Progress
            {
                char *ref = strstr ( buffer, "audio" );
                if ( ref != NULL )
                {
                    ref += 6; // strlen( "audio" ) == 6
                    ref = strtok( ref, " ");
                    if ( call == NULL )
                    {
                        this->call = new VZ_call ( this->my_ext, this->my_rtp_port, this->peer_ext, atoi( ref ) );
                        if ( debug_alloc_vz_call ) vz_debug ( "VZ_Call :: %p", this->call );
                        if ( debug_rtp ) vz_debug ("[%d] Session in Progress ( %d, %d, %d, %d ( %s ) ) ",this->my_ext, this->my_ext, this->my_rtp_port, this->peer_ext, atoi( ref ), ref );
                        if ( call == NULL ) memory_is_over = true;
                    }
                    waiting = true;
                }
            }
        }
        
        if ( status == sip_trying ){
            if ( sip_response == 180 ){
                if ( debug_invite ) vz_debug ("[%d] ringing", this->my_ext );
                sip_set_status ( sip_ringing );
            }
        }
        
        if ( status == sip_waiting_trying ){
            if ( sip_response == 100 ){
                if ( debug_invite ) vz_debug ("[%d] trying", this->my_ext )
                sip_set_status ( sip_trying );
            }
        }
        
        if ( status == sip_on_call )
        {
            if ( !( strncasecmp( buffer, "bye ", 4 ) ) )
            {   
                build_reply_package ();
                
                int send = sock.sendTo ( sip_server, this -> buffer, strlen ( this -> buffer ) );
                if ( send not_eq strlen ( this -> buffer ) )
                {
                    if ( debug_reconnect ) vz_debug (""
                        "[%d] Reconnect SIP -- RCV BYE from * -- ( expected, realized ) ( %d, %d )", 
                        this -> my_ext, strlen ( this -> buffer ), send 
                    );
                    
                    __reconnect__ ();
                    miss_sip_rcv_bye_send_pkg ++;
                }
                
                if ( debug_invite ) vz_debug (""
                    "[%d] Bye request received from * - sizeof ( bye reply pkg ) :: %d", 
                    this -> my_ext, strlen ( this -> buffer ) 
                );
                
                set_sip_rtp_port ( 0 );
                
                listen_SIP_server_return = my_ext;
            }
        }
    }
    
    return length;
}

void Sip::reset_call ( void ) { if( call != NULL ) call = NULL; }

int Sip::get_ext ( void ) { return my_ext; }

int Sip::get_port ( void ) { return my_port; }

int Sip::get_sip_rtp_port ( void ) { return my_rtp_port; }

void Sip::set_sip_rtp_port ( const int new_my_rtp_port )
{ 
    this->my_rtp_port = new_my_rtp_port; 
    if ( debug_rtp ) vz_debug ( "[%d] this->my_rtp_port ( %d ) = new_my_rtp_port( %d )", this->my_ext, this->my_rtp_port, new_my_rtp_port );
}

int Sip::print_yourself ( void )
{
    vz_printf ("\r\n");
    vz_printf ("Values ::\r\n");
    vz_printf ("server_ip :: %s", server_ip );
    vz_printf ("server_port :: %d", server_port );
    vz_printf ("my_ip :: %s", my_ip );
    vz_printf ("my_port :: %d", my_port );
    vz_printf ("my_ext :: %d", my_ext );
    vz_printf ("my_rtp_port :: %d", my_rtp_port );
    vz_printf ("my_display :: %s", my_display );
    vz_printf ("peer_ext :: %d", peer_ext );
    vz_printf ("fill_random_aux :: %s", fill_random_aux );
    vz_printf ("last_invite_tag :: %s", last_invite_tag );
    vz_printf ("last_invite_callid :: %s", last_invite_callid );
    vz_printf ("SVNREV :: %s", SVNREV );
    vz_printf ("char buffer[ 1024 ] :: %p", ( void * ) buffer );
    
    //FIXME esse tipo de tag existe como metalinguagem ???
    //TOTHINK o que fazer pra entender melhor o estado dos sockets
    vz_printf ("UDPSocket sock :: %p", ( void * ) &sock );
    vz_printf ("Endpoint sip_server :: %p", ( void * ) &sip_server );
    
    vz_printf ("call :: %p", ( void * ) call );
    vz_printf ("invite_timer :: %d", ( int ) invite_timer.read () );
    vz_printf ("waiting ::  %s", ( waiting ) ? "true" : "false" );
    vz_printf ("listen_SIP_server_return :: %d", listen_SIP_server_return );
    vz_printf ("\r\n");

    return ( sizeof( Sip ) );    
}

int Sip::retry_send_last_invite_pkg_to_ast ( void )
{
    char callbox_string [ 32 ];
    snprintf ( callbox_string, sizeof ( callbox_string ) -1, "%i", my_ext );
    
    int cseq = 0;

    call = NULL;

    build_invite_package ( &cseq, true );
    
    if ( debug_invite ) vz_debug ("cseq::%d", cseq );
    
    int send = 0;
    
    if ( drop_invite_to_ast_pkg )
    {
            vz_debug ("[%d] Droped invite pkg to ast", this->my_ext );
    }
        else
    {
        
        send = sock.sendTo ( sip_server, buffer, strlen ( buffer ) );
        
        if ( send not_eq strlen ( buffer ) )
        {
            if ( debug_reconnect ) vz_debug ("[%d] Reconnect SIP -- Invite", this->my_ext );
            __reconnect__ ();
            miss_sip_invite_send_pkg ++;
        }
     
        if ( debug_invite || debug_reconnect ) vz_debug ("[%d] Return value for invite pkg %d", this->my_ext, send );
    }
    
    return ( send );
}

void Sip::update ( void )
{
    cm -> get_server_ip ( this -> server_ip );
    
    this -> server_port = cm -> get_server_port ();
    
    cm -> get_header_ip ( this -> my_ip );
    
    this -> peer_ext = cm -> get_server_ext ();
    
    sip_server.set_address ( this -> server_ip , this -> server_port );
    
    __reconnect__ ();
}