After a period of study, I finally had a certain understanding of the SIP. During the learning process, I encountered too many problems, such as being depressed and disappointed. But I bit my teeth and came back. I was touched by the fact that I met some very enthusiastic friends on the Internet and gave me some questions without interrupting them. Thanks to them, especially the friendly big dog, I hope he will see this article one day.
I developed it using the exosip protocol stack. I wrote a <simple SIP call example> online, but it seems that there are some problems. For Beginners, we can get a good example, and the understanding of SIP can get twice the result with half the effort. So I will take out my own example for your reference. If you have any questions, please correct me.
You only need to correct and compile the IP address.
/*************************************** ***
Compilation Method:
Gcc xxx. C-o XXX-lexosip2
****************************************/
/******************* UAS ******************* **********************************
This article can be reproduced at will, but the source must be retained
Author: rainfish
Web: http://blog.csdn.net/bat603/
Test environment: exosip3.0.1/Redhat as 4
**************************************** ***********************************/
# Include <exosip2/exosip. h>
# Include <osip2/osip_mt.h>
# Include <stdio. h>
# Include <stdlib. h>
# Include <netinet/in. h>
# Include <sys/socket. h>
# Include <sys/types. h>
Int
Main (INT argc, char * argv [])
{
Exosip_event_t * Je = NULL;
Osip_message_t * ACK = NULL;
Osip_message_t * invite = NULL;
Osip_message_t * answer = NULL;
Sdp_message_t * remote_sdp = NULL;
Int call_id, dialog_id;
Int I, J;
Int ID;
Char * sour_call = "SIP: 133@192.168.0.133 ";
Char * dest_call = "SIP: 140@192.168.0.140: 5060 ";
Char command;
Char TMP [4096];
Char localip [128];
Int Pos = 0;
// Initialize the SIP
I = exosip_init ();
If (I! = 0)
{
Printf ("can't initialize exosip! /N ");
Return-1;
}
Else
{
Printf ("exosip_init successfully! /N ");
}
I = exosip_listen_addr (ipproto_udp, null, 5060, af_inet, 0 );
If (I! = 0)
{
Exosip_quit ();
Fprintf (stderr, "exosip_listen_addr error! /Ncouldn't initialize transport layer! /N ");
}
For (;;)
{
// Listen for message arrival
Je = exosip_event_wait (0, 50 );
// The protocol stack carries this statement. The specific function is unknown.
Exosip_lock ();
Exosip_default_action (JE );
Exosip_automatic_refresh ();
Exosip_unlock ();
If (JE = NULL) // No message is received
Continue;
// Printf ("the CID is % s, did is % s/n", je-> did, je-> CID );
Switch (Je-> type)
{
Case exosip_message_new: // new message arrival
Printf ("exosip_message_new! /N ");
If (msg_is_message (Je-> request) // If the received message type is message
{
{
Osip_body_t * body;
Osip_message_get_body (Je-> request, 0, & Body );
Printf ("I get the MSG is: % s/n", body-> body );
// Printf ("the CID is % s, did is % s/n", je-> did, je-> CID );
}
// According to the rule, you need to reply to the 200 OK message
Exosip_message_build_answer (Je-& gt; tid, 200, & answer );
Exosip_message_send_answer (Je-& gt; tid, 200, answer );
}
Break;
Case exosip_call_invite:
// Obtain the Message Details.
Printf ("received a invite MSG from % s: % s, username is % s, password is % s/n", je-> request-> req_uri-> host,
Je-> request-> req_uri-> port, je-> request-> req_uri-> username, je-> request-> req_uri-> password );
// Obtain the message body. The message is in SDP format.
Remote_sdp = exosip_get_remote_sdp (Je-> did );
Call_id = Je-> CID;
Dialog_id = Je-> did;
Exosip_lock ();
Exosip_call_send_answer (Je-> tid, 180, null );
I = exosip_call_build_answer (Je-> tid, 200, & answer );
If (I! = 0)
{
Printf ("this request MSG is invalid! Cann' t response! /N ");
Exosip_call_send_answer (Je-> tid, 400, null );
}
Else
{
Snprintf (TMP, 4096,
"V = 0/R/N"
"O = anonymous 0 0 in ip4 0.0.0.0/R/N"
"T = 1 10/R/N"
"A = Username: rainfish/R/N"
"A = password: 123/R/N ");
// Set the response SDP message body and analyze the message body in the next step.
// Directly reply to the original message without analyzing the message body.
Osip_message_set_body (answer, TMP, strlen (TMP ));
Osip_message_set_content_type (answer, "application/SDP ");
Exosip_call_send_answer (Je-& gt; tid, 200, answer );
Printf ("Send 200 over! /N ");
}
Exosip_unlock ();
// Display the attribute content in the SDP message body, which is scheduled to store our information
Printf ("the info is:/N ");
While (! Osip_list_eol (remote_sdp-> a_attributes, POS ))
{
Sdp_attribute_t *;
At = (sdp_attribute_t *) osip_list_get (remote_sdp-> a_attributes, POS );
Printf ("% s: % s/n", At-> a_att_field, At-> a_att_value ); // The reason why attribute a must be stored in the SDP message body must be two columns
Pos ++;
}
Break;
Case exosip_call_ack:
Printf ("Ack recieved! /N ");
// Printf ("the CID is % s, did is % s/n", je-> did, je-> CID );
Break;
Case exosip_call_closed:
Printf ("the remote hold the session! /N ");
// Exosip_call_build_ack (dialog_id, & ACK );
// Exosip_call_send_ack (dialog_id, ACK );
I = exosip_call_build_answer (Je-> tid, 200, & answer );
If (I! = 0)
{
Printf ("this request MSG is invalid! Cann' t response! /N ");
Exosip_call_send_answer (Je-> tid, 400, null );
}
Else
{
Exosip_call_send_answer (Je-& gt; tid, 200, answer );
Printf ("Bye send 200 over! /N ");
}
Break;
Case exosip_call_message_new: // the difference between this type and exosip_message_new is explained in the source code.
/*
/* Request related events within CILS (Response t invite )*/
Exosip_call_message_new,/** <announce new incoming request .*/
/* Response received ed for request outside cballs */
Exosip_message_new,/** <announce new incoming request .*/
I don't quite understand either. The understanding is: exosip_call_message_new is the arrival of a new message in a call, such as Ring trying. Therefore, after receiving the message, you must determine
This message type, exosip_message_new, indicates that the incoming message is not in the call.
This explanation is for reference only.
*/
Printf ("exosip_call_message_new/N ");
If (msg_is_info (Je-> request) // If the info method is transmitted
{
Exosip_lock ();
I = exosip_call_build_answer (Je-> tid, 200, & answer );
If (I = 0)
{
Exosip_call_send_answer (Je-& gt; tid, 200, answer );
}
Exosip_unlock ();
{
Osip_body_t * body;
Osip_message_get_body (Je-> request, 0, & Body );
Printf ("the body is % s/n", body-> body );
}
}
Break;
Default:
Printf ("cocould not parse the MSG! /N ");
}
}
}
/******************* UAC ******************* **********************************
This article can be reproduced at will, but the source must be retained
Author: rainfish
Web: http://blog.csdn.net/bat603/
Test environment: exosip3.0.1/Redhat as 4
**************************************** ***********************************/
# Include <exosip2/exosip. h>
# Include <stdio. h>
# Include <stdlib. h>
# Include <netinet/in. h>
# Include <sys/socket. h>
# Include <sys/types. h>
Int
Main (INT argc, char * argv [])
{
Exosip_event_t * Je;
Osip_message_t * Reg = NULL;
Osip_message_t * invite = NULL;
Osip_message_t * ACK = NULL;
Osip_message_t * info = NULL;
Osip_message_t * message = NULL;
Int call_id, dialog_id;
Int I, flag;
Int flag1 = 1;
Int ID;
Char x identity = "SIP: 140@192.168.0.140 ";
Char * registerer = "SIP: 192.168.0.133: 5060 ";
Char * source_call = "SIP: 140@192.168.0.140 ";
Char * dest_call = "SIP: 133@192.168.0.133: 5060 ";
Char command;
Char TMP [4096];
Char localip [128];
Printf ("r register with the server/n ");
Printf ("C cancel registration/n ");
Printf ("I initiate a call request/n ");
Printf ("H hanging/n ");
Printf ("Q exit Program/n ");
Printf ("s execution method info/n ");
Printf ("m execution method message/n ");
// Initialization
I = exosip_init ();
If (I! = 0)
{
Printf ("couldn't initialize exosip! /N ");
Return-1;
}
Else
{
Printf ("exosip_init successfully! /N ");
}
I = exosip_listen_addr (ipproto_udp, null, 5060, af_inet, 0 );
If (I! = 0)
{
Exosip_quit ();
Fprintf (stderr, "couldn't initialize transport layer! /N ");
Return-1;
}
Flag = 1;
While (FLAG)
{
Printf ("Please input the Comand:/N ");
Scanf ("% C", & command );
Getchar ();
Switch (command)
{
Case 'r ':
Printf ("this modal isn' t commp leted! /N ");
Break;
Case 'I':/* invite */
I = exosip_call_build_initial_invite (& invite, dest_call, source_call, null, "This si a call for a conversation ");
If (I! = 0)
{
Printf ("intial invite failed! /N ");
Break;
}
// In SDP format, property A is a custom format, that is, it can store its own information, but it can only be two columns, such as account information
// However, It is tested that the format is "V o t" and the cause is unknown. It is estimated that the protocol stack needs to be checked during transmission.
Snprintf (TMP, 4096,
"V = 0/R/N"
"O = anonymous 0 0 in ip4 0.0.0.0/R/N"
"T = 1 10/R/N"
"A = Username: rainfish/R/N"
"A = password: 123/R/N ");
Osip_message_set_body (invite, TMP, strlen (TMP ));
Osip_message_set_content_type (invite, "application/SDP ");
Exosip_lock ();
I = exosip_call_send_initial_invite (invite );
Exosip_unlock ();
Flag1 = 1;
While (flag1)
{
Je = exossip_event_wait (0,200 );
If (JE = NULL)
{
Printf ("no response or the time is over! /N ");
Break;
}
Switch (Je-> type)
{
Case exosip_call_invite:
Printf ("A New invite reveived! /N ");
Break;
Case exosip_call_proceeding:
Printf ("proceeding! /N ");
Break;
Case exosip_call_ringing:
Printf ("ringing! /N ");
// Call_id = Je-> CID;
// Dialog_id = Je-> did;
Printf ("call_id is % d, dialog_id is % d/N", je-> CID, je-> did );
Break;
Case exosip_call_answered:
Printf ("OK! Connected! /N ");
Call_id = Je-> CID;
Dialog_id = Je-> did;
Printf ("call_id is % d, dialog_id is % d/N", je-> CID, je-> did );
Exosip_call_build_ack (Je-> did, & ACK );
Exosip_call_send_ack (Je-> did, ACK );
Flag1 = 0;
Break;
Case exosip_call_closed:
Printf ("the other Sid closed! /N ");
Break;
Case exosip_call_ack:
Printf ("Ack received! /N ");
Break;
Default:
Printf ("other response! /N ");
Break;
}
Exosip_event_free (JE );
}
Break;
Case 'H ':
Printf ("holded! /N ");
Exosip_lock ();
Exosip_call_terminate (call_id, dialog_id );
Exosip_unlock ();
Break;
Case 'C ':
Printf ("this modal isn' t commp leted! /N ");
Break;
Case's ':
// Transfer info Method
Exosip_call_build_info (dialog_id, & info );
Snprintf (TMP, 4096,
"Hello, rainfish ");
Osip_message_set_body (Info, TMP, strlen (TMP ));
// The format can be set as needed. Text/plain indicates text information.
Osip_message_set_content_type (Info, "text/plain ");
Exosip_call_send_request (dialog_id, Info );
Break;
Case 'M ':
// Message transmission method, that is, instant message. Compared with the info method, I think the main difference is that messages do not need to be connected and information is transmitted directly, whereas info must
// Transmit data based on invite.
Printf ("The mothed: Message/N ");
Exosip_message_build_request (& message, "message", dest_call, source_call, null );
Snprintf (TMP, 4096,
"Hellor rainfish ");
Osip_message_set_body (message, TMP, strlen (TMP ));
// Assume the format is XML.
Osip_message_set_content_type (message, "text/XML ");
Exosip_message_send_request (Message );
Break;
Case 'q ':
Exosip_quit ();
Printf ("exit the setup! /N ");
Flag = 0;
Break;
}
}
Return (0 );
}