Sie sind auf Seite 1von 80

CONTENTS

1. Introduction
1.1 Brief Description of the Project……
2
1.2 Module
Description…………………….3
2. Feasibility Study…………………………………..4
3. Protocol Overview
3.1 SIP Functionality……………………….5
3.2 SIP Architecture………………………..6
3.3 SIP Entities……………………………….7
3.4 SIP Methods………………………………
20
3.5 SIP Session
Setup……………………….21
3.6 SIP Mobility
Modes……………………..27
3.7 SIP
Messages……………………………..29
4. Softphone Overview………………………………
31
5. Linphone Implementation………………………
31
5.1 User Frontend
5.2 Liblinlibrary
5.2.1
eXoSIP2………………………….32
5.2.2 Mediadtreamer2………………
33
5.2.3
ortp……………………………….34
6. Coding
Section……………………………………...35
7. Output
Screens……………………………………..67
8. Implementation and
Maintenance……………73
9. Conclusion……………………………………………
74
10. Bibliography…………………………………………
75
Title of the project
The project is entitled as “SIP based Softphone”

BRIEF DESCRIPTION OF THE PROJECT


This project is aimed at developing a SIP based
Softphone that is of importance to an organization. A Softphone is
the software you can use for making VoIP calls. A Softphone is a
software program for making telephone calls over the internet
using a general purpose computer, rather than using dedicated
hardware. This Softphone is designed to behave like a traditional
telephone, appearing as an image of a phone, with a display
panel and buttons with which the user can interact. Softphone is
used with a headset connected to the soundcard of the PC, or
with a USB phone.

SIP is an application-layer control protocol that can


establish, modify, and terminate multimedia sessions
(conferences) such as Internet telephony calls. SIP can also invite
participants to already existing sessions, such as multicast
conferences. Media can be added to (and removed from) an
existing session. SIP transparently supports name mapping and
redirection services, which supports personal mobility, users can
maintain a single externally visible identifier regardless of their
network location.

As a traditional text based Internet protocol, it


resembles the hypertext transfer protocol (HTTP) and simple mail
transfer protocol (SMTP). SIP uses Session Description Protocol
(SDP) for media description.SIP works on both IPv4 and IPv6.
MODULE DESCRIPTION
This project is going to consist of following modules,
which are described as follows:

MAIN MODULES:
 Init API - manage mediastreamer2 library.

 Filter API - manage mediastreamer2 filters.

 Sound Card API - manage audio capture/play filters.

 Sound Card Manager API

 Sound Card Filter API

 Ticker API - manage mediastreamer2 graphs.

 Camera API - manage video capture devices

CLASS INDEX

 JB Parameters

 RTP Profile

 RTP Session

DIRECTORIES
 linphone-3.2.1

• Console

• CoreApi
• gtk/glade

• Mediastreamer2

FEASIBILITY STUDY

 TECHNICAL FEASIBILTY:
Evaluating the technical feasibility is the trickiest part of a
feasibility study. This is because, at this point of time, not
too many detailed design of the system is available, making
it difficult issues like performance, costs on account of the
kind of technology to be deployed.

A number of issues have to be considered while doing a


technical analysis like to understand the different
technologies involved in the proposed system and find out
whether the organizations currently possesses the required
technologies.

The various technologies required in this project are as


follows:

1. For Programming: C

2. For Interface: GTK+/libglade

 OPERATIONAL FEASIBILITY:
The communication scenario should be user centric and
device centric. Since the proposed technology lead towards
the unification of different technologies and is independent
of the communicative devices, the new system was
considered to be operational feasible.

 ECONOMIC FEASIBILTY
Economic feasibility attempt to outweigh the costs of
developing and implementing a new system. This feasibility
study gives economic justification for the system. The other
benefit includes increased customer satisfaction,
improvement in quality, improved accuracy of operations,
better documentation and increased productivity.

PROTOCOL OVERVIEW
The Session Initiation Protocol (SIP) is part of the Internet
Multimedia Architecture, which consists of many precise
protocols that have been designed to perform one function.
New services and applications can be created by combining
multiple protocols together in a manner best suited for the
implementations purpose. This type of design is very flexible
and is a driver for constant innovation and development. It is
not likely that a service could be created using SIP alone,
although SIP does not depend on any other protocol. The
current excitement around SIP has made some developers
forget that SIP has been designed to be a signaling protocol
and should not be used for tasks that are better suited for
other protocols, such as data transport.
Fig: Internet Multimedia Architecture
SIP FUNCTIONALITY

SIP is an application-layer control protocol that can


establish, modify, and terminate multimedia sessions
(conferences) such as Internet telephony calls. SIP works
independently of the session being established. SIP
supports five facets of establishing and terminating
multimedia communications:

1. User Location: Determination of the End System to be


used for Communication.
2. User Availability: Determination of the Willingness of
the Called Party to Engage in Communication.
3. User Capabilities: Determination of the Media and
Media Parameters to be used.
4. Session Setup: "Ringing", Establishment of Session
Parameters at both Called and Calling Party.
5. Session Management: Including Transfer and
Termination of Sessions, modifying session parameters,
and invoking services

Users in a SIP network are identified by unique SIP


addresses. A SIP address is similar to an e-mail address
and is in the format of sip:userID@domain.com. Users
register with a Registrar Server using their assigned SIP
addresses. The Registrar Server provides this information
to the Location Server upon request.

An important feature of SIP is that it does not define the


type of session that is being established, only how it
should be managed. SIP is not a vertically integrated
communications system. This flexibility means that SIP
can be used for an enormous number of applications and
services, including interactive gaming, music and video
on demand as well as voice, video and Web conferencing.

SIP ARCHITECTURE
The SIP protocol defines four logical entities: User Agents,
Proxy Servers, Redirect Servers and Registrars. Most
implementations combine the Proxy Server, Redirect
Sever and/or Registrar into one server that is commonly
called the SIP Server. The SIP Server also often includes a
non-SIP entity called the Location Server that provides
location services and Presence Sever that provides
presence information about the users.

Fig: Sip Architecture

It is important to remember that SIP is a protocol and not


a complete system; therefore there is no reference SIP
architecture. There is much possible architecture
depending on the needs of the local installation.

It is important to remember that SIP is a protocol and not


a complete system; therefore there is no reference SIP
architecture. There are possible architectures depending
on the needs of the user or organization concerned.

Basic SIP Components


SIP sessions utilize up to four major components: SIP User
Agents, SIP Registrar Servers, SIP Proxy Servers and SIP
Redirect Servers. Together, these systems deliver
messages embedded with the SDP protocol defining their
content and characteristics to complete a SIP session.
Below is a high-level description of each SIP component
and the role it plays in this process:

(1)USER AGENTS (UA): User agents (UAs) are applications


installed on SIP endpoints, such as an IP phone, mobile
phone, wireless device or PDA, or a laptop or desktop PC
that interface between the user and the SIP network. A
UA can act as either a client or a server.

 User Agent Client (UAC) — a client application that


initiates SIP requests. A user agent client is a
logical entity that creates a new request, and then
uses the client transaction state machinery to send
it. The role of UAC lasts only for the duration of
that transaction. In other words, if a piece of
software initiates a request, it acts as a UAC for
the duration of that transaction. If it receives a
request later, it assumes the role of a user agent
server for the processing of that transaction.
 User Agent Server (UAS)—a server application that
contacts the user when a SIP request is received
and that returns a response on behalf of the user.
The response accepts, rejects, or redirects the
request. This role lasts only for the duration of
that transaction.

Example SIP user agents are: SIP phones (hardware), SIP


based soft phones (PC) and SIP based IM clients (MS
Windows Messenger).

SIP SERVER
SIP Servers are essential network elements that enable
SIP endpoints to exchange messages, register user
location, and seamlessly move between networks. SIP
Servers enable network operators to install routing and
security policies, authenticate users and manage user
locations.

With the advance of SIP, server logic has become


increasingly complex. SIP Servers need to deal with
varying network topologies (such as public Internet
networks, cellular networks, and broadband residential
networks), complex routing policies, and security and SIP
extensions. SIP Servers often need to handle high
message/transaction rates and yield real-time
performance and scalability, high throughput, and low
delay.
SIP Server applications may take many forms, but the SIP
standard defines three general types of server
functionality that apply to all—Proxy, Redirect and
Registrar servers. These standard functionalities can be
used according to the needs of the specific
implementation. A SIP Server can also function as a
Presence Server or a Back-to-Back User Agent (B2BUA).
In addition, since SIP defines other event types, such as
Winfo and Register, a SIP Server may function as an
Events Server for handling the various SIP events.

The SIP baseline specification RFC 3261 (previously RFC


2543bis) divides SIP Server functionality into the following
parts:

 SIP Registrar Server—handles location registration


messages.
 SIP Redirect Server—returns “contact this
address” responses.
 SIP Proxy Server—forwards SIP requests and
responses.

REGISTRAR SERVER
Registrar server is a database that contains the location
of all User Agents within a domain. The Registrar
authenticates and registers users when they come online,
and stores information on the users’ logical identities and
the communications devices or physical entities (IP
address) of the communication devices they can use. It
accepts registration requests and maps client’s address
to user’s sign-in name or SIP URI. The devices are
identified by their URIs. In SIP messaging, these servers
retrieve and send participants’ IP addresses and other
pertinent information to the SIP Proxy Server.
The SIP standard defines a registrar server as “a server
that accepts REGISTER requests and places the
information it receives in those requests into the location
service for the domain it handles”. REGISTER requests
are generated by clients in order to establish or remove a
mapping between their externally known SIP address and
the address they wish to be contacted at. The REGISTER
request can also be used to retrieve all the existing
mappings saved for a specific address.

Fig: SIP Registration

 REDIRECT SERVER
Redirect Server allow SIP Proxy Servers to direct SIP
session invitations to external domains. Upon receiving
SIP request, it directs the client to contact an alternate
set of SIP addresses SIP Redirect Servers may reside in
the same hardware as SIP Registrar Severs and SIP Proxy
Servers. For example, if a call is destined for
bob@amway.com and the user is on the road, the
company’s redirect server may reply to the caller’s UA (or
to the requesting proxy server) with the contact address
of the user’s mobile phone, so that the incoming call can
be redirected to the mobile phone.

Fig: Request Redirection

The scenario in Figure illustrates a redirection scenario.


Note that the second INVITE request is generated
with the same dialog identifiers, Call-ID, and To
and From headers as the first INVITE request, but
with a different CSeq value.
Redirection allows servers to push back routing
information for a request in a response to the client,
thereby aiding in locating the target of the request, while
taking themselves out of the loop of further messaging
for this transaction.

Redirect servers typically are not aware of the state of


dialogs (calls, subscriptions), only of the state of the
individual transactions they are handling, making them
transaction-stateful elements. Redirection is designed as
a simple and quick procedure, allowing for redirect
servers to be highly scalable and to yield high-
performance. Redirect servers are sometimes used as a
load balancing devices.

 PROXY SERVER:
Proxy Server route SIP requests to User Agent Servers
(UAS) and SIP responses to User Agent Clients (UAC). It
primarily plays the role of routing. A Proxy Server is
designed to be mostly transparent to UAs. It accept
session requests made by a SIP UA and query the SIP
Registrar Server to obtain the recipient UA’s addressing
information. It then forwards the session invitation
directly to the recipient UA if it is located in the same
domain or to a Proxy Server via Redirect Server if the UA
resides in another domain. A proxy is involved only in the
setup and teardown of a communication session. After
user agents establish a session, communications occur
directly between the parties. The SIP standard allows
proxies to perform actions such as validate requests,
authenticate users, fork requests, resolve addresses,
cancel pending calls, Record-Route and Loose-Route, and
detect and handle loops. A Proxy interprets, and, if
necessary, rewrites a request message before forwarding
it. Proxy servers are allowed to change messages only in
specific and limited ways. For example, a proxy is not
allowed to modify the SDP body of an INVITE. Apart from
a few exceptions, proxies cannot generate requests at
their own initiative. Therefore a proxy cannot terminate
an existing call by generating a BYE request.

The SIP specification defines two types of SIP proxies:


 Stateful Proxy
 Stateless Proxy
STATELESS PROXY

A stateless proxy is a “simple message forwarder”, as described


in the SIP standard. When receiving a request, the stateless proxy
processes the request much like a stateful proxy; however the
stateless proxy forwards the message in a stateless fashion—
without saving any transaction context. This means that once the
message is forwarded the proxy “forgets” ever handling this
message.

Stateless forwarding allows for improved performance and


scalability, but has some consequences:
 A stateless proxy cannot associate responses with forwarded
requests because it retains no knowledge of the requests it
has forwarded. Therefore, the proxy application cannot know
if a transaction was successful or not.
 A stateless proxy cannot associate retransmissions of
requests and responses with the previous instance of these
messages. It processes retransmissions exactly as if this is
the first copy of the message it received. If the message is
lost, the proxy will not retransmit it. Retransmission is the
responsibility of stateful UAs or proxies Because of their
high-throughput capabilities, stateless proxies are often used
at the core of carrier and service provider networks assisting
in forwarding SIP messages on the network. Stateless
proxies may also be used as load balancers.

STATEFUL PROXY

When stateful, the proxy processes transactions rather than


individual messages. The proxy manages two types of
transactions—Server Transactions to receive requests and
return responses, and Client Transactions to send requests and
receive responses. An incoming request is processed by a server
transaction and then forwarded downstream by one or more
client transactions. An incoming response is received by the
matching client transaction and forwarded back to the server
transaction. Associating between client and server transactions
and managing the overall state of this request is the responsibility
of the Proxy Core Object. The Proxy Core Object chooses the
destination address and instantiates one or more client
transaction objects accordingly. The Proxy Core Object also
collects the responses from the different client transactions and
chooses the response that will be sent upstream via the server
transaction.

A stateful proxy is aware of the state of transactions and message


history, and can therefore perform better-informed processing on
incoming messages. For example, a stateful proxy can identify a
retransmission of an incoming message and forward the message
only in situations that require retransmission forwarding, whereas
a stateless proxy cannot identify retransmissions and have to
forward every message it encounters. A stateful proxy can also
generate retransmissions in cases of message loss. In addition, a
stateful proxy can locally process incoming CANCEL requests and
generate CANCEL requests as needed.

REQUEST VALIDATION

Before routing a request, a SIP Server (proxy or redirect) needs to


validate the request to make sure it can actually proceed with
processing this message. The message has to pass the following
validity checks:
(1)Reasonable Syntax Check
The request must be well-formed enough to be handled by the
server. However, this applies only to specific fields in the
message which the server must process. All other parts should
not be checked or fixed by the proxy.
(2)URI scheme check
The URI scheme must be a scheme that the proxy understands
and knows how to route. If not, the proxy must return a 416
(Unsupported URI Scheme) response.

(3)Max-Forwards check
Max-Forwards is a message field that indicates how many more
hops the message is allowed to traverse. Each proxy that handles
the message decrements this number by one. If the message
contains a Max-Forwards value of zero, the proxy must return a
483 (Too many hops) response. This mechanism allows
preventing a message from going into an endless loop between a
set of proxies.

(4)Proxy-Require
The client may indicate certain SIP extensions in the Proxy-
Require fields that the proxy must support in order to successfully
handle this request. The proxy must inspect this field and verify
that it supports all the extensions listed in the field.

(5)Authentication
If the SIP Server determines it has to authenticate the originator
of the message, it has to make sure the message contains
credentials that authenticate the user. If the message does not
contain credentials or the credentials failed to authenticate the
user, the proxy may return a 407 response containing a
challenge.

ADDRESS RESOLUTION: Once a proxy has validated an


incoming request and decided to forward it, it must determine the
destination(s) to which the message is to be forwarded before
sending the messages. The proxy does two types of address
resolution:

 Determining the Target-Set—The proxy resolves the


request SIP destination address (Request URI) to a set of SIP
addresses

 DNS Resolution—the proxy resolves each of the SIP


destination addresses to a transport address of the form:
{transport protocol, IP address, port}

1. DETERMINING THE TARGET-SET

The first process in address resolution, known as obtaining a


target-set in the SIP specification, results in producing a set of SIP
addresses. Essentially this stage maps from SIP address to SIP
addresses. A target-set is obtained in one of two ways:

• Predefined Target-Set
This is the simpler case, where the destination address of the
request is such that the proxy must automatically forward to the
destination address without trying to resolve to other addresses.
One such case is where the request-URI is in a domain for which
the SIP Server is not responsible. For example, a proxy
sip:proxy1.acme.com which is responsible for the domain
acme.com receiving a request for sip:bob@example.com must
proxy the request to sip:bob@example.com.

• Target-Set Determined by Proxy If the target-set is not


dictated by the message, the proxy may employ whatever
mechanism it may wish to determine the target-set. Some
options are:
a) Accessing a location service updated by a SIP registrar
b) Reading from a database
c) Consulting a presence server
d) Using other protocols
e) Performing algorithmic substitutions on the destination
address
2. DNS RESOLUTION Before forwarding a message, the
proxy must resolve the message to concrete transport
addresses which it can use in sending the message. Proxies,
as other SIP entities, use the DNS mechanism described in
RFC 3263. DNS queries to map a given SIP address to a
prioritized set of transport addresses of the form: {transport
protocol, IP address, port}

CANCEL
The scenario shows CANCEL processing. A stateful proxy may
choose to generate a CANCEL request for any pending INVITE
request it has previously forwarded.
A proxy receiving a CANCEL request must try and match it to an
existing INVITE context and cancel any pending client
transactions associated with this INVITE. If an INVITE context is
not found, the proxy must statelessly forward the CANCEL
request.
AUTHENTICATION

The scenario shows authentication. When a UAC sends a request


to a proxy server, the proxy server may decide to authenticate
the originator before the request is processed. The proxy may
send a 407 response (Proxy Authentication Required) with a
Proxy-Authenticate header containing the challenge. The client
can re-send the request with a Proxy-Authorization header which
provides the credentials that match the challenge.

Authentication by proxy is useful for the following:


• Verifying that the originator of the request is indeed a
authorized user entitled to receive services (avoiding service
theft)
• Asserting that certain message fields were not altered by a
third party
• SIP authentication also allows for multi-level authentication
by different proxies along the signaling path.
SIP MESSAGES
There are two types of SIP messages:
Requests—Sent from the Client to the Server.
Responses—Sent from the Server to the Client.

 For registering contact information (binding management):

1. REGISTER: SIP offers a discovery capability. If a user wants to


initiate a session with another user, SIP must discover the current
host(s) at which the destination user is reachable. This discovery
process is frequently accomplished by SIP network elements such
as proxy servers and redirect servers which are responsible for
receiving a request, determining where to send it based on
knowledge of the location of the user, and then sending it there.
To do this SIP network elements consult an abstract service
known as a Location. Service, which provides address bindings for
a particular domain. REGISTER requests add, remove, and query
bindings. A REGISTER request can add a new binding between an
address-of-record and one or more contact addresses.
Registration on behalf of a particular address-of-record can be
performed by a suitably authorized third party. A client can also
remove previous bindings or query to determine which bindings
are currently in place for an address-of-record.

 For Setting Up Session:

2. INVITE: When a user agent client desires to initiate a session


(for example, audio, video, or a game), it formulates an INVITE
request. The INVITE request asks a server to establish a session.
This request may be forwarded by proxies, eventually arriving at
one or more UAS that can potentially accept the invitation. These
UASs will frequently need to query the user about whether to
accept the invitation.
3. ACK: ACK requests are used to acknowledge the reception of a
final response to an INVITE. (SIP has three-way handshake:
INVITE-final response-ACK)

4. CANCEL: The CANCEL request, as the name implies, is used to


cancel a previous request sent by a client. Specifically, it asks the
UAS to cease processing the request and to generate an error
response to that request. CANCEL has no effect on a request to
which a UAS has already given a final response. Because of this, it
is most useful to CANCEL requests to which it can take a server
long time to respond. For this reason, CANCEL is best for INVITE
requests, which can take a long time to generate a response. In
that usage, a UAS that receives a CANCEL request for an INVITE,
but has not yet sent a final response, would "stop ringing", and
then respond to the INVITE with a specific error response.

 For terminating sessions:

5. BYE: The BYE request is used to terminate a specific session or


attempted session.

 For querying servers about their capabilities:

6. OPTIONS: The SIP method OPTIONS allows a UA to query


another UA or a proxy server as to its capabilities. This allows a
client to discover information about the supported methods,
content types, extensions, codec, etc. without "ringing" the other
party. For example, before a client inserts a Require header field
into an INVITE listing an option that it is not certain the
destination UAS supports, the client can query the destination
UAS with an OPTIONS to see if this option is returned in a
Supported header field. All UAs MUST support the OPTIONS
method.
SIP SESSION SETUP
(1)SESSION ESTABLISHMENT AND TERMINATION: Figure
shows the interaction between a User Agent Client (UAC) and a
User Agent Server (UAS) during trivial session establishment
and termination

SESSION ESTABLISHMENT CALL FLOW:-


1. The calling User Agent Client sends an INVITE message to Bob’s
SIP address: sip:bob@acme.com. This message also contains an
SDP packet describing the media capabilities of the calling
terminal.
2. The UAS receives the request and immediately responds with a
100-Trying response message.
3. The UAS starts “ringing” to inform Bob of the new call.
Simultaneously a 180 (Ringing) message is sent to the UAC.
4. The UAS sends a 182 (Queued) call status message to report
that the call is behind two other calls in the queue.
5. The UAS sends a 182 (Queued) call status message to report
that the call is behind one other call in the queue.
6. Bob picks up the call and the UAS sends a 200 (OK) message to
the calling UA. This message also contains an SDP packet
describing the media capabilities of Bob’s terminal.
7. The calling UAC sends an ACK request to confirm the 200 (OK)
response was received.

SESSION TERMINATION CALL FLOW:-


1. The caller decides to end the call and “hangs-up”. This results
in a BYE request being sent to Bob’s UAS at SIP address
sip:bob@lab.acme.com
2. Bob’s UAS responds with 200 (OK) message and notifies Bob
that the conversation has ended.

(2)SESSION REDIRECTION: A Simple Call Redirection Scenario.


Session Redirection Call Flow:-
1. First a SIP INVITE message is sent to bob@acme.com, but finds
the Redirect server sip.acme.com along the signaling path.
2. The Redirect server looks up Bob’s current location in a
Location Service using a non-SIP protocol (for example, LDAP).
3. The Location Service returns Bob’s current location: SIP
address 3573572@gwtelco.com.
4. The Redirect Server returns this information to the calling UAC
using a 302 (Moved Temporarily) response. In the response
message it enters a contact header and sets the value to Bob’s
current location,
3573572@gwtelco.com.
5. The calling UAC acknowledges the response by sending an ACK
message.
6. The calling UAC then continues the transaction directly with
gw.telco.com by sending a new INVITE.
7. gw.telco.com is able to notify Bob’s terminal of the call and Bob
“picks up” the call. A 200 (OK) response is sent back to the calling
UAC.
8. The calling UAC acknowledges with an ACK message.
(3)SESSION PROXYING:-

Session Proxying Call Flow:-


1. An INVITE message is sent to bob@ acme.com, but finds the
Proxy server sip.acme.com along the signaling path.
2. The Proxy server immediately responds with a 100 (Trying)
provisional response.
3. The Proxy server looks-up Bob’s current location in a Location
Service using a non-SIP protocol (For example, LDAP).
4. The Location Service returns Bob’s current location: SIP
address bob@lab.acme.com.
5. The Proxy server decides to proxy the call and creates a new
INVITE message based on the original INVITE message, but with
the request URI in the start line changed to bob@lab.acme.com.
The Proxy server sends this request to the UAS at lab.acme.com.
6. The UAS responds first with a 100 (Trying).
7. The UAS responds with a 180 (Ringing) response.
8. The Proxy server forwards the 180 (Ringing) response back to
the calling UA.
9. When the call is accepted by the user (for example, by picking
up the handset) the UAS at lab.acme.com sends a 200 (OK)
response. In this example, Bob’s UAS inserts a Contact header
into the response with the value bob@lab.acme.com. Further SIP
communication will be sent directly to it and not via the Proxy
Server. This action is optional.
10. The Proxy forwards the 200 (OK) response back to the calling
UAC.
11. The calling UA sends an ACK directly to Bob’s UA at the lab
(according to the Contact header it found in the 200 (OK)
response).

SESSION DESCRIPTION PROTOCOL (SDP): SDP is the protocol


used to describe multimedia session announcement, multimedia
session invitation and other forms of multimedia session initiation.
A multimedia session is defined, for these purposes, as a set of
media streams that exist for duration of time.

SDP packets usually include the following information:

Session information:
 Session name and purpose.
 Time(s) the session is active.
 Information about the bandwidth to be used by the session.
 Contact information for the person responsible for the
session.

Media information:
 Type of media, such as video and audio.
 Transport protocol, such as RTP/UDP/IP and H.320
 Media format, such as H.261 video and MPEG video.
 Multicast address and Transport Port for media (IP multicast
session).
 Remote addresses for media and Transport port for contact
address (IP unicast session).
SIP MOBILITY MODES
SIP Pioneer Henning Schulzrinne defines 3 Modes for SIP Mobility:

(1)TERMINAL MOBIITY: Terminal mobility refers to the


traditional mobility that one thinks of when speaking about a
mobile phone. The terminal itself is mobile and can move around
a geographical space and connect to multiple network
attachment points using the same identifier, i.e. a cell phone can
move from one cell to another without disconnecting a call.
Terminal mobility can be implemented in different protocol layers.
Mobile IP provides a network layer mobility solution that hides
address changes from protocols running on top of the network
layer (IP).
Mobile IP does this by providing two IP addresses: one constant
address as the end point identifier, and one temporary care-of
address for the location of the terminal. SIP on the other hand
provides application layer mobility, where the application itself
detects the movement of the device and adapts to the new
location and can maintain connectivity even if the IP address of
the device is changed. SIP handles terminal mobility by modifying
(i.e. changing the IP address of) an existing session with the
SIP registration mechanism and the re-INVITE method. The SIP
registration mechanism binds a user level identifier to a
temporary IP address or host name instead of a permanent IP
address.

(2)USER MOBILITY: User mobility means that the user is


reachable under the same identifier on several networks, at
several terminals, possibly at the same time. In other words a
user can be reached on any device that has been registered into
a location service by the use via a single SIP address, making the
user’s device choice transparent to third parties that are trying to
reach them. This means that the user is able to move across
different terminal devices and be reached with the same logical
address, the SIP address.
For example a user may want to be reachable via a traditional
PSTN phone, a PC and a wireless device. The user may want to
use these devices either at the same time or alternate between
them.
The user may want to use different devices for different purposes,
e.g., for private and professional communication. The SIP address
incorporates all addresses under it and thus enables user
mobility.
The user is contacted on the device, in the location and with the
interaction mode, that the user has registered himself with for
that moment as a preference. SIP Proxy Servers, Redirect Servers
and
Registrars handle user mobility.

(3) SERVICE MOBILITY


Service mobility is when the user is able to access the same
services, independent of device and network used. Example
Services are: user address book, speed dial entries and buddy
lists, to name a few. Service mobility is a desirable feature for
networks that enable user mobility. Since user mobility assumes
that the end user uses multiple devices (personal and non-
personal), it follows that the user should have the same services
available for all used devices.

(4)SESSION MOBILITY
Session mobility means that it is possible to move an on-going
session to new terminal(s) without terminating the session.
Session mobility also incorporates the ability to split a session
across end devices into one collaborative application e.g. wall
display, cell phone and pc (softphone). Session mobility is
handled in SIP with the REFER method. SIP only needs to know
that the entity of the new device is the same entity as it was for
the previous address (not who the person really is). To initiate the
session transfer a REFER request is sent that indicates the new
address where the session is moved to. The receiver of the REFER
request then negotiates a new session to the new address using
the normal INVITE exchange. If the session is to be split across
multiple participants, each participant must be invited separately.
For example additional media (e.g. video streaming) could be
added to a call after moving the call from a cell phone to a PC
softphone. The Cell phone might have not supported video
streaming or the user might simply not have been willing to pay
for video over the mobile network. The session can be modified
with the SIP MODIFY method.

SIP MESSAGE FORMAT


SIP messages have three kinds of headers:
 General Headers: These are used in both requests &
responses and contain basic information like TO and FROM
fields.
 Request Header: Part of Request messages and contains
fields like SUBJECT and PRIORITY.
 Response Header: Part of Response Messages and
contains fields like UNSUPPORTED and RETRY-AFTER fields.
(1)SIP REQUEST MESSAGE:
The requestor (Alice) wants to connect with the server (Bob) .The
INVITE request contains a number of header fields. Header fields
are named attributes that include a unique identifier for the call,
the destination address, Alice's address, and information about
the type of session that Alice wishes to establish with Bob.
(2)SIP RESPONSE MESSAGE: The Server (Bob) now acts as a
Client and send Response to the callee (Alice). The Response
contains a number of header fields repeated from Request
message and very few changes are made in the rest of the
Header Files. After the recipient of Response Message by Alice,
the task of SIP Server is finished and Communications takes place
between Alice and Bob directly without further interruptions.
SIP SOFTPHONE OVERVIEW
In computing, a softphone is a software program for making
telephone calls over the Internet using a general purpose
computer, rather than using dedicated hardware. Often a
softphone is designed to behave like a traditional telephone,
sometimes appearing as an image of a phone, with a display
panel and buttons with which the user can interact.

LINPHONE is a VoIP application for Linux operating system uses


the Session Initiation Protocol for communication and is licensed
under the GNU General Public License. Linphone uses GTK+ for
GUI and on Linux it can be also run as a console-mode
application. Of course, even though Linphone is a software tool, in
order to use it, you’ll need some basic hardware, such as a
headset and a microphone. And if you want to use Linphone as a
complete phone system you’ll need an account with a VoIP
provider.

Audio codec support: Speex (narrow band and wideband), G.711,


GSM, and iLBC , Video codec support: H263-1998, MPEG-4, Theora
and H.264 (thanks to a plug-in based on x264), with resolutions
from QCIF(176x144) to SVGA(800x600) provided that network
bandwidth and CPU power are sufficient.

Features:
• Audio with the following codec: Speex (narrow band and
wideband), G711 (ulaw,alaw), GSM, and iLBC (through an
optional plug-in)
• Video with codec: H263-1998, MPEG4, theora and H264
(thanks to a plug-in based on x264), with resolutions from
QCIF (176x144) to SVGA (800x600) provided that network
bandwidth and CPU power are sufficient.
• Supports any webcam with V4L or V4L2 driver under Linux
• Text instant messaging and presence
• Address book
• DTMF (telephone tones) support using SIP INFO or RFC2833
• Echo cancelation using the Speex Echo Canceller
• SIP proxy support: registrar, proxies, with digest
authentication
• STUN support for traversal of UDP NATs
• Sound backend using either ALSA (the most efficient), OSS,
or arts (KDE sound daemon)
• Supports IPv6
• Bandwidth limitations are signaled using SDP resulting in
audio and video session established with bitrates that fits
the user's network capabilities.
• Can use plug-in: to add new codec, or new core
functionalities.

Linphone is divided in two parts:

 The User Frontends: The gtk+/glade interface

 Liblinphone: This is the library that implements all the


functionalities of linphone.
It depends on these parts:

• eXosip2: The SIP user agent library, based on libosip2

• mediastreamer2: A powerful library to make


audio/video streaming and processing.

• ortp: A RTP library.

Mediastreamer2 - the multimedia streaming engine


Mediastreamer2 is a powerful and light weighted streaming
engine specialized for voice/video telephony applications.
It is the library that is responsible for all the receiving and sending
of multimedia streams in linphone, including voice/video capture,
encoding and decoding, and rendering.

Features:
• Read/Write from to an alsa device, an oss device, a windows
waveapi device
• Send and receive RTP packets
• Encode and decode the following formats: speex, G711,
GSM, H263, theora, iLBC, MPEG4, and H264.
• Read and write from/to a wav file
• Read YUV pictures from a webcam (provided that it has
video4linux v1 or v2 driver)
• Display YUV pictures (using SDL library or native apis on
windows)
• Dual tones generation
• Echo cancelation, using the extraordinary echo canceler
algorithm from the speex library
• Audio conferencing
• Audio parametric equalizer using a FIR filter
• Volume control, automatic gain control
• Works on linux, windows XP
• macos X audio only, video support in progress

Mediastreamer2 can be extended with dynamic plugins, currently


a H264 and an ILBC codec plugins are available.

ortp, a Real-time Transport Protocol library


Features:

• Written in C, works under Linux (and probably any Unix) and


Windows.
• Implement the RFC3550 (RTP) with a easy to use API with
high and low level access.
• Includes support for multiples profiles, AV profile (RFC3551)
being the one by default.
• Includes a packet scheduler for to send and recv packet "on
time", according to their timestamp. Scheduling is optionnal,
rtp sessions can remain not scheduled.
• Supports mutiplexing IO, so that hundreds of RTP sessions
can be scheduled by a single thread.
• Features an adaptive jitter algorithm for a receiver to adapt
to the clockrate of the sender.
• Supports part of RFC2833 for telephone events over RTP.
• The API is well documented using gtk-doc.
• Licensed under the Lesser Gnu Public License.
• RTCP messages sent periodically since 0.7.0 (compound
packet including sender report or receiver report + SDES)
• Includes an API to parse incoming RTCP packets.

liblinphone
liblinphone is a high level library to make a SIP phone.

This library includes ALL the features of linphone. It is designed to


be easy to use, directly from a user interface.
Its API is described in coreapi/linphonecore.h .
Making a SIP call is as easy as:
/* first create a LinphoneCore object: this initialize your virtual SIP
phone*/
/* note: vtable is a structure that contains callbacks you must
implement to get notified
of various kind of information*/
LinphoneCore *lc=linphone_core_new(&vtable,".myconfig",NULL);
/* initiate an outgoing call*/
linphone_core_invite(lc,"sip:alice@example.net");
...
/* and periodically (ex: every 100ms) call this function to make
the linphone engine to work:*/
linphone_core_iterate(lc);

/*terminate this call*/


linphone_core_terminate(lc,"sip:alice@example.net");
CODING

config.h
/* config.h. Generated from config.h.in by configure. */

/* config.h.in. Generated from configure.in by autoheader. */

/* Define if building universal (internal helper macro) */

/* #undef AC_APPLE_UNIVERSAL_BUILD */

/* Tells whether localisation is possible */

#define ENABLE_NLS 1

/* The name of the gettext package name */

#define GETTEXT_PACKAGE "linphone"

/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the

CoreFoundation framework. */

/* #undef HAVE_CFLOCALECOPYCURRENT */

/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in

the CoreFoundation framework. */

/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */

/* Define if the GNU dcgettext() function is already present or preinstalled.

*/
#define HAVE_DCGETTEXT 1

/* Define to 1 if you have the <dlfcn.h> header file. */

#define HAVE_DLFCN_H 1

/* Defined when eXosip_get_version is available */

#define HAVE_EXOSIP_GET_VERSION 1

/* Define to 1 if you have the `getifaddrs' function. */

#define HAVE_GETIFADDRS 1

/* Tells wheter localisation is possible */

#define HAVE_GETTEXT 1

/* Define to 1 if you have the `get_current_dir_name' function. */

#define HAVE_GET_CURRENT_DIR_NAME 1

/* Define to 1 if you have the <history.h> header file. */

/* #undef HAVE_HISTORY_H */

/* Define if you have the iconv() function. */

/* #undef HAVE_ICONV */

/* Define to 1 if you have the <inttypes.h> header file. */

#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `eXosip2' library (-leXosip2). */

#define HAVE_LIBEXOSIP2 1

/* Define to 1 if you have the `intl' library (-lintl). */

/* #undef HAVE_LIBINTL */

/* Define to 1 if you have the `ortp' library (-lortp). */

/* #undef HAVE_LIBORTP */

/* Define to 1 if you have the <memory.h> header file. */

#define HAVE_MEMORY_H 1

/* Define to 1 if you have the <readline.h> header file. */

/* #undef HAVE_READLINE_H */

/* Define to 1 if you have the <readline/history.h> header file. */

#define HAVE_READLINE_HISTORY_H 1

/* Define to 1 if you have the <readline/readline.h> header file. */

#define HAVE_READLINE_READLINE_H 1

/* Define to 1 if you have the <stdint.h> header file. */

#define HAVE_STDINT_H 1

/* Define to 1 if you have the <stdlib.h> header file. */

#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `stpcpy' function. */

#define HAVE_STPCPY 1

/* Define to 1 if you have the <strings.h> header file. */

#define HAVE_STRINGS_H 1

/* Define to 1 if you have the <string.h> header file. */

#define HAVE_STRING_H 1

/* Define to 1 if you have the `strndup' function. */

#define HAVE_STRNDUP 1

/* Define to 1 if you have the <sys/stat.h> header file. */

#define HAVE_SYS_STAT_H 1

/* Define to 1 if you have the <sys/types.h> header file. */

#define HAVE_SYS_TYPES_H 1

/* Define to 1 if you have the <unistd.h> header file. */

#define HAVE_UNISTD_H 1

/* All supported languages */

#define LINPHONE_ALL_LANGS "fr it de ja es pl cs nl sv pt_BR hu ru zh_CN"

/* Windows appdata subdir where linphonerc can be found */


#define LINPHONE_CONFIG_DIR "Linphone"

/* path of liblinphone plugins, not mediastreamer2 plugins */

#define LINPHONE_PLUGINS_DIR "/usr/local/lib/liblinphone/plugins"

/* Linphone's version number */

#define LINPHONE_VERSION "3.2.1"

/* Define to the sub-directory in which libtool stores uninstalled libraries.

*/

#define LT_OBJDIR ".libs/"

/* Define to 1 if your C compiler doesn't accept -c and -o together. */

/* #undef NO_MINUS_C_MINUS_O */

/* Name of package */

/* #undef PACKAGE */

/* Define to the address where bug reports for this package should be sent. */

/* #undef PACKAGE_BUGREPORT */

/* Defines the place where data are found */

#define PACKAGE_DATA_DIR "/usr/local/share"

/* Defines the place where locales can be found */

#define PACKAGE_LOCALE_DIR "/usr/local/share/locale"


/* Define to the full name of this package. */

/* #undef PACKAGE_NAME */

/* Defines the place where linphone sounds are found */

#define PACKAGE_SOUND_DIR "/usr/local/share/sounds/linphone"

/* Define to the full name and version of this package. */

/* #undef PACKAGE_STRING */

/* Define to the one symbol short name of this package. */

/* #undef PACKAGE_TARNAME */

/* Define to the home page for this package. */

/* #undef PACKAGE_URL */

/* Define to the version of this package. */

/* #undef PACKAGE_VERSION */

/* Define to 1 if you have the ANSI C header files. */

/* #undef STDC_HEADERS */

/* Tell whether date_version.h must be used */

/* #undef USE_BUILDDATE_VERSION */

/* Version number of package */


/* #undef VERSION */

/* defined if video support is available */

#define VIDEO_ENABLED 1

/* Tell whether RSVP support should be compiled. */

/* #undef VINCENT_MAURY_RSVP */

/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most

significant byte first (like Motorola and SPARC, unlike Intel). */

#if defined AC_APPLE_UNIVERSAL_BUILD

# if defined __BIG_ENDIAN__

# define WORDS_BIGENDIAN 1

# endif

#else

# ifndef WORDS_BIGENDIAN

/* # undef WORDS_BIGENDIAN */

# endif

#endif

/* Defined if we are compiling for arm processor */

/* #undef __ARM__ */

/* Define to `__inline__' or `__inline' if that's what the C compiler

calls it, or to nothing if 'inline' is not supported under any name. */

#ifndef __cplusplus
/* #undef inline */

#endif

Linphonec.c
#include <errno.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <limits.h>
#include <ctype.h>

#include <linphonecore.h>
#include "private.h" /*coreapi/private.h, needed for LINPHONE_VERSION */
#include "linphonec.h"

#ifdef WIN32
#include <ws2tcpip.h>
#include <ctype.h>
#include <conio.h>
#else
#include <sys/socket.h>
#include <netdb.h>
#include <sys/un.h>
#include <sys/stat.h>
#endif
#ifdef HAVE_GETTEXT

#include <libintl.h>

#ifndef _

#define _(String) gettext(String)

#endif

#else

#define _(something) (something)

#endif

/***************************************************************************
*
* Types
*
***************************************************************************/
typedef struct {
LinphoneAuthInfo *elem[MAX_PENDING_AUTH];
int nitems;
} LPC_AUTH_STACK;

/***************************************************************************
*
* Forward declarations
*
***************************************************************************/

char *lpc_strip_blanks(char *input);

static int handle_configfile_migration(void);


static int copy_file(const char *from, const char *to);
static int linphonec_parse_cmdline(int argc, char **argv);
static int linphonec_init(int argc, char **argv);
static int linphonec_main_loop (LinphoneCore * opm, char * sipAddr);
static int linphonec_idle_call (void);
#ifdef HAVE_READLINE
static int linphonec_initialize_readline(void);
static int linphonec_finish_readline();
static char **linephonec_readline_completion(const char *text,
int start, int end);
#endif

/* These are callback for linphone core */


static void linphonec_call_received(LinphoneCore *lc, const char *from);
static void linphonec_prompt_for_auth(LinphoneCore *lc, const char *realm,
const char *username);
static void linphonec_display_something (LinphoneCore * lc, const char
*something);
static void linphonec_display_url (LinphoneCore * lc, const char *something,
const char *url);
static void linphonec_display_warning (LinphoneCore * lc, const char
*something);
static void stub () {}
static void linphonec_notify_received(LinphoneCore *lc,LinphoneFriend *fid,
const char *from, const char *status, const char *img);
static void linphonec_new_unknown_subscriber(LinphoneCore *lc,
LinphoneFriend *lf, const char *url);
static void linphonec_bye_received(LinphoneCore *lc, const char *from);
static void linphonec_text_received(LinphoneCore *lc, LinphoneChatRoom *cr,
const char *from, const char *msg);
static void linphonec_display_status (LinphoneCore * lc, const char
*something);
static void linphonec_general_state (LinphoneCore * lc, LinphoneGeneralState
*gstate);
static void linphonec_dtmf_received(LinphoneCore *lc, int dtmf);
static void print_prompt(LinphoneCore *opm);
/***************************************************************************
*
* Global variables
*
***************************************************************************/

LinphoneCore linphonec;
FILE *mylogfile;
#ifdef HAVE_READLINE
static char *histfile_name=NULL;
static char last_in_history[256];
#endif
//auto answer (-a) option
static bool_t auto_answer=FALSE;
static bool_t answer_call=FALSE;
static bool_t vcap_enabled=FALSE;
static bool_t display_enabled=FALSE;
static bool_t preview_enabled=FALSE;
static bool_t show_general_state=FALSE;
static bool_t unix_socket=FALSE;
static bool_t linphonec_running=TRUE;
LPC_AUTH_STACK auth_stack;
static int trace_level = 0;
static char *logfile_name = NULL;
static char configfile_name[PATH_MAX];
static char *sipAddr = NULL; /* for autocall */
static ortp_pipe_t client_sock=ORTP_PIPE_INVALID;
char prompt[PROMPT_MAX_LEN];

static ortp_thread_t pipe_reader_th;


static bool_t pipe_reader_run=FALSE;
static ortp_pipe_t server_sock;

LinphoneCoreVTable linphonec_vtable = {
.show =(ShowInterfaceCb) stub,
.inv_recv = linphonec_call_received,
.bye_recv = linphonec_bye_received,
.notify_recv = linphonec_notify_received,
.new_unknown_subscriber = linphonec_new_unknown_subscriber,
.auth_info_requested = linphonec_prompt_for_auth,
.display_status = linphonec_display_status,
.display_message=linphonec_display_something,
#ifdef VINCENT_MAURY_RSVP
/* the yes/no dialog box */
.display_yes_no= (DisplayMessageCb) stub,
#endif
.display_warning=linphonec_display_warning,
.display_url=linphonec_display_url,
.display_question=(DisplayQuestionCb)stub,
.text_received=linphonec_text_received,
.general_state=linphonec_general_state,
.dtmf_received=linphonec_dtmf_received
};

/***************************************************************************
*
* Linphone core callbacks
*
***************************************************************************/

/*
* Linphone core callback
*/
static void
linphonec_display_something (LinphoneCore * lc, const char *something)
{
fprintf (stdout, "%s\n%s", something,prompt);
fflush(stdout);
}

/*
* Linphone core callback
*/
static void
linphonec_display_status (LinphoneCore * lc, const char *something)
{
fprintf (stdout, "%s\n%s", something,prompt);
fflush(stdout);
}

/*
* Linphone core callback
*/
static void
linphonec_display_warning (LinphoneCore * lc, const char *something)
{
fprintf (stdout, "Warning: %s\n%s", something,prompt);
fflush(stdout);
}

/*
* Linphone core callback
*/
static void
linphonec_display_url (LinphoneCore * lc, const char *something, const char
*url)
{
fprintf (stdout, "%s : %s\n", something, url);
}

/*
* Linphone core callback
*/
static void
linphonec_call_received(LinphoneCore *lc, const char *from)
{
linphonec_set_caller(from);
if ( auto_answer) {
answer_call=TRUE;
}
}

/*
* Linphone core callback
*/
static void
linphonec_prompt_for_auth(LinphoneCore *lc, const char *realm, const char
*username)
{
/* no prompt possible when using pipes or tcp mode*/
if (unix_socket){
linphone_core_abort_authentication(lc,NULL);
}else{
LinphoneAuthInfo *pending_auth;

if ( auth_stack.nitems+1 > MAX_PENDING_AUTH )


{
fprintf(stderr,
"Can't accept another authentication request.\n"
"Consider incrementing MAX_PENDING_AUTH macro.\n");
return;
}

pending_auth=linphone_auth_info_new(username,NULL,NULL,NULL,realm
);
auth_stack.elem[auth_stack.nitems++]=pending_auth;
}
}

/*
* Linphone core callback
*/
static void
linphonec_notify_received(LinphoneCore *lc,LinphoneFriend *fid,
const char *from, const char *status, const char *img)
{
printf("Friend %s is %s\n", from, status);
// todo: update Friend list state (unimplemented)
}

/*
* Linphone core callback
*/
static void
linphonec_new_unknown_subscriber(LinphoneCore *lc, LinphoneFriend *lf,
const char *url)
{
printf("Friend %s requested subscription "
"(accept/deny is not implemented yet)\n", url);
// This means that this person wishes to be notified
// of your presence information (online, busy, away...).

linphonec_text_received(LinphoneCore *lc, LinphoneChatRoom *cr,


const char *from, const char *msg)
{
printf("%s: %s\n", from, msg);
// TODO: provide mechanism for answering.. ('say' command?)
}

static void linphonec_dtmf_received(LinphoneCore *lc, int dtmf){


fprintf(stdout,"Receiving tone %c\n",dtmf);
fflush(stdout);
}

static void
linphonec_general_state (LinphoneCore * lc, LinphoneGeneralState *gstate)
{
if (show_general_state) {
switch(gstate->new_state) {
case GSTATE_POWER_OFF:
printf("GSTATE_POWER_OFF");
break;
case GSTATE_POWER_STARTUP:
printf("GSTATE_POWER_STARTUP");
break;
case GSTATE_POWER_ON:
printf("GSTATE_POWER_ON");
break;
case GSTATE_POWER_SHUTDOWN:
printf("GSTATE_POWER_SHUTDOWN");
break;
case GSTATE_REG_NONE:
printf("GSTATE_REG_NONE");
break;
case GSTATE_REG_OK:
printf("GSTATE_REG_OK");
break;
case GSTATE_REG_FAILED:
printf("GSTATE_REG_FAILED");
break;
case GSTATE_CALL_IDLE:
printf("GSTATE_CALL_IDLE");
break;
case GSTATE_CALL_OUT_INVITE:
printf("GSTATE_CALL_OUT_INVITE");
break;
case GSTATE_CALL_OUT_CONNECTED:
printf("GSTATE_CALL_OUT_CONNECTED");
break;
case GSTATE_CALL_IN_INVITE:
printf("GSTATE_CALL_IN_INVITE");
break;
case GSTATE_CALL_IN_CONNECTED:
printf("GSTATE_CALL_IN_CONNECTED");
break;
case GSTATE_CALL_END:
printf("GSTATE_CALL_END");
break;
case GSTATE_CALL_ERROR:
printf("GSTATE_CALL_ERROR");
break;
default:
printf("GSTATE_UNKNOWN_%d",gstate->new_state);
}
if (gstate->message) printf(" %s", gstate->message);
printf("\n");
}
}

static char received_prompt[PROMPT_MAX_LEN];


static ms_mutex_t prompt_mutex;
static bool_t have_prompt=FALSE;

static void *prompt_reader_thread(void *arg){


char *ret;
char tmp[PROMPT_MAX_LEN];
while ((ret=fgets(tmp,sizeof(tmp),stdin))!=NULL){
ms_mutex_lock(&prompt_mutex);
strcpy(received_prompt,ret);
have_prompt=TRUE;
ms_mutex_unlock(&prompt_mutex);
}
return NULL;
}

static void start_prompt_reader(void){


ortp_thread_t th;
ms_mutex_init(&prompt_mutex,NULL);
ortp_thread_create(&th,NULL,prompt_reader_thread,NULL);
}

static ortp_pipe_t create_server_socket(void){


char path[128];
#ifndef WIN32
snprintf(path,sizeof(path)-1,"linphonec-%i",getuid());
#else
{
char username[128];
DWORD size=sizeof(username)-1;
GetUserName(username,&size);
snprintf(path,sizeof(path)-1,"linphonec-%s",username);
}
#endif
return ortp_server_pipe_create(path);
}

static void *pipe_thread(void*p){


char tmp[250];
server_sock=create_server_socket();
if (server_sock==ORTP_PIPE_INVALID) return NULL;
while(pipe_reader_run){
while(client_sock!=ORTP_PIPE_INVALID){ /*sleep until the last
command is finished*/

/***************************************************************************/
/*
* Main
*
* Use globals:
*
* - char *histfile_name
* - FILE *mylogfile
*/
int
main (int argc, char *argv[])
{

if (! linphonec_init(argc, argv) ) exit(EXIT_FAILURE);

linphonec_main_loop (&linphonec, sipAddr);

linphonec_finish(EXIT_SUCCESS);

exit(EXIT_SUCCESS); /* should never reach here */


}

/*
* Initialize linphonec
*/
static int
linphonec_init(int argc, char **argv)
{

//g_mem_set_vtable(&dbgtable);

/*
* Set initial values for global variables
*/
mylogfile = NULL;
snprintf(configfile_name, PATH_MAX, "%s/.linphonerc",
getenv("HOME"));

/* Handle configuration filename changes */


switch (handle_configfile_migration())
{
case -1: /* error during file copies */
fprintf(stderr,
"Error in configuration file migration\n");
break;

case 0: /* nothing done */


case 1: /* migrated */
default:
break;
}

void
print_usage (int exit_status)
{
fprintf (stdout, "\n\
usage: linphonec [-c file] [-s sipaddr] [-a] [-V] [-d level ] [-l logfile]\n\
linphonec -v\n\
\n\
-c file specify path of configuration file.\n\
-d level be verbose. 0 is no output. 6 is all output\n\
-l logfile specify the log file for your SIP phone\n\
-s sipaddress specify the sip call to do at startup\n\
-a enable auto answering for incoming calls\n\
-V enable video features globally (disabled by default)\n\
-C enable video capture only (disabled by default)\n\
-D enable video display only (disabled by default)\n\
-S show general state messages (disabled by default)\n\
-v or --version display version and exits.\n");

exit(exit_status);
}

/*
*
* Called every second from main read loop.
*
* Will use the following globals:
*
* - LinphoneCore linphonec
* - LPC_AUTH_STACK auth_stack;
*
*/
static int
linphonec_idle_call ()
{
LinphoneCore *opm=&linphonec;

/* Uncomment the following to verify being called */


/* printf(".\n"); */

linphone_core_iterate(opm);
if (answer_call){
fprintf (stdout, "-------auto answering to call-------\n" );
linphone_core_accept_call(opm,NULL);
answer_call=FALSE;
}

if ( auth_stack.nitems )
{
/*
* Inhibit command completion
* during password prompts
*/
#ifdef HAVE_READLINE
rl_inhibit_completion=1;
#endif
linphonec_prompt_for_auth_final(opm);
#ifdef HAVE_READLINE
rl_inhibit_completion=0;
#endif
}

return 0;
}

#ifdef HAVE_READLINE
/*
* Use globals:
*
* - char *histfile_name (also sets this)
* - char *last_in_history (allocates it)
*/
static int
/*
* Parse command line switches
*
* Use globals:
*
* - int trace_level
* - char *logfile_name
* - char *configfile_name
* - char *sipAddr
*/
static int
linphonec_parse_cmdline(int argc, char **argv)
{
int arg_num=1;

while (arg_num < argc)


{
int old_arg_num = arg_num;
if (strncmp ("-d", argv[arg_num], 2) == 0)
{
arg_num++;
if (arg_num < argc)
trace_level = atoi (argv[arg_num]);
else
trace_level = 1;
}
else if (strncmp ("-l", argv[arg_num], 2) == 0)
{
arg_num++;
if (arg_num < argc)
logfile_name = argv[arg_num];
}
else if (strncmp ("-c", argv[arg_num], 2) == 0)
{
if ( ++arg_num >= argc ) print_usage(EXIT_FAILURE);

if (access(argv[arg_num],F_OK)!=0 )
{
fprintf (stderr,
"Cannot open config file %s.\n",
argv[arg_num]);
exit(EXIT_FAILURE);
}
snprintf(configfile_name, PATH_MAX, "%s", argv[arg_num]);
}
else if (strncmp ("-s", argv[arg_num], 2) == 0)
{
arg_num++;
if (arg_num < argc)
sipAddr = argv[arg_num];
}
else if (strncmp ("-a", argv[arg_num], 2) == 0)
{
auto_answer = TRUE;
}
else if (strncmp ("-C", argv[arg_num], 2) == 0)
{
vcap_enabled = TRUE;
}
else if (strncmp ("-D", argv[arg_num], 2) == 0)
{
display_enabled = TRUE;
}
else if (strncmp ("-V", argv[arg_num], 2) == 0)
{
display_enabled = TRUE;
vcap_enabled = TRUE;
preview_enabled=TRUE;
}
else if ((strncmp ("-v", argv[arg_num], 2) == 0)
||
(strncmp
("--version", argv[arg_num],
strlen ("--version")) == 0))
{
printf ("version: " LINPHONE_VERSION "\n");
exit (EXIT_SUCCESS);
}

return 1;
}

* This function helps transparently migrating from one


* to the other layout using the following heuristic:
*
* IF new_config EXISTS => do nothing
* ELSE IF old_cli_config EXISTS => copy to new_config
* ELSE IF old_gui_config EXISTS => copy to new_config
*
* Returns:
* 0 if it did nothing
* 1 if it migrated successfully
* -1 on error
*/
static int
#ifdef HAVE_READLINE
static char **
linephonec_readline_completion(const char *text, int start, int end)
{
char **matches = NULL;

/*
* Prevent readline from falling
* back to filename-completion
*/
rl_attempted_completion_over=1;

/*
* If this is the start of line we complete with commands
*/
if ( ! start )
{
return rl_completion_matches(text, linphonec_command_generator);
}

/*
* Otherwise, we should peek at command name
* or context to implement a smart completion.
* For example: "call .." could return
* friends' sip-uri as matches
*/

return matches;
}
#endif
/*
* Strip blanks from a string.
* Return a pointer into the provided string.
* Modifies input adding a NULL at first
* of trailing blanks.
*/
char *
lpc_strip_blanks(char *input)
{
char *iptr;

/* Find first non-blank */


while(*input && isspace(*input)) ++input;

/* Find last non-blank */


iptr=input+strlen(input);
if (iptr > input) {
while(isspace(*--iptr));
*(iptr+1)='\0';
}
return input
}
/****************************************************************************

shell.c
#include <stdio.h>

#include <stdlib.h>

#ifdef WIN32
#include <windows.h>

#include <winbase.h>

#include <ws2tcpip.h>

#include <ctype.h>

#include <conio.h>

#else

#include <sys/socket.h>

#include <netdb.h>

#include <sys/un.h>

#endif

#include "ortp/ortp.h"

#define DEFAULT_REPLY_SIZE 4096

#define STATUS_REGISTERED (1<<0)

#define STATUS_REGISTERING (1<<1)

#define STATUS_DIALING (1<<2)

#define STATUS_AUTOANSWER (1<<3)

#define STATUS_IN_CONNECTED (1<<4) /* incoming call accepted */

#define STATUS_OUT_CONNECTED (1<<5) /*outgoing call accepted */

static int make_status_value(const char *status_string){

int ret=0;

if (strstr(status_string,"registered, identity=")){

ret|=STATUS_REGISTERED;

if (strstr(status_string,"registered=-1")){
ret|=STATUS_REGISTERING;

if (strstr(status_string,"autoanswer=1")){

ret|=STATUS_AUTOANSWER;

if (strstr(status_string,"dialing")){

ret|=STATUS_DIALING;

if (strstr(status_string,"Call out")){

ret|=STATUS_OUT_CONNECTED;

if (strstr(status_string,"hook=answered")){

ret|=STATUS_IN_CONNECTED;

return ret;

static int send_command(const char *command, char *reply, int reply_len, int
print_errors){

ortp_pipe_t pp;

int i;

int err;

char path[128];

#ifndef WIN32

snprintf(path,sizeof(path)-1,"linphonec-%i",getuid());

#else

{
char username[128];

DWORD size=sizeof(username)-1;

GetUserName(username,&size);

snprintf(path,sizeof(path)-1,"linphonec-%s",username);

#endif

if ((pp=ortp_client_pipe_connect(path))==ORTP_PIPE_INVALID){

if (print_errors) fprintf(stderr,"ERROR: Failed to connect pipe:


%s\n",strerror(errno));

return -1;

if (ortp_pipe_write(pp,(uint8_t*)command,strlen(command))==-1){

if (print_errors) fprintf(stderr,"ERROR: Fail to send command to remote


linphonec\n");

ortp_client_pipe_close(pp);

return -1;

/*wait for replies */

i=0;

while ((err=ortp_pipe_read(pp,(uint8_t*)&reply[i],reply_len-i-1))>0){

i+=err;

reply[i]='\0';

ortp_client_pipe_close(pp);

return 0;

}
static void print_usage(void){

fprintf(stderr,"Usage:\nlinphonecsh <action> [arguments]\n"

"where action is one of\n"

"\tinit\t\t: spawn a linphonec daemon (first step to make other


actions)\n"

"\t\t\tfollowed by the arguments sent to linphonec\n"

"\tgeneric\t\t: sends a generic command to the running linphonec


daemon\n"

"\t\t\tfollowed by the generic command surrounded by quotes,\n\t\t\t for


example \"call sip:joe@example.net\"\n"

"\tregister\t: register; arguments are \n\t\t\t--host <host>\n\t\t\t--


username <username>\n\t\t\t--password <password>\n"

"\tunregister\t: unregister\n"

"\tdial\t\t: dial <sip uri or number>\n"

"\tstatus\t\t: can be 'status register', 'status autoanswer' or 'status


hook'\n"

"\tsoundcard\t: can be 'soundcard capture', 'soundcard playback',


'soundcard ring',\n"

"\t\t\t followed by an optional number representing the index of the


soundcard,\n"

"\t\t\t in which case the soundcard is set instead of just read.\n"

"\texit\t\t: make the linphonec daemon to exit.\n"

);

exit(-1);

#define MAX_ARGS 10

#ifndef WIN32
static void spawn_linphonec(int argc, char *argv[]){

char * args[10];

int i,j;

pid_t pid;

j=0;

args[j++]="linphonec";

args[j++]="--pipe";

args[j++]="-c";

args[j++]="/dev/null";

for(i=0;i<argc;++i){

args[j++]=argv[i];

args[j++]=NULL;

pid = fork();

if (pid < 0){

fprintf(stderr,"Could not fork\n");

exit(-1);

if (pid == 0) {

int fd;

/*we are the new process*/

setsid();

fd = open("/dev/null", O_RDWR);

if (fd==-1){
fprintf(stderr,"Could not open /dev/null\n");

exit(-1);

dup2(fd, 0);

dup2(fd, 1);

dup2(fd, 2);

close(fd);

if (execvp("linphonec",args)==-1){

fprintf(stderr,"Fail to spawn linphonec: %s\n",strerror(errno));

exit(-1);

#else

static void spawn_linphonec(int argc, char *argv[]){

PROCESS_INFORMATION pinfo;

STARTUPINFO si;

ZeroMemory( &si, sizeof(si) );

si.cb = sizeof(si);

ZeroMemory( &pinfo, sizeof(pinfo) );

BOOL ret=CreateProcess(NULL,"linphoned.exe --pipe -c NUL",

NULL,
NULL,

FALSE,

0,

NULL,

NULL,

&si,

&pinfo);

if (!ret){

fprintf(stderr,"Spawning of linphonec.exe failed.\n");

}else{

WaitForInputIdle(pinfo.hProcess,1000);

#endif

static int send_generic_command(const char *command, int print_result){

char reply[DEFAULT_REPLY_SIZE];

int err;

err=send_command(command,reply,sizeof(reply),print_result);

if (err==0 && print_result) {

printf("%s",reply);

fflush(stdout);

return err;

}
static int register_execute(int argc, char *argv[]){

char cmd[512];

char *username=NULL;

char *host=NULL;

char *passwd=NULL;

int i;

for(i=0;i<argc;++i){

if (strcmp(argv[i],"--host")==0){

i++;

if (i<argc){

host=argv[i];

}else print_usage();

}else if (strcmp(argv[i],"--username")==0){

i++;

if (i<argc){

username=argv[i];

}else print_usage();

}else if (strcmp(argv[i],"--password")==0){

i++;

if (i<argc){

passwd=argv[i];

}else print_usage();

}else print_usage();

if (username==NULL) {
fprintf(stderr,"Missing --username\n");

print_usage();

if (host==NULL) {

fprintf(stderr,"Missing --host\n");

print_usage();

if (passwd) snprintf(cmd,sizeof(cmd),"register sip:%s@%s sip:%s


%s",username,host,host,passwd);

else snprintf(cmd,sizeof(cmd),"register sip:%s@%s sip:


%s",username,host,host);

return send_generic_command(cmd,TRUE);

static int unregister_execute(int argc, char *argv[]){

return send_generic_command("unregister",FALSE);

static int dial_execute(int argc, char *argv[]){

char cmd[512];

if (argc==1){

snprintf(cmd,sizeof(cmd),"call %s",argv[0]);

return send_generic_command(cmd,TRUE);

}else{

print_usage();

return -1;

}
static int status_execute(int argc, char *argv[]){

char cmd[512];

char reply[DEFAULT_REPLY_SIZE];

int err;

if (argc==1){

snprintf(cmd,sizeof(cmd),"status %s",argv[0]);

err=send_command(cmd,reply,sizeof(reply),TRUE);

if (err==0) {

printf("%s",reply);

err=make_status_value(reply);

return err;

}else{

print_usage();

return -1;

static int parse_card_index(const char *reply){

int index=-1;

reply=strstr(reply,"device #");

if (!reply || sscanf(reply,"device #%i",&index)!=1){

fprintf(stderr,"Error while parsing linphonec daemon output !\n");

return index;

}
static int soundcard_execute(int argc, char *argv[]){

char cmd[512];

char reply[DEFAULT_REPLY_SIZE];

int err;

if (argc==1){

snprintf(cmd,sizeof(cmd),"soundcard %s",argv[0]);

err=send_command(cmd,reply,sizeof(reply),TRUE);

if (err==0) {

printf("%s",reply);

return parse_card_index(reply);

}else if (argc==2){/*setting a soundcard */

snprintf(cmd,sizeof(cmd),"soundcard %s %s",argv[0],argv[1]);

err=send_command(cmd,reply,sizeof(reply),TRUE);

if (err==0) {

printf("%s",reply);

return 0;

}else{

print_usage();

return -1;

int main(int argc, char *argv[]){

int argi;

if (argc<2){
print_usage();

return -1;

ortp_init();
for(argi=1;argi<argc;++argi){

if (strcmp(argv[argi],"init")==0){

/*check if there is running instance*/

if (send_generic_command("help",0)==0){

fprintf(stderr,"A running linphonec has been found, not spawning a


second one.\n");

return 0;

spawn_linphonec(argc-argi-1,&argv[argi+1]);

return 0;

}else if (strcmp(argv[argi],"generic")==0){

if (argi+1<argc){

return send_generic_command(argv[argi+1],1);

}else print_usage();

}else if (strcmp(argv[argi],"register")==0){

return register_execute(argc-argi-1,&argv[argi+1]);

}else if (strcmp(argv[argi],"unregister")==0){

return unregister_execute(argc-argi-1,&argv[argi+1]);

}else if (strcmp(argv[argi],"dial")==0){

return dial_execute(argc-argi-1,&argv[argi+1]);

}else if (strcmp(argv[argi],"hangup")==0){

send_generic_command("terminate",FALSE);
send_generic_command("duration",TRUE);

}else if (strcmp(argv[argi],"status")==0){

return status_execute(argc-argi-1,&argv[argi+1]);

}else if (strcmp(argv[argi],"soundcard")==0){

return soundcard_execute(argc-argi-1,&argv[argi+1]);

}else if (strcmp(argv[argi],"exit")==0){

return send_generic_command("quit",TRUE);

}else print_usage();

return 0;

IMPLEMENTATION SCREENS

1.LINPHONE INTERFACE
2.INCOMING CALL

3.CALLING USERAGENT

4.CALLEE USERAGENT
5.PRESENCE MANAGEABILITY
6.LINPHONE-CALL HISTORY

7
.LINPHONE-AUDIO AND VIDEO MODE
8.LINPHONE-NETWORK SETTINGS

9.LINPHONE-MULTIMEDIA SETTINGS

10.LINPHONE-MANAGE SIP ACCOUNTS


11.LINPHONE-CODECS
MAINTENANCE
The requirement of software maintenance arises on
account of the three main reasons

• CORRECTIVE: - Corrective maintenance of a


software product becomes necessary to rectify the
bugs observed while the system is in use

• ADAPTIVE:- A software product might need


maintenance when the customers need the product
to run on new platforms, on new operating systems,
or when they need the product to be interfaced with
new hardware or software.

• PERFECTIVE:- A software product needs


maintenance to support the new features that users
want it to support, to change different functionalities
of the system according to customer demands, or to
enhance the performance of the system.
CONCLUSION
The Project “SIP Based Softphone” has been developed
as per the Requirement Specifications. It has been
developed in Pure C and the complete “SIP Based
Softphone” has been completely utilized and tested with
available knowledge, resources and throughput reports
which are prepared manually.

The design of “SIP Based Softphone” is so flexible that


any modules and functionalities can be incorporated
easily in it.
BIBLIOGRAPHY
Books
Camarillo, G., “SIP Demystified”, 2002
Sinnreich, H., Johnston, A., “Internet Communications
Using SIP”, 2001
Johnston, A., “Understanding the Session Initiation
Protocol”, 2001
Web sites
SIP Forum: http://www.sipforum.org
SIP Center: http://www.sipcenter.com
SIP Advantage: http://www.sipadvantage.com
IETF
SIP WG: http://www.ietf.org/html.charters/sip-charter.html

Das könnte Ihnen auch gefallen