Note:
1. The oSIP version in the following article is 3.0.1
2. exosip version 3.0.1
3. compiling environment: Windows XP Professional version + VS 2005
4. The sample program is downloaded at http://blog.csdn.net/bat603/and modified (originally in Linux)
5. If you want to repost this article, describe the source
6. I am only in touch with SIP (haha, less than a week). There must be many mistakes. please correct me.
Step 1: Download:
Go to http://www.gnu.org/software/osip/download the latest osipdatabase and decompress it
Go to http://savannah.gnu.org/projects/exosip/download the latest exsoip library and decompress it
Step 2: Compile osip3.0.1:
1. Open libosip2-3.0.1/platform/vsnet/Osip. sln with vs2005
2. Generate release DLL for the osip2 and osipparser2 Projects
3. The generated lib/DLL is located under: libosip2-3.0.1/platform/vsnet/release dll/
Step 3: Compile exosip3.0.1:
1. Open libeXosip2-3.0.1/platform/vsnet/exosip. sln with vs2005
2. Copy the libosip2-3.0.1/include/osip2 directory to libeXosip2-3.0.1/include/
3. Copy the libosip2-3.0.1/include/osipparser2 directory to libeXosip2-3.0.1/include/
4. Create the lib directory under the libeXosip2-3.0.1 directory
5. Copy the libosip2-3.0.1/platform/vsnet/release dll/osip2.lib file generated in step 2 to the libeXosip2-3.0.1/lib directory
6. Copy the libosip2-3.0.1/platform/vsnet/release dll/osipparser2.lib file generated in step 2 to the libeXosip2-3.0.1/lib directory
7. Modify project properties and add dnsapi. Lib iphlpapi. Lib ws2_32.lib osip2.lib osipparser2.lib library input.
8. Modify the project properties and add the library directory.../../lib.
9. Change the project output to. dll. The default value is. Lib.
10. Compile relase DLL
11. The generated lib/DLL is located under: libeXosip2-3.0.1/platform/vsnet/release/
Step 4: Compile the sample program:
Save the following program as UAS. cpp
[Copy to clipboard]
Code:
// UAS. cpp: defines the entry point of the console application.
//
# I nclude <exosip2/exosip. h>
# I nclude <stdio. h>
# I nclude <stdlib. h>
# I nclude <winsock2.h>
/*
# I nclude <netinet/in. h>
# I nclude <sys/socket. h>
# I nclude <sys/types. h> */
# Pragma comment (Lib, "osip2.lib ")
# Pragma comment (Lib, "osipparser2.lib ")
# Pragma comment (Lib, "exosip. lib ")
# Pragma comment (Lib, "iphlpapi. lib ")
# Pragma comment (Lib, "dnsapi. lib ")
# Pragma comment (Lib, "ws2_32.lib ")
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: 24@10.16.79.24 ";
Char * dest_call = "SIP: 24@10.16.79.24: 5061"; // Client IP
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 OK Information
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 CILS
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 ");
}
}
}
Save the following program as UAC. cpp
[Copy to clipboard]
Code:
// UAC. cpp: defines the entry point of the console application.
//
# I nclude <exosip2/exosip. h>
# I nclude <stdio. h>
# I nclude <stdlib. h>
# I nclude <winsock2.h>
/*
# I nclude <netinet/in. h>
# I nclude <sys/socket. h>
# I nclude <sys/types. h> */
# Pragma comment (Lib, "osip2.lib ")
# Pragma comment (Lib, "osipparser2.lib ")
# Pragma comment (Lib, "exosip. lib ")
# Pragma comment (Lib, "iphlpapi. lib ")
# Pragma comment (Lib, "dnsapi. lib ")
# Pragma comment (Lib, "ws2_32.lib ")
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: 24@10.16.79.24 ";
Char * registerer = "SIP: 10.16.79.24: 5060"; // server IP
Char * source_call = "SIP: 24@10.16.79.24 ";
Char * dest_call = "SIP: 24@10.16.79.24: 5060"; // server IP
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, 5061, 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 );
}
To compile these two programs, you must note that the header file path of Osip/exosip and the Lib library path generated in step 2/3 should be set correctly.
Step 5: run the sample program:
1. Copy the three DLL files generated in step 2/step 3 to the program running directory.
2. Now you can run it!