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”

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.

This project is going to consist of following modules, which are described as follows:

 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

  

JB Parameters RTP Profile RTP Session


• •

Console CoreApi

• •

gtk/glade Mediastreamer2

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

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 considered to be operational feasible.




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.

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 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 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.

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 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 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 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 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

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.

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.

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 ProxyRequire 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}



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 which is responsible for the domain receiving a request for must proxy the request to

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


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}

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.

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.

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.

(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: 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 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, but finds the Redirect server 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 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, 5. The calling UAC acknowledges the response by sending an ACK message. 6. The calling UAC then continues the transaction directly with by sending a new INVITE. 7. 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.


Session Proxying Call Flow:1. An INVITE message is sent to bob@, but finds the Proxy server 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 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 The Proxy server sends this request to the UAS at 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 sends a 200 (OK) response. In this example, Bob’s UAS inserts a Contact header into the response with the value 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 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 nonpersonal), 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 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.

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.


• •

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 audio/video streaming and processing. ortp: A RTP library. to make

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.

• • • • • • • • • • • • •

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 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,""); ... /* 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,"");

/* config.h. Generated from by configure. */ /* Generated from 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 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

#include #include #include #include #include #include #include #include <errno.h> <sys/time.h> <sys/types.h> <unistd.h> <string.h> <signal.h> <limits.h> <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) #endif
/*************************************************************************** * * Types * ***************************************************************************/


typedef struct { LinphoneAuthInfo *elem[MAX_PENDING_AUTH]; int nitems; } LPC_AUTH_STACK; /*************************************************************************** * * Forward declarations * ***************************************************************************/ char *lpc_strip_blanks(char *input); static static static static static static #ifdef static static static #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; int handle_configfile_migration(void); int copy_file(const char *from, const char *to); int linphonec_parse_cmdline(int argc, char **argv); int linphonec_init(int argc, char **argv); int linphonec_main_loop (LinphoneCore * opm, char * sipAddr); int linphonec_idle_call (void); HAVE_READLINE int linphonec_initialize_readline(void); int linphonec_finish_readline(); char **linephonec_readline_completion(const char *text, int start, int end);

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 -D -S -v or --version }

enable video capture only (disabled by default)\n\ enable video display only (disabled by default)\n\ show general state messages (disabled by default)\n\ display version and exits.\n");


/* * * 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)='###BOT_TEXT###'; } return input } /****************************************************************************

#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]='###BOT_TEXT###'; 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 ###BOT_TEXT###quot;call;\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); } }


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; }

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; }













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.

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.

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: SIP Center: SIP Advantage: IETF SIP WG: