voltando a versao de n aberturas e fechamentos de sockets data 19/09

Dependencies:   EthernetInterface NTPClient mbed-rtos mbed EALib

Fork of header_main_publish by VZTECH

Revision:
0:4d17cd9c8f9d
Child:
1:a1758104fa1d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sip.cpp	Tue Sep 09 20:01:24 2014 +0000
@@ -0,0 +1,1069 @@
+#include "sip.h"
+#include "utils.h"
+
+void Sip::__init_sock__( void ){
+    sip_server.set_address( this->server_ip , this->server_port );
+    sock.set_blocking( false, 1 ); // verificar isso com mais cuidado depois
+    sock.bind( this->my_port );
+    sock.init();
+}
+
+void Sip::__end_sock__(){
+    sock.close(); 
+}
+
+Sip::Sip( char * server_ip, int server_port, char * my_ip, int my_port, int my_ext, int peer_ext, int id ){
+    this->id = id;
+    strncpy( this->server_ip, server_ip, 20 );
+    this->server_ip[19] = 0;
+    this->server_port = server_port;
+    strncpy( this->my_ip, my_ip, 20 );
+    this->my_ip[19] = 0;
+    this->my_port = my_port;
+    this->my_rtp_port = fill_random_rtp_port();
+    this->my_ext = my_ext;
+    itoa( this->my_ext, this->my_display, 10 );
+    this->peer_ext = peer_ext;
+ 
+    strcpy( this->fill_random_aux, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789pP" );
+    strcpy( this->last_invite_tag, "" );
+    strcpy( this->last_invite_callid, "");
+    strcpy( this->SVNREV, "COLA" );
+    status = sip_idle;
+    
+    __init_sock__();
+}
+ 
+Sip::Sip(){
+    this->id = __MY_EXT__;
+    strncpy( this->server_ip, __SEVER_IP__, 20 );
+    this->server_ip[19] = 0;
+    this->server_port = __SERVER_PORT__;
+    strncpy( this->my_ip, __MY_IP__, 20 );
+    this->my_ip[19] = 0;
+    this->my_port = __MY_PORT__;
+    this->my_rtp_port = fill_random_rtp_port();
+    this->my_ext = __MY_EXT__;
+    itoa( this->my_ext, this->my_display, 10 );
+    this->peer_ext = __PEER_EXT__;
+ 
+    strcpy( this->fill_random_aux, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789pP" );
+    strcpy( this->last_invite_tag, "" );
+    strcpy( this->last_invite_callid, "");
+    strcpy( this->SVNREV, "COLA" );
+    status = sip_idle;
+    
+    __init_sock__();
+}
+ 
+Sip::Sip( int id, uint16_t my_port ){
+    this->id = id;
+    strncpy( this->server_ip, __SEVER_IP__, 20 );
+    this->server_ip[19] = 0;
+    this->server_port = __SERVER_PORT__;
+    strncpy( this->my_ip, __MY_IP__, 20 );
+    this->my_ip[19] = 0;
+    this->my_port = my_port;
+    this->my_rtp_port = fill_random_rtp_port();
+    this->my_ext = id;
+    itoa( this->my_ext, this->my_display, 10 );
+    this->peer_ext = __PEER_EXT__;
+ 
+    strcpy( this->fill_random_aux, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789pP" );
+    strcpy( this->last_invite_tag, "" );
+    strcpy( this->last_invite_callid, "");
+    strcpy( this->SVNREV, "COLA" );
+    status = sip_idle;
+    
+    __init_sock__();
+}
+ 
+Sip::Sip( int id, uint16_t my_port, int dest_ext  ){
+    this->id = id;
+    strncpy( this->server_ip, __SEVER_IP__, 20 );
+    this->server_ip[19] = 0;
+    this->server_port = __SERVER_PORT__;
+    strncpy( this->my_ip, __MY_IP__, 20 );
+    this->my_ip[19] = 0;
+    this->my_port = my_port;
+    this->my_rtp_port = fill_random_rtp_port();
+    this->my_ext = id;
+    itoa( this->my_ext, this->my_display, 10 );
+    this->peer_ext = dest_ext;
+ 
+    strcpy( this->fill_random_aux, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789pP" );
+    strcpy( this->last_invite_tag, "" );
+    strcpy( this->last_invite_callid, "");
+    strcpy( this->SVNREV, "COLA" );
+    status = sip_idle;
+    
+    __init_sock__();
+}
+ 
+Sip::~Sip(){
+    __end_sock__();
+}
+ 
+void Sip::registry(){
+    char out[ 1000 ];
+    build_registry_package( buffer );
+    sock.sendTo( sip_server, buffer, sizeof( buffer ) );
+    sock.receiveFrom( sip_server, buffer, sizeof( buffer ) );
+    if( decode_gettag( (unsigned char *)buffer, "cseq: ", out ) ){
+        if(strlen( out ) > 7){
+            if(strcasecmp("options",out+strlen(out)-7) == 0){
+                char ans[ 2000 ];
+                build_reply_package( ans, (unsigned char*)buffer );
+                sock.sendTo( sip_server, ans, sizeof( ans ) );
+            }
+        }
+    }
+}
+
+VZ_call * Sip::old_invite(){
+    Timer t;
+    char buffer[ 1024 ];
+    char callbox_string[ 32 ];
+    itoa( get_id(), callbox_string, 10 );
+    int cseq;
+ 
+    build_invite_package( buffer, callbox_string, &cseq );
+    sock.sendTo( sip_server, buffer, sizeof( buffer ) );
+ 
+    t.start();
+    while( sock.receiveFrom( sip_server, buffer, sizeof( buffer ) ) < 1 ) {
+        if( t.read() > __INVITE_MAX_WAITING_TIME__ ) { /* Trying package */
+            change_sip_server();
+            t.reset();
+            break;
+        }
+    }
+    while( sock.receiveFrom( sip_server, buffer, sizeof( buffer ) ) < 1 ) {
+        if( t.read() > __INVITE_MAX_WAITING_TIME__ ) { /* Ringing package */
+            change_sip_server();
+            t.reset();
+            break;
+        }
+    }
+    int call_trying = 1;
+    while( call_trying-- ){
+        while( sock.receiveFrom( sip_server, buffer, sizeof( buffer ) ) < 1 ) {
+            if( t.read() > __INVITE_MAX_WAITING_TIME__ ) { /* ok package */
+                change_sip_server();
+                t.reset();
+                break;
+            }
+        }
+        wait( 3 );
+        char * ref = strstr( buffer, "audio" );
+        if( ref != NULL ){
+            ref += 6; /*audio */
+            ref = strtok( ref, " ");
+            VZ_call * call = new VZ_call( this->my_ext, this->my_rtp_port, this->peer_ext, atoi( ref ) );
+            char ans[ 1024 ];
+            build_ack_package( ans, ( unsigned char *)buffer );
+            sock.sendTo( sip_server, ans, sizeof( ans ) );
+            
+            return( call );
+        }
+    }
+    return( NULL );
+}
+
+VZ_call * Sip::invite(){
+    Timer t;
+    char callbox_string[ 32 ];
+    itoa( get_id(), callbox_string, 10 );
+ 
+    if( status != sip_on_call ) set_status(status, sip_waiting_trying );
+    
+    else return( NULL );
+    
+    int cseq = 0;
+ 
+    build_invite_package( buffer, callbox_string, &cseq );
+    sock.sendTo( sip_server, buffer, sizeof( buffer ) );
+ 
+    debug_msg( "Inicio do invite" );
+    debug_msg( "Sip::status::%d", status );
+    t.start();
+
+    sock.set_blocking( false, 5 );
+    
+    char buffer_eth_invite[ 1024 ];
+    int loop_times = 0;
+    int received_loop_times = 0;
+    Timer reconnect;
+    reconnect.start();
+    static int id_ = 0;
+    int length = 0;
+    bool print = false;
+    while( t.read() < __INVITE_MAX_WAITING_TIME__ ){    
+        loop_times++;        
+        length = sock.receiveFrom( sip_server, buffer_eth_invite, sizeof( buffer_eth_invite ) );
+        if( length > 0 ){
+            reconnect.reset();
+            debug_msg("Pacotes recebidos :: %d", id_ );
+            buffer_eth_invite[ length ] = 0;
+            debug_msg("-- %d :: %s --", id_++, buffer_eth_invite );
+            received_loop_times++;
+            if( ( status == sip_trying ) || ( status == sip_ringing ) ){            
+                if( !( strncasecmp( buffer_eth_invite + 12, "ok", strlen("ok") ) ) ){
+                    // tratar depois o esquema do Cseq ::
+                    debug_msg( "Cseq == %d", cseq );
+                    set_status(status, sip_on_call);
+                    char *ref = strstr( buffer_eth_invite, "audio" );
+                    debug_msg("ok");
+                    if( ref != NULL ){
+                        ref += 6; // audio 
+                        ref = strtok( ref, " ");
+                        VZ_call * call = new VZ_call( this->my_ext, this->my_rtp_port, this->peer_ext, atoi( ref ) );
+                        char ans[ 1024 ];
+                        build_ack_package( ans, ( unsigned char *)buffer_eth_invite );
+                        sock.sendTo( sip_server, ans, sizeof( ans ) );
+                        
+                        debug_msg("Call nao alocada -- Sip::status::%d -- loop_times :: %d :: received_loop_times :: %d", status, loop_times, received_loop_times );
+                        set_status( status, sip_on_call );
+                        return( call );
+                        
+                    }
+                }
+            }
+            if( status == sip_trying ){
+                if( !( strncasecmp( buffer_eth_invite + 12, "ringing", strlen("ringing") ) ) ){
+                    debug_msg("ringing");
+                    t.reset();
+                    set_status( status, sip_ringing );
+                }
+            }
+            if( status == sip_waiting_trying ){
+                if( !( strncasecmp( buffer_eth_invite + 12, "trying", strlen("trying") ) ) ){
+                    debug_msg("trying")
+                    t.reset();
+                    set_status( status, sip_trying );
+                }
+            }
+        }else if( reconnect.read() > 4 ){
+            sock.close();
+            sock.bind( this->my_port );
+            sock.init();
+            sock.set_blocking( false, 1 );
+            debug_msg("Reconnect");
+            reconnect.reset();
+            //sock.sendTo( sip_server, buffer, sizeof( buffer ) );
+            led4 = !led4;
+            print = true;
+        }
+        if( print ) debug_msg( "Lidos : %d --", length );
+    }
+    
+    debug_msg("Call nao alocada -- Sip::status::%d -- loop_times :: %d :: received_loop_times :: %d", status, loop_times, received_loop_times );
+    if( t.read() > __INVITE_MAX_WAITING_TIME__ ){
+        set_status(status, sip_denied);
+    }
+    return( NULL );
+}
+ 
+char * Sip::build_registry_package( char * buffer ){
+    char branch[ SIP_MAXFIELDSIZE ];
+    char tag[ SIP_MAXFIELDSIZE ];
+    char callid[ SIP_MAXFIELDSIZE ];
+    fill_random16h( branch );
+    fill_random( tag, 18 );
+    fill_random16h( callid );
+    char itoa_buffer[ 65 ];
+    strcpy( buffer, "REGISTER sip:" );
+    strcat( buffer, server_ip );
+    strcat( buffer, ":" );
+    itoa( server_port, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, " SIP/2.0\r\nVia: SIP/2.0/UDP " );
+    strcat( buffer, my_ip );
+    strcat( buffer, ":" );
+    itoa( my_port, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, ";branch=" );
+    strcat( buffer, branch );
+    strcat( buffer, "\r\nFrom: " );
+    itoa( my_ext, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, " <sip:" );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, "@" ); 
+    strcat( buffer, server_ip );
+    strcat( buffer, ":" );
+    itoa( server_port, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, ">;tag=" );
+    strcat( buffer, tag );
+    strcat( buffer, "\r\nTo: " );
+    itoa( my_ext, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, " <sip:" );
+    itoa( my_ext, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, "@" );
+    strcat( buffer, server_ip );
+    strcat( buffer, ":" );
+    itoa( server_port, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, ">\r\nCall-ID: " );
+    strcat( buffer, callid );
+    strcat( buffer, "\r\nCSeq: " );
+    itoa( get_cseq(), itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, " REGISTER\r\n" );
+    strcat( buffer, "Max-Forwards: " );
+    itoa( 70, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, "\r\n" );
+    
+    strcat( buffer, "Contact: " );
+    itoa( my_ext, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, " <sip:" );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, "@" );
+    strcat( buffer, my_ip );
+    strcat( buffer, ":" );
+    itoa( server_port, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, ">;expires=120" );
+    //itoa( 1200, itoa_buffer, 10 );
+    //strcat( buffer, itoa_buffer );
+    strcat( buffer, "\r\n" );
+    
+    strcat( buffer, "User-Agent: VZtech/pabxdriver-" );
+    strcat( buffer, SVNREV );
+    strcat( buffer, "\r\nContent-Length: 0\r\n" );
+    strcat( buffer, SIP_ALLOW );
+    strcat( buffer, "\r\n\r\n" );              
+    buffer[ SIP_MAXMSGSIZE - 1 ] = 0;
+    return buffer;
+}
+ 
+char * Sip::build_invite_package( char * pkg, char * callbox_string, int * cseq ){
+    char header[ SIP_MAXMSGSIZE ], body[ SIP_MAXMSGSIZE ];
+    char branch[ SIP_MAXFIELDSIZE ];
+    char tag[ SIP_MAXFIELDSIZE ];
+    char callid[ SIP_MAXFIELDSIZE ];
+    char itoa_buffer[ 65 ];
+    *cseq = get_cseq();
+    fill_random16h( branch );
+    fill_random( tag,18 );
+    fill_random16h( callid );
+ 
+    strcpy( last_invite_tag,tag );
+    strcpy( last_invite_callid, callid );
+    
+    strcpy( header, "INVITE sip:" );
+    itoa( this->peer_ext, itoa_buffer, 10 );
+    strcat( header, itoa_buffer );
+    strcat( header, "@" );
+    strcat( header, this->server_ip );
+    strcat( header, ":" );
+    itoa( this->server_port, itoa_buffer, 10 );
+    strcat( header, itoa_buffer );
+    strcat( header, " SIP/" );
+    itoa( 2, itoa_buffer, 10 );
+    strcat( header, itoa_buffer );
+    strcat( header, "." );
+    itoa( 0, itoa_buffer, 10 );
+    strcat( header, itoa_buffer );
+    strcat( header, "\r\n" );
+    strcat( header, "Via: SIP/" );
+    itoa( 2, itoa_buffer, 10 );
+    strcat( header, itoa_buffer );
+    strcat( header, "." );
+    itoa( 0, itoa_buffer, 10 );
+    strcat( header, itoa_buffer );
+    strcat( header, "/UDP"  );
+    strcat( header, this->my_ip );
+    strcat( header, ":" );
+    itoa( this->my_port, itoa_buffer, 10 );
+    strcat( header, itoa_buffer );
+    strcat( header, ";branch="  );
+    strcat( header, branch );
+    strcat( header, "\r\n" );
+    strcat( header, "From: " );
+    strcat( header, callbox_string );
+    strcat( header, " <sip:" );
+    itoa( this->my_ext, itoa_buffer, 10 );
+    strcat( header, itoa_buffer );
+    strcat( header, "@" );
+    strcat( header, this->server_ip );
+    strcat( header, ":" );
+    itoa( this->server_port, itoa_buffer, 10 );
+    strcat( header, itoa_buffer );
+    strcat( header, ">;tag=" );
+    strcat( header, tag );
+    strcat( header, "\r\n" );
+    strcat( header, "To: <sip:" );
+    itoa( this->peer_ext, itoa_buffer, 10 );
+    strcat( header, itoa_buffer );
+    strcat( header, "@" );
+    strcat( header, this->server_ip );
+    strcat( header, ":" );
+    itoa( this->server_port, itoa_buffer, 10 );
+    strcat( header, itoa_buffer );
+    strcat( header, ">\r\n" );
+    strcat( header, "Call-ID: " );
+    strcat( header, callid );
+    strcat( header, "@" );
+    strcat( header, this->my_ip );
+    strcat( header, "\r\n" );
+    strcat( header, "CSeq: " );
+    itoa( *cseq, itoa_buffer, 10 );
+    strcat( header, itoa_buffer );
+    strcat( header, " INVITE\r\n" );
+    strcat( header, "Contact: " );
+    itoa( this->my_ext, itoa_buffer, 10 );
+    strcat( header, itoa_buffer );
+    strcat( header, " <sip:" );
+    itoa( this->my_ext, itoa_buffer, 10 );
+    strcat( header, itoa_buffer );
+    strcat( header, "@" );
+    strcat( header, this->my_ip );
+    strcat( header, ":" );
+    itoa( this->my_port, itoa_buffer, 10 );
+    strcat( header, itoa_buffer );
+    strcat( header, ">\r\n" );
+    strcat( header, "Max-Forwards: " );
+    itoa( 20, itoa_buffer, 10 );
+    strcat( header, itoa_buffer );
+    strcat( header, "\r\n" );
+    strcat( header, "User-Agent: VZtech/pabxdriver-" );
+    strcat( header, SVNREV );
+    strcat( header, "\r\n" );
+    strcat( header, "Expires: " );
+    itoa( 70, itoa_buffer, 10 );
+    strcat( header, itoa_buffer );
+    strcat( header, "\r\n" );
+    strcat( header, SIP_ALLOW );
+    strcat( header, "\r\n" );
+    strcat( header, "Content-Type: application/sdp\r\n" );
+    header[ SIP_MAXMSGSIZE - 1 ] = 0;
+    
+    strcpy( body, "v=0\r\n" );
+    strcat( body, "o=- " );
+    itoa( 7377, itoa_buffer, 10 );
+    strcat( body, itoa_buffer );
+    strcat( body, " " );
+    itoa( 18176, itoa_buffer, 10 );
+    strcat( body, itoa_buffer );
+    strcat( body, " IN IP" );
+    itoa( 4, itoa_buffer, 10 );
+    strcat( body, itoa_buffer );
+    strcat( body, " " );
+    strcat( body, this->my_ip );
+    strcat( body, "\r\n" );
+    strcat( body, "s=-\r\n" );
+    strcat( body, "c=IN IP" );
+    itoa( 4, itoa_buffer, 10 );
+    strcat( body, itoa_buffer );
+    strcat( body, " " );
+    strcat( body, this->my_ip );
+    strcat( body, "\r\n" );
+    strcat( body, "t=" );
+    itoa( 0, itoa_buffer, 10 );
+    strcat( body, itoa_buffer );
+    strcat( body, " " );
+    itoa( 0, itoa_buffer, 10 );
+    strcat( body, itoa_buffer );
+    strcat( body, "\r\n" );
+    strcat( body, "m=audio " );
+    itoa( this->my_rtp_port, itoa_buffer, 10 );
+    strcat( body, itoa_buffer );
+    strcat( body, " RTP/AVP " );
+    itoa( 8, itoa_buffer, 10 );
+    strcat( body, itoa_buffer );
+    strcat( body, " " );
+    itoa( 101, itoa_buffer, 10 );
+    strcat( body, itoa_buffer );
+    strcat( body, "\r\n" );
+    strcat( body, "a=rtpmap:" );
+    itoa( 8, itoa_buffer, 10 );
+    strcat( body, itoa_buffer );
+    strcat( body, " PCMA/" );
+    itoa( 8000, itoa_buffer, 10 );
+    strcat( body, itoa_buffer );
+    strcat( body, "/" );
+    itoa( 1, itoa_buffer, 10 );
+    strcat( body, itoa_buffer );
+    strcat( body, "\r\n" );
+    strcat( body, "a=rtpmap:" );
+    itoa( 101, itoa_buffer, 10 );
+    strcat( body, itoa_buffer );
+    strcat( body, " telephone-event/" );
+    itoa( 8000, itoa_buffer, 10 );
+    strcat( body, itoa_buffer );
+    strcat( body, "\r\n" );
+    strcat( body, "a=fmtp: " );
+    itoa( 101, itoa_buffer, 10 );
+    strcat( body, itoa_buffer );
+    strcat( body, " " );
+    itoa( 0, itoa_buffer, 10 );
+    strcat( body, itoa_buffer );
+    strcat( body, "-" );
+    itoa( 11, itoa_buffer, 10 );
+    strcat( body, itoa_buffer );
+    body[ SIP_MAXMSGSIZE - 1 ] = 0;
+ 
+    make_content_length( header, body, pkg );
+    return( pkg );
+}
+ 
+char * Sip::make_content_length( char * header, char * body, char * pkg ){
+    int size;
+    char itoa_buffer[ 65 ];
+    size = strlen( body );
+    strcpy( pkg, header );
+    strcat( pkg, "Content-Length: " );
+    itoa( size, itoa_buffer, 10 );
+    strcat( pkg, itoa_buffer );
+    strcat( pkg, "\r\n\r\n" );
+    strcat( pkg, body );
+    pkg[ SIP_MAXMSGSIZE - 1 ] = 0;
+    return pkg;
+}
+ 
+char * Sip::build_bye_package( char * buffer ){
+    char branch[SIP_MAXFIELDSIZE];
+    char tag[SIP_MAXFIELDSIZE];
+    char itoa_buffer[ 65 ];
+    fill_random16h(branch);
+    fill_random(tag,18);
+    
+    strcpy( buffer, "BYE sip:" );
+    itoa( this->peer_ext, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, "@" );
+    strcat( buffer, this->server_ip );
+    strcat( buffer, ":" );
+    itoa( this->server_port, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, " SIP/2.0\r\n" );
+    strcat( buffer, "Via: SIP/2.0/UDP " );
+    strcat( buffer, this->my_ip );
+    strcat( buffer, ":" );
+    itoa( this->my_port, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, ";branch=" );
+    strcat( buffer, branch );
+    strcat( buffer, "\r\n" );
+    strcat( buffer, "From: " );          
+    itoa( this->my_ext, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, " <sip:" );
+    itoa( this->my_ext, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, "@" );
+    strcat( buffer, this->server_ip );
+    strcat( buffer, ":" );
+    itoa( this->server_port, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, ">;tag=" );
+    strcat( buffer, last_invite_tag );
+    strcat( buffer, "\r\n" );
+    strcat( buffer, "To: <sip:" );
+    itoa( this->peer_ext, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, "@" );
+    strcat( buffer, this->server_ip );
+    strcat( buffer, ":" );
+    itoa( this->server_port, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, ">;tag=" );
+    strcat( buffer, tag );
+    strcat( buffer, "\r\n" );
+    strcat( buffer, "Call-ID: " );
+    strcat( buffer, last_invite_callid );
+    strcat( buffer, "@" );
+    strcat( buffer, this->my_ip );
+    strcat( buffer, "\r\n" );
+    strcat( buffer, "CSeq: " );
+    itoa( get_cseq(), itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, " BYE\r\n" );
+    strcat( buffer, "Max-Forwards: 70\r\n" );
+    strcat( buffer, "User-Agent: VZtech/pabxdriver-" );
+    strcat( buffer, SVNREV );
+    strcat( buffer, "\r\n" );          
+    strcat( buffer, "Content-Length: 0\r\n\r\n" );
+    return( buffer );
+}
+char * Sip::build_ack_package( char * buffer, unsigned char * orig ){
+    char to[ SIP_MAXFIELDSIZE ];
+    char from[ SIP_MAXFIELDSIZE ];
+    char callid[ SIP_MAXFIELDSIZE ];
+    char via[ SIP_MAXFIELDSIZE ];
+    char branch[ SIP_MAXFIELDSIZE ];
+    char cseq[ SIP_MAXFIELDSIZE ];
+    char itoa_buffer[ 65 ];
+    // FIXME confirmar se nao preciso converter todos os ints com itoa
+    if( decode_gettag( orig, "to: ", to ) == 0) {
+        buffer[ 0 ] = 0;
+        return NULL;
+    }
+    if( decode_gettag( orig, "from: ", from ) == 0) {
+        buffer[ 0 ] = 0;
+        return NULL;
+    }
+    if( decode_gettag( orig, "call-id: ", callid ) == 0) {
+        buffer[ 0 ] = 0;
+        return NULL;
+    }
+    decode_branch( orig, branch );
+    decode_cseq( orig, cseq );
+ 
+    if( strlen( via ) > 6 ) {
+        if( strcasecmp( ";rport", via+strlen( via )-6) == 0) {
+            via[strlen(via)-6] = 0;
+        }
+    }
+    strcpy( buffer, "ACK sip:" );
+    itoa( this->peer_ext, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, "@" );
+    strcat( buffer, this->server_ip );
+    strcat( buffer, ":" );
+    itoa( this->server_port, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, " SIP/2.0\r\n" );
+    strcat( buffer, "Via: SIP/2.0/UDP " );
+    strcat( buffer, this->my_ip );
+    strcat( buffer, ":" );
+    itoa( this->my_port, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, ";branch=" );
+    strcat( buffer, branch );
+    strcat( buffer, "\r\n" );
+    strcat( buffer, "From: " );
+    strcat( buffer, from );
+    strcat( buffer, "\r\n" );
+    strcat( buffer, "To: " );
+    strcat( buffer, to );
+    strcat( buffer, "\r\n" );
+    strcat( buffer, "Call-ID: " );
+    strcat( buffer, callid );
+    strcat( buffer, "\r\n" );
+    strcat( buffer, "CSeq: " );
+    strcat( buffer, cseq );
+    strcat( buffer, " ACK\r\n" );
+    strcat( buffer, "Max-Forwards: 70\r\n" );
+    strcat( buffer, "Contact: " );
+    itoa( this->my_ext, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, " <sip:" );
+    itoa( this->my_ext, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, "@" );
+    strcat( buffer, this->my_ip );
+    strcat( buffer, ":" );
+    itoa( this->my_port, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, ">\r\n" );
+    strcat( buffer, "User-Agent: VZtech/pabxdriver-" );
+    strcat( buffer, SVNREV );
+    strcat( buffer, "\r\n" );
+    strcat( buffer, "Content-Length: 0\r\n\r\n" );
+    buffer[SIP_MAXMSGSIZE-1] = 0;
+    return( buffer );
+}
+ 
+int Sip::get_return_code( char * buffer ){
+    char a[32];
+    int i = 0, j;
+    if( strncmp( "SIP/", buffer, 4 ) != 0 ) return 0;
+    if( strlen( buffer ) < 32) return 0;
+    strncpy( a, buffer, 31 );
+    a[ 31 ] = 0;
+    while ( a[ i ] > ' ') i++;
+    j = i+i;
+    while( (a[ j ] >= '0') && ( a[ j ] <= '9') ) j++;
+    a[ j ] = 0;
+    return atoi( a + i + 1 );
+}
+ 
+char * Sip::build_generic_reply_package(char * buffer, unsigned char * orig, char * tag){
+    char to[ SIP_MAXFIELDSIZE ];
+    char from[ SIP_MAXFIELDSIZE ];
+    char callid[ SIP_MAXFIELDSIZE ];
+    char cseq[ SIP_MAXFIELDSIZE ];
+    char via[ SIP_MAXFIELDSIZE ];
+ 
+    if( decode_gettag( orig, "to: ", to ) == 0) {
+        buffer[0] = 0;
+        return NULL;
+    }
+    if( decode_gettag( orig, "from: ", from ) == 0) {
+        buffer[0] = 0;
+        return NULL;
+    }
+    if( decode_gettag( orig, "call-id: ", callid ) == 0) {
+        buffer[0] = 0;
+        return NULL;
+    }
+    if( decode_gettag( orig, "cseq: ", cseq ) == 0) {
+        buffer[0] = 0;
+        return NULL;
+    }
+    if( decode_gettag( orig, "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;
+        }
+    }
+ 
+    strcpy( buffer, "SIP/2.0 " );
+    strcat( buffer, tag );
+    strcat( buffer, "\r\n" );
+    strcat( buffer, "To: " );
+    strcat( buffer, to );
+    strcat( buffer, "\r\n" );
+    strcat( buffer, "From: " );
+    strcat( buffer, from );
+    strcat( buffer, "\r\n" );
+    strcat( buffer, "Call-ID: " );
+    strcat( buffer, callid );
+    strcat( buffer, "\r\n" );
+    strcat( buffer, "CSeq: " );
+    strcat( buffer, cseq );
+    strcat( buffer, "\r\n" );
+    strcat( buffer, "Via: " );
+    strcat( buffer, via );
+    strcat( buffer, "\r\n" );
+    strcat( buffer, "Server: VZtech/pabxdriver-" );
+    strcat( buffer, SVNREV );
+    strcat( buffer, "\r\n" );
+    strcat( buffer, "Content-Length: 0\r\n\r\n" );
+    buffer[ SIP_MAXMSGSIZE - 1 ] = 0;
+    return( buffer );
+}
+char * Sip::build_trying_package( char * buffer, unsigned char * orig ){   
+    // FIXME trocar 100 para itoa( 100 ... )
+    build_generic_reply_package( buffer, orig, "100 Trying" );
+    return( buffer );
+}
+ 
+char * Sip::build_busy_package( char * buffer, unsigned char * orig ){   
+    // FIXME trocar 100 para itoa( 100 ... )
+    build_generic_reply_package( buffer, orig, "486 Busy Here");
+    return( buffer );
+}
+char * Sip::build_reply_package( char * buffer, unsigned char * orig ){
+    char to[ SIP_MAXFIELDSIZE ];
+    char from[ SIP_MAXFIELDSIZE ];
+    char callid[ SIP_MAXFIELDSIZE ];
+    char cseq[ SIP_MAXFIELDSIZE ];
+    char via[ SIP_MAXFIELDSIZE ];
+    char tag[ SIP_MAXFIELDSIZE ];
+ 
+    if( decode_gettag( orig, "to: ", to ) == 0) {
+        buffer[ 0 ] = 0;
+        return NULL;
+    }
+    if( decode_gettag( orig, "from: ", from ) == 0) {
+        buffer[ 0 ] = 0;
+        return NULL;
+    }
+    if( decode_gettag( orig, "call-id: ", callid ) == 0 ) {
+        buffer[ 0 ] = 0;
+        return NULL;
+    }
+    if( decode_gettag( orig, "cseq: ", cseq) == 0 ) {
+        buffer[ 0 ] = 0;
+        return NULL;
+    }
+    if( decode_gettag( orig, "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);
+    
+    strcpy( buffer, "SIP/2.0 200 OK\r\n" );
+    strcat( buffer, "To: " );
+    strcat( buffer, to );
+    strcat( buffer, ";tag=" );
+    strcat( buffer, tag );
+    strcat( buffer, "\r\n" );
+    
+    strcat( buffer, "From: " );
+    strcat( buffer, from );
+    strcat( buffer, "\r\n" );
+    
+    strcat( buffer, "Call-ID: " );
+    strcat( buffer, callid );
+    strcat( buffer, "\r\n" );
+    
+    strcat( buffer, "CSeq: " );
+    strcat( buffer, cseq );
+    strcat( buffer, "\r\n" );
+    
+    strcat( buffer, "Via: " );
+    strcat( buffer, via );
+    strcat( buffer, "\r\n" );
+    
+    strcat( buffer, "Server: VZtech/pabxdriver-" );
+    strcat( buffer, SVNREV );
+    strcat( buffer, "\r\n" );
+    strcat( buffer, "Content-Length: 0\r\n" );
+    strcat( buffer, SIP_ALLOW );
+    strcat( buffer, "\r\n\r\n" );
+    
+    buffer[ SIP_MAXMSGSIZE - 1 ] = 0;
+    return( buffer );
+}
+char * Sip::fill_random16h(char * buffer ){
+    fill_random( buffer, 16 );
+    buffer[ 7 ] = '-';
+    return( buffer );
+}
+ 
+char * Sip::fill_random( char * buffer, int size ){
+    static uint16_t seed = time( NULL );
+    seed += 1;
+    srand( seed );
+ 
+    int i;
+    for (i=0; i<size; i++) {
+        buffer[ i ] = fill_random_aux[ rand() & 0x3f ];
+    }
+    buffer[ size ] = 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( unsigned char * package, char * cseq ){
+    char pkg[ 2048 ], cs[ 2048 ];
+    if( decode_gettag( package, "cseq: ", pkg ) != 0) {
+        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( unsigned char * package, char * branch ){
+    char pkg[ 2048 ];
+    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( unsigned char * package, char * tag, char * out ){
+    int size, i, cmpsize;
+    cmpsize = strlen( tag );
+    size = strlen( ( char * )package )-cmpsize;
+    for ( 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::get_id( void ){
+    return this->id;
+}
+int Sip::get_my_rtp_port( void ){
+    return this->my_rtp_port;
+}
+inline int Sip::fill_random_rtp_port(){  
+    // o range [ 16384 - 32767 ] eh configuravel no server
+    return ( ( this->my_ext + 16384 ) > 32767 ) ? ( ( this->my_ext + 16384 ) % ( 32767 - 16384 ) + 16384 ) : this->my_ext + 16384;
+}
+ 
+void Sip::change_sip_server(){
+    // just in case sip server don't answer, invite another server
+    // mudar para os sets
+    set_server_ip( get_next_server_ip( this->buffer) );
+    set_server_ext( get_next_server_ext() );
+    set_server_port( get_next_server_port() );
+    registry();
+}
+ 
+char * Sip::get_next_server_ip( char * server_ip ){
+    strcpy( server_ip, this->server_ip );
+    return server_ip;
+}
+int Sip::get_next_server_port(){
+    return this->server_port;
+}
+int Sip::get_next_server_ext(){
+    return this->peer_ext;
+}
+void Sip::set_server_port( int new_server_port ){
+    this->server_port = new_server_port;
+}
+void Sip::set_server_ext( int new_server_ext ){
+    this->peer_ext = new_server_ext;
+}
+void Sip::set_server_ip( char * new_server_ip ){
+    strcpy( this->server_ip, new_server_ip );
+    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 ){
+    sock.set_blocking( false, 3 ); // verificar isso com mais cuidado depois
+    uint8_t read = sock.receiveFrom( sip_server, this->buffer, sizeof( this->buffer ) );
+    if( read > 0 ){
+        debug_msg( "-- SIP recebeu algo --" );
+        if( !( strncasecmp( buffer, "bye", strlen("bye") ) ) ){
+            char ans[ 2000 ];
+            build_reply_package( ans, (unsigned char*)buffer );
+            sock.sendTo( sip_server, ans, sizeof( ans ) );
+            
+            debug_msg(" Server request BYE to %d ext", my_ext );
+            return( this->my_ext );
+        }else if( !( strncasecmp( buffer, "options", strlen("options") ) ) ){
+            char ans[ 2000 ];
+            debug_msg(" Options received ");
+            build_reply_package( ans, (unsigned char*)buffer );
+            sock.sendTo( sip_server, ans, sizeof( ans ) );
+        }
+    }
+    return( 0 ); 
+}
+
+void Sip::set_ext( int ext ){
+    my_ext = ext;
+}
+
+void Sip::set_port( int port ){
+    my_port = port;
+}
+
+void Sip::send_bye( void ){
+    build_bye_package( this->buffer );
+    sock.sendTo( sip_server, build_bye_package( this->buffer ), sizeof( this->buffer ) );
+}
+
+void Sip::send_unregistry_pkg(){
+    build_unregistry_package( this->buffer );
+    for( register int i = 0; i < 7; i++ )
+        sock.sendTo( sip_server, build_bye_package( this->buffer ), sizeof( this->buffer ) );
+}
+
+char * Sip::build_unregistry_package( char * buffer ){
+    char branch[ SIP_MAXFIELDSIZE ];
+    char tag[ SIP_MAXFIELDSIZE ];
+    char callid[ SIP_MAXFIELDSIZE ];
+    fill_random16h( branch );
+    fill_random( tag, 18 );
+    fill_random16h( callid );
+    char itoa_buffer[ 65 ];
+    strcpy( buffer, "REGISTER sip:" );
+    strcat( buffer, server_ip );
+    strcat( buffer, ":" );
+    itoa( server_port, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, " SIP/2.0\r\nVia: SIP/2.0/UDP " );
+    strcat( buffer, my_ip );
+    strcat( buffer, ":" );
+    itoa( my_port, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, ";branch=" );
+    strcat( buffer, branch );
+    strcat( buffer, "\r\nFrom: " );
+    itoa( my_ext, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, " <sip:" );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, "@" ); 
+    strcat( buffer, server_ip );
+    strcat( buffer, ":" );
+    itoa( server_port, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, ">;tag=" );
+    strcat( buffer, tag );
+    strcat( buffer, "\r\nTo: " );
+    itoa( my_ext, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, " <sip:" );
+    itoa( my_ext, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, "@" );
+    strcat( buffer, server_ip );
+    strcat( buffer, ":" );
+    itoa( server_port, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, ">\r\nCall-ID: " );
+    strcat( buffer, callid );
+    strcat( buffer, "\r\nCSeq: " );
+    itoa( get_cseq(), itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, " REGISTER\r\n" );
+    strcat( buffer, "Max-Forwards: " );
+    itoa( 70, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, "\r\n" );
+    
+    strcat( buffer, "Contact: " );
+    itoa( my_ext, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, " <sip:" );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, "@" );
+    strcat( buffer, my_ip );
+    strcat( buffer, ":" );
+    itoa( server_port, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, ">;expires=0\r\n" );
+    /*
+    strcat( buffer, ">;expires=" );
+    itoa( 0, itoa_buffer, 10 );
+    strcat( buffer, itoa_buffer );
+    strcat( buffer, "\r\n" );
+    */
+    
+    strcat( buffer, "User-Agent: VZtech/pabxdriver-" );
+    strcat( buffer, SVNREV );
+    strcat( buffer, "\r\nContent-Length: 0\r\n" );
+    strcat( buffer, SIP_ALLOW );
+    strcat( buffer, "\r\n\r\n" );              
+    buffer[ SIP_MAXMSGSIZE - 1 ] = 0;
+    return buffer;
+}
\ No newline at end of file