Initial import

git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@1 3f6dc0c8-ddfe-455d-9043-3cd528dc4637
This commit is contained in:
aymeric 2008-09-04 15:47:34 +00:00
commit 2b8200409c
1602 changed files with 411919 additions and 0 deletions

24
linphone/.cvsignore Normal file
View file

@ -0,0 +1,24 @@
Makefile
Makefile.in
aclocal.m4
autom4te.cache
compile
config.guess
config.h
config.h.in
config.log
config.status
config.sub
configure
depcomp
install-sh
intltool-extract
intltool-merge
intltool-update
libtool
ltmain.sh
missing
mkinstalldirs
speex
stamp-h1
linphone.spec

1101
linphone/ABOUT-NLS Normal file

File diff suppressed because it is too large Load diff

57
linphone/AUTHORS Normal file
View file

@ -0,0 +1,57 @@
Simon MORLAT (simon dot morlat at linphone dot org) wrotes:
- main graphical program (gnome)
- RTP library (oRTP)
- SIP user-agent library (osipua)
- audio library (mediastreamer), for codec and i/o handling.
- sipomatic, the automatic sip replier, which is often used for testing.
Florian Wintertein < f-win at gmx dot net > wrotes the console version of linphone (linphonec)
in console/ directory.
Aymeric Moizard (jack at atosc dot org) wrotes:
- the oSIP SIP transactionnal stack (not part of linphone)
- some piece of code of the osip distribution have been reused in osipua
- presence information support in osipua
- and contributes to some parts of osipua (digest authentification)
For more information about oSIP, see http://osip.atosc.org
Sharath Udupa is developing the media_api, a usefull library to manage audio and video streams
for basic calls as well as conference.
Sandro Santilli < strk at keybit dot net > wrote enhancements in the
console interface (readline, new commands) and some bug fixes for
the core api.
Bryan Ogawa ( bko at cisco dot com ) sent a patch that made the linphone-0.7.1 release.
This patch fixed several issues in the SIP part while working with proxies.
Koichi KUNITAKE < kunitake at linux-ipv6 dot org > has contributed a patch bringing
full IPv6 support.
The Speex codec is a project from Jean Marc Valin. See http://speex.sourceforge.net for more
information.
The GSM library was written by :
Jutta Degener and Carsten Bormann,Technische Universitaet Berlin.
The LPC10-1.5 library was written by:
Andy Fingerhut
Applied Research Laboratory <-- this line is optional if
Washington University, Campus Box 1045/Bryan 509 you have limited space
One Brookings Drive
Saint Louis, MO 63130-4899
jaf@arl.wustl.edu
http://www.arl.wustl.edu/~jaf/
See text files in gsmlib and lpc10-1.5 directories for further information.
G711 library has some code from the alsa-lib on http://www.alsa-project.org
Icons by Pablo Marcelo Moia.
Translations:
fr: Simon Morlat
en: Simon Morlat and Delphine Perreau
it: Alberto Zanoni <alberto.zanoni@-NO-SPAM-PLEASE!-tiscalinet.it>
de: Jean-Jacques Sarton <jj.sarton@-NO-SPAM-PLEASE-t-online.de>
es: Jesús Benítez <gnelson at inMail dot sk>

9
linphone/BUGS Normal file
View file

@ -0,0 +1,9 @@
linphone-1.0.0:
It seems ipv6 support is "broken". Some help is welcome.
linphone-0.12.0
When compiling with gcc-2.95.4 on debian, an assert fails and cause abort()
in libasound (alsa-lib). When compiling with gcc-3.2, it does not happen.
It seems that asoundlib and linphone must be compiled with the same compiler.
Simon MORLAT

340
linphone/COPYING Normal file
View file

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

513
linphone/ChangeLog Normal file
View file

@ -0,0 +1,513 @@
2008-09-02 Francois-Xavier Kowalski <fix@hp.com>
* gtk/Makefile.am (INCLUDES): 1.6
Deprecated automake directive INCLUDES does not work within a
conditionnal.
2008-08-22 Francois-Xavier Kowalski <fix@hp.com>
* mediastreamer2/src/Makefile.am (libmediastreamer_la_SOURCES+): 1.27
Deliver swscale.h in case ffmpeg does not come with libswscale
(in which case the swscale feature is included into
libavcodec). Also deliver ffmpeg-priv.h wrapper.
* mediastreamer2/src/videoout.c: 1.39
* mediastreamer2/src/videodec.c: 1.24
* mediastreamer2/src/sizeconv.c: 1.14
* mediastreamer2/src/pixconv.c: 1.13
* mediastreamer2/src/nowebcam.c: 1.15
Use ffmpeg-priv,h
* mediastreamer2/mediastreamer-config.h.in: 1.13
Remove from CVSm as it is generated by autoheader
* mediastreamer2/configure.ac: 1.47
Use pkg-config to check for arts
* mediastreamer2/acinclude.m4: 1.12
Remove -I/usr/include and -L/usr/lib(64) from CFLAGS and LIBS.
Check for ffmpeg swscale feature into libavcodec or into
libswscale
2007-09-26 Francois-Xavier Kowalski <fix@hp.com>
* m4/exosip.m4: 1.3
make Linphone buildable with the eXosip/osip version that ships
with Fedora.
* oRTP/include/ortp/stun_udp.h: 1.9
* mediastreamer2/include/mediastreamer2/msvideo.h: 1.7
* mediastreamer2/include/mediastreamer2/msticker.h: 1.6
* mediastreamer2/include/mediastreamer2/msqueue.h: 1.3
Clean ANSI/C vs. ANSI/C++ differences
2007-08-01 Sandro Santilli <strk@keybit.net>
* console/commands.c: Clean up commands 'nat', 'stun'
and 'firewall' to be more intuitive.
2007-02-03 Francois-Xavier Kowalski <fix@hp.com>
* m4/osip.m4 (OSIP_CFLAGS): 1.2
* gnome/Makefile.am (linphone_applet_LDADD): 1.33
* coreapi/Makefile.am (liblinphone_la_CFLAGS): 1.38
* console/Makefile.am (sipomatic_LDADD): 1.45
Cope with osip2-2.2.2 delivered as legacy on FC6. New option
"--with-osip-version"
2007-01-18 Francois-Xavier Kowalski <fix@hp.com>
* oRTP/Makefile.am: 1.24
* mediastreamer2/Makefile.am: 1.30
* Makefile.am: 1.45
Fix RPM package generattion to cope with
<https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=206841>
2007-01-17 gettextize <bug-gnu-gettext@gnu.org>
* m4/gettext.m4: Upgrade to gettext-0.16.1.
* m4/lib-link.m4: Upgrade to gettext-0.16.1.
* m4/lib-prefix.m4: Upgrade to gettext-0.16.1.
* m4/nls.m4: Upgrade to gettext-0.16.1.
* m4/po.m4: Upgrade to gettext-0.16.1.
* m4/codeset.m4: Upgrade to gettext-0.16.1.
* m4/intl.m4: New file, from gettext-0.16.1.
* m4/intldir.m4: New file, from gettext-0.16.1.
* m4/intmax.m4: Upgrade to gettext-0.16.1.
* m4/inttypes_h.m4: Upgrade to gettext-0.16.1.
* m4/inttypes-pri.m4: Upgrade to gettext-0.16.1.
* m4/lock.m4: New file, from gettext-0.16.1.
* m4/longdouble.m4: Upgrade to gettext-0.16.1.
* m4/longlong.m4: Upgrade to gettext-0.16.1.
* m4/size_max.m4: Upgrade to gettext-0.16.1.
* m4/stdint_h.m4: Upgrade to gettext-0.16.1.
* m4/ulonglong.m4: Upgrade to gettext-0.16.1.
* m4/visibility.m4: New file, from gettext-0.16.1.
* m4/Makefile.am (EXTRA_DIST): Add the new files.
2006-10-18 Sandro Santilli <strk@keybit.net>
* console/Makefile.am: set osip includes last in the
search path.
2006-09-19 Francois-Xavier Kowalski <fix@hp.com>
* linphone.spec.in (BuildRequires): 1.8
Add RPM build-time dependency on gettext-devel to define
AM_GNU_GETTEXT.
2006-07-26 Sandro Santilli <strk@keybit.net>
* .cvsignore, developer-docs/mediastreamer/.cvsignore,
ipkg/.cvsignore, mediastreamer2/.cvsignore,
mediastreamer2/build/.cvsignore,
mediastreamer2/build/win32native/.cvsignore,
mediastreamer2/include/.cvsignore,
mediastreamer2/include/mediastreamer2/.cvsignore,
mediastreamer2/plugins/.cvsignore,
mediastreamer2/src/.cvsignore,
mediastreamer2/tests/.cvsignore,
oRTP/build/win32/.cvsignore,
oRTP/build/win32native/.cvsignore,
oRTP/src/tests/win_receiver/.cvsignore,
oRTP/src/tests/win_sender/.cvsignore,
po/.cvsignore, share/cs/.cvsignore:
Added-fixed .cvsignore files
2006-07-20 gettextize <bug-gnu-gettext@gnu.org>
* m4/codeset.m4: New file, from gettext-0.14.6.
* m4/gettext.m4: New file, from gettext-0.14.6.
* m4/glibc2.m4: New file, from gettext-0.14.6.
* m4/glibc21.m4: New file, from gettext-0.14.6.
* m4/iconv.m4: New file, from gettext-0.14.6.
* m4/intdiv0.m4: New file, from gettext-0.14.6.
* m4/intmax.m4: New file, from gettext-0.14.6.
* m4/inttypes.m4: New file, from gettext-0.14.6.
* m4/inttypes_h.m4: New file, from gettext-0.14.6.
* m4/inttypes-pri.m4: New file, from gettext-0.14.6.
* m4/isc-posix.m4: New file, from gettext-0.14.6.
* m4/lcmessage.m4: New file, from gettext-0.14.6.
* m4/lib-ld.m4: New file, from gettext-0.14.6.
* m4/lib-link.m4: New file, from gettext-0.14.6.
* m4/lib-prefix.m4: New file, from gettext-0.14.6.
* m4/longdouble.m4: New file, from gettext-0.14.6.
* m4/longlong.m4: New file, from gettext-0.14.6.
* m4/nls.m4: New file, from gettext-0.14.6.
* m4/po.m4: New file, from gettext-0.14.6.
* m4/printf-posix.m4: New file, from gettext-0.14.6.
* m4/progtest.m4: New file, from gettext-0.14.6.
* m4/signed.m4: New file, from gettext-0.14.6.
* m4/size_max.m4: New file, from gettext-0.14.6.
* m4/stdint_h.m4: New file, from gettext-0.14.6.
* m4/uintmax_t.m4: New file, from gettext-0.14.6.
* m4/ulonglong.m4: New file, from gettext-0.14.6.
* m4/wchar_t.m4: New file, from gettext-0.14.6.
* m4/wint_t.m4: New file, from gettext-0.14.6.
* m4/xsize.m4: New file, from gettext-0.14.6.
* m4/Makefile.am (EXTRA_DIST): Add the new files.
* Makefile.am (EXTRA_DIST): Add config.rpath.
2006-07-07 Francois-Xavier Kowalski <fix@hp.com>
* linphone.spec.in (Version): 1.7
Force build of gtk-doc, as the default choice that comes with
GTK_DOC_CHECK m4 macro is "no".
2006-05-17 Francois-Xavier Kowalski <fix@hp.com>
* configure.in: 1.179
* configure.in: 1.178
Allow rpm users to use oRTP packages built from Linphone root.
May 8 2006 : Sandro Santilli <strk@keybit.net>
* configure.in: lowered libspeex requirement to 1.1.6
undefined yet: linphone-1.4.0
- new audio/video streaming engine (mediastreamer2) that let the following improvements:
+ split video frame to get them smaller than MTU
+ less video latency
+ video supported at CIF and QCIF resolution with variable framerate.
+ arts sound input/output
+ improved sound latency with alsa
+ alsa support works with dmix/dsnoop
+ old oss drivers that don't like select and non blocking mode should finally work
- lpc10-15 support removed (speex does better at 8kbit/s)
- jack support unported to mediastreamer2, sorry : volunteer needed
- video resolution and framerate set according to bandwidth constraints.
- linphonec new "soundcard" command to list and choose sound devices.
- new download and upload bandwidth parameters.
March 31 2006: linphone-1.3.4
- fix linphonec bug in auto-answer mode: was terminating call after a few seconds.
March 28 2006: linphone-1.3.3
- various FedoraCore 4 compile problem solved
- fix video bug ('could not mmap': happening on kernel>=2.6.15 with pwc driver)
- SIP register were not using route field (submitted patch)
March 17 2006: linphone-1.3.2
- fix early media call problem: ack for 200ok was never sent.
March 10 2006: linphone-1.3.1
- fix compile errors with gcc-2.95 (thanks Wolfram Gloger)
March 8 2006 : linphone-1.3.0 (SUMMARY)
- a lots of improvements in linphonec (see strk 's Changelogs below)
- telephone event problem with sipomatic.
- updated cz translation.
- fix bugs around addressbook.
- video support with H263-1998/RFC2429 nearly clean.
- added timeout for incoming calls
February 20 2006 : Sandro Santilli <strk@keybit.net>
* console/commands.c: added filter support for
command 'friend list'.
February 13 2006 : Sandro Santilli <strk@keybit.net>
* console/linphonec.c: fixed unused variable warning.
February 02 2006 : Sandro Santilli <strk@keybit.net>
Console:
- Padded vtable with missing callbacks
(fixing a segfault on friends subscription)
- Handled friends notify (bare version)
- Handled text messages receive (bare version)
- Printed message on subscription request (bare version)
- Added 'friend list' and 'friend call' commands
- Allowed for multiple DTMF send in a single line
- Added status-specific callback (bare version)
January 26 2006 : Sandro Santilli <strk@keybit.net>
- Core: fixed bug in linphone_core_set_nat_address refusing
to set address if use flag was off, added support
for NULL addr parameter to only change use flag.
- Support: added missing GFileTest enum values
- Console: 'nat' commands, cleanups
January 25 2006 : Sandro Santilli <strk@keybit.net>
- Core: added request uri in proxy registration failure message
- Console: removed the -t switch
(terminate on close is default behaviour)
January 20 2006 : Sandro Santilli <strk@keybit.net>
- Console:
linphonec_init() and linphonec_finish() functions. Handled
SIGINT and SIGTERM to invoke linphonec_finish(). Handling of
auto-termination (-t) moved to linphonec_finish(). Reworked main
(input read) loop to not rely on 'terminate' and 'run' variable
(dropped). configfile_name allocated on stack using PATH_MAX
limit. Changed print_usage signature to allow for an exit_status
specification.
January 18 2006 : Sandro Santilli <strk@keybit.net>
- Console:
Command completion inhibited
in proxy addition and auth request prompts. Avoided use of
readline's internal filename completion.
January 14 2006 : Sandro Santilli <strk@keybit.net>
- Console:
Reworked commands interface to use a table structure, used by
command line parser and help function. Implemented first
level of completion (commands). Added notification of
invalid "answer" and "terminate" commands (no incoming call,
no active call). Forbidden "call" intialization when a call is
already active. Cleaned up all commands, adding more feedback
and error checks.
January 13 2006 : Sandro Santilli <strk@keybit.net>
- Console:
Added linphonec.h. Code layout change (added comments, forward
decl, globals on top, copyright notices and Logs). Handled
out-of-memory condition on history management. Removed
assumption on sizeof(char). Fixed bug in authentication
prompt (introduced by readline). Added support for multiple
authentication requests (up to MAX_PENDING_AUTH).
January 12 2006 : Sandro Santilli <strk@keybit.net>
- Console:
Changed default configuration file to ~/.linphonerc,
automatically handling migration from old layout if not present
(use ~/.linphonec or ~/.gnome2/linphone). Added compile-time
define to show identity in prompt. Used EXIT_SUCCESS and
EXIT_FAILURE macros.
Made readline use ~/.linphonec_history file for
reading/writing. Fixed auto-call handling code. Fixed
OOB write of sscanf() in linphonec_parse_command_line().
Simplified control flow in linphonec_main_loop().
Put linphonec_{initialize,finish}_readline() calls out of
main_loop(). Removed redundant exit(0) at end of main().
Fixed small leaks.
December 14 2005 : linphone-1.2.0
- various ipv6 bugfixes (again)
- fix po.pl file (was utf-8 but declared as iso8902)
- enum/automatic proxy conflict solved. use "sip:7887488478" for enums, just "382884824" to go through the default proxy.
- experimental video support progresses, compliance improved.
- remove ilbc from source tree: it is now available as a separete plugin.
- updated to work with lastest ffmpeg cvs
- fix bug when answering 'busy here'; active call was closed !
- fix Ctrl+H bug in linphonec
- added bresilian translation
- added swedish translation
- uri bar improvements
- fix a DoS attack by setting a payload type number > 127
August 24 2005 : linphone-1.1.0
- peer to peer text chat
- automatic sip url completion when using a default proxy:
when user types 'mymother' in the url bar, linphone calls sip:mymother@[default-proxy]
- ilbc 20 and 30 miliseconds frames support
- support for setting a soundcard for playback and another for record
- ipv6 bugfixes: works with ipv6 local loopback with sipomatic at least ! Needs to be tested in a real network.
- gtk interface bugfixes
- increase max supported sound devices (was 5).
- automatic incoming redirections
- experimental video support (needs special compilation procedure, see mailing lists)
March 27 2005 : linphone-1.0.1
- patch for NAT traversal (SDP connection address in SDP answer)
- patch for writing correct port information when NAT is enabled
- patch for always using "rport" extension to traverse NAT with
signalling.
- patch for saving/restoring correct configuration of proxy:
"reg_register" -> "reg_sendregister" and fix for saving "expires"
March 21 2005 : linphone-1.0.0
- switch from osipua to eXosip/osip2 for improved sip functionnalities and compliance.
- support for presence (busy, online...) for everyone in the address book (uses SUBSCRIBE/NOTIFY)
- support for PUBLISH (presence information through sip servers)
- support for configuring multiple proxies.
- RTP adaptive jitter buffer ( provides lower latency )
- RTCP coumpound messages sent periodically.
- on demand digest authentication for INVITE and REGISTER
- support for 183 with sdp answers.
- add support for jackd (contributed)
- call logging
- arm build improved
- cz and nl translations contributed.
January 2004 : linphone-0.12.2
- add enum support (see RFC3241 and RFC3026)
Thanks to Rene Bartsch < ml at bartschnet dot de > for its usefull
and precious help.
- interactive presence box (no more need to click OK to confirm)
- update spanish translation
- alsa interface: the user can choose precisely the pcm device to be used
by setting the sound/alsadev parameter of the config file.
- use 1 RTP socket instead of 2: this makes linphone NAT-friendly.
Thursday October 2 2003 : linphone-0.12.1
- add support for personalizing rings.
- make glib dependency optionnal (but recommended).
- add polish translation.
- use of libartsc to suspend arts instead of killing him.
Tuesday August 19 2003 : linphone-0.12.0
- add support for speex/16000
- re-enable alsa support (0.9.x)
- few improvements on gui.
- added spanish translation by Jesús Benítez <gnelson at inMail dot sk>
Monday April 05 2003: linphone-0.11.0
- merge ipv6 support patch, contributed by Koichi KUNITAKE
< kunitake at linux-ipv6 dot org > (thanks !)
- some improvements on graphical interface.
Friday Feb 28 2003 : linphone-0.10.1
- add firewall friendly capability
- compiles all well on arm-linux
- bugfixes.
Friday Jan 24 2003 : linphone-0.10.0
- Gnome interface ported to gnome-2
- Unified core engine for both graphical and console interface.
- Many bug fix and improvements in the SIP stack.
- Japoneese translations and manual added, by Yamaguchi Yoshiya.
- updated for speex-1.0rc1
- ported to FreeBSD thanks to Georg Shwarz
Monday Oct 21 2002 : linphone-0.9.1
- AMD: add support for the "received" and "rport" parameter in osipua.
Monday Oct 21 2002 : linphone-0.9.1
- integration of the patch of Lenaic Huard that adds the ability for linphone to send
dtmf tones through rtp (only reported to console interface).
- following this patch, a nice keypad has been added to the graphical interface to bring
the fonctionnality of the patch gui's users.
- integration of the patch of Aymeric Moizard, concerning compliance with RFC3261 (new
sip's RFC) using the new dialog_t api of libosip.
- updated for use of speex-beta1 (speex codec)
- osipua fix by jack@atosc.org
1: reject calls with 603
2: establishement of 1 early dialog for incoming calls.
3: update to libosip CVS and its new OSIP_TRACE MACROs.
4: fix presence handling.
5: fix expires header in REGISTER.
Monday Aug 26 2002: linphone-0.9.0
- the sdp rtpmap string for alaw and mulaw codec was incorrect.
Sunday Aug 4 2002: linphone-0.9.0pre3
Non visible changes:
- Linphone's internal audio architecture is ported to the new mediastreamer architecture.
The mediastreamer library is already present in linphone since October 29 2001 but
was never used at this time by the core program. Now lots of work has be done inside the
mediastreamer so that it is ready to be used by the core program. As a consequence, the
old architecture defined by the audio/ directory and the codec.c io.c files is dropped.
The mediastreamer architecture provides a modular framework for audio and video
processing. It includes various audio and video codecs (or wrappers to third party
audio and video codecs).
Visible changes:
- The Speex codec (http://speex.sourceforge.net) is now availlable to linphone, since it has
its mediastreamer wrapper. This patent-free codec provides two bitrates, the lowest
being able to work with 56k dialup connections. This is a very important step, because
from now only the low quality LPC10 codec was availlable for such connections.
- Thanks to Florian Winsterstein (f-win at gmx.de), a console version of linphone called
"linphonec" is availlable. Linphonec can be compiled without gnome.
Wednesday May 8 2002: linphone-0.8.0
Visible changes:
- Updated to libosip-0.8.5, that reflects the lastest sip draft.
- Uses the SDP parser the libosip, and uses also a modified version of its SDP negociator.
The MediaDesc object is removed, now osipua users have to deal with BodyHandler's, as the
SdpHandler that deals with sdp message generation and negociation.
The SDP parser and negociator can use the a=rtpmap fields, so that compliance is improved.
- LPC10-1.5 codec has been assigned payload type 115 instead of 4 previously. This breaks
compatibility with older versions of linphone.
- oRTP (the new RTP library) is used in place of the old lprtplib.
- fix endianess problems in the audio part.
Non visible changes (changes on libraries not currently used by linphone but used later):
- mediastreamer has new working objects: webcam image capture, mpeg encoding and decoding
thanks to the libavcodec (ffmpeg) library, rtp wrapper thanks to oRTP.
Tuesday April 15 2002: linphone-0.7.2
- A crash in property box "apply" fixed.
- bugfix in osipua.
Tuesday March 12 2002: linphone-0.7.1
- Some bug fixes by Bryan Ogawa in osipua: route, record-route, tags.
Friday March 1 2002: linphone-0.7.0
- Digest authentification support added by Aymeric.
- Improvements in property box.
- Translations in German and Italian by J.J. Sarton and A. Zanoni
- Bugfix and improvements in the osipua stack.
- Better handling of the registration parameters (the user can set its own address of record).
Thu December 6 2001
-osipua.c: Memory allocations.
fi call of from_tag_add(...,sgetcopy(ua->fromtag));
-utils.c: Memory allocations.
-CallLegs are removed automatically by the osipua layer (eg: when a transaction timed out).
Tue November 27 2001
-Bugfix in osipua for proxy support: record-route and route header support, request-uri bug fixed.
-New choice "outbound proxy" in the property box.
-Fix compilation issues.
Mon October 29 2001
-New unithreaded design of the osipua library, based on libosip-0.7.x series.
-Asynchronous name resolution in osipua.
-To and From tag support added.
-Proxy support added. The user can choose between registering for a redirect server, or
registering for a proxy server. When he choose proxy, then all requests are sent to the proxy.
-New good looking graphical interface.
-Mediastreamer is included, but still unused. It has a begin of gtkdoc dcocumentation.
Wed September 26 2001
-Add registration and redirection ability in gui and osipua.
-Critical bugs in osipua/osip fixed.
-Display all sip error strings in appbar.
-Documentation translated in French.
Tue August 21 2001
- Add address book functionnality
- Add ringback
- Minor bugfixes in configure.in, src/callbacks.c
- Work with libosip-0.6.1
Wed August 1 2001:
- Integration with osip sip stack. lpsiplib is no more used and abandonned. osipua provides the session level
on top of osip.
- added G711 codecs.
- configuration structures and api re-written for more clarity.
- new codec selection box
- new sytem for codec registration
- automatic selection of codecs regarding to network connection type.
- add resizing ability for icon applet.
June 2001: linphone-0.3.0
-Nearly all code in linphone is object oriented.
-linphone can be run as a gnome applet, or as a silent dameon, or as a normal application.
-bugfixes in sip/sdp messages.
-addition of a test program called sipomatic that can automatically answers to call. (for test)
-add io_disk implementation of the audio lib. this can be used to replace the sond card by io on file system.
Tue May 15 2001: linphone-0.2.1
-Fix a stupid bug in the audio library.
Fri May 11 2001: linphone-0.2.0
-add many missing features of version 0.1.0 (for the property box)
-audio levels on the main window.
-Sip library modified: now it uses one thread, and should be able to handle several calls in the future.
-audio library is more performant. It is able to find itself the best blocksize (latency) by testing the driver.
-interactive help on the property box and user manual.
-add an icon.
linphone-0.1.0 :
Released on april,19 2001
Initial version.

236
linphone/INSTALL Normal file
View file

@ -0,0 +1,236 @@
Installation Instructions
*************************
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free
Software Foundation, Inc.
This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it.
Basic Installation
==================
These are generic installation instructions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. (Caching is
disabled by default to prevent problems with accidental use of stale
cache files.)
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You only need
`configure.ac' if you want to change it or regenerate `configure' using
a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that the
`configure' script does not know about. Run `./configure --help' for
details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not support the `VPATH'
variable, you have to compile the package for one architecture at a
time in the source code directory. After you have installed the
package for one architecture, use `make distclean' before reconfiguring
for another architecture.
Installation Names
==================
By default, `make install' installs the package's commands under
`/usr/local/bin', include files under `/usr/local/include', etc. You
can specify an installation prefix other than `/usr/local' by giving
`configure' the option `--prefix=PREFIX'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' cannot figure out automatically,
but needs to determine by the type of machine the package will run on.
Usually, assuming the package is built to be run on the _same_
architectures, `configure' can figure that out, but if it prints a
message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the option `--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share, you
can create a site shell script called `config.site' that gives default
values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script). Here is a another example:
/bin/bash ./configure CONFIG_SHELL=/bin/bash
Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent
configuration-related scripts to be executed by `/bin/bash'.
`configure' Invocation
======================
`configure' recognizes the following options to control how it operates.
`--help'
`-h'
Print a summary of the options to `configure', and exit.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.

42
linphone/Makefile.am Normal file
View file

@ -0,0 +1,42 @@
## Process this file with automake to produce Makefile.in
# let make re-run automake upon need
ACLOCAL_AMFLAGS = -I m4
if EXTERNAL_ORTP
ORTP_DIR =
else
ORTP_DIR = oRTP
endif
SUBDIRS = m4 pixmaps po ipkg $(ORTP_DIR) mediastreamer2\
media_api coreapi console gtk gtk-glade share
EXTRA_DIST = config.rpath linphone2.glade BUGS linphone.kdevprj \
intltool-extract.in \
intltool-merge.in \
intltool-update.in \
README.arm \
autogen.sh \
linphone.spec.in linphone.spec
ACLOCAL_FLAGS=-I$(top_srcdir)/m4
DISTCLEANFILES= intltool-extract intltool-merge intltool-update po/stamp-it po/.intltool-merge-cache
# `make rpm'
all-local: linphone.spec
linphone.spec: linphone.spec.in
.phony: rpm
rpm:
$(MAKE) dist
# Create "Specfile" at the same level as the tarball content
-rm -f $(PACKAGE)-$(VERSION).tar
gunzip $(PACKAGE)-$(VERSION).tar.gz
cp $(PACKAGE).spec Specfile
tar --append --file=$(PACKAGE)-$(VERSION).tar Specfile
gzip $(PACKAGE)-$(VERSION).tar
# <https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=2068410>
TAR_OPTIONS=--wildcards rpmbuild -ta --clean --rmsource --rmspec $(PACKAGE)-$(VERSION).tar.gz

75
linphone/NEWS Normal file
View file

@ -0,0 +1,75 @@
linphone-2.1.1 -- February 13, 2008
* fix interroperability bug with Asterisk about a BYE not sent by linphone.
* fix alsa support weakness (capture underruns not recovered)
linphone-2.1.0 -- January 25, 2008
* 4CIF support
* enable resizing of video output
* hu translation added
linphone-2.0.1 -- November 30, 2007
* fix interop issue with asterisk
* answer OPTIONS and other SIP messages
* allow usage of ALSA user pcm devices with the sound->alsadev config item.
linphone-2.0.0 -- November 15, 2007
* port to libeXosip2-3.0.x with libosip2-3.0.x
* implements early media
* implements incoming re-INVITE
* presence support improvements
* ipv6 working on windows
* implements SDP over 200ok/ACK
* add experimental snow codec support
* answers to VFU request in SIP-INFO by sending an I-frame.
* ffmpeg rate control enabled, improved mpeg4 quality for low bandwidths
* separate video grabbing and display in linphonec
linphone-1.7.1 -- April 16, 2007
* cz translation
* compilation bugfixes (when video support is disabled)
* fix IM icons path bug
linphone-1.7.0 -- April 11, 2007
* new splash screen when no webcam is detected
* new friend commands for linphonec
* gnome interface becomes gtk-only
* fix issue with codec bitrate settings when no bandwidth limits are given
* open rtp sockets before sending SDP offer or answer (so that we don't miss the
first I-frame)
linphone-1.6.0 -- January 23, 2007
* Video4Linux V2 support with mjpeg cameras
* use MPEG4 config string provided in the SDP (if any)
* fix bug when choosing an invalid ring sound file
* fix bug when using quickcam driver with CIF size
* reduce audio bandwidth usage for <128kbit/s connections with video
linphone-1.5.1 -- November 14, 2006
* fix translations
linphone-1.5.0 -- October 11, 2006
* compliant theora support (using Luca Barbato's draft)
* mpeg4 support (compliant with RFC3016)
* controls to display and modify video codec list (gnome interface)
* banwidth usage improvements
* splash screen when no webcam is detected
linphone-1.4.1 -- September 18, 2006
* fixes crash when attempting to make two simultaneous calls
* fixes crash when having no soundcard
* require theora>=1.0.0-alpha7
* do not allow resizing of the gnome interface
* do not change mixer settings at startup
linphone-1.4.0 -- September 11, 2006
* no more glib dependency at all
* new mediastreamer2 framework for audio/video streaming
* stable video support with H.263-1998
* echo cancelation
* experimental theora support
* jack support unported to mediastreamer2, sorry : volunteer needed
* video resolution and framerate set according to bandwidth constraints.
* linphonec new "soundcard" command to list and choose sound devices.
* new download and upload bandwidth parameters used to find suitable video/audio codec choice and parameters.
* new 'play' and 'record' functions to linphonec to play and record wav files
* arts sound backend

53
linphone/README Normal file
View file

@ -0,0 +1,53 @@
******************Building linphone ***********************************
- you need at least:
- libosip2>=3.0.3
- libeXosip2>=3.0.3
- speex>=1.1.6
- libreadline
+ gsm codec (gsm source package or libgsm-dev or gsm-devel) (optional)
+ if you want to gtk interface:
- gtk>=2.4.0
+ if you want video support:
- SDL>=1.2.10
- libavcodec (ffmpeg) from a year 2007 or later cvs
with their corresponding -dev or -devel package if you don't use source packages.
************************************** user documentation *********************
go to linphone's web site: http://www.linphone.org
******************************** DEVELOPER documentation ********************
Here is a short description of the content of the source tree.
- oRTP/ is a poweful implementation of the RTP protocol. See the oRTP/README for more details.
It is used by the mediastreamer to send and receive streams to the network.
- mediastreamer2/ is one of the important part of linphone. It is a framework library for audio
and video processing. It contains several objects for grabing audio and video and outputing
it (through rtp, to file).
It contains also codec objects to compress audio and video streams.
The mediastream.h files contain routines to easyly setup audio streams.
- mediastreamer/ is deprecated.
- media_api/ is going to be an easy to use library to handle audio and video session. It uses
the mediastreamer at the backend to do the processing. It is going to be the only interface
between the core application and the mediastreamer. At the moment this library is still in
early stages of development and is unused by the core application.
- coreapi/ is the central point of linphone, which handles relationship between sip signalisation and media
streaming. It contains an easy to use api to create a sip phone.
- gtk/ is the directory that contains the gui frontend of linphone. It uses all libraries descibed above.
- console/
* linphonec.c is the main file for the console version of linphone.
* sipomatic.c / sipomatic.h contains the code for sipomatic, the test program that auto-answer to linphone calls. If you want to understand
how linphone runs, this is a good start example.
- share/ contains translation, documentation, rings and hello sound files.

12
linphone/README.CVS Normal file
View file

@ -0,0 +1,12 @@
In order to compile from CVS, you have to first install:
- pkg-config
- intltool (intltool-devel if rpm)
- install the mandatory and optional dependencies described in README file.
Then:
./autogen.sh #to generate the configure script
./configure # with desired options
make
Simon MORLAT < simon dot morlat at linphone dot org >

93
linphone/README.M68k.txt Normal file
View file

@ -0,0 +1,93 @@
LINPHONE ON M68k-LINUX (by GIAN)
********************************
The console version of linphone works on arm-linux, but also on m68k-linux? Im trying to provide this:
* I used the same toolchain specified in the LTIB menu configuration, that is, on my system:
/opt/mtwk/usr/local/m68k-linux/gcc-3.4.0-glibc-2.3.2-v4e
* I have created within my home directory a ColdFire-install-environment/ directory, copied into it the fresh tarballs of libogg-1.1.3, libosip2-2.2.2, speex-1.1.12, linphone-1.4.0 readline-5.1 and ncurses-5.5 (readline needs ncurses) Uncompressed all these
tarballs.
Very important things common to all packages being cross compiled:
******************************************************************
* Copy the ipaq-config.site in the ipkg/ directory of linphone into some safe place, for example:
cp /home/gianluca/ColdFire-install-environment/linphone-1.4.0-install/linphone-1.4.0/ipkg/ipag-config.site /home/gianluca/ColdFire-install-environment/linphone-1.4.0-install/
Edit the ipaq-config.site file and replace all the arm-linux strings with m68k-linux one. Add also the mcfv4e flag to the CFLAGS, CXXFLAGS, and CPPFLAGS labels.
* You need a directory that we call M68K_INSTALL_TREE that will own files in the same way they will be installed on the target computer.
mkdir /ColdFire-linphonec-1.4.0-mcfv4e
export M68K_INSTALL_TREE=/ColdFire-linphonec-1.4.0-mcfv4e
export CONFIG_SITE=/home/gianluca/ColdFire-install-environment/linphone-1.4.0-install/ipaq-config.site
export PATH=$PATH:/opt/mtwk/usr/local/m68k-linux/gcc-3.4.0-glibc-2.3.2-v4e/bin
Cross compiling ncurses for M68k:
********************************
./configure --prefix=/usr --host=m68k-linux --with-gnu-ld --with-shared
make
make install DESTDIR=$M68K_INSTALL_TREE
Cross compiling readline for M68k:
*********************************
./configure --prefix=/usr --host=m68k-linux --with-gnu-ld --disable-static
make
make install DESTDIR=$M68K_INSTALL_TREE
Cross compiling libosip for M68k:
********************************
./configure --prefix=/usr --host=m68k-linux --with-gnu-ld --disable-static
make
make install DESTDIR=$M68K_INSTALL_TREE
Cross compiling libogg for M68k:
********************************
./configure --prefix=/usr --host=m68k-linux --with-gnu-ld --disable-static enable-fixed-point
make
make install DESTDIR=$M68K_INSTALL_TREE
Cross compiling speex for M68k:
********************************
./configure --prefix=/usr --host=m68k-linux --with-gnu-ld --disable-static --enable-fixed-point --enable-m68k-asm --with-ogg=/ColdFire-linphonec-1.4.0-mcfv4e/usr --with-ogg-includes=/ColdFire-linphonec-1.4.0-mcfv4e/usr/include with-ogg-libraries=/ColdFire-linphonec-1.4.0-mcfv4e/usr/lib --disable-oggtest
make
make install DESTDIR=$M68K_INSTALL_TREE
cp /home/gianluca/ColdFire-iinstall-environment/linphone-1.4.0-install/linphone-1.4.0/mediastreamer2/src/.libs/libquickstream.so.0.0.0 /opt/mtwk/usr/local/m68k-linux/gcc-3.4.0-glibc-2.3.2-v4e/m68k-linux/lib
cd /opt/mtwk/usr/local/m68k-linux/gcc-3.4.0-glibc-2.3.2-v4e/m68k-linux/lib
ln -s libquickstream.so.0.0.0 libquickstream.so.0
ln -s libquickstream.so.0.0.0 libquickstream.so
cp /home/gianluca/ColdFire-install-environment/linphone-1.4.0-install/linphone-1.4.0/mediastreamer2/src/.libs/libmediastreamer.so.0.0.0 /opt/mtwk/usr/local/m68k-linux/gcc-3.4.0-glibc-2.3.2-v4e/m68k-linux/lib
cd /opt/mtwk/usr/local/m68k-linux/gcc-3.4.0-glibc-2.3.2-v4e/m68k-linux/lib
ln -s libmediastreamer.so.0.0.0 libmediastreamer.so.0
ln -s libmediastreamer.so.0.0.0 libmediastreamer.so
Cross compiling linphone for M68k:
********************************
First you need to remove all .la files from the M68K_INSTALL_TREE because it confuses libtool and makes
the linker use your build machine binaries instead of the m68k-crosscompiled ones.
rm -f $M68K_INSTALL_TREE/usr/lib/*.la
#for some reason pkg-config doesn't like cross-compiling...
export PKG_CONFIG=/usr/bin/pkg-config
./configure --prefix=/usr --host=m68k-linux --with-gnu-ld --disable-static --disable-strict --enable-gnome_ui=no --enable-alsa --disable-glib --disable-video --with-osip=$ARM_INSTALL_TREE/usr --with-osipparser=$ARM_INSTALL_TREE/usr --with-readline=$ARM_INSTALL_TREE/usr SPEEX_CFLAGS="-I$ARM_INSTALL_TREE/usr/include" SPEEX_LIBS="-L$ARM_INSTALL_TREE/usr/lib -lspeex"
make
make install DESTDIR=$M68K_INSTALL_TREE
Binaries can also be stripped with m68k-linux-strip to save more space.
Running linphone under the ColdFire board
********************************************
You just have to start linphone from a terminal by typing 'linphonec'.
Gianluca Salvador

106
linphone/README.arm Normal file
View file

@ -0,0 +1,106 @@
LINPHONE ON ARM-LINUX (HANDHELD COMPUTERS)
******************************************
The console version of linphone works on arm-linux and has been tested on ipaqs
under the familiar linux distribution (http://www.handhelds.org).
You can find .ipk binary packages on the linphone's download page.
If you want to build your own arm-linux packages, here are some instructions to
cross compile linphone and its dependencies: readline, speex and libosip.
This is my own experience on cross compiling software. As there is no precise
step by step documentation (as far as I know) on how to cross-compile on arm,
there is no guaranty that the following instructions are the best way to do it.
First, be aware that only the console version of linphone can compile on ARM.
* You need the lastest arm toolchain from http://www.handhelds.org. Uncompress it in / .
It contains all the cross-compilation tools. Be sure that the arm-linux-gcc binaries
are in your PATH (export PATH=$PATH:/usr/local/arm/3.4.1/bin/ , for example)
* create within your home directory a arm/ directory, copy into it the fresh
tarballs of libosip2>=2.2.x, speex>=1.1.6, linphone>=1.2.1 readline>=5.1 and ncurses>=5.5 (readline needs ncurses)
Uncompress all these
tarballs.
Very important things common to all packages being cross compiled:
******************************************************************
* copy the ipaq-config.site in the ipkg/ directory of linphone into some safe place,
for example: ~/ipaq-config.site .
* You need a directory that we call ARM_INSTALL_TREE that will own files in the same way they will be installed on the target computer.
It is also used to build linphone over the arm binaries of its dependencies (speex,osip,ncurses,readline).
For example:
export CONFIG_SITE=~/ipaq-config.site
export ARM_INSTALL_TREE=/armbuild
Cross compiling ncurses for ARM:
********************************
./configure --prefix=/usr --host=arm-linux --with-gnu-ld --with-shared
make
make install DESTDIR=$ARM_INSTALL_TREE
make install DESTDIR=`pwd`/armbuild
Cross compiling readline for ARM:
*********************************
./configure --prefix=/usr --host=arm-linux --with-gnu-ld --disable-static
make
make install DESTDIR=$ARM_INSTALL_TREE
make install DESTDIR=`pwd`/armbuild
Cross compiling libosip for ARM:
********************************
./configure --prefix=/usr --host=arm-linux --with-gnu-ld --disable-static
make
make install DESTDIR=$ARM_INSTALL_TREE
make install DESTDIR=`pwd`/armbuild
Cross compiling speex for ARM:
********************************
First you need to remove ogg headers from your build system to avoid a dirty conflict between
your build machine binaries and the arm binaries. They are usually in a libogg-dev package (rpm or deb).
Then:
./configure --prefix=/usr --host=arm-linux --with-gnu-ld --disable-static --enable-fixed-point --enable-arm-asm
make
make install DESTDIR=$ARM_INSTALL_TREE
make install DESTDIR='pwd'/armbuild
Cross compiling linphone for ARM
********************************
First you need to remove all .la files from the ARM_INSTALL_TREE because it confuses libtool and makes
the linker use your build machine binaries instead of the arm-crosscompiled ones.
rm -f $ARM_INSTALL_TREE/usr/lib/*.la
#for some reason pkg-config doesn't like cross-compiling...
export PKG_CONFIG=/usr/bin/pkg-config
./configure --prefix=/usr --host=arm-linux --with-gnu-ld --disable-static \
--disable-glib --with-osip=$ARM_INSTALL_TREE/usr \
--with-readline=$ARM_INSTALL_TREE/usr \
SPEEX_CFLAGS="-I$ARM_INSTALL_TREE/usr/include" \
SPEEX_LIBS="-L$ARM_INSTALL_TREE/usr/lib -lspeex "
make
make install DESTDIR='pwd'/armbuild
You can use the install trees libosip2-x.x.x/armbuild speex-x.x.x/armbuild and
linphone-0.x.x/armbuild/ to make binary packages of
each software, as ipkgs for the familiar distribution (http://www.familiar.org).
In the ipkg/ directory of linphone you can find .control files for ipkg-build.
In order to make the osip ipkg, you have to do the following:
- create a directory named CONTROL inside libosip2-2.2.x/armbuild
- copy the libosip.control file into CONTROL/ and rename it into "control".
- edit the "control" file to adjust version number accordingly.
- remove the non essential parts of libosip inside libosip2-2.x.x/armbuild/usr/ : just
leave the lib/ directory. This saves space on the destination computer.
- then inside libosip2-2.x.x, run ipkg-build -o root -g root armbuild
The same procedure applies to make linphone's ipkg.
Binaries can also be stripped with arm-linux-strip to save more space.
Running linphone under the handheld computer
********************************************
You just have to start linphone from a terminal by typing 'linphonec'.
Simon

22
linphone/TODO Normal file
View file

@ -0,0 +1,22 @@
hot stuff:
---------
* ice support
* run a user given command upon incoming calls
* linphonec on win32
* RTP inactivity timeout to close lost calls.
low priority:
-------------
* random RTP ports (to enable direct mapping NAT)
* zeroconf support for advertising services (cool stuff!)
* have the possibility to define several profiles (config files) and switch between them
* display call duration
* help tips for the registration box
* The length (or duration) of the call could be displayed (see icons2.png)
* 2. There could be a sound effect for "busy" - a short "beep-beep-beep" would be sufficient (try http://www.google.com/search?q=busy.wav)
* The call history could be a bit more clear (see history.png). And it
should be saved somewhere, so you can track your calls if you need to...
* move resampling stuff to use speex instead of libresample.

26
linphone/autogen.sh Executable file
View file

@ -0,0 +1,26 @@
#!/bin/sh
AM_VERSION="1.9"
if ! type aclocal-$AM_VERSION 1>/dev/null 2>&1; then
# automake-1.9 (recommended) is not available on Fedora 8
AUTOMAKE=automake
ACLOCAL=aclocal
else
ACLOCAL=aclocal-${AM_VERSION}
AUTOMAKE=automake-${AM_VERSION}
fi
echo "Generating build scripts in linphone..."
set -x
libtoolize --copy --force
autoheader
$ACLOCAL -I m4
$AUTOMAKE --force-missing --add-missing --copy
autoconf
rm -rf config.cache
echo "Generating build scripts in oRTP..."
cd oRTP && ./autogen.sh && cd -
echo "Generating build scripts in mediastreamer2..."
cd mediastreamer2 && ./autogen.sh && cd -

140
linphone/build.mk Executable file
View file

@ -0,0 +1,140 @@
#!/usr/bin/make -f
# This script "automatically" builds some binary distribution of linphone :
# debian packages (sid) and familiar (arm-linux/ipaq) packages.
# generation of rpms can be added in the future.
# it can be invoked in the following way:
# ./build.mk debs LINPHONE=<path to linphone's tar.gz>
# ./build.mk all LINPHONE=<path to linphone's tar.gz> GLIB=<path to glib>2.2's tar.gz>
# LIBOSIP=<path to libosip's tar.gz>
#
ARMROOT=/armbuild
ARMTOOLCHAIN=/usr/local/arm/3.2.3/bin
all: check debs ipks
clean:
rm -f *.stamp
rm -rf build-debs
rm -rf build-ipks
check:
@if test -n "${LD_PRELOAD}" ; then echo "ERROR: LD_PRELOAD is set !!"; exit 1;fi
ipks: ipkg-tools.stamp libosip.ipk linphone.ipk clean
ipkg-tools.stamp:
if which ipkg-build ; then echo "Found ipkg-build." ;\
else echo "** ERROR ** Cannot find ipkg-build"; exit 1; fi
if test -e $(ARMTOOLCHAIN)/arm-linux-gcc ; then \
echo "arm toolchain seems ok.";\
else echo "** ERROR ** Cannot find arm toolchain."; exit 1; fi
touch ipkg-tools.stamp
glib.ipk : glib.stamp linphone-sources-ipk.stamp
rm -rf build-ipks/glib*
cp $(GLIB) build-ipks/.
export CONFIG_SITE=`pwd`/build-ipks/ipaq-config.site && \
cd build-ipks && tar -xvzf glib*.tar.gz && rm -f glib*.tar.gz && cd glib* && \
./configure --prefix=$(ARMROOT)/usr --host=arm-linux --with-gnu-ld --disable-static \
&& make AM_CFLAGS=-DSSIZE_MAX=0xffffffff && make install && \
make install prefix=`pwd`$(ARMROOT)/usr
echo "Building .ipk file..."
cd build-ipks/glib*$(ARMROOT) && mkdir CONTROL && cd CONTROL && \
cp ../../../linphone*/ipkg/glib.control control && \
cd ../.. && rm -rf armbuild/usr/include
cd build-ipks/glib* && ipkg-build -o root -g root armbuild/
cp build-ipks/glib*/*.ipk .
libosip.ipk : libosip.stamp linphone-sources-ipk.stamp
rm -rf build-ipks/libosip*
cp $(LIBOSIP) build-ipks/
export CONFIG_SITE=`pwd`/build-ipks/ipaq-config.site && \
cd build-ipks && tar -xvzf libosip*.tar.gz && rm -f libosip*.tar.gz && cd libosip* && \
./configure --prefix=$(ARMROOT)/usr --host=arm-linux --with-gnu-ld --disable-static \
&& make && make install && make install prefix=`pwd`$(ARMROOT)/usr
echo "Building .ipk file..."
cd build-ipks/libosip*$(ARMROOT) && mkdir CONTROL && cd CONTROL && \
cp ../../../linphone*/ipkg/libosip.control control &&\
cd ../.. && rm -rf armbuild/usr/include
cd build-ipks/libosip* && ipkg-build -o root -g root armbuild/
cp build-ipks/libosip*/*.ipk .
linphone.ipk : linphone.stamp linphone-sources-ipk.stamp
export CONFIG_SITE=`pwd`/build-ipks/ipaq-config.site && \
cd build-ipks/linphone* && export PKG_CONFIG_PATH=$(ARMROOT)/usr/lib/pkgconfig &&\
./configure --prefix=$(ARMROOT)/usr --with-realprefix=/usr --host=arm-linux \
--with-gnu-ld --disable-static --disable-gnome_ui --disable-glib --with-osip=$(ARMROOT)/usr \
--disable-ogg --disable-rtcp && make && make install prefix=`pwd`$(ARMROOT)/usr
echo "Building .ipk file..."
cd build-ipks/linphone*$(ARMROOT) && mkdir -p CONTROL && cd CONTROL && \
cp -f ../../ipkg/linphone.control control &&\
cd ../.. && rm -rf armbuild/usr/include armbuild/usr/share/gtk-doc \
&& cd armbuild/usr/share/sounds/linphone/rings && \
rm -f rock.wav sweet.wav bigben.wav toy.wav tapping.wav synth.wav && cd - \
cd build-ipks/linphone* && ipkg-build -o root -g root armbuild/
cp -f build-ipks/linphone*/*.ipk .
build-ipks.stamp:
-@touch $(ARMROOT)/dummy
@if test -e $(ARMROOT)/dummy ; \
then echo "armroot is fine: $(ARMROOT)"; \
else \
echo "** ERROR: you need to create a $(ARMROOT) directory readable and writeable by the user running this build script.";\
exit 1;\
fi
rm -f $(ARMROOT)/dummy
touch build-ipks.stamp
mkdir build-ipks
linphone-sources-ipk.stamp: linphone.stamp build-ipks.stamp
cp $(LINPHONE) build-ipks/.
cd build-ipks && tar -xvzf linphone*.tar.gz && cp linphone*/ipkg/ipaq-config.site . \
&& rm -f linphone*.tar.gz
touch linphone-sources-ipk.stamp
debs: linphone.stamp clean
rm -f linphone.stamp
rm -rf build-debs
mkdir build-debs
cp $(LINPHONE) build-debs/.
cd build-debs && tar -xvzf *.tar.gz && cd linphone* && dpkg-buildpackage -rfakeroot
cp build-debs/*.deb .
linphone.stamp:
@if test -n "$(LINPHONE)" ; \
then echo "linphone source is $(LINPHONE)" ; \
touch linphone.stamp; \
else \
echo "No linphone source found." ; \
exit 1; \
fi
libosip.stamp:
@if test -n "$(LIBOSIP)" ; \
then echo "libosip source is $(LIBOSIP)" ; \
touch libosip.stamp; \
else \
echo "No libosip source found." ; \
exit 1; \
fi
glib.stamp:
@if test -n "$(GLIB)" ; \
then echo "glib source is $(GLIB)" ; \
else \
echo "No glib source found." ; \
exit -1; \
fi
@if which glib-genmarshal ; \
then \
echo "native glib-2.2 found on build host." ; \
touch glib.stamp ;\
else \
echo "** ERROR ** You need a working glib>2.2 on the build machine to be able to crosscompile it for arm." ;\
echo "** ERROR ** Please install a glib on this machine."; exit 1; \
fi

614
linphone/config.rpath Executable file
View file

@ -0,0 +1,614 @@
#! /bin/sh
# Output a system dependent set of variables, describing how to set the
# run time search path of shared libraries in an executable.
#
# Copyright 1996-2006 Free Software Foundation, Inc.
# Taken from GNU libtool, 2001
# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
#
# The first argument passed to this file is the canonical host specification,
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
# or
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld
# should be set by the caller.
#
# The set of defined variables is at the end of this script.
# Known limitations:
# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer
# than 256 bytes, otherwise the compiler driver will dump core. The only
# known workaround is to choose shorter directory names for the build
# directory and/or the installation directory.
# All known linkers require a `.a' archive for static linking (except MSVC,
# which needs '.lib').
libext=a
shrext=.so
host="$1"
host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
# Code taken from libtool.m4's _LT_CC_BASENAME.
for cc_temp in $CC""; do
case $cc_temp in
compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
\-*) ;;
*) break;;
esac
done
cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'`
# Code taken from libtool.m4's AC_LIBTOOL_PROG_COMPILER_PIC.
wl=
if test "$GCC" = yes; then
wl='-Wl,'
else
case "$host_os" in
aix*)
wl='-Wl,'
;;
darwin*)
case $cc_basename in
xlc*)
wl='-Wl,'
;;
esac
;;
mingw* | pw32* | os2*)
;;
hpux9* | hpux10* | hpux11*)
wl='-Wl,'
;;
irix5* | irix6* | nonstopux*)
wl='-Wl,'
;;
newsos6)
;;
linux*)
case $cc_basename in
icc* | ecc*)
wl='-Wl,'
;;
pgcc | pgf77 | pgf90)
wl='-Wl,'
;;
ccc*)
wl='-Wl,'
;;
como)
wl='-lopt='
;;
*)
case `$CC -V 2>&1 | sed 5q` in
*Sun\ C*)
wl='-Wl,'
;;
esac
;;
esac
;;
osf3* | osf4* | osf5*)
wl='-Wl,'
;;
sco3.2v5*)
;;
solaris*)
wl='-Wl,'
;;
sunos4*)
wl='-Qoption ld '
;;
sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
wl='-Wl,'
;;
sysv4*MP*)
;;
unicos*)
wl='-Wl,'
;;
uts4*)
;;
esac
fi
# Code taken from libtool.m4's AC_LIBTOOL_PROG_LD_SHLIBS.
hardcode_libdir_flag_spec=
hardcode_libdir_separator=
hardcode_direct=no
hardcode_minus_L=no
case "$host_os" in
cygwin* | mingw* | pw32*)
# FIXME: the MSVC++ port hasn't been tested in a loooong time
# When not using gcc, we currently assume that we are using
# Microsoft Visual C++.
if test "$GCC" != yes; then
with_gnu_ld=no
fi
;;
interix*)
# we just hope/assume this is gcc and not c89 (= MSVC++)
with_gnu_ld=yes
;;
openbsd*)
with_gnu_ld=no
;;
esac
ld_shlibs=yes
if test "$with_gnu_ld" = yes; then
# Set some defaults for GNU ld with shared library support. These
# are reset later if shared libraries are not supported. Putting them
# here allows them to be overridden if necessary.
# Unlike libtool, we use -rpath here, not --rpath, since the documented
# option of GNU ld is called -rpath, not --rpath.
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
case "$host_os" in
aix3* | aix4* | aix5*)
# On AIX/PPC, the GNU linker is very broken
if test "$host_cpu" != ia64; then
ld_shlibs=no
fi
;;
amigaos*)
hardcode_libdir_flag_spec='-L$libdir'
hardcode_minus_L=yes
# Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
# that the semantics of dynamic libraries on AmigaOS, at least up
# to version 4, is to share data among multiple programs linked
# with the same dynamic library. Since this doesn't match the
# behavior of shared libraries on other platforms, we cannot use
# them.
ld_shlibs=no
;;
beos*)
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
:
else
ld_shlibs=no
fi
;;
cygwin* | mingw* | pw32*)
# hardcode_libdir_flag_spec is actually meaningless, as there is
# no search path for DLLs.
hardcode_libdir_flag_spec='-L$libdir'
if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
:
else
ld_shlibs=no
fi
;;
interix3*)
hardcode_direct=no
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
;;
linux*)
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
:
else
ld_shlibs=no
fi
;;
netbsd*)
;;
solaris*)
if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
ld_shlibs=no
elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
:
else
ld_shlibs=no
fi
;;
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
case `$LD -v 2>&1` in
*\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
ld_shlibs=no
;;
*)
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
else
ld_shlibs=no
fi
;;
esac
;;
sunos4*)
hardcode_direct=yes
;;
*)
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
:
else
ld_shlibs=no
fi
;;
esac
if test "$ld_shlibs" = no; then
hardcode_libdir_flag_spec=
fi
else
case "$host_os" in
aix3*)
# Note: this linker hardcodes the directories in LIBPATH if there
# are no directories specified by -L.
hardcode_minus_L=yes
if test "$GCC" = yes; then
# Neither direct hardcoding nor static linking is supported with a
# broken collect2.
hardcode_direct=unsupported
fi
;;
aix4* | aix5*)
if test "$host_cpu" = ia64; then
# On IA64, the linker does run time linking by default, so we don't
# have to do anything special.
aix_use_runtimelinking=no
else
aix_use_runtimelinking=no
# Test if we are trying to use run time linking or normal
# AIX style linking. If -brtl is somewhere in LDFLAGS, we
# need to do runtime linking.
case $host_os in aix4.[23]|aix4.[23].*|aix5*)
for ld_flag in $LDFLAGS; do
if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
aix_use_runtimelinking=yes
break
fi
done
;;
esac
fi
hardcode_direct=yes
hardcode_libdir_separator=':'
if test "$GCC" = yes; then
case $host_os in aix4.[012]|aix4.[012].*)
collect2name=`${CC} -print-prog-name=collect2`
if test -f "$collect2name" && \
strings "$collect2name" | grep resolve_lib_name >/dev/null
then
# We have reworked collect2
hardcode_direct=yes
else
# We have old collect2
hardcode_direct=unsupported
hardcode_minus_L=yes
hardcode_libdir_flag_spec='-L$libdir'
hardcode_libdir_separator=
fi
;;
esac
fi
# Begin _LT_AC_SYS_LIBPATH_AIX.
echo 'int main () { return 0; }' > conftest.c
${CC} ${LDFLAGS} conftest.c -o conftest
aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
}'`
if test -z "$aix_libpath"; then
aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
}'`
fi
if test -z "$aix_libpath"; then
aix_libpath="/usr/lib:/lib"
fi
rm -f conftest.c conftest
# End _LT_AC_SYS_LIBPATH_AIX.
if test "$aix_use_runtimelinking" = yes; then
hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
else
if test "$host_cpu" = ia64; then
hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
else
hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
fi
fi
;;
amigaos*)
hardcode_libdir_flag_spec='-L$libdir'
hardcode_minus_L=yes
# see comment about different semantics on the GNU ld section
ld_shlibs=no
;;
bsdi[45]*)
;;
cygwin* | mingw* | pw32*)
# When not using gcc, we currently assume that we are using
# Microsoft Visual C++.
# hardcode_libdir_flag_spec is actually meaningless, as there is
# no search path for DLLs.
hardcode_libdir_flag_spec=' '
libext=lib
;;
darwin* | rhapsody*)
hardcode_direct=no
if test "$GCC" = yes ; then
:
else
case $cc_basename in
xlc*)
;;
*)
ld_shlibs=no
;;
esac
fi
;;
dgux*)
hardcode_libdir_flag_spec='-L$libdir'
;;
freebsd1*)
ld_shlibs=no
;;
freebsd2.2*)
hardcode_libdir_flag_spec='-R$libdir'
hardcode_direct=yes
;;
freebsd2*)
hardcode_direct=yes
hardcode_minus_L=yes
;;
freebsd* | kfreebsd*-gnu | dragonfly*)
hardcode_libdir_flag_spec='-R$libdir'
hardcode_direct=yes
;;
hpux9*)
hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
hardcode_libdir_separator=:
hardcode_direct=yes
# hardcode_minus_L: Not really in the search PATH,
# but as the default location of the library.
hardcode_minus_L=yes
;;
hpux10*)
if test "$with_gnu_ld" = no; then
hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
hardcode_libdir_separator=:
hardcode_direct=yes
# hardcode_minus_L: Not really in the search PATH,
# but as the default location of the library.
hardcode_minus_L=yes
fi
;;
hpux11*)
if test "$with_gnu_ld" = no; then
hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
hardcode_libdir_separator=:
case $host_cpu in
hppa*64*|ia64*)
hardcode_direct=no
;;
*)
hardcode_direct=yes
# hardcode_minus_L: Not really in the search PATH,
# but as the default location of the library.
hardcode_minus_L=yes
;;
esac
fi
;;
irix5* | irix6* | nonstopux*)
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
hardcode_libdir_separator=:
;;
netbsd*)
hardcode_libdir_flag_spec='-R$libdir'
hardcode_direct=yes
;;
newsos6)
hardcode_direct=yes
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
hardcode_libdir_separator=:
;;
openbsd*)
hardcode_direct=yes
if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
else
case "$host_os" in
openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
hardcode_libdir_flag_spec='-R$libdir'
;;
*)
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
;;
esac
fi
;;
os2*)
hardcode_libdir_flag_spec='-L$libdir'
hardcode_minus_L=yes
;;
osf3*)
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
hardcode_libdir_separator=:
;;
osf4* | osf5*)
if test "$GCC" = yes; then
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
else
# Both cc and cxx compiler support -rpath directly
hardcode_libdir_flag_spec='-rpath $libdir'
fi
hardcode_libdir_separator=:
;;
solaris*)
hardcode_libdir_flag_spec='-R$libdir'
;;
sunos4*)
hardcode_libdir_flag_spec='-L$libdir'
hardcode_direct=yes
hardcode_minus_L=yes
;;
sysv4)
case $host_vendor in
sni)
hardcode_direct=yes # is this really true???
;;
siemens)
hardcode_direct=no
;;
motorola)
hardcode_direct=no #Motorola manual says yes, but my tests say they lie
;;
esac
;;
sysv4.3*)
;;
sysv4*MP*)
if test -d /usr/nec; then
ld_shlibs=yes
fi
;;
sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*)
;;
sysv5* | sco3.2v5* | sco5v6*)
hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
hardcode_libdir_separator=':'
;;
uts4*)
hardcode_libdir_flag_spec='-L$libdir'
;;
*)
ld_shlibs=no
;;
esac
fi
# Check dynamic linker characteristics
# Code taken from libtool.m4's AC_LIBTOOL_SYS_DYNAMIC_LINKER.
libname_spec='lib$name'
case "$host_os" in
aix3*)
;;
aix4* | aix5*)
;;
amigaos*)
;;
beos*)
;;
bsdi[45]*)
;;
cygwin* | mingw* | pw32*)
shrext=.dll
;;
darwin* | rhapsody*)
shrext=.dylib
;;
dgux*)
;;
freebsd1*)
;;
kfreebsd*-gnu)
;;
freebsd* | dragonfly*)
;;
gnu*)
;;
hpux9* | hpux10* | hpux11*)
case $host_cpu in
ia64*)
shrext=.so
;;
hppa*64*)
shrext=.sl
;;
*)
shrext=.sl
;;
esac
;;
interix3*)
;;
irix5* | irix6* | nonstopux*)
case "$host_os" in
irix5* | nonstopux*)
libsuff= shlibsuff=
;;
*)
case $LD in
*-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;;
*-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;;
*-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;;
*) libsuff= shlibsuff= ;;
esac
;;
esac
;;
linux*oldld* | linux*aout* | linux*coff*)
;;
linux*)
;;
knetbsd*-gnu)
;;
netbsd*)
;;
newsos6)
;;
nto-qnx*)
;;
openbsd*)
;;
os2*)
libname_spec='$name'
shrext=.dll
;;
osf3* | osf4* | osf5*)
;;
solaris*)
;;
sunos4*)
;;
sysv4 | sysv4.3*)
;;
sysv4*MP*)
;;
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
;;
uts4*)
;;
esac
sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"`
shlibext=`echo "$shrext" | sed -e 's,^\.,,'`
escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <<EOF
# How to pass a linker flag through the compiler.
wl="$escaped_wl"
# Static library suffix (normally "a").
libext="$libext"
# Shared library suffix (normally "so").
shlibext="$shlibext"
# Flag to hardcode \$libdir into a binary during linking.
# This must work even if \$libdir does not exist.
hardcode_libdir_flag_spec="$escaped_hardcode_libdir_flag_spec"
# Whether we need a single -rpath flag with a separated argument.
hardcode_libdir_separator="$hardcode_libdir_separator"
# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
# resulting binary.
hardcode_direct="$hardcode_direct"
# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
# resulting binary.
hardcode_minus_L="$hardcode_minus_L"
EOF

378
linphone/configure.in Normal file
View file

@ -0,0 +1,378 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT([linphone],[2.99.4],[linphone-developers@nongnu.org])
dnl Source packaging numbers
LINPHONE_MAJOR_VERSION=$(echo $PACKAGE_VERSION | cut -d. -f1)
LINPHONE_MINOR_VERSION=$(echo $PACKAGE_VERSION | cut -d. -f2)
LINPHONE_MICRO_VERSION=$(echo $PACKAGE_VERSION | cut -d. -f3)
LINPHONE_EXTRA_VERSION=$(echo $PACKAGE_VERSION | cut -d. -f4)
dnl program extension
LINPHONE_VERSION=$LINPHONE_MAJOR_VERSION.$LINPHONE_MINOR_VERSION.${LINPHONE_MICRO_VERSION}.${LINPHONE_EXTRA_VERSION}
LIBLINPHONE_SO_VERSION=`expr $LINPHONE_MINOR_VERSION + $LINPHONE_MAJOR_VERSION`:$LINPHONE_MICRO_VERSION:$LINPHONE_MINOR_VERSION
AC_SUBST(LIBLINPHONE_SO_VERSION, $LIBLINPHONE_SO_VERSION)
AC_SUBST(LINPHONE_VERSION)
AC_MSG_NOTICE([$PACKAGE_NAME-$PACKAGE_VERSION A full featured audio/video sip phone.])
AC_MSG_NOTICE([licensed under the terms of the General Public License (GPL)])
AM_INIT_AUTOMAKE([tar-ustar])
AC_CONFIG_HEADER(config.h)
AC_SUBST([mkdir_p])
AC_ISC_POSIX
AC_PROG_CC
AC_C_INLINE
AM_PROG_CC_STDC
AC_HEADER_STDC
dnl localization tools
ifdef([IT_PROG_INTLTOOL],[IT_PROG_INTLTOOL],[AC_PROG_INTLTOOL])
dnl Initialize libtool
AC_PROG_LIBTOOL
AM_PROG_LIBTOOL
AC_ENABLE_SHARED(yes)
AC_ENABLE_STATIC(no)
dnl Add the languages which your application supports here.
PKG_PROG_PKG_CONFIG
ALL_LINGUAS="fr it de ja es pl cs nl sv pt_BR hu"
GETTEXT_PACKAGE=linphone
AM_GNU_GETTEXT([external])
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",[The name of the gettext package name])
AC_CHECK_LIB(intl,libintl_gettext)
AC_CHECK_FUNCS([get_current_dir_name strndup stpcpy] )
dnl conditionnal build of console interface.
AC_ARG_ENABLE(console_ui,
[ --enable-console_ui=[yes/no] Turn on or off compilation of console interface [default=yes]],
[case "${enableval}" in
yes) console_ui=true ;;
no) console_ui=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-console_ui) ;;
esac],[console_ui=true])
dnl conditionnal build of gtk interface.
AC_ARG_ENABLE(gtk_ui,
[ --enable-gtk_ui=[yes/no] Turn on or off compilation of gtk interface [default=yes]],
[case "${enableval}" in
yes) gtk_ui=true ;;
no) gtk_ui=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-gtk_ui) ;;
esac],[gtk_ui=true])
dnl conditionnal build of old gtk interface.
AC_ARG_ENABLE(old-gtk_ui,
[ --enable-old-gtk_ui=[yes/no] Turn on or off compilation of old gtk interface [default=no]],
[case "${enableval}" in
yes) old_gtk_ui=true ;;
no) old_gtk_ui=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-old-gtk_ui) ;;
esac],[old_gtk_ui=false])
if test "$gtk_ui" = "true" ; then
PKG_CHECK_MODULES(LIBGTK, gtk+-2.0 >= 2.4.0 gthread-2.0, ,gtk_ui=false)
AC_SUBST(LIBGTK_CFLAGS)
AC_SUBST(LIBGTK_LIBS)
if test "$gtk_ui" = "true" ; then
AC_DEFINE(HAVE_GTK,1,[Defined if we can use the gtk api])
else
missing_gtk_libs=true
fi
else
echo "GTK interface compilation is disabled."
fi
if test "$gtk_ui" = "true" ; then
PKG_CHECK_MODULES(GNOME_APPLETS, libpanelapplet-2.0 >= 2.0.0 ,
build_gnome_applet=true,build_gnome_applet=false)
AC_SUBST(GNOME_APPLETS_CFLAGS)
AC_SUBST(GNOME_APPLETS_LIBS)
PKG_CHECK_MODULES(LIBGLADE, libglade-2.0 >= 2.4.0 , glade_ui=true, glade_ui=false)
AC_SUBST(LIBGLADE_CFLAGS)
AC_SUBST(LIBGLADE_LIBS)
else
build_gnome_applet=false
fi
dnl os-specific problems not handled by existing macros.
case "$host_os" in
*freebsd*)
LDFLAGS="$LDFLAGS -pthread"
;;
esac
case "$host_cpu" in
*arm*)
AC_DEFINE(__ARM__,1,[Defined if we are compiling for arm processor])
use_arm_toolchain=yes
;;
esac
AC_ARG_WITH( realprefix,
[ --with-realprefix Set the real installation prefix. This option has to be used for cross-compilation only. (ex:/usr or /usr/local)[default=none] ],
[ realprefix=${withval}],[ realprefix="none" ])
AC_ARG_ENABLE(manual,
[ --disable-manual Do not attempt to build html linphone's user documentation],
[case "${enableval}" in
yes) build_manual=yes ;;
no) build_manual=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-manual) ;;
esac],[build_manual=yes])
dnl enable ipv6 support
AC_ARG_ENABLE(ipv6,
[ --enable-ipv6 Turn on ipv6 support],
[case "${enableval}" in
yes) ipv6=true;;
no) ipv6=false;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-ipv6) ;;
esac],[ipv6=true])
IPV6_CFLAGS=
if test x$ipv6 = xtrue ; then
IPV6_CFLAGS=-DINET6
fi
AC_SUBST(IPV6_CFLAGS)
dnl enable truespeech codec support
AC_ARG_ENABLE(truespeech,
[ --enable-truespeech Turn on TrueSpeech support (x86 only)],
[case "${enableval}" in
yes) truespeech=true;;
no) truespeech=false;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-truespeech) ;;
esac],[truespeech=false])
TRUESPEECH_CFLAGS=
if test x$truespeech = xtrue ; then
TRUESPEECH_CFLAGS=-DTRUESPEECH
fi
AC_SUBST(TRUESPEECH_CFLAGS)
AM_CONDITIONAL([BUILD_TRUESPEECH], [test x$truespeech = xtrue])
dnl support for RSVP (by Vincent Maury)
AC_ARG_ENABLE(rsvp,
[ --enable-rsvp enable support for QoS reservations.],
AC_DEFINE(VINCENT_MAURY_RSVP,1,[Tell whether RSVP support
should be compiled.]) )
if test "x${prefix}" = "xNONE"; then
prefix=${ac_default_prefix}
fi
dnl Set PACKAGE_LOCALE_DIR in config.h.
DATADIRNAME=share
AC_DEFINE_UNQUOTED(PACKAGE_LOCALE_DIR, "${prefix}/${DATADIRNAME}/locale",[Defines the place where locales can be found])
AC_DEFINE_UNQUOTED(PACKAGE_DATA_DIR, "${prefix}/${DATADIRNAME}",[Defines the place where data are found])
dnl Set PACKAGE_SOUND_DIR in config.h.
AC_DEFINE_UNQUOTED(PACKAGE_SOUND_DIR, "${prefix}/${DATADIRNAME}/sounds/linphone",[Defines the place where linphone sounds are found])
dnl check if we have the getifaddrs() sytem call
AC_CHECK_FUNCS(getifaddrs)
dnl check for osip2
LP_CHECK_OSIP2
dnl setup flags for exosip library
LP_SETUP_EXOSIP
if test "$console_ui" = "true" ; then
dnl check gnu readline
LP_CHECK_READLINE
else
echo "Console interface compilation is disabled."
fi
AC_WORDS_BIGENDIAN
dnl normaly this should only by done by mediastreamer2/configure.ac
dnl but to workaround bugs when cross-compiling for arm-linux,
dnl we need to have SPEEX_LIBS defined
dnl Furthermore it is good to repeat here all mediastreamer2 toggles
dnl since top-level configure --help will not print them.
PKG_CHECK_MODULES(SPEEX, speex >= 1.1.6, build_speex=yes)
AC_SUBST(SPEEX_LIBS)
dnl conditionnal build of video support
AC_ARG_ENABLE(video,
[ --enable-video Turn on video support compiling],
[case "${enableval}" in
yes) video=true ;;
no) video=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-video) ;;
esac],[video=true])
AC_ARG_WITH( ffmpeg,
[ --with-ffmpeg Sets the installation prefix of ffmpeg, needed for video support. [default=/usr] ],
[ ffmpegdir=${withval}],[ ffmpegdir=/usr ])
AC_ARG_WITH( sdl,
[ --with-sdl Sets the installation prefix of libSDL, needed for video support. [default=/usr] ],
[ libsdldir=${withval}],[ libsdldir=/usr ])
if test "$video" = "true"; then
AC_DEFINE(VIDEO_ENABLED,1,[defined if video support is available])
fi
AC_ARG_ENABLE(alsa,
[ --enable-alsa Turn on alsa native support compiling],
[case "${enableval}" in
yes) alsa=true ;;
no) alsa=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-alsa) ;;
esac],[alsa=true])
AC_ARG_ENABLE(artsc,
[ --enable-artsc Turn on artsc (kde) sound input/output (auto) ],
[case "${enableval}" in
yes) artsc=true ;;
no) artsc=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-artsc) ;;
esac],[artsc=false])
AC_ARG_ENABLE(portaudio,
[ --enable-portaudio Turn on portaudio native support compiling],
[case "${enableval}" in
yes) portaudio=true ;;
no) portaudio=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-portaudio) ;;
esac],[portaudio=false])
dnl same thing for media_api
AM_CONDITIONAL(BUILD_MEDIA_API, test x$media_api = xtrue)
dnl build console if required
AM_CONDITIONAL(BUILD_CONSOLE, test x$console_ui = xtrue)
dnl build gtk if required
AM_CONDITIONAL(BUILD_GTK, test x$old_gtk_ui = xtrue)
dnl build gnome applet if possible
AM_CONDITIONAL(BUILD_GNOME_APPLET, test x$build_gnome_applet = xtrue)
dnl special things for arm-linux cross compilation toolchain
AM_CONDITIONAL(ARMBUILD, test x$use_arm_toolchain = xyes)
dnl compilation of gtk-glade user interface
AM_CONDITIONAL(BUILD_GLADE_UI, [test x$glade_ui = xtrue ] )
##################################################
# Stricter build options (after external packages)
##################################################
AC_ARG_ENABLE(strict,
AC_HELP_STRING([--enable-strict],
[Build with stricter options (gcc only) @<:@yes@:>@]),[
strictness="${enableval}"],[strictness=yes]
)
if test "$GCC$strictness" = "yesyes" ; then
STRICT_OPTIONS="-Wall -Wp,-D_FORTIFY_SOURCE=2"
STRICT_OPTIONS="$STRICT_OPTIONS -Werror"
CFLAGS="$CFLAGS -fno-strict-aliasing"
fi
AC_SUBST(STRICT_OPTIONS)
AC_CONFIG_SUBDIRS( mediastreamer2 )
dnl check for db2html (docbook) to generate html user manual
AC_CHECK_PROG(have_sgmltools,sgmltools, yes, no)
AM_CONDITIONAL(ENABLE_MANUAL, test x$have_sgmltools$build_manual = xyesyes )
dnl for external use of linphone libs
LINPHONE_CFLAGS="-I${includedir} -I${includedir}/linphone -I${includedir}/ortp "
LINPHONE_LIBS="-L${libdir} -llinphone"
AC_SUBST(LINPHONE_CFLAGS)
AC_SUBST(LINPHONE_LIBS)
AC_DEFINE_UNQUOTED(LINPHONE_VERSION,"$PACKAGE_VERSION",[Linphone's version number])
AC_ARG_ENABLE(external-ortp,
[ --enable-external-ortp Use external oRTP library],
[case "${enableval}" in
yes) external_ortp=true ;;
no) external_ortp=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-external-ortp) ;;
esac],[external_ortp=false])
if test "$external_ortp" = 'true'; then
LP_CHECK_ORTP
else
AC_CONFIG_SUBDIRS( oRTP )
ORTP_CFLAGS="-I\$(top_srcdir)/oRTP/include"
ORTP_LIBS="\$(top_builddir)/oRTP/src/libortp.la"
if test x$ac_cv_c_bigendian = xyes ; then
ORTP_CFLAGS="$ORTP_CFLAGS -DORTP_BIGENDIAN"
fi
fi
AC_SUBST(ORTP_CFLAGS)
AC_SUBST(ORTP_LIBS)
AM_CONDITIONAL(EXTERNAL_ORTP, [test "$external_ortp" = 'true'])
dnl Packaging: Pick oRTP version from ${top_srcdir}/oRTP/configure.ac
dnl Feel free to propose an alternative & cleaner version...
top_srcdir=`dirname $0`
changequote(, )dnl
ORTP_VERSION=`grep -E ^[AC]+_INIT ${top_srcdir}/oRTP/configure.ac | sed -e 's:^.*_INIT(.*,\[\(.*\)\]):\1:g'`
MS2_VERSION=`grep -E ^[AC]+_INIT ${top_srcdir}/mediastreamer2/configure.ac | sed -e 's:^.*_INIT(.*,\[\(.*\)\]):\1:g'`
changequote([, ])dnl
AC_SUBST([ORTP_VERSION])
AC_SUBST([MS2_VERSION])
AC_OUTPUT([
Makefile
m4/Makefile
po/Makefile.in
pixmaps/Makefile
ipkg/Makefile
ipkg/linphone.control
media_api/Makefile
coreapi/Makefile
gtk/Makefile
gtk-glade/Makefile
console/Makefile
share/Makefile
share/C/Makefile
share/fr/Makefile
share/it/Makefile
share/ja/Makefile
share/cs/Makefile
share/linphone.pc
linphone.spec
])
echo "Linphone build configuration ended."
if test x$gtk_ui = xtrue ; then
echo "* GTK interface will be compiled."
fi
if test x$gtk_ui = xtrue ; then
echo "* Console interface will be compiled."
fi
if test x$glade_ui = xtrue ; then
echo "* Gtk-glade still in early development interface will be compiled"
fi
if test "$have_db2html" = "no" ; then
echo "* db2html not found; user documentation will not be generated."
fi
echo "Now type 'make' to compile, and then 'make install' as root to install it."

View file

@ -0,0 +1,7 @@
.deps
.libs
Makefile
Makefile.in
linphonec
sipomatic
wav2raw

View file

@ -0,0 +1,37 @@
## Process this file with automake to produce Makefile.in
if BUILD_CONSOLE
INCLUDES = \
-I$(top_srcdir)\
-I$(top_srcdir)/coreapi\
$(ORTP_CFLAGS) \
-I$(top_srcdir)/exosip \
-I$(top_srcdir)/mediastreamer2/include
bin_PROGRAMS = linphonec sipomatic
linphonec_SOURCES = linphonec.c linphonec.h commands.c
linphonec_LDADD = $(top_builddir)/coreapi/liblinphone.la $(READLINE_LIBS) $(OSIP_LIBS)
sipomatic_SOURCES=\
sipomatic.c sipomatic.h
sipomatic_LDADD= $(INTLLIBS) \
$(top_builddir)/coreapi/liblinphone.la \
$(OSIP_LIBS)
endif
AM_CFLAGS=$(STRICT_OPTIONS) -DENABLE_TRACE -D_ORTP_SOURCE $(VIDEO_CFLAGS) $(READLINE_CFLAGS) $(OSIP_CFLAGS)
AM_LDFLAGS= $(top_builddir)/mediastreamer2/src/libmediastreamer.la \
$(ORTP_LIBS) \
$(SPEEX_LIBS) \
$(OSIP_LIBS)

20
linphone/console/TODO Normal file
View file

@ -0,0 +1,20 @@
In pseudo-order of priority:
---------------------------
- Exctract presence info in friends list
- Allow friend call arg to be a pattern
- hide input during password insertions
[ could use ncurses noecho() ]
- Allow for single-shot mode (call somebody and quit after the fact)
maybe "linphonec [OPTS] <sip-uri>" would do..
Unfortunately the -s switch would confuse people, I'd rather
change its semantic to "source file" where file wold contain
a list of commands, so ./linephone -s myfriend.sip would call
yourfriend...
- implement "smart" command completion

1236
linphone/console/commands.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,51 @@
# this file is used to store user config values for linphonec
# please modify and copy it to ~/.linphonec
#
#
logfile=~/linphonec.log
debuglevel=0
local_addr=192.168.1.10
if_name=eth0
# type of network connection 4 = ethernet
con_type=4
# rtp
audio_rtp_port=7078
jitt_comp=150
# audio
driver_mode=0
rec_lev=100
play_lev=100
source=109
autokill=0
# sip
sip_port=5060
use_registrar=0
username=1006
hostname=192.168.1.1
registrar=sip:192.168.1.1:5060
reg_passwd=
addr_of_rec=sip:1006@192.168.1.1
reg_expires=900
as_proxy=1
as_redirect=0
as_outbound=1
# codecs
audio_codecs=259 371 264 256
# short dial
s0=sip:1002@130.83.176.121
s1=sip:1001@192.168.1.1
s2=sip:1002@192.168.1.1
s3=sip:1003@192.168.1.1
s4=sip:1004@192.168.1.1

1114
linphone/console/linphonec.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,134 @@
/****************************************************************************
*
* $Id: linphonec.h,v 1.3 2006/01/20 14:12:34 strk Exp $
*
* Copyright (C) 2005 Sandro Santilli <strk@keybit.net>
*
****************************************************************************
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
****************************************************************************/
#ifndef LINPHONEC_H
#define LINPHONEC_H 1
#ifdef HAVE_READLINE_H
#include <readline.h>
#else
#ifdef HAVE_READLINE_READLINE_H
#include <readline/readline.h>
#endif
#endif
#ifdef HAVE_HISTORY_H
#include <history.h>
#else
#ifdef HAVE_READLINE_HISTORY_H
#include <readline/history.h>
#endif
#endif
/**************************************************************************
*
* Compile-time defines
*
**************************************************************************/
#define HISTSIZE 500 /* how many lines of input history */
#define PROMPT_MAX_LEN 256 /* max len of prompt string */
#define LINE_MAX_LEN 256 /* really needed ? */
/*
* Define this to have your primary contact
* as the prompt string
*/
/* #define IDENTITY_AS_PROMPT 1 */
/*
* Time between calls to linphonec_idle_call during main
* input read loop in microseconds.
*/
#define LPC_READLINE_TIMEOUT 1000000
/*
* Filename of linphonec history
*/
#define LPC_HIST_FILE "~/.linphonec_history"
/*
* Maximum number of pending authentications
*/
#define MAX_PENDING_AUTH 8
/**************************************************************************
*
* Types
*
**************************************************************************/
/*
* A structure which contains information on the commands this program
* can understand.
*/
typedef int (*lpc_cmd_handler)(LinphoneCore *, char *);
typedef struct {
char *name; /* User printable name of the function. */
lpc_cmd_handler func; /* Function to call to do the job. */
char *help; /* Short help for this function. */
char *doc; /* Long description. */
} LPC_COMMAND;
/***************************************************************************
*
* Forward declarations
*
***************************************************************************/
extern int linphonec_parse_command_line(LinphoneCore *lc, char *cl);
extern char *linphonec_command_generator(const char *text, int state);
extern void linphonec_finish(int exit_status);
#endif /* def LINPHONEC_H */
/****************************************************************************
*
* $Log: linphonec.h,v $
* Revision 1.3 2006/01/20 14:12:34 strk
* Added linphonec_init() and linphonec_finish() functions.
* Handled SIGINT and SIGTERM to invoke linphonec_finish().
* Handling of auto-termination (-t) moved to linphonec_finish().
* Reworked main (input read) loop to not rely on 'terminate'
* and 'run' variable (dropped). configfile_name allocated on stack
* using PATH_MAX limit. Changed print_usage signature to allow
* for an exit_status specification.
*
* Revision 1.2 2006/01/14 13:29:32 strk
* Reworked commands interface to use a table structure,
* used by command line parser and help function.
* Implemented first level of completion (commands).
* Added notification of invalid "answer" and "terminate"
* commands (no incoming call, no active call).
* Forbidden "call" intialization when a call is already active.
* Cleaned up all commands, adding more feedback and error checks.
*
* Revision 1.1 2006/01/13 13:00:29 strk
* Added linphonec.h. Code layout change (added comments, forward decl,
* globals on top, copyright notices and Logs). Handled out-of-memory
* condition on history management. Removed assumption on sizeof(char).
* Fixed bug in authentication prompt (introduced by readline).
* Added support for multiple authentication requests (up to MAX_PENDING_AUTH).
*
*
****************************************************************************/

View file

@ -0,0 +1,467 @@
/***************************************************************************
linphone - sipomatic.c
This is a test program for linphone. It acts as a sip server and answers to linphone's
call.
-------------------
begin : ven mar 30
copyright : (C) 2001 by Simon MORLAT
email : simon.morlat@linphone.org
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <signal.h>
#include "sipomatic.h"
#include <eXosip2/eXosip.h>
int run_cond=1;
Sipomatic sipomatic;
int sipomatic_accept_audio_offer(sdp_context_t *ctx,sdp_payload_t *payload);
int sipomatic_accept_video_offer(sdp_context_t *ctx,sdp_payload_t *payload);
sdp_handler_t sipomatic_sdp_handler={
sipomatic_accept_audio_offer, /*from remote sdp */
sipomatic_accept_video_offer,
NULL,
NULL,
NULL,
NULL,
};
void stop_handler(int signum)
{
run_cond=0;
}
void sipomatic_process_event(Sipomatic *obj,eXosip_event_t *ev)
{
Call *call;
switch(ev->type){
case EXOSIP_CALL_INVITE:
call_new(obj,ev);
break;
case EXOSIP_CALL_CLOSED:
case EXOSIP_CALL_CANCELLED:
call=sipomatic_find_call(obj,ev->did);
if (call==NULL){
ms_warning("Could not find call with did %i !",ev->did);
}
call_release(call);
call_destroy(call);
break;
default:
break;
}
eXosip_event_free(ev);
}
void endoffile_cb(void *ud, unsigned int ev,void * arg){
Call*call=(Call*)ud;
call->eof=1;
}
void call_accept(Call *call)
{
sdp_context_t *ctx;
PayloadType *payload;
char *hellofile;
static int call_count=0;
char record_file[250];
osip_message_t *msg=NULL;
sprintf(record_file,"/tmp/sipomatic%i.wav",call_count);
ctx=call->sdpc;
payload=rtp_profile_get_payload(call->profile,call->audio.pt);
if (strcmp(payload->mime_type,"telephone-event")==0){
/* telephone-event is not enough to accept a call */
ms_message("Cannot accept call with only telephone-event.\n");
eXosip_call_send_answer(call->did,415,NULL);
call->state=CALL_STATE_FINISHED;
return;
}
if (payload->clock_rate==16000){
hellofile=call->root->file_path16000hz;
}else hellofile=call->root->file_path8000hz;
eXosip_call_build_answer(call->tid,200,&msg);
osip_message_set_content_type(msg,"application/sdp");
osip_message_set_body(msg,call->sdpc->answerstr,strlen(call->sdpc->answerstr));
eXosip_call_send_answer(call->tid,200,msg);
call->audio_stream=audio_stream_new(call->audio.localport,call->root->ipv6);
audio_stream_start_with_files(call->audio_stream, call->profile,
call->audio.remaddr,call->audio.remoteport,call->audio.remoteport+1,
call->audio.pt,20,hellofile,record_file);
call_count++;
#ifdef VIDEO_ENABLED
if (call->video.remoteport!=0){
video_stream_send_only_start(call->video_stream,call->profile,
call->video.remaddr,call->video.remoteport,call->video.remoteport+1,call->video.pt, 60,
ms_web_cam_manager_get_default_cam(ms_web_cam_manager_get()));
}
#endif
call->time=time(NULL);
call->state=CALL_STATE_RUNNING;
ms_filter_set_notify_callback(call->audio_stream->soundread,endoffile_cb,(void*)call);
}
PayloadType * sipomatic_payload_is_supported(sdp_payload_t *payload,RtpProfile *local_profile,RtpProfile *dialog_profile)
{
int localpt;
if (payload->a_rtpmap!=NULL){
localpt=rtp_profile_get_payload_number_from_rtpmap(local_profile,payload->a_rtpmap);
}else{
localpt=payload->pt;
ms_warning("payload has no rtpmap.");
}
if (localpt>=0){
/* this payload is supported in our local rtp profile, so add it to the dialog rtp
profile */
PayloadType *rtppayload;
rtppayload=rtp_profile_get_payload(local_profile,localpt);
if (rtppayload==NULL) return NULL;
/*check if we have the appropriate coder/decoder for this payload */
if (strcmp(rtppayload->mime_type,"telephone-event")!=0) {
if (!ms_filter_codec_supported(rtppayload->mime_type)) {
ms_message("Codec %s is not supported.", rtppayload->mime_type);
return NULL;
}
}
rtppayload=payload_type_clone(rtppayload);
rtp_profile_set_payload(dialog_profile,payload->pt,rtppayload);
/* add to the rtp payload type some other parameters (bandwidth) */
if (payload->b_as_bandwidth!=0) rtppayload->normal_bitrate=payload->b_as_bandwidth*1000;
if (payload->a_fmtp!=NULL)
payload_type_set_send_fmtp(rtppayload,payload->a_fmtp);
if (strcasecmp(rtppayload->mime_type,"iLBC")==0){
/*default to 30 ms mode */
payload->a_fmtp="ptime=30";
payload_type_set_recv_fmtp(rtppayload,payload->a_fmtp);
}
return rtppayload;
}
return NULL;
}
int sipomatic_accept_audio_offer(sdp_context_t *ctx,sdp_payload_t *payload)
{
static int audioport=8000;
Call *call=(Call*)sdp_context_get_user_pointer(ctx);
PayloadType *supported;
struct stream_params *params=&call->audio;
/* see if this codec is supported in our local rtp profile*/
supported=sipomatic_payload_is_supported(payload,&av_profile,call->profile);
if (supported==NULL) {
ms_message("Refusing codec %i (%s)",payload->pt,payload->a_rtpmap);
return -1;
}
if (strcmp(supported->mime_type,"telephone-event")==0) return 0;
if (params->ncodecs==0 ){
/* this is the first codec we may accept*/
params->localport=payload->localport=audioport;
params->remoteport=payload->remoteport;
params->line=payload->line;
params->pt=payload->pt; /* remember the first payload accepted */
params->remaddr=payload->c_addr;
params->ncodecs++;
audioport+=4;
}else{
/* refuse all other audio lines*/
if(params->line!=payload->line) return -1;
}
return 0;
}
int sipomatic_accept_video_offer(sdp_context_t *ctx,sdp_payload_t *payload)
{
#ifdef VIDEO_ENABLED
static int videoport=80000;
Call *call=(Call*)sdp_context_get_user_pointer(ctx);
PayloadType *supported;
struct stream_params *params=&call->video;
/* see if this codec is supported in our local rtp profile*/
supported=sipomatic_payload_is_supported(payload,&av_profile,call->profile);
if (supported==NULL) {
ms_message("Refusing video codec %i (%s)",payload->pt,payload->a_rtpmap);
return -1;
}
if (params->ncodecs==0 ){
/* this is the first codec we may accept*/
params->localport=payload->localport=videoport;
params->remoteport=payload->remoteport;
params->line=payload->line;
params->pt=payload->pt; /* remember the first payload accepted */
params->remaddr=payload->c_addr;
params->ncodecs++;
videoport+=4;
}else{
/* refuse all other video lines*/
if(params->line!=payload->line) return -1;
}
return 0;
#else
return -1;
#endif
}
void sipomatic_init(Sipomatic *obj, char *url, bool_t ipv6)
{
osip_uri_t *uri=NULL;
int port=5064;
obj->ipv6=ipv6;
if (url==NULL){
url=getenv("SIPOMATIC_URL");
if (url==NULL){
if (ipv6) url="sip:robot@[::1]:5064";
else url="sip:robot@127.0.0.1:5064";
}
}
if (url!=NULL) {
osip_uri_init(&uri);
if (osip_uri_parse(uri,url)==0){
if (uri->port!=NULL) port=atoi(uri->port);
}else{
ms_warning("Invalid identity uri:%s",url);
}
}
ms_message("Starting using url %s",url);
ms_mutex_init(&obj->lock,NULL);
obj->calls=NULL;
obj->acceptance_time=5;
obj->max_call_time=300;
obj->file_path8000hz=ms_strdup_printf("%s/%s",PACKAGE_SOUND_DIR,ANNOUCE_FILE8000HZ);
obj->file_path16000hz=ms_strdup_printf("%s/%s",PACKAGE_SOUND_DIR,ANNOUCE_FILE16000HZ);
osip_trace_initialize(OSIP_INFO1,stdout);
osip_trace_initialize(OSIP_INFO2,stdout);
osip_trace_initialize(OSIP_WARNING,stdout);
osip_trace_initialize(OSIP_ERROR,stdout);
osip_trace_initialize(OSIP_BUG,stdout);
osip_trace_initialize(OSIP_FATAL,stdout);
osip_trace_enable_level(OSIP_INFO1);
osip_trace_enable_level(OSIP_INFO2);
osip_trace_enable_level(OSIP_WARNING);
osip_trace_enable_level(OSIP_ERROR);
osip_trace_enable_level(OSIP_BUG);
osip_trace_enable_level(OSIP_FATAL);
eXosip_init();
eXosip_set_user_agent("sipomatic-" LINPHONE_VERSION "/eXosip");
eXosip_listen_addr(IPPROTO_UDP,NULL,port,ipv6 ? AF_INET6 : AF_INET,0);
}
void sipomatic_uninit(Sipomatic *obj)
{
ms_mutex_destroy(&obj->lock);
eXosip_quit();
}
void sipomatic_iterate(Sipomatic *obj)
{
MSList *elem;
MSList *to_be_destroyed=NULL;
Call *call;
double elapsed;
eXosip_event_t *ev;
while((ev=eXosip_event_wait(0,0))!=NULL){
sipomatic_process_event(obj,ev);
}
elem=obj->calls;
while(elem!=NULL){
call=(Call*)elem->data;
elapsed=time(NULL)-call->time;
switch(call->state){
case CALL_STATE_INIT:
if (elapsed>obj->acceptance_time){
call_accept(call);
}
break;
case CALL_STATE_RUNNING:
if (elapsed>obj->max_call_time || call->eof){
call_release(call);
to_be_destroyed=ms_list_append(to_be_destroyed,call);
}
break;
}
elem=ms_list_next(elem);
}
for(;to_be_destroyed!=NULL; to_be_destroyed=ms_list_next(to_be_destroyed)){
call_destroy((Call*)to_be_destroyed->data);
}
}
Call* sipomatic_find_call(Sipomatic *obj,int did)
{
MSList *it;
Call *call=NULL;
for (it=obj->calls;it!=NULL;it=ms_list_next(it)){
call=(Call*)it->data;
if ( call->did==did) return call;
}
return call;
}
Call * call_new(Sipomatic *root, eXosip_event_t *ev)
{
Call *obj;
char *sdpans;
int status;
sdp_message_t *sdp;
sdp_context_t *sdpc;
sdp=eXosip_get_sdp_info(ev->request);
sdpc=sdp_handler_create_context(&sipomatic_sdp_handler,NULL,"sipomatic",NULL);
obj=ms_new0(Call,1);
obj->profile=rtp_profile_new("remote");
eXosip_call_send_answer(ev->tid,100,NULL);
sdp_context_set_user_pointer(sdpc,obj);
sdpans=sdp_context_get_answer(sdpc,sdp);
if (sdpans!=NULL){
eXosip_call_send_answer(ev->tid,180,NULL);
}else{
status=sdp_context_get_status(sdpc);
eXosip_call_send_answer(ev->tid,status,NULL);
sdp_context_free(sdpc);
rtp_profile_destroy(obj->profile);
ms_free(obj);
return NULL;
}
obj->sdpc=sdpc;
obj->did=ev->did;
obj->tid=ev->tid;
obj->time=time(NULL);
obj->audio_stream=NULL;
obj->state=CALL_STATE_INIT;
obj->eof=0;
obj->root=root;
root->calls=ms_list_append(root->calls,obj);
return obj;
}
void call_release(Call *call)
{
eXosip_call_terminate(0,call->did);
if (call->audio_stream!=NULL) audio_stream_stop(call->audio_stream);
#ifdef VIDEO_ENABLED
if (call->video_stream!=NULL) video_stream_send_only_stop(call->video_stream);
#endif
call->state=CALL_STATE_FINISHED;
}
void call_destroy(Call *obj)
{
obj->root->calls=ms_list_remove(obj->root->calls,obj);
rtp_profile_destroy(obj->profile);
sdp_context_free(obj->sdpc);
ms_free(obj);
}
void sipomatic_set_annouce_file(Sipomatic *obj, char *file)
{
if (obj->file_path8000hz!=NULL){
ms_free(obj->file_path8000hz);
}
obj->file_path8000hz=ms_strdup(file);
}
void display_help()
{
printf("sipomatic [-u sip-url] [-f annouce-file ] [-s port]\n"
"sipomatic -h or --help: display this help.\n"
"sipomatic -v or --version: display version information.\n"
" -u sip-url : specify the sip url sipomatic listens and answers.\n"
" -f annouce-file : set the annouce file (16 bit raw format,8000Hz)\n"
" -6 enable ipv6 network usage\n");
exit(0);
}
char *getarg(int argc, char*argv[], int i)
{
if (i<argc){
return argv[i];
}
else display_help();
return NULL;
}
int main(int argc, char *argv[])
{
int sendport=5070;
char *file=NULL;
char *url=NULL;
bool_t ipv6=FALSE;
int i;
for(i=1;i<argc;i++){
if ( (strcmp(argv[i],"-h")==0) || (strcmp(argv[i],"--help")==0) ){
display_help();
continue;
}
if ( (strcmp(argv[i],"-v")==0) || (strcmp(argv[i],"--version")==0) ){
printf("version: " LINPHONE_VERSION "\n");
exit(0);
}
if (strcmp(argv[i],"-u")==0){
i++;
url=getarg(argc,argv,i);
continue;
}
if (strcmp(argv[i],"-s")==0){
char *port;
i++;
port=getarg(argc,argv,i);
sendport=atoi(port);
continue;
}
if (strcmp(argv[i],"-f")==0){
i++;
file=getarg(argc,argv,i);
continue;
}
if (strcmp(argv[i],"-6")==0){
ipv6=TRUE;
continue;
}
}
signal(SIGINT,stop_handler);
ortp_init();
ms_init();
ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
rtp_profile_set_payload(&av_profile,115,&payload_type_lpc1015);
rtp_profile_set_payload(&av_profile,110,&payload_type_speex_nb);
rtp_profile_set_payload(&av_profile,111,&payload_type_speex_wb);
rtp_profile_set_payload(&av_profile,112,&payload_type_ilbc);
rtp_profile_set_payload(&av_profile,101,&payload_type_telephone_event);
rtp_profile_set_payload(&av_profile,116,&payload_type_truespeech);
rtp_profile_set_payload(&av_profile,98,&payload_type_h263_1998);
sipomatic_init(&sipomatic,url,ipv6);
if (file!=NULL) sipomatic_set_annouce_file(&sipomatic,file);
while (run_cond){
sipomatic_iterate(&sipomatic);
usleep(20000);
}
return(0);
}

View file

@ -0,0 +1,96 @@
/***************************************************************************
linphone - sipomatic.c
This is a test program for linphone. It acts as a sip server and answers to linphone's
call.
-------------------
begin : ven mar 30
copyright : (C) 2001 by Simon MORLAT
email : simon.morlat@free.fr
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "../coreapi/linphonecore.h"
#include "../coreapi/sdphandler.h"
#include <eXosip2/eXosip.h>
#undef PACKAGE
#undef VERSION
#include "mediastreamer2/mediastream.h"
#include <ortp/ortp.h>
#include <ortp/telephonyevents.h>
#define ANNOUCE_FILE8000HZ "hello8000.wav"
#define ANNOUCE_FILE16000HZ "hello16000.wav"
struct _Sipomatic
{
ms_mutex_t lock;
MSList *calls;
double acceptance_time;
double max_call_time;
char *file_path8000hz;
char *file_path16000hz;
bool_t ipv6;
};
typedef struct _Sipomatic Sipomatic;
void sipomatic_init(Sipomatic *obj, char *url, bool_t ipv6);
void sipomatic_uninit(Sipomatic *obj);
void sipomatic_iterate(Sipomatic *obj);
#define sipomatic_lock(obj) ms_mutex_lock(&(obj)->lock);
#define sipomatic_unlock(obj) ms_mutex_unlock(&(obj)->lock);
void sipomatic_set_annouce_file(Sipomatic *obj, char *file);
struct stream_params{
int ncodecs;
int line;
int localport;
int remoteport;
int pt;
char *remaddr;
};
struct _Call
{
Sipomatic *root;
sdp_context_t *sdpc;
int time;
int did;
int tid;
AudioStream *audio_stream;
#ifdef VIDEO_ENABLED
VideoStream *video_stream;
#endif
int state;
struct _CallParams *params;
int eof;
RtpProfile *profile;
struct stream_params audio;
struct stream_params video;
};
#define CALL_STATE_INIT 0
#define CALL_STATE_RUNNING 1
#define CALL_STATE_FINISHED 2
typedef struct _Call Call;
Call * call_new(Sipomatic *obj, eXosip_event_t *ev);
void call_accept(Call *call);
void call_release(Call *call);
void call_destroy(Call *call);
Call* sipomatic_find_call(Sipomatic *obj,int cid);

View file

@ -0,0 +1,67 @@
#include "../config.h"
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
int main(int argc, char *argv[])
{
int ifd,ofd;
char *name,*p;
char buf[200];
int len;
if (argc<2) return -1;
name=malloc(strlen(argv[1])+10);
sprintf(name,"%s",argv[1]);
p=strstr(name,".raw");
if (p!=NULL){
sprintf(p,"%s",".wav\0");
}else{
sprintf(name,"%s%s",argv[1],".raw");
}
ifd=open(name,O_RDONLY);
if (ifd<0) {
perror("Could not open input file");
return -1;
}
ofd=open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP);
if (ofd<0) {
perror("Could not open output file");
return -1;
}
len=read(ifd,buf,20);
printf("len=%i\n",len);
/* erase the wav header */
if (len>0){
memset(buf,0,20);
write(ofd,buf,20);
}else{
printf("Error while processing %s: %s\n",argv[1],strerror(errno));
return -1;
};
while ( (len=read(ifd,buf,200))>0){
#ifdef WORDS_BIGENDIAN
for (i=0;i<len/2;i+=2){
tmp=buf[i];
buf[i]=buf[i+1];
buf[i+1]=tmp;
}
#endif
write(ofd,buf,len);
}
close(ifd);
close(ofd);
return 0;
}

View file

@ -0,0 +1,7 @@
Makefile
Makefile.in
.deps
.libs
*.lo
*.la
*.loT

View file

@ -0,0 +1,46 @@
## Process this file with automake to produce Makefile.in
linphone_includedir=$(includedir)/linphone
linphone_include_HEADERS=linphonecore.h ../config.h lpconfig.h
INCLUDES = \
-I$(top_srcdir)\
-I$(top_srcdir)/mediastreamer2/include
lib_LTLIBRARIES=liblinphone.la
liblinphone_la_SOURCES=\
linphonecore.c linphonecore.h private.h\
exevents.c exevents.h \
misc.c \
enum.c enum.h \
sdphandler.c sdphandler.h \
presence.c \
proxy.c \
friend.c \
authentication.c \
lpconfig.c lpconfig.h \
chat.c \
general_state.c
liblinphone_la_LDFLAGS= -version-info $(LIBLINPHONE_SO_VERSION)
liblinphone_la_LIBADD= \
$(EXOSIP_LIBS) \
$(top_builddir)/mediastreamer2/src/libmediastreamer.la
AM_CFLAGS=$(STRICT_OPTIONS) \
$(OSIP_CFLAGS) \
$(EXOSIP_CFLAGS) \
$(ORTP_CFLAGS) \
-DENABLE_TRACE \
-DLOG_DOMAIN=\"LinphoneCore\" \
$(IPV6_CFLAGS) \
-DORTP_INET6 \
$(VIDEO_CFLAGS)

View file

@ -0,0 +1,273 @@
/***************************************************************************
* authentication.c
*
* Fri Jul 16 12:08:34 2004
* Copyright 2004 Simon MORLAT
* simon.morlat@linphone.org
****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "linphonecore.h"
#include "private.h"
#include <eXosip2/eXosip.h>
#include <osipparser2/osip_message.h>
#include "lpconfig.h"
extern LinphoneProxyConfig *linphone_core_get_proxy_config_from_rid(LinphoneCore *lc, int rid);
extern void linphone_proxy_config_set_realm(LinphoneProxyConfig *cfg, const char *realm);
extern void linphone_core_retry_proxy_register(LinphoneCore *lc, const char *realm);
LinphoneAuthInfo *linphone_auth_info_new(const char *username, const char *userid,
const char *passwd, const char *ha1,const char *realm)
{
LinphoneAuthInfo *obj=ms_new0(LinphoneAuthInfo,1);
if (username!=NULL && (strlen(username)>0) ) obj->username=ms_strdup(username);
if (userid!=NULL && (strlen(userid)>0)) obj->userid=ms_strdup(userid);
if (passwd!=NULL && (strlen(passwd)>0)) obj->passwd=ms_strdup(passwd);
if (ha1!=NULL && (strlen(ha1)>0)) obj->ha1=ms_strdup(ha1);
if (realm!=NULL && (strlen(realm)>0)) obj->realm=ms_strdup(realm);
obj->works=FALSE;
obj->first_time=TRUE;
return obj;
}
void linphone_auth_info_set_passwd(LinphoneAuthInfo *info, const char *passwd){
if (info->passwd!=NULL) {
ms_free(info->passwd);
info->passwd=NULL;
}
if (passwd!=NULL && (strlen(passwd)>0)) info->passwd=ms_strdup(passwd);
}
void linphone_auth_info_destroy(LinphoneAuthInfo *obj){
if (obj->username!=NULL) ms_free(obj->username);
if (obj->userid!=NULL) ms_free(obj->userid);
if (obj->passwd!=NULL) ms_free(obj->passwd);
if (obj->ha1!=NULL) ms_free(obj->ha1);
if (obj->realm!=NULL) ms_free(obj->realm);
ms_free(obj);
}
void linphone_auth_info_write_config(LpConfig *config, LinphoneAuthInfo *obj, int pos)
{
char key[50];
sprintf(key,"auth_info_%i",pos);
lp_config_clean_section(config,key);
if (obj==NULL){
return;
}
if (obj->username!=NULL){
lp_config_set_string(config,key,"username",obj->username);
}
if (obj->userid!=NULL){
lp_config_set_string(config,key,"userid",obj->userid);
}
if (obj->passwd!=NULL){
lp_config_set_string(config,key,"passwd",obj->passwd);
}
if (obj->ha1!=NULL){
lp_config_set_string(config,key,"ha1",obj->ha1);
}
if (obj->realm!=NULL){
lp_config_set_string(config,key,"realm",obj->realm);
}
lp_config_sync(config);
}
LinphoneAuthInfo *linphone_auth_info_new_from_config_file(LpConfig * config, int pos)
{
char key[50];
const char *username,*userid,*passwd,*ha1,*realm;
sprintf(key,"auth_info_%i",pos);
if (!lp_config_has_section(config,key)){
return NULL;
}
username=lp_config_get_string(config,key,"username",NULL);
userid=lp_config_get_string(config,key,"userid",NULL);
passwd=lp_config_get_string(config,key,"passwd",NULL);
ha1=lp_config_get_string(config,key,"ha1",NULL);
realm=lp_config_get_string(config,key,"realm",NULL);
return linphone_auth_info_new(username,userid,passwd,ha1,realm);
}
static bool_t key_match(const char *tmp1, const char *tmp2){
if (tmp1==NULL && tmp2==NULL) return TRUE;
if (tmp1!=NULL && tmp2!=NULL && strcmp(tmp1,tmp2)==0) return TRUE;
return FALSE;
}
static int auth_info_compare(const void *pinfo,const void *pref){
LinphoneAuthInfo *info=(LinphoneAuthInfo*)pinfo;
LinphoneAuthInfo *ref=(LinphoneAuthInfo*)pref;
if (key_match(info->realm,ref->realm) && key_match(info->username,ref->username)) return 0;
return -1;
}
LinphoneAuthInfo *linphone_core_auth_info_find(LinphoneCore *lc, const char *realm, const char *username)
{
LinphoneAuthInfo ref;
MSList *elem;
ref.realm=(char*)realm;
ref.username=(char*)username;
elem=ms_list_find_custom(lc->auth_info,auth_info_compare,(void*)&ref);
if (elem==NULL) return NULL;
return (LinphoneAuthInfo*)elem->data;
}
void linphone_core_add_auth_info(LinphoneCore *lc, LinphoneAuthInfo *info)
{
int n;
MSList *elem;
char *userid;
if (info->userid==NULL || info->userid[0]=='\0') userid=info->username;
else userid=info->userid;
eXosip_lock();
eXosip_add_authentication_info(info->username,userid,
info->passwd,info->ha1,info->realm);
eXosip_unlock();
/* if the user was prompted, re-allow automatic_action */
if (lc->automatic_action>0) lc->automatic_action--;
/* find if we are attempting to modify an existing auth info */
elem=ms_list_find_custom(lc->auth_info,auth_info_compare,info);
if (elem!=NULL){
linphone_auth_info_destroy((LinphoneAuthInfo*)elem->data);
elem->data=(void *)info;
n=ms_list_position(lc->auth_info,elem);
}else {
lc->auth_info=ms_list_append(lc->auth_info,(void *)info);
n=ms_list_size(lc->auth_info)-1;
}
}
void linphone_core_abort_authentication(LinphoneCore *lc, LinphoneAuthInfo *info){
if (lc->automatic_action>0) lc->automatic_action--;
}
void linphone_core_remove_auth_info(LinphoneCore *lc, LinphoneAuthInfo *info){
int len=ms_list_size(lc->auth_info);
int newlen;
int i;
MSList *elem;
lc->auth_info=ms_list_remove(lc->auth_info,info);
newlen=ms_list_size(lc->auth_info);
/*printf("len=%i newlen=%i\n",len,newlen);*/
linphone_auth_info_destroy(info);
for (i=0;i<len;i++){
linphone_auth_info_write_config(lc->config,NULL,i);
}
for (elem=lc->auth_info,i=0;elem!=NULL;elem=ms_list_next(elem),i++){
linphone_auth_info_write_config(lc->config,(LinphoneAuthInfo*)elem->data,i);
}
}
void linphone_core_clear_all_auth_info(LinphoneCore *lc){
MSList *elem;
int i;
eXosip_lock();
eXosip_clear_authentication_info();
eXosip_unlock();
for(i=0,elem=lc->auth_info;elem!=NULL;elem=ms_list_next(elem),i++){
LinphoneAuthInfo *info=(LinphoneAuthInfo*)elem->data;
linphone_auth_info_destroy(info);
linphone_auth_info_write_config(lc->config,NULL,i);
}
ms_list_free(lc->auth_info);
lc->auth_info=NULL;
}
void linphone_authentication_ok(LinphoneCore *lc, eXosip_event_t *ev){
char *prx_realm=NULL,*www_realm=NULL;
osip_proxy_authorization_t *prx_auth;
osip_authorization_t *www_auth;
osip_message_t *msg=ev->request;
char *username;
LinphoneAuthInfo *as=NULL;
username=osip_uri_get_username(msg->from->url);
osip_message_get_proxy_authorization(msg,0,&prx_auth);
osip_message_get_authorization(msg,0,&www_auth);
if (prx_auth!=NULL)
prx_realm=osip_proxy_authorization_get_realm(prx_auth);
if (www_auth!=NULL)
www_realm=osip_authorization_get_realm(www_auth);
if (prx_realm==NULL && www_realm==NULL){
ms_message("No authentication info in the request, ignoring");
return;
}
/* see if we already have this auth information , not to ask it everytime to the user */
if (prx_realm!=NULL)
as=linphone_core_auth_info_find(lc,prx_realm,username);
if (www_realm!=NULL)
as=linphone_core_auth_info_find(lc,www_realm,username);
if (as){
ms_message("Authentication for user=%s realm=%s is working.",username,prx_realm ? prx_realm : www_realm);
as->works=TRUE;
}
}
void linphone_core_find_or_ask_for_auth_info(LinphoneCore *lc,const char *username,const char* realm, int tid)
{
LinphoneAuthInfo *as;
if ((as=linphone_core_auth_info_find(lc,realm,username))==NULL ||
(as->works==FALSE && as->first_time==FALSE) ) {
if (lc->vtable.auth_info_requested!=NULL) {
lc->vtable.auth_info_requested(lc,realm,username);
lc->automatic_action++;/*suspends eXosip_automatic_action until the user supplies a password */
}
if (as) as->first_time=FALSE;
}
}
void linphone_process_authentication(LinphoneCore *lc, eXosip_event_t *ev)
{
char *prx_realm=NULL,*www_realm=NULL;
osip_proxy_authenticate_t *prx_auth;
osip_www_authenticate_t *www_auth;
osip_message_t *resp=ev->response;
char *username;
if (strcmp(ev->request->sip_method,"REGISTER")==0) {
gstate_new_state(lc, GSTATE_REG_FAILED, "Authentication required");
}
username=osip_uri_get_username(resp->from->url);
prx_auth=(osip_proxy_authenticate_t*)osip_list_get(&resp->proxy_authenticates,0);
www_auth=(osip_proxy_authenticate_t*)osip_list_get(&resp->www_authenticates,0);
if (prx_auth!=NULL)
prx_realm=osip_proxy_authenticate_get_realm(prx_auth);
if (www_auth!=NULL)
www_realm=osip_www_authenticate_get_realm(www_auth);
if (prx_realm==NULL && www_realm==NULL){
ms_warning("No realm in the server response.");
return;
}
/* see if we already have this auth information , not to ask it everytime to the user */
if (prx_realm!=NULL)
linphone_core_find_or_ask_for_auth_info(lc,username,prx_realm,ev->tid);
if (www_realm!=NULL)
linphone_core_find_or_ask_for_auth_info(lc,username,www_realm,ev->tid);
}

109
linphone/coreapi/chat.c Normal file
View file

@ -0,0 +1,109 @@
/***************************************************************************
* chat.c
*
* Sun Jun 5 19:34:18 2005
* Copyright 2005 Simon Morlat
* Email simon dot morlat at linphone dot org
****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "linphonecore.h"
#include "private.h"
#include <eXosip2/eXosip.h>
LinphoneChatRoom * linphone_core_create_chat_room(LinphoneCore *lc, const char *to){
char *real_url=NULL;
osip_from_t *parsed_url=NULL;
char *route;
if (linphone_core_interpret_url(lc,to,&real_url,&parsed_url,&route)){
LinphoneChatRoom *cr=ms_new0(LinphoneChatRoom,1);
cr->lc=lc;
cr->peer=real_url;
cr->peer_url=parsed_url;
cr->route=route;
lc->chatrooms=ms_list_append(lc->chatrooms,(void *)cr);
return cr;
}
return NULL;
}
void linphone_chat_room_destroy(LinphoneChatRoom *cr){
LinphoneCore *lc=cr->lc;
lc->chatrooms=ms_list_remove(lc->chatrooms,(void *) cr);
osip_from_free(cr->peer_url);
ms_free(cr->peer);
ms_free(cr->route);
}
void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg){
const char *identity=linphone_core_get_identity(cr->lc);
osip_message_t *sip=NULL;
eXosip_message_build_request(&sip,"MESSAGE",cr->peer,identity,cr->route);
osip_message_set_content_type(sip,"text/plain");
osip_message_set_body(sip,msg,strlen(msg));
eXosip_message_send_request(sip);
}
bool_t linphone_chat_room_matches(LinphoneChatRoom *cr, osip_from_t *from){
if (cr->peer_url->url->username && from->url->username &&
strcmp(cr->peer_url->url->username,from->url->username)==0) return TRUE;
return FALSE;
}
void linphone_chat_room_text_received(LinphoneChatRoom *cr, LinphoneCore *lc, const char *from, const char *msg){
if (lc->vtable.text_received!=NULL) lc->vtable.text_received(lc, cr, from, msg);
}
void linphone_core_text_received(LinphoneCore *lc, eXosip_event_t *ev){
MSList *elem;
const char *msg;
LinphoneChatRoom *cr=NULL;
char *cleanfrom;
osip_from_t *from_url=ev->request->from;
osip_body_t *body=NULL;
osip_message_get_body(ev->request,0,&body);
if (body==NULL){
ms_error("Could not get text message from SIP body");
return;
}
msg=body->body;
from_2char_without_params(from_url,&cleanfrom);
for(elem=lc->chatrooms;elem!=NULL;elem=ms_list_next(elem)){
cr=(LinphoneChatRoom*)elem->data;
if (linphone_chat_room_matches(cr,from_url)){
break;
}
cr=NULL;
}
if (cr==NULL){
/* create a new chat room */
cr=linphone_core_create_chat_room(lc,cleanfrom);
}
linphone_chat_room_text_received(cr,lc,cleanfrom,msg);
osip_free(cleanfrom);
}
void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void * ud){
cr->user_data=ud;
}
void * linphone_chat_room_get_user_data(LinphoneChatRoom *cr){
return cr->user_data;
}

172
linphone/coreapi/enum.c Normal file
View file

@ -0,0 +1,172 @@
/*
linphone
Copyright (C) 2000 Simon MORLAT (simon.morlat@linphone.org)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* enum lookup code */
#include <errno.h>
#include <string.h>
#include "enum.h"
#define DNS_ANSWER_MAX_SIZE 2048
char *create_enum_domain(const char *number){
int len=strlen(number);
char *domain=ms_malloc((len*2)+10);
int i,j;
for (i=0,j=len-1;j>=0;j--){
domain[i]=number[j];
i++;
domain[i]='.';
i++;
}
strcpy(&domain[i],"e164.arpa");
ms_message("enum domain for %s is %s",number,domain);
return domain;
}
bool_t is_a_number(const char *str){
char *p=(char *)str;
bool_t res=FALSE;
bool_t space_found=FALSE;
for(;;p++){
switch(p[0]){
case '9':
case '8':
case '7':
case '6':
case '5':
case '4':
case '3':
case '2':
case '1':
case '0':
res=TRUE;
if (space_found) return FALSE; /* avoid splited numbers */
break;
case '\0':
return res;
break;
case ' ':
space_found=TRUE;
break;
default:
return FALSE;
}
}
return FALSE;
}
//4970072278724
bool_t is_enum(const char *sipaddress, char **enum_domain){
char *p;
p=strstr(sipaddress,"sip:");
if (p==NULL) return FALSE; /* enum should look like sip:4369959250*/
else p+=4;
if (is_a_number(p)){
if (enum_domain!=NULL){
*enum_domain=create_enum_domain(p);
}
return TRUE;
}
return FALSE;
}
int enum_lookup(const char *enum_domain, enum_lookup_res_t **res){
int err;
//char dns_answer[DNS_ANSWER_MAX_SIZE];
char *begin,*end;
char *host_result, *command;
int i;
bool_t forkok;
/*
ns_msg handle;
int count;
memset(&handle,0,sizeof(handle));
*res=NULL;
ms_message("Resolving %s...",enum_domain);
err=res_search(enum_domain,ns_c_in,ns_t_naptr,dns_answer,DNS_ANSWER_MAX_SIZE);
if (err<0){
ms_warning("Error resolving enum:",herror(h_errno));
return -1;
}
ns_initparse(dns_answer,DNS_ANSWER_MAX_SIZE,&handle);
count=ns_msg_count(handle,ns_s_an);
for(i=0;i<count;i++){
ns_rr rr;
memset(&rr,0,sizeof(rr));
ns_parserr(&handle,ns_s_an,i,&rr);
ms_message("data=%s",ns_rr_rdata(rr));
}
*/
command=ms_strdup_printf("host -t naptr %s",enum_domain);
forkok=lp_spawn_command_line_sync(command,&host_result,&err);
ms_free(command);
if (forkok){
if (err!=0){
ms_warning("Host exited with %i error status.",err);
return -1;
}
}else{
ms_warning("Could not spawn the \'host\' command.");
return -1;
}
ms_message("Answer received from dns (err=%i): %s",err,host_result);
begin=strstr(host_result,"sip:");
if (begin==0) {
ms_warning("No sip address found in dns naptr answer.");
return -1;
}
*res=ms_malloc0(sizeof(enum_lookup_res_t));
err=0;
for(i=0;i<MAX_ENUM_LOOKUP_RESULTS;i++){
end=strstr(begin,"!");
if (end==NULL) goto parse_error;
end[0]='\0';
(*res)->sip_address[i]=ms_strdup(begin);
err++;
begin=strstr(end+1,"sip:");
if (begin==NULL) break;
}
ms_free(host_result);
return err;
parse_error:
ms_free(*res);
ms_free(host_result);
*res=NULL;
ms_warning("Parse error in enum_lookup().");
return -1;
}
void enum_lookup_res_free(enum_lookup_res_t *res){
int i;
for (i=0;i<MAX_ENUM_LOOKUP_RESULTS;i++){
if (res->sip_address[i]!=NULL) ms_free(res->sip_address[i]);
}
ms_free(res);
}

35
linphone/coreapi/enum.h Normal file
View file

@ -0,0 +1,35 @@
/*
linphone
Copyright (C) 2000 Simon MORLAT (simon.morlat@free.fr)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef ENUM_LOOKUP_H
#define ENUM_LOOKUP_H
#include "private.h"
#define MAX_ENUM_LOOKUP_RESULTS 10
typedef struct enum_lookup_res{
char *sip_address[MAX_ENUM_LOOKUP_RESULTS];
}enum_lookup_res_t;
bool_t is_enum(const char *sipaddress, char **enum_domain);
int enum_lookup(const char *enum_domain, enum_lookup_res_t **res);
void enum_lookup_res_free(enum_lookup_res_t *res);
#endif

1012
linphone/coreapi/exevents.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,40 @@
/*
linphone
Copyright (C) 2000 Simon MORLAT (simon.morlat@free.fr)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef EXEVENTS_H
#define EXEVENTS_H
#include <eXosip2/eXosip.h>
#include "sdphandler.h"
void linphone_core_process_event(LinphoneCore *lc, eXosip_event_t *ev);
/* these are the SdpHandler callbacks: we are called in to be aware of the content
of the SDP messages exchanged */
int linphone_set_audio_offer(sdp_context_t *ctx);
int linphone_set_video_offer(sdp_context_t *ctx);
int linphone_accept_audio_offer(sdp_context_t *ctx,sdp_payload_t *payload);
int linphone_accept_video_offer(sdp_context_t *ctx,sdp_payload_t *payload);
int linphone_read_audio_answer(sdp_context_t *ctx,sdp_payload_t *payload);
int linphone_read_video_answer(sdp_context_t *ctx,sdp_payload_t *payload);
void linphone_core_text_received(LinphoneCore *lc, eXosip_event_t *ev);
#endif

736
linphone/coreapi/friend.c Normal file
View file

@ -0,0 +1,736 @@
/***************************************************************************
* friend.c
*
* Sat May 15 15:25:16 2004
* Copyright 2004 Simon Morlat
* Email
****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "linphonecore.h"
#include "private.h"
#include <eXosip2/eXosip.h>
#include <osipparser2/osip_message.h>
#include "lpconfig.h"
const char *linphone_online_status_to_string(LinphoneOnlineStatus ss){
const char *str=NULL;
switch(ss){
case LINPHONE_STATUS_UNKNOWN:
str=_("Unknown");
break;
case LINPHONE_STATUS_ONLINE:
str=_("Online");
break;
case LINPHONE_STATUS_BUSY:
str=_("Busy");
break;
case LINPHONE_STATUS_BERIGHTBACK:
str=_("Be right back");
break;
case LINPHONE_STATUS_AWAY:
str=_("Away");
break;
case LINPHONE_STATUS_ONTHEPHONE:
str=_("On the phone");
break;
case LINPHONE_STATUS_OUTTOLUNCH:
str=_("Out to lunch");
break;
case LINPHONE_STATUS_NOT_DISTURB:
str=_("Do not disturb");
break;
case LINPHONE_STATUS_MOVED:
str=_("Moved");
break;
case LINPHONE_STATUS_ALT_SERVICE:
str=_("Using another messaging service");
break;
case LINPHONE_STATUS_OFFLINE:
str=_("Offline");
break;
case LINPHONE_STATUS_PENDING:
str=_("Pending");
break;
case LINPHONE_STATUS_CLOSED:
str=_("Closed");
break;
default:
str=_("Unknown-bug");
}
return str;
}
static int friend_data_compare(const void * a, const void * b, void * data){
osip_from_t *fa=((LinphoneFriend*)a)->url;
osip_from_t *fb=((LinphoneFriend*)b)->url;
char *ua,*ub;
ua=fa->url->username;
ub=fb->url->username;
if (ua!=NULL && ub!=NULL) {
//printf("Comparing usernames %s,%s\n",ua,ub);
return strcasecmp(ua,ub);
}
else {
/* compare hosts*/
ua=fa->url->host;
ub=fb->url->host;
if (ua!=NULL && ub!=NULL){
int ret=strcasecmp(ua,ub);
//printf("Comparing hostnames %s,%s,res=%i\n",ua,ub,ret);
return ret;
}
else return -1;
}
}
static int friend_compare(const void * a, const void * b){
return friend_data_compare(a,b,NULL);
}
MSList *find_friend(MSList *fl, const osip_from_t *friend, LinphoneFriend **lf){
MSList *res=NULL;
LinphoneFriend dummy;
if (lf!=NULL) *lf=NULL;
dummy.url=(osip_from_t*)friend;
res=ms_list_find_custom(fl,friend_compare,&dummy);
if (lf!=NULL && res!=NULL) *lf=(LinphoneFriend*)res->data;
return res;
}
LinphoneFriend *linphone_find_friend_by_nid(MSList *l, int nid){
MSList *elem;
for (elem=l;elem!=NULL;elem=elem->next){
LinphoneFriend *lf=(LinphoneFriend*)elem->data;
if (lf->nid==nid) return lf;
}
return NULL;
}
LinphoneFriend *linphone_find_friend_by_sid(MSList *l, int sid){
MSList *elem;
for (elem=l;elem!=NULL;elem=elem->next){
LinphoneFriend *lf=(LinphoneFriend*)elem->data;
if (lf->sid==sid) return lf;
}
return NULL;
}
void __linphone_friend_do_subscribe(LinphoneFriend *fr){
char *friend=NULL;
const char *route=NULL;
const char *from=NULL;
osip_message_t *msg=NULL;
osip_from_to_str(fr->url,&friend);
if (fr->proxy!=NULL){
route=fr->proxy->reg_route;
from=fr->proxy->reg_identity;
}else from=linphone_core_get_primary_contact(fr->lc);
if (fr->sid<0){
/* people for which we don't have yet an answer should appear as offline */
fr->lc->vtable.notify_recv(fr->lc,(LinphoneFriend*)fr,friend,_("Gone"),"sip-closed.png");
}
eXosip_lock();
eXosip_subscribe_build_initial_request(&msg,friend,from,route,"presence",600);
eXosip_subscribe_send_initial_request(msg);
eXosip_unlock();
osip_free(friend);
}
LinphoneFriend * linphone_friend_new(){
LinphoneFriend *obj=ms_new0(LinphoneFriend,1);
obj->out_did=-1;
obj->in_did=-1;
obj->nid=-1;
obj->sid=-1;
obj->pol=LinphoneSPAccept;
obj->status=LINPHONE_STATUS_OFFLINE;
obj->subscribe=TRUE;
return obj;
}
LinphoneFriend *linphone_friend_new_with_addr(const char *addr){
LinphoneFriend *fr=linphone_friend_new();
if (linphone_friend_set_sip_addr(fr,addr)<0){
linphone_friend_destroy(fr);
return NULL;
}
return fr;
}
int linphone_friend_set_sip_addr(LinphoneFriend *lf, const char *addr){
int err;
osip_from_t *fr=NULL;
osip_from_init(&fr);
err=osip_from_parse(fr,addr);
if (err<0) {
ms_warning("Invalid friend sip uri: %s",addr);
osip_from_free(fr);
return -1;
}
if (lf->url!=NULL) osip_from_free(lf->url);
lf->url=fr;
return 0;
}
int linphone_friend_set_name(LinphoneFriend *lf, const char *name){
osip_from_t *fr=lf->url;
if (fr==NULL){
ms_error("linphone_friend_set_sip_addr() must be called before linphone_friend_set_name().");
return -1;
}
if (fr->displayname!=NULL){
osip_free(fr->displayname);
fr->displayname=NULL;
}
if (name && name[0]!='\0'){
fr->displayname=osip_strdup(name);
}
return 0;
}
int linphone_friend_send_subscribe(LinphoneFriend *fr, bool_t val){
fr->subscribe=val;
return 0;
}
int linphone_friend_set_inc_subscribe_policy(LinphoneFriend *fr, LinphoneSubscribePolicy pol)
{
fr->pol=pol;
return 0;
}
int linphone_friend_set_proxy(LinphoneFriend *fr, struct _LinphoneProxyConfig *cfg){
fr->proxy=cfg;
return 0;
}
void linphone_friend_set_sid(LinphoneFriend *lf, int sid){
lf->sid=sid;
}
void linphone_friend_set_nid(LinphoneFriend *lf, int nid){
lf->nid=nid;
lf->inc_subscribe_pending=TRUE;
}
void add_presence_body(osip_message_t *notify, LinphoneOnlineStatus online_status)
{
char buf[1000];
#ifdef SUPPORT_MSN
int atom_id = 1000;
#endif
char *contact_info;
osip_contact_t *ct=NULL;
osip_message_get_contact(notify,0,&ct);
osip_contact_to_str(ct,&contact_info);
#ifdef SUPPORT_MSN
if (online_status==LINPHONE_STATUS_ONLINE)
{
sprintf(buf, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence\n\
PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
<status status=\"open\" />\n\
<msnsubstatus substatus=\"online\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else if (online_status==LINPHONE_STATUS_BUSY)
{
sprintf(buf, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence\n\
PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
<status status=\"inuse\" />\n\
<msnsubstatus substatus=\"busy\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else if (online_status==LINPHONE_STATUS_BERIGHTBACK)
{
sprintf(buf, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence\n\
PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
<status status=\"inactive\" />\n\
<msnsubstatus substatus=\"berightback\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else if (online_status==LINPHONE_STATUS_AWAY)
{
sprintf(buf, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence\n\
PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
<status status=\"inactive\" />\n\
<msnsubstatus substatus=\"away\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else if (online_status==LINPHONE_STATUS_ONTHEPHONE)
{
sprintf(buf, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence\n\
PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
<status status=\"inuse\" />\n\
<msnsubstatus substatus=\"onthephone\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else if (online_status==LINPHONE_STATUS_OUTTOLUNCH)
{
sprintf(buf, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence\n\
PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
<status status=\"inactive\" />\n\
<msnsubstatus substatus=\"outtolunch\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else
{
sprintf(buf, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence\n\
PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
<status status=\"inactive\" />\n\
<msnsubstatus substatus=\"away\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
osip_message_set_body(notify, buf, strlen(buf));
osip_message_set_content_type(notify, "application/xpidf+xml");
#else
if (online_status==LINPHONE_STATUS_ONLINE)
{
sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>online</note>\n\
</tuple>\n\
</presence>",
contact_info, contact_info);
}
else if (online_status==LINPHONE_STATUS_BUSY)
{
sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>busy</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>busy</note>\n\
</tuple>\n\
</presence>",
contact_info, contact_info);
}
else if (online_status==LINPHONE_STATUS_BERIGHTBACK)
{
sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>in-transit</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>be right back</note>\n\
</tuple>\n\
</presence>",
contact_info, contact_info);
}
else if (online_status==LINPHONE_STATUS_AWAY)
{
sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>away</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>away</note>\n\
</tuple>\n\
</presence>",
contact_info, contact_info);
}
else if (online_status==LINPHONE_STATUS_ONTHEPHONE)
{
sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>on-the-phone</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>on the phone</note>\n\
</tuple>\n\
</presence>",
contact_info, contact_info);
}
else if (online_status==LINPHONE_STATUS_OUTTOLUNCH)
{
sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>meal</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>out to lunch</note>\n\
</tuple>\n\
</presence>",
contact_info, contact_info);
}
else
{
/* */
sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n%s",
contact_info,
"<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>closed</basic>\n\
<es:activities>\n\
<es:activity>permanent-absence</e:activity>\n\
</es:activities>\n\
</status>\n\
</tuple>\n\
\n</presence>\n");
}
osip_message_set_body(notify, buf, strlen(buf));
osip_message_set_content_type(notify, "application/pidf+xml");
#endif
osip_free(contact_info);
}
void linphone_friend_notify(LinphoneFriend *lf, int ss, LinphoneOnlineStatus os){
//printf("Wish to notify %p, lf->nid=%i\n",lf,lf->nid);
if (lf->in_did!=-1){
osip_message_t *msg=NULL;
const char *identity;
if (lf->proxy!=NULL) identity=lf->proxy->reg_identity;
else identity=linphone_core_get_primary_contact(lf->lc);
eXosip_lock();
eXosip_insubscription_build_notify(lf->in_did,ss,0,&msg);
if (msg!=NULL){
osip_message_set_contact(msg,identity);
add_presence_body(msg,os);
eXosip_insubscription_send_request(lf->in_did,msg);
}else ms_error("could not create notify for incoming subscription.");
eXosip_unlock();
}
}
static void linphone_friend_unsubscribe(LinphoneFriend *lf){
if (lf->out_did!=-1) {
osip_message_t *msg=NULL;
eXosip_lock();
eXosip_subscribe_build_refresh_request(lf->out_did,&msg);
if (msg){
osip_message_set_expires(msg,"0");
eXosip_subscribe_send_refresh_request(lf->out_did,msg);
}else ms_error("Could not build subscribe refresh request !");
eXosip_unlock();
}
}
void linphone_friend_destroy(LinphoneFriend *lf){
linphone_friend_notify(lf,EXOSIP_SUBCRSTATE_TERMINATED,LINPHONE_STATUS_CLOSED);
linphone_friend_unsubscribe(lf);
if (lf->url!=NULL) osip_from_free(lf->url);
ms_free(lf);
}
void linphone_friend_check_for_removed_proxy(LinphoneFriend *lf, LinphoneProxyConfig *cfg){
if (lf->proxy==cfg){
lf->proxy=NULL;
}
}
char *linphone_friend_get_addr(LinphoneFriend *lf){
char *ret,*tmp;
if (lf->url==NULL) return NULL;
osip_uri_to_str(lf->url->url,&tmp);
ret=ms_strdup(tmp);
osip_free(tmp);
return ret;
}
char *linphone_friend_get_name(LinphoneFriend *lf){
if (lf->url==NULL) return NULL;
if (lf->url->displayname==NULL) return NULL;
return ms_strdup(lf->url->displayname);
}
char * linphone_friend_get_url(LinphoneFriend *lf){
char *tmp,*ret;
if (lf->url==NULL) return NULL;
osip_from_to_str(lf->url,&tmp);
ret=ms_strdup(tmp);
ms_free(tmp);
return ret;
}
bool_t linphone_friend_get_send_subscribe(const LinphoneFriend *lf){
return lf->subscribe;
}
LinphoneSubscribePolicy linphone_friend_get_inc_subscribe_policy(const LinphoneFriend *lf){
return lf->pol;
}
LinphoneOnlineStatus linphone_friend_get_status(const LinphoneFriend *lf){
return lf->status;
}
void linphone_friend_apply(LinphoneFriend *fr, LinphoneCore *lc){
if (fr->url==NULL) {
ms_warning("No sip url defined.");
return;
}
fr->lc=lc;
if (fr->inc_subscribe_pending){
switch(fr->pol){
case LinphoneSPWait:
linphone_friend_notify(fr,EXOSIP_SUBCRSTATE_PENDING,LINPHONE_STATUS_PENDING);
break;
case LinphoneSPAccept:
if (fr->lc!=NULL)
{
linphone_friend_notify(fr,EXOSIP_SUBCRSTATE_ACTIVE,fr->lc->presence_mode);
}
break;
case LinphoneSPDeny:
linphone_friend_notify(fr,EXOSIP_SUBCRSTATE_TERMINATED,LINPHONE_STATUS_CLOSED);
break;
}
fr->inc_subscribe_pending=FALSE;
}
if (fr->subscribe && fr->out_did==-1){
__linphone_friend_do_subscribe(fr);
}
ms_message("linphone_friend_apply() done.");
}
void linphone_friend_edit(LinphoneFriend *fr){
}
void linphone_friend_done(LinphoneFriend *fr){
ms_return_if_fail(fr!=NULL);
if (fr->lc==NULL) return;
linphone_friend_apply(fr,fr->lc);
}
void linphone_core_add_friend(LinphoneCore *lc, LinphoneFriend *lf)
{
ms_return_if_fail(lf->lc==NULL);
ms_return_if_fail(lf->url!=NULL);
linphone_friend_apply(lf,lc);
lc->friends=ms_list_append(lc->friends,lf);
return ;
}
void linphone_core_remove_friend(LinphoneCore *lc, LinphoneFriend* fl){
MSList *el=ms_list_find(lc->friends,(void *)fl);
if (el!=NULL){
lc->friends=ms_list_remove_link(lc->friends,el);
linphone_friend_destroy((LinphoneFriend*)el->data);
}
}
#define key_compare(key, word) strncasecmp((key),(word),strlen(key))
LinphoneSubscribePolicy __policy_str_to_enum(const char* pol){
if (key_compare("accept",pol)==0){
return LinphoneSPAccept;
}
if (key_compare("deny",pol)==0){
return LinphoneSPDeny;
}
if (key_compare("wait",pol)==0){
return LinphoneSPWait;
}
ms_warning("Unrecognized subscribe policy: %s",pol);
return LinphoneSPWait;
}
LinphoneProxyConfig *__index_to_proxy(LinphoneCore *lc, int index){
if (index>=0) return (LinphoneProxyConfig*)ms_list_nth_data(lc->sip_conf.proxies,index);
else return NULL;
}
LinphoneFriend * linphone_friend_new_from_config_file(LinphoneCore *lc, int index){
const char *tmp;
char item[50];
int a;
LinphoneFriend *lf;
LpConfig *config=lc->config;
sprintf(item,"friend_%i",index);
if (!lp_config_has_section(config,item)){
return NULL;
}
tmp=lp_config_get_string(config,item,"url",NULL);
if (tmp==NULL) {
return NULL;
}
lf=linphone_friend_new_with_addr(tmp);
if (lf==NULL) {
return NULL;
}
tmp=lp_config_get_string(config,item,"pol",NULL);
if (tmp==NULL) linphone_friend_set_inc_subscribe_policy(lf,LinphoneSPWait);
else{
linphone_friend_set_inc_subscribe_policy(lf,__policy_str_to_enum(tmp));
}
a=lp_config_get_int(config,item,"subscribe",0);
linphone_friend_send_subscribe(lf,a);
a=lp_config_get_int(config,item,"proxy",-1);
if (a!=-1) {
linphone_friend_set_proxy(lf,__index_to_proxy(lc,a));
}
return lf;
}
const char *__policy_enum_to_str(LinphoneSubscribePolicy pol){
switch(pol){
case LinphoneSPAccept:
return "accept";
break;
case LinphoneSPDeny:
return "deny";
break;
case LinphoneSPWait:
return "wait";
break;
}
ms_warning("Invalid policy enum value.");
return "wait";
}
void linphone_friend_write_to_config_file(LpConfig *config, LinphoneFriend *lf, int index){
char key[50];
char *tmp;
int a;
sprintf(key,"friend_%i",index);
if (lf==NULL){
lp_config_clean_section(config,key);
return;
}
if (lf->url!=NULL){
osip_from_to_str(lf->url,&tmp);
if (tmp==NULL) {
return;
}
lp_config_set_string(config,key,"url",tmp);
osip_free(tmp);
}
lp_config_set_string(config,key,"pol",__policy_enum_to_str(lf->pol));
lp_config_set_int(config,key,"subscribe",lf->subscribe);
if (lf->proxy!=NULL){
a=ms_list_index(lf->lc->sip_conf.proxies,lf->proxy);
lp_config_set_int(config,key,"proxy",a);
}else lp_config_set_int(config,key,"proxy",-1);
}

View file

@ -0,0 +1,101 @@
/****************************************************************************
*
* File: general_state.c
*
* Copyright (C) 2006, 2007 Thomas Reitmayr <treitmayr@yahoo.com>
*
****************************************************************************
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
****************************************************************************/
#include "linphonecore.h"
static gstate_t _gstates[GSTATE_GROUP_CALL+1];
#if 0
static const char *_gstates_text[] = {
"GSTATE_POWER_OFF", /* 0 */
"GSTATE_POWER_STARTUP", /* 1 */
"GSTATE_POWER_ON", /* 2 */
"GSTATE_POWER_SHUTDOWN", /* 3 */
NULL, NULL, NULL, NULL, NULL, NULL,
"GSTATE_REG_NONE", /* 10 */
"GSTATE_REG_OK", /* 11 */
"GSTATE_REG_FAILED", /* 12 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
"GSTATE_CALL_IDLE", /* 20 */
"GSTATE_CALL_OUT_INVITE", /* 21 */
"GSTATE_CALL_OUT_CONNECTED", /* 22 */
"GSTATE_CALL_IN_INVITE", /* 23 */
"GSTATE_CALL_IN_CONNECTED", /* 24 */
"GSTATE_CALL_END", /* 25 */
"GSTATE_CALL_ERROR" /* 26 */
};
#endif
/* set the initial states */
void gstate_initialize(void) {
_gstates[GSTATE_GROUP_POWER] = GSTATE_POWER_OFF;
_gstates[GSTATE_GROUP_REG] = GSTATE_REG_NONE;
_gstates[GSTATE_GROUP_CALL] = GSTATE_CALL_IDLE;
}
/* retrieve the current state of the specified state group */
gstate_t gstate_get_state(gstate_group_t group) {
return _gstates[group];
}
void gstate_new_state(struct _LinphoneCore *lc,
gstate_t new_state,
const char *message) {
LinphoneGeneralState states_arg;
/* determine the affected group */
if (new_state < GSTATE_REG_NONE)
states_arg.group = GSTATE_GROUP_POWER;
else if (new_state < GSTATE_CALL_IDLE)
states_arg.group = GSTATE_GROUP_REG;
else
states_arg.group = GSTATE_GROUP_CALL;
/* store the new state while remembering the old one */
states_arg.new_state = new_state;
states_arg.old_state = _gstates[states_arg.group];
_gstates[states_arg.group] = new_state;
states_arg.message = message;
/*printf("gstate_new_state: %s\t-> %s\t(%s)\n",
_gstates_text[states_arg.old_state],
_gstates_text[states_arg.new_state],
message);*/
/* call the virtual method */
if (lc->vtable.general_state)
lc->vtable.general_state(lc, &states_arg);
/* immediately proceed to idle state */
if (new_state == GSTATE_CALL_END ||
new_state == GSTATE_CALL_ERROR)
gstate_new_state(lc, GSTATE_CALL_IDLE, NULL);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,715 @@
/*
linphone
Copyright (C) 2000 Simon MORLAT (simon.morlat@linphone.org)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef LINPHONECORE_H
#define LINPHONECORE_H
#include <osipparser2/osip_message.h>
#include "ortp/ortp.h"
#include "ortp/payloadtype.h"
#include "mediastreamer2/mscommon.h"
#ifdef __cplusplus
extern "C" {
#endif
struct _MSSndCard;
struct _LinphoneCore;
bool_t payload_type_enabled(struct _PayloadType *pt);
void payload_type_set_enable(struct _PayloadType *pt,int value);
const char *payload_type_get_description(struct _PayloadType *pt);
int payload_type_get_bitrate(PayloadType *pt);
const char *payload_type_get_mime(PayloadType *pt);
int payload_type_get_rate(PayloadType *pt);
struct _LpConfig;
typedef struct sip_config
{
char *contact;
char *guessed_contact;
int sip_port;
MSList *proxies;
MSList *deleted_proxies;
int inc_timeout; /*timeout after an un-answered incoming call is rejected*/
bool_t use_info;
bool_t guess_hostname;
bool_t loopback_only;
bool_t ipv6_enabled;
bool_t sdp_200_ack;
} sip_config_t;
typedef struct rtp_config
{
int audio_rtp_port;
int video_rtp_port;
int audio_jitt_comp; /*jitter compensation*/
int video_jitt_comp; /*jitter compensation*/
int nortp_timeout;
}rtp_config_t;
typedef struct net_config
{
char *nat_address;
char *stun_server;
char *relay;
int download_bw;
int upload_bw;
int firewall_policy;
int mtu;
bool_t nat_sdp_only;
}net_config_t;
typedef struct sound_config
{
struct _MSSndCard * ring_sndcard; /* the playback sndcard currently used */
struct _MSSndCard * play_sndcard; /* the playback sndcard currently used */
struct _MSSndCard * capt_sndcard; /* the capture sndcard currently used */
const char **cards;
int latency; /* latency in samples of the current used sound device */
char rec_lev;
char play_lev;
char ring_lev;
char source;
char pad;
char *local_ring;
char *remote_ring;
bool_t ec;
} sound_config_t;
typedef struct codecs_config
{
MSList *audio_codecs; /* list of audio codecs in order of preference*/
MSList *video_codecs; /* for later use*/
}codecs_config_t;
typedef struct video_config{
struct _MSWebCam *device;
const char **cams;
bool_t capture;
bool_t show_local;
bool_t display;
}video_config_t;
typedef struct ui_config
{
int is_daemon;
int is_applet;
unsigned int timer_id; /* the timer id for registration */
}ui_config_t;
typedef struct autoreplier_config
{
int enabled;
int after_seconds; /* accept the call after x seconds*/
int max_users; /* maximum number of user that can call simultaneously */
int max_rec_time; /* the max time of incoming voice recorded */
int max_rec_msg; /* maximum number of recorded messages */
const char *message; /* the path of the file to be played */
}autoreplier_config_t;
struct _LinphoneCore;
struct _sdp_context;
typedef struct _StreamParams
{
int initialized;
int line;
int localport;
int remoteport;
int remotertcpport;
char *remoteaddr;
int pt;
char *relay_session_id;
} StreamParams;
typedef enum _LCState{
LCStateInit,
LCStateRinging,
LCStateAVRunning
}LCState;
typedef enum _LinphoneCallDir {LinphoneCallOutgoing, LinphoneCallIncoming} LinphoneCallDir;
typedef struct _LinphoneCall
{
struct _LinphoneCore *core;
StreamParams audio_params;
StreamParams video_params;
LinphoneCallDir dir;
struct _RtpProfile *profile; /*points to the local_profile or to the remote "guessed" profile*/
struct _LinphoneCallLog *log;
int cid; /*call id */
int did; /*dialog id */
int tid; /*last transaction id*/
struct _sdp_context *sdpctx;
time_t start_time;
LCState state;
bool_t auth_pending;
} LinphoneCall;
LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, const osip_from_t *from, const osip_to_t *to);
LinphoneCall * linphone_call_new_incoming(struct _LinphoneCore *lc, const char *from, const char *to, int cid, int did , int tid);
#define linphone_call_set_state(lcall,st) (lcall)->state=(st)
void linphone_call_destroy(struct _LinphoneCall *obj);
typedef enum _LinphoneCallStatus {
LinphoneCallSuccess,
LinphoneCallAborted,
LinphoneCallMissed
} LinphoneCallStatus;
typedef struct _LinphoneCallLog{
LinphoneCallDir dir;
LinphoneCallStatus status;
char *from;
char *to;
char start_date[128];
int duration;
} LinphoneCallLog;
/* private: */
LinphoneCallLog * linphone_call_log_new(LinphoneCall *call, char *local, char * remote);
void linphone_call_log_completed(LinphoneCallLog *calllog, LinphoneCall *call);
void linphone_call_log_destroy(LinphoneCallLog *cl);
/*public: */
char * linphone_call_log_to_str(LinphoneCallLog *cl);
typedef enum{
LinphoneSPWait,
LinphoneSPDeny,
LinphoneSPAccept
}LinphoneSubscribePolicy;
typedef enum _LinphoneOnlineStatus{
LINPHONE_STATUS_UNKNOWN,
LINPHONE_STATUS_ONLINE,
LINPHONE_STATUS_BUSY,
LINPHONE_STATUS_BERIGHTBACK,
LINPHONE_STATUS_AWAY,
LINPHONE_STATUS_ONTHEPHONE,
LINPHONE_STATUS_OUTTOLUNCH,
LINPHONE_STATUS_NOT_DISTURB,
LINPHONE_STATUS_MOVED,
LINPHONE_STATUS_ALT_SERVICE,
LINPHONE_STATUS_OFFLINE,
LINPHONE_STATUS_PENDING,
LINPHONE_STATUS_CLOSED,
LINPHONE_STATUS_END
}LinphoneOnlineStatus;
const char *linphone_online_status_to_string(LinphoneOnlineStatus ss);
typedef struct _LinphoneFriend{
osip_from_t *url;
int in_did;
int out_did;
int sid;
int nid;
LinphoneSubscribePolicy pol;
LinphoneOnlineStatus status;
struct _LinphoneProxyConfig *proxy;
struct _LinphoneCore *lc;
bool_t subscribe;
bool_t inc_subscribe_pending;
}LinphoneFriend;
LinphoneFriend * linphone_friend_new();
LinphoneFriend *linphone_friend_new_with_addr(const char *addr);
int linphone_friend_set_sip_addr(LinphoneFriend *fr, const char *uri);
int linphone_friend_set_name(LinphoneFriend *fr, const char *name);
int linphone_friend_send_subscribe(LinphoneFriend *fr, bool_t val);
int linphone_friend_set_inc_subscribe_policy(LinphoneFriend *fr, LinphoneSubscribePolicy pol);
int linphone_friend_set_proxy(LinphoneFriend *fr, struct _LinphoneProxyConfig *cfg);
void linphone_friend_edit(LinphoneFriend *fr);
void linphone_friend_done(LinphoneFriend *fr);
void linphone_friend_destroy(LinphoneFriend *lf);
/* memory returned by those 3 functions must be freed */
char *linphone_friend_get_name(LinphoneFriend *lf);
char *linphone_friend_get_addr(LinphoneFriend *lf);
char *linphone_friend_get_url(LinphoneFriend *lf); /* name <sip address> */
bool_t linphone_friend_get_send_subscribe(const LinphoneFriend *lf);
LinphoneSubscribePolicy linphone_friend_get_inc_subscribe_policy(const LinphoneFriend *lf);
LinphoneOnlineStatus linphone_friend_get_status(const LinphoneFriend *lf);
#define linphone_friend_url(lf) ((lf)->url)
void linphone_friend_write_to_config_file(struct _LpConfig *config, LinphoneFriend *lf, int index);
LinphoneFriend * linphone_friend_new_from_config_file(struct _LinphoneCore *lc, int index);
typedef struct _LinphoneProxyConfig
{
struct _LinphoneCore *lc;
char *reg_proxy;
char *reg_identity;
char *reg_route;
char *realm;
int expires;
int reg_time;
int rid;
bool_t frozen;
bool_t reg_sendregister;
bool_t auth_pending;
bool_t registered;
bool_t publish;
} LinphoneProxyConfig;
LinphoneProxyConfig *linphone_proxy_config_new(void);
int linphone_proxy_config_set_server_addr(LinphoneProxyConfig *obj, const char *server_addr);
void linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *identity);
void linphone_proxy_config_set_route(LinphoneProxyConfig *obj, const char *route);
void linphone_proxy_config_expires(LinphoneProxyConfig *obj, const int expires);
void linphone_proxy_config_enable_register(LinphoneProxyConfig *obj, bool_t val);
#define linphone_proxy_config_enableregister linphone_proxy_config_enable_register
void linphone_proxy_config_edit(LinphoneProxyConfig *obj);
int linphone_proxy_config_done(LinphoneProxyConfig *obj);
void linphone_proxy_config_enable_publish(LinphoneProxyConfig *obj, bool_t val);
#define linphone_proxy_config_get_route(obj) ((obj)->reg_route)
#define linphone_proxy_config_get_identity(obj) ((obj)->reg_identity)
#define linphone_proxy_config_publish_enabled(obj) ((obj)->publish)
#define linphone_proxy_config_get_addr(obj) ((obj)->reg_proxy)
#define linphone_proxy_config_get_expires(obj) ((obj)->expires)
#define linphone_proxy_config_register_enabled(obj) ((obj)->reg_sendregister)
/* destruction is called automatically when removing the proxy config */
void linphone_proxy_config_destroy(LinphoneProxyConfig *cfg);
LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(struct _LpConfig *config, int index);
void linphone_proxy_config_write_to_config_file(struct _LpConfig* config,LinphoneProxyConfig *obj, int index);
typedef struct _LinphoneAuthInfo
{
char *username;
char *realm;
char *userid;
char *passwd;
char *ha1;
bool_t works;
bool_t first_time;
}LinphoneAuthInfo;
LinphoneAuthInfo *linphone_auth_info_new(const char *username, const char *userid,
const char *passwd, const char *ha1,const char *realm);
void linphone_auth_info_set_passwd(LinphoneAuthInfo *info, const char *passwd);
/* you don't need those function*/
void linphone_auth_info_destroy(LinphoneAuthInfo *info);
LinphoneAuthInfo * linphone_auth_info_new_from_config_file(struct _LpConfig *config, int pos);
struct _LinphoneChatRoom{
struct _LinphoneCore *lc;
char *peer;
char *route;
osip_from_t *peer_url;
void * user_data;
};
typedef struct _LinphoneChatRoom LinphoneChatRoom;
LinphoneChatRoom * linphone_core_create_chat_room(struct _LinphoneCore *lc, const char *to);
void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg);
void linphone_chat_room_destroy(LinphoneChatRoom *cr);
void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void * ud);
void * linphone_chat_room_get_user_data(LinphoneChatRoom *cr);
/* describes the different groups of states */
typedef enum _gstate_group {
GSTATE_GROUP_POWER,
GSTATE_GROUP_REG,
GSTATE_GROUP_CALL
} gstate_group_t;
typedef enum _gstate {
/* states for GSTATE_GROUP_POWER */
GSTATE_POWER_OFF = 0, /* initial state */
GSTATE_POWER_STARTUP,
GSTATE_POWER_ON,
GSTATE_POWER_SHUTDOWN,
/* states for GSTATE_GROUP_REG */
GSTATE_REG_NONE = 10, /* initial state */
GSTATE_REG_OK,
GSTATE_REG_FAILED,
/* states for GSTATE_GROUP_CALL */
GSTATE_CALL_IDLE = 20, /* initial state */
GSTATE_CALL_OUT_INVITE,
GSTATE_CALL_OUT_CONNECTED,
GSTATE_CALL_IN_INVITE,
GSTATE_CALL_IN_CONNECTED,
GSTATE_CALL_END,
GSTATE_CALL_ERROR
} gstate_t;
struct _LinphoneGeneralState {
gstate_t old_state;
gstate_t new_state;
gstate_group_t group;
const char *message;
};
typedef struct _LinphoneGeneralState LinphoneGeneralState;
/* retrieve the current state of the specified state group */
gstate_t gstate_get_state(gstate_group_t group);
/* private: set the initial states */
void gstate_initialize(void);
/* private: set a new state */
void gstate_new_state(struct _LinphoneCore *lc, gstate_t new_state, const char *message);
typedef void (*ShowInterfaceCb)(struct _LinphoneCore *lc);
typedef void (*InviteReceivedCb)(struct _LinphoneCore *lc, const char *from);
typedef void (*ByeReceivedCb)(struct _LinphoneCore *lc, const char *from);
typedef void (*DisplayStatusCb)(struct _LinphoneCore *lc, const char *message);
typedef void (*DisplayMessageCb)(struct _LinphoneCore *lc, const char *message);
typedef void (*DisplayUrlCb)(struct _LinphoneCore *lc, const char *message, const char *url);
typedef void (*DisplayQuestionCb)(struct _LinphoneCore *lc, const char *message);
typedef void (*LinphoneCoreCbFunc)(struct _LinphoneCore *lc,void * user_data);
typedef void (*NotifyReceivedCb)(struct _LinphoneCore *lc, LinphoneFriend * fid, const char *url, const char *status, const char *img);
typedef void (*NewUnknownSubscriberCb)(struct _LinphoneCore *lc, LinphoneFriend *lf, const char *url);
typedef void (*AuthInfoRequested)(struct _LinphoneCore *lc, const char *realm, const char *username);
typedef void (*CallLogUpdated)(struct _LinphoneCore *lc, struct _LinphoneCallLog *newcl);
typedef void (*TextMessageReceived)(struct _LinphoneCore *lc, LinphoneChatRoom *room, const char *from, const char *message);
typedef void (*GeneralStateChange)(struct _LinphoneCore *lc, LinphoneGeneralState *gstate);
typedef struct _LinphoneVTable
{
ShowInterfaceCb show;
InviteReceivedCb inv_recv;
ByeReceivedCb bye_recv;
NotifyReceivedCb notify_recv;
NewUnknownSubscriberCb new_unknown_subscriber;
AuthInfoRequested auth_info_requested;
DisplayStatusCb display_status;
DisplayMessageCb display_message;
#ifdef VINCENT_MAURY_RSVP
/* the yes/no dialog box */
DisplayMessageCb display_yes_no;
#endif
DisplayMessageCb display_warning;
DisplayUrlCb display_url;
DisplayQuestionCb display_question;
CallLogUpdated call_log_updated;
TextMessageReceived text_received;
GeneralStateChange general_state;
} LinphoneCoreVTable;
typedef struct _LCCallbackObj
{
LinphoneCoreCbFunc _func;
void * _user_data;
}LCCallbackObj;
typedef enum _LinphoneFirewallPolicy{
LINPHONE_POLICY_NO_FIREWALL,
LINPHONE_POLICY_USE_NAT_ADDRESS,
LINPHONE_POLICY_USE_STUN
} LinphoneFirewallPolicy;
typedef struct _LinphoneCore
{
LinphoneCoreVTable vtable;
struct _LpConfig *config;
net_config_t net_conf;
sip_config_t sip_conf;
rtp_config_t rtp_conf;
sound_config_t sound_conf;
video_config_t video_conf;
codecs_config_t codecs_conf;
ui_config_t ui_conf;
autoreplier_config_t autoreplier_conf;
LinphoneProxyConfig *default_proxy;
MSList *friends;
MSList *auth_info;
struct _RingStream *ringstream;
LCCallbackObj preview_finished_cb;
bool_t preview_finished;
LinphoneCall *call; /* the current call, in the future it will be a list of calls (conferencing)*/
int rid; /*registration id*/
MSList *queued_calls; /* used by the autoreplier */
MSList *call_logs;
MSList *chatrooms;
int max_call_logs;
int missed_calls;
struct _AudioStream *audiostream; /**/
struct _VideoStream *videostream;
struct _VideoStream *previewstream;
struct _RtpProfile *local_profile;
MSList *subscribers; /* unknown subscribers */
int minutes_away;
LinphoneOnlineStatus presence_mode;
LinphoneOnlineStatus prev_mode;
char *alt_contact;
void *data;
ms_mutex_t lock;
char *play_file;
char *rec_file;
time_t prevtime;
int dw_audio_bw;
int up_audio_bw;
int dw_video_bw;
int up_video_bw;
int audio_bw;
int automatic_action;
bool_t use_files;
bool_t apply_nat_settings;
#ifdef VINCENT_MAURY_RSVP
/* QoS parameters*/
int rsvp_enable;
int rpc_enable;
#endif
} LinphoneCore;
#define LINPHONE_IPADDR_SIZE 64
/* THE main API */
void linphone_core_enable_logs(FILE *file);
void linphone_core_enable_logs_with_cb(OrtpLogFunc logfunc);
void linphone_core_disable_logs(void);
const char *linphone_core_get_version(void);
LinphoneCore *linphone_core_new(const LinphoneCoreVTable *vtable,
const char *config_path, void* userdata);
void linphone_core_init(LinphoneCore *lc, const LinphoneCoreVTable *vtable,
const char *config_path, void * userdata);
/* function to be periodically called in a main loop */
void linphone_core_iterate(LinphoneCore *lc);
int linphone_core_invite(LinphoneCore *lc, const char *url);
int linphone_core_refer(LinphoneCore *lc, const char *url);
bool_t linphone_core_inc_invite_pending(LinphoneCore*lc);
bool_t linphone_core_in_call(const LinphoneCore *lc);
int linphone_core_accept_call(LinphoneCore *lc, const char *url);
int linphone_core_terminate_call(LinphoneCore *lc, const char *url);
void linphone_core_send_dtmf(LinphoneCore *lc,char dtmf);
int linphone_core_set_primary_contact(LinphoneCore *lc, const char *contact);
const char *linphone_core_get_primary_contact(LinphoneCore *lc);
void linphone_core_set_guess_hostname(LinphoneCore *lc, bool_t val);
bool_t linphone_core_get_guess_hostname(LinphoneCore *lc);
bool_t linphone_core_ipv6_enabled(LinphoneCore *lc);
void linphone_core_enable_ipv6(LinphoneCore *lc, bool_t val);
osip_from_t *linphone_core_get_primary_contact_parsed(LinphoneCore *lc);
/*0= no bandwidth limit*/
void linphone_core_set_download_bandwidth(LinphoneCore *lc, int bw);
void linphone_core_set_upload_bandwidth(LinphoneCore *lc, int bw);
int linphone_core_get_download_bandwidth(const LinphoneCore *lc);
int linphone_core_get_upload_bandwidth(const LinphoneCore *lc);
#ifdef VINCENT_MAURY_RSVP
/* QoS functions */
int linphone_core_set_rpc_mode(LinphoneCore *lc, int on); /* on = 1 (RPC_ENABLE = 1) */
int linphone_core_set_rsvp_mode(LinphoneCore *lc, int on); /* on = 1 (RSVP_ENABLE = 1) */
int linphone_core_change_qos(LinphoneCore *lc, int answer); /* answer = 1 for yes, 0 for no */
#endif
/* returns a MSList of PayloadType */
const MSList *linphone_core_get_audio_codecs(const LinphoneCore *lc);
int linphone_core_set_audio_codecs(LinphoneCore *lc, MSList *codecs);
/* returns a MSList of PayloadType */
const MSList *linphone_core_get_video_codecs(const LinphoneCore *lc);
int linphone_core_set_video_codecs(LinphoneCore *lc, MSList *codecs);
bool_t linphone_core_check_payload_type_usability(LinphoneCore *lc, PayloadType *pt);
int linphone_core_add_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *config);
void linphone_core_remove_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *config);
const MSList *linphone_core_get_proxy_config_list(const LinphoneCore *lc);
void linphone_core_set_default_proxy(LinphoneCore *lc, LinphoneProxyConfig *config);
void linphone_core_set_default_proxy_index(LinphoneCore *lc, int index);
int linphone_core_get_default_proxy(LinphoneCore *lc, LinphoneProxyConfig **config);
void linphone_core_add_auth_info(LinphoneCore *lc, LinphoneAuthInfo *info);
void linphone_core_remove_auth_info(LinphoneCore *lc, LinphoneAuthInfo *info);
void linphone_core_abort_authentication(LinphoneCore *lc, LinphoneAuthInfo *info);
void linphone_core_clear_all_auth_info(LinphoneCore *lc);
int linphone_core_get_audio_jittcomp(LinphoneCore *lc);
void linphone_core_set_audio_jittcomp(LinphoneCore *lc, int value);
int linphone_core_get_audio_port(const LinphoneCore *lc);
int linphone_core_get_video_port(const LinphoneCore *lc);
int linphone_core_get_nortp_timeout(const LinphoneCore *lc);
void linphone_core_set_audio_port(LinphoneCore *lc, int port);
void linphone_core_set_video_port(LinphoneCore *lc, int port);
void linphone_core_set_nortp_timeout(LinphoneCore *lc, int port);
void linphone_core_set_use_info_for_dtmf(LinphoneCore *lc, bool_t use_info);
bool_t linphone_core_get_use_info_for_dtmf(LinphoneCore *lc);
int linphone_core_get_sip_port(LinphoneCore *lc);
void linphone_core_set_sip_port(LinphoneCore *lc,int port);
void linphone_core_set_inc_timeout(LinphoneCore *lc, int seconds);
int linphone_core_get_inc_timeout(LinphoneCore *lc);
void linphone_core_set_stun_server(LinphoneCore *lc, const char *server);
const char * linphone_core_get_stun_server(const LinphoneCore *lc);
void linphone_core_set_nat_address(LinphoneCore *lc, const char *addr);
const char *linphone_core_get_nat_address(const LinphoneCore *lc);
void linphone_core_set_firewall_policy(LinphoneCore *lc, LinphoneFirewallPolicy pol);
LinphoneFirewallPolicy linphone_core_get_firewall_policy(const LinphoneCore *lc);
const char * linphone_core_get_relay_addr(const LinphoneCore *lc);
int linphone_core_set_relay_addr(LinphoneCore *lc, const char *addr);
/* sound functions */
/* returns a null terminated static array of string describing the sound devices */
const char** linphone_core_get_sound_devices(LinphoneCore *lc);
int linphone_core_get_ring_level(LinphoneCore *lc);
int linphone_core_get_play_level(LinphoneCore *lc);
int linphone_core_get_rec_level(LinphoneCore *lc);
void linphone_core_set_ring_level(LinphoneCore *lc, int level);
void linphone_core_set_play_level(LinphoneCore *lc, int level);
void linphone_core_set_rec_level(LinphoneCore *lc, int level);
const char * linphone_core_get_ringer_device(LinphoneCore *lc);
const char * linphone_core_get_playback_device(LinphoneCore *lc);
const char * linphone_core_get_capture_device(LinphoneCore *lc);
int linphone_core_set_ringer_device(LinphoneCore *lc, const char * devid);
int linphone_core_set_playback_device(LinphoneCore *lc, const char * devid);
int linphone_core_set_capture_device(LinphoneCore *lc, const char * devid);
char linphone_core_get_sound_source(LinphoneCore *lc);
void linphone_core_set_sound_source(LinphoneCore *lc, char source);
void linphone_core_set_ring(LinphoneCore *lc, const char *path);
const char *linphone_core_get_ring(LinphoneCore *lc);
int linphone_core_preview_ring(LinphoneCore *lc, const char *ring,LinphoneCoreCbFunc func,void * userdata);
typedef enum {RINGBACK_TYPE_FR,RINGBACK_TYPE_US} RingBackType;
void linphone_core_set_ringback(LinphoneCore *lc,RingBackType type);
RingBackType linphone_core_get_ringback(LinphoneCore *lc);
void linphone_core_enable_echo_cancelation(LinphoneCore *lc, bool_t val);
bool_t linphone_core_echo_cancelation_enabled(LinphoneCore *lc);
void linphone_core_set_presence_info(LinphoneCore *lc,int minutes_away,const char *contact,LinphoneOnlineStatus os);
LinphoneOnlineStatus linphone_core_get_presence_info(const LinphoneCore *lc);
void linphone_core_add_friend(LinphoneCore *lc, LinphoneFriend *fr);
void linphone_core_remove_friend(LinphoneCore *lc, LinphoneFriend *fr);
void linphone_core_reject_subscriber(LinphoneCore *lc, LinphoneFriend *lf);
/* a list of LinphoneFriend */
const MSList * linphone_core_get_friend_list(LinphoneCore *lc);
/* notify all friends that have subscribed */
void linphone_core_notify_all_friends(LinphoneCore *lc, LinphoneOnlineStatus os);
/* returns a list of LinphoneCallLog */
MSList * linphone_core_get_call_logs(LinphoneCore *lc);
/* video support */
void linphone_core_enable_video(LinphoneCore *lc, bool_t vcap_enabled, bool_t display_enabled);
bool_t linphone_core_video_enabled(LinphoneCore *lc);
/*play/record support: use files instead of soundcard*/
void linphone_core_use_files(LinphoneCore *lc, bool_t yesno);
void linphone_core_set_play_file(LinphoneCore *lc, const char *file);
void linphone_core_set_record_file(LinphoneCore *lc, const char *file);
void linphone_core_enable_video_preview(LinphoneCore *lc, bool_t val);
bool_t linphone_core_video_preview_enabled(const LinphoneCore *lc);
/* returns a null terminated static array of string describing the webcams */
const char** linphone_core_get_video_devices(const LinphoneCore *lc);
int linphone_core_set_video_device(LinphoneCore *lc, const char *id);
const char *linphone_core_get_video_device(const LinphoneCore *lc);
int linphone_core_get_mtu(const LinphoneCore *lc);
void linphone_core_set_mtu(LinphoneCore *lc, int mtu);
bool_t linphone_core_is_in_main_thread(LinphoneCore *lc);
void *linphone_core_get_user_data(LinphoneCore *lc);
/* returns LpConfig object to read/write to the config file: usefull if you wish to extend
the config file with your own sections */
struct _LpConfig *linphone_core_get_config(LinphoneCore *lc);
void linphone_core_uninit(LinphoneCore *lc);
void linphone_core_destroy(LinphoneCore *lc);
/* end of lecacy api */
/*internal use only */
#define linphone_core_lock(lc) ms_mutex_lock(&(lc)->lock)
#define linphone_core_unlock(lc) ms_mutex_unlock((&lc)->lock)
void linphone_core_start_media_streams(LinphoneCore *lc, LinphoneCall *call);
void linphone_core_stop_media_streams(LinphoneCore *lc);
const char * linphone_core_get_identity(LinphoneCore *lc);
const char * linphone_core_get_route(LinphoneCore *lc);
bool_t linphone_core_interpret_url(LinphoneCore *lc, const char *url, char **real_url, osip_to_t **real_parsed_url, char **route);
#ifdef __cplusplus
}
#endif
#endif

354
linphone/coreapi/lpconfig.c Normal file
View file

@ -0,0 +1,354 @@
/***************************************************************************
* lpconfig.c
*
* Thu Mar 10 11:13:44 2005
* Copyright 2005 Simon Morlat
* Email simon.morlat@linphone.org
****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#define MAX_LEN 1024
#include "linphonecore.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#define lp_new0(type,n) (type*)calloc(sizeof(type),n)
#include "lpconfig.h"
#define LISTNODE(_struct_) \
struct _struct_ *_prev;\
struct _struct_ *_next;
typedef struct _ListNode{
LISTNODE(_ListNode)
} ListNode;
typedef void (*ListNodeForEachFunc)(ListNode *);
ListNode * list_node_append(ListNode *head,ListNode *elem){
ListNode *e=head;
while(e->_next!=NULL) e=e->_next;
e->_next=elem;
elem->_prev=e;
return head;
}
ListNode * list_node_remove(ListNode *head, ListNode *elem){
ListNode *before,*after;
before=elem->_prev;
after=elem->_next;
if (before!=NULL) before->_next=after;
if (after!=NULL) after->_prev=before;
elem->_prev=NULL;
elem->_next=NULL;
if (head==elem) return after;
return head;
}
void list_node_foreach(ListNode *head, ListNodeForEachFunc func){
for (;head!=NULL;head=head->_next){
func(head);
}
}
#define LIST_PREPEND(e1,e2) ( (e2)->_prev=NULL,(e2)->_next=(e1),(e1)->_prev=(e2),(e2) )
#define LIST_APPEND(head,elem) ((head)==0 ? (elem) : (list_node_append((ListNode*)(head),(ListNode*)(elem)), (head)) )
#define LIST_REMOVE(head,elem)
/* returns void */
#define LIST_FOREACH(head) list_node_foreach((ListNode*)head)
typedef struct _LpItem{
char *key;
char *value;
} LpItem;
typedef struct _LpSection{
char *name;
MSList *items;
} LpSection;
struct _LpConfig{
FILE *file;
char *filename;
MSList *sections;
};
LpItem * lp_item_new(const char *key, const char *value){
LpItem *item=lp_new0(LpItem,1);
item->key=strdup(key);
item->value=strdup(value);
return item;
}
LpSection *lp_section_new(const char *name){
LpSection *sec=lp_new0(LpSection,1);
sec->name=strdup(name);
return sec;
}
void lp_item_destroy(void *pitem){
LpItem *item=(LpItem*)pitem;
free(item->key);
free(item->value);
free(item);
}
void lp_section_destroy(LpSection *sec){
free(sec->name);
ms_list_for_each(sec->items,lp_item_destroy);
ms_list_free(sec->items);
free(sec);
}
void lp_section_add_item(LpSection *sec,LpItem *item){
sec->items=ms_list_append(sec->items,(void *)item);
}
void lp_config_add_section(LpConfig *lpconfig, LpSection *section){
lpconfig->sections=ms_list_append(lpconfig->sections,(void *)section);
}
void lp_config_remove_section(LpConfig *lpconfig, LpSection *section){
lpconfig->sections=ms_list_remove(lpconfig->sections,(void *)section);
lp_section_destroy(section);
}
static bool_t is_first_char(const char *start, const char *pos){
const char *p;
for(p=start;p<pos;p++){
if (*p!=' ') return FALSE;
}
return TRUE;
}
void lp_config_parse(LpConfig *lpconfig){
char tmp[MAX_LEN];
LpSection *cur=NULL;
if (lpconfig->file==NULL) return;
while(fgets(tmp,MAX_LEN,lpconfig->file)!=NULL){
char *pos1,*pos2;
pos1=strchr(tmp,'[');
if (pos1!=NULL && is_first_char(tmp,pos1) ){
pos2=strchr(pos1,']');
if (pos2!=NULL){
int nbs;
char secname[MAX_LEN];
secname[0]='\0';
/* found section */
*pos2='\0';
nbs = sscanf(pos1+1,"%s",secname);
if (nbs == 1 ){
if (strlen(secname)>0){
cur=lp_section_new(secname);
lp_config_add_section(lpconfig,cur);
}
}else{
ms_warning("parse error!");
}
}
}else {
pos1=strchr(tmp,'=');
if (pos1!=NULL){
char key[MAX_LEN];
key[0]='\0';
*pos1='\0';
if (sscanf(tmp,"%s",key)>0){
pos1++;
pos2=strchr(pos1,'\n');
if (pos2==NULL) pos2=pos1+strlen(pos2);
else {
*pos2='\0'; /*replace the '\n' */
pos2--;
}
/* remove ending white spaces */
for (; pos2>pos1 && *pos2==' ';pos2--) *pos2='\0';
if (pos2-pos1>=0){
/* found a pair key,value */
if (cur!=NULL){
lp_section_add_item(cur,lp_item_new(key,pos1));
/*printf("Found %s %s=%s\n",cur->name,key,pos1);*/
}else{
ms_warning("found key,item but no sections");
}
}
}
}
}
}
}
LpConfig * lp_config_new(const char *filename){
LpConfig *lpconfig=lp_new0(LpConfig,1);
if (filename!=NULL){
lpconfig->filename=strdup(filename);
lpconfig->file=fopen(filename,"rw");
if (lpconfig->file!=NULL){
lp_config_parse(lpconfig);
fclose(lpconfig->file);
/* make existing configuration files non-group/world-accessible */
if (chmod(filename, S_IRUSR | S_IWUSR) == -1)
ms_warning("unable to correct permissions on "
"configuration file: %s",
strerror(errno));
lpconfig->file=NULL;
}
}
return lpconfig;
}
void lp_item_set_value(LpItem *item, const char *value){
free(item->value);
item->value=strdup(value);
}
void lp_config_destroy(LpConfig *lpconfig){
if (lpconfig->filename!=NULL) free(lpconfig->filename);
ms_list_for_each(lpconfig->sections,(void (*)(void*))lp_section_destroy);
ms_list_free(lpconfig->sections);
free(lpconfig);
}
LpSection *lp_config_find_section(LpConfig *lpconfig, const char *name){
LpSection *sec;
MSList *elem;
/*printf("Looking for section %s\n",name);*/
for (elem=lpconfig->sections;elem!=NULL;elem=ms_list_next(elem)){
sec=(LpSection*)elem->data;
if (strcmp(sec->name,name)==0){
/*printf("Section %s found\n",name);*/
return sec;
}
}
return NULL;
}
LpItem *lp_section_find_item(LpSection *sec, const char *name){
MSList *elem;
LpItem *item;
/*printf("Looking for item %s\n",name);*/
for (elem=sec->items;elem!=NULL;elem=ms_list_next(elem)){
item=(LpItem*)elem->data;
if (strcmp(item->key,name)==0) {
/*printf("Item %s found\n",name);*/
return item;
}
}
return NULL;
}
void lp_section_remove_item(LpSection *sec, LpItem *item){
sec->items=ms_list_remove(sec->items,(void *)item);
lp_item_destroy(item);
}
const char *lp_config_get_string(LpConfig *lpconfig, const char *section, const char *key, const char *default_string){
LpSection *sec;
LpItem *item;
sec=lp_config_find_section(lpconfig,section);
if (sec!=NULL){
item=lp_section_find_item(sec,key);
if (item!=NULL) return item->value;
}
return default_string;
}
int lp_config_get_int(LpConfig *lpconfig,const char *section, const char *key, int default_value){
const char *str=lp_config_get_string(lpconfig,section,key,NULL);
if (str!=NULL) return atoi(str);
else return default_value;
}
void lp_config_set_string(LpConfig *lpconfig,const char *section, const char *key, const char *value){
LpItem *item;
LpSection *sec=lp_config_find_section(lpconfig,section);
if (sec!=NULL){
item=lp_section_find_item(sec,key);
if (item!=NULL){
if (value!=NULL)
lp_item_set_value(item,value);
else lp_section_remove_item(sec,item);
}else{
if (value!=NULL)
lp_section_add_item(sec,lp_item_new(key,value));
}
}else if (value!=NULL){
sec=lp_section_new(section);
lp_config_add_section(lpconfig,sec);
lp_section_add_item(sec,lp_item_new(key,value));
}
}
void lp_config_set_int(LpConfig *lpconfig,const char *section, const char *key, int value){
char tmp[30];
snprintf(tmp,30,"%i",value);
lp_config_set_string(lpconfig,section,key,tmp);
}
void lp_item_write(LpItem *item, FILE *file){
fprintf(file,"%s=%s\n",item->key,item->value);
}
void lp_section_write(LpSection *sec, FILE *file){
fprintf(file,"[%s]\n",sec->name);
ms_list_for_each2(sec->items,(void (*)(void*, void*))lp_item_write,(void *)file);
fprintf(file,"\n");
}
int lp_config_sync(LpConfig *lpconfig){
FILE *file;
if (lpconfig->filename==NULL) return -1;
#ifndef WIN32
/* don't create group/world-accessible files */
(void) umask(S_IRWXG | S_IRWXO);
#endif
file=fopen(lpconfig->filename,"w");
if (file==NULL){
ms_warning("Could not write %s !",lpconfig->filename);
return -1;
}
ms_list_for_each2(lpconfig->sections,(void (*)(void *,void*))lp_section_write,(void *)file);
fclose(file);
return 0;
}
int lp_config_has_section(LpConfig *lpconfig, const char *section){
if (lp_config_find_section(lpconfig,section)!=NULL) return 1;
return 0;
}
void lp_config_clean_section(LpConfig *lpconfig, const char *section){
LpSection *sec=lp_config_find_section(lpconfig,section);
if (sec!=NULL){
lp_config_remove_section(lpconfig,sec);
}
}

View file

@ -0,0 +1,48 @@
/***************************************************************************
* lpconfig.h
*
* Thu Mar 10 15:02:49 2005
* Copyright 2005 Simon Morlat
* Email simon.morlat@linphone.org
****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef LPCONFIG_H
#define LPCONFIG_H
typedef struct _LpConfig LpConfig;
#ifdef __cplusplus
extern "C" {
#endif
LpConfig * lp_config_new(const char *filename);
const char *lp_config_get_string(LpConfig *lpconfig, const char *section, const char *key, const char *default_string);
int lp_config_get_int(LpConfig *lpconfig,const char *section, const char *key, int default_value);
void lp_config_set_string(LpConfig *lpconfig,const char *section, const char *key, const char *value);
void lp_config_set_int(LpConfig *lpconfig,const char *section, const char *key, int value);
int lp_config_sync(LpConfig *lpconfig);
int lp_config_has_section(LpConfig *lpconfig, const char *section);
void lp_config_clean_section(LpConfig *lpconfig, const char *section);
void lp_config_destroy(LpConfig *cfg);
#ifdef __cplusplus
}
#endif
#endif

450
linphone/coreapi/misc.c Normal file
View file

@ -0,0 +1,450 @@
/*
linphone
Copyright (C) 2000 Simon MORLAT (simon.morlat@linphone.org)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "private.h"
#include "mediastreamer2/mediastream.h"
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#ifndef WIN32
static char lock_name[80];
static char lock_set=0;
/* put a lock file in /tmp. this is called when linphone runs as a daemon*/
int set_lock_file()
{
FILE *lockfile;
snprintf(lock_name,80,"/tmp/linphone.%i",getuid());
lockfile=fopen(lock_name,"w");
if (lockfile==NULL)
{
printf("Failed to create lock file.\n");
return(-1);
}
fprintf(lockfile,"%i",getpid());
fclose(lockfile);
lock_set=1;
return(0);
}
/* looks if there is a lock file. If presents return its content (the pid of the already running linphone), if not found, returns -1*/
int get_lock_file()
{
int pid;
FILE *lockfile;
snprintf(lock_name,80,"/tmp/linphone.%i",getuid());
lockfile=fopen(lock_name,"r");
if (lockfile==NULL)
return(-1);
if (fscanf(lockfile,"%i",&pid)!=1){
ms_warning("Could not read pid in lock file.");
fclose(lockfile);
return -1;
}
fclose(lockfile);
return pid;
}
/* remove the lock file if it was set*/
int remove_lock_file()
{
int err=0;
if (lock_set)
{
err=unlink(lock_name);
lock_set=0;
}
return(err);
}
#endif
char *int2str(int number)
{
char *numstr=ms_malloc(10);
snprintf(numstr,10,"%i",number);
return numstr;
}
void check_sound_device(LinphoneCore *lc)
{
int fd,len;
int a;
char *file=NULL;
char *i810_audio=NULL;
char *snd_pcm_oss=NULL;
char *snd_mixer_oss=NULL;
char *snd_pcm=NULL;
fd=open("/proc/modules",O_RDONLY);
if (fd>0){
/* read the entire /proc/modules file and check if sound conf seems correct */
/*a=fstat(fd,&statbuf);
if (a<0) ms_warning("Can't stat /proc/modules:%s.",strerror(errno));
len=statbuf.st_size;
if (len==0) ms_warning("/proc/modules has zero size!");
*/
/***** fstat does not work on /proc/modules for unknown reason *****/
len=6000;
file=ms_malloc(len+1);
a=read(fd,file,len);
if (a<len) file=ms_realloc(file,a+1);
file[a]='\0';
i810_audio=strstr(file,"i810_audio");
if (i810_audio!=NULL){
/* I'm sorry i put this warning in comments because
* i don't use yet the right driver !! */
/* lc->vtable.display_warning(lc,_("You are currently using the i810_audio driver.\nThis driver is buggy and so does not work with Linphone.\nWe suggest that you replace it by its equivalent ALSA driver,\neither with packages from your distribution, or by downloading\nALSA drivers at http://www.alsa-project.org."));*/
goto end;
}
snd_pcm=strstr(file,"snd-pcm");
if (snd_pcm!=NULL){
snd_pcm_oss=strstr(file,"snd-pcm-oss");
snd_mixer_oss=strstr(file,"snd-mixer-oss");
if (snd_pcm_oss==NULL){
lc->vtable.display_warning(lc,_("Your computer appears to be using ALSA sound drivers.\nThis is the best choice. However the pcm oss emulation module\nis missing and linphone needs it. Please execute\n'modprobe snd-pcm-oss' as root to load it."));
}
if (snd_mixer_oss==NULL){
lc->vtable.display_warning(lc,_("Your computer appears to be using ALSA sound drivers.\nThis is the best choice. However the mixer oss emulation module\nis missing and linphone needs it. Please execute\n 'modprobe snd-mixer-oss' as root to load it."));
}
}
}else {
#ifdef __linux
ms_warning("Could not open /proc/modules.");
#endif
}
/* now check general volume. Some user forget to rise it and then complain that linphone is
not working */
/* but some other users complain that linphone should not change levels...
if (lc->sound_conf.sndcard!=NULL){
a=snd_card_get_level(lc->sound_conf.sndcard,SND_CARD_LEVEL_GENERAL);
if (a<50){
ms_warning("General level is quite low (%i). Linphone rises it up for you.",a);
snd_card_set_level(lc->sound_conf.sndcard,SND_CARD_LEVEL_GENERAL,80);
}
}
*/
end:
if (file!=NULL) ms_free(file);
if (fd>0) close(fd);
}
#define UDP_HDR_SZ 8
#define RTP_HDR_SZ 12
#define IP4_HDR_SZ 20 /*20 is the minimum, but there may be some options*/
const char *payload_type_get_description(PayloadType *pt){
return (const char *)pt->user_data;
}
void payload_type_set_enable(PayloadType *pt,int value)
{
if ((value)!=0) payload_type_set_flag(pt,PAYLOAD_TYPE_ENABLED); \
else payload_type_unset_flag(pt,PAYLOAD_TYPE_ENABLED);
}
bool_t payload_type_enabled(PayloadType *pt) {
return (((pt)->flags & PAYLOAD_TYPE_ENABLED)!=0);
}
int payload_type_get_bitrate(PayloadType *pt)
{
return pt->normal_bitrate;
}
const char *payload_type_get_mime(PayloadType *pt){
return pt->mime_type;
}
int payload_type_get_rate(PayloadType *pt){
return pt->clock_rate;
}
static double get_audio_payload_bandwidth(const PayloadType *pt){
double npacket=50;
double packet_size;
int bitrate;
bitrate=pt->normal_bitrate;
packet_size=(double)(bitrate/(50*8))+UDP_HDR_SZ+RTP_HDR_SZ+IP4_HDR_SZ;
return packet_size*8.0*npacket;
}
void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc, const PayloadType *pt){
lc->audio_bw=(int)(get_audio_payload_bandwidth(pt)/1000.0);
/*update*/
linphone_core_set_upload_bandwidth(lc,lc->net_conf.upload_bw);
}
static void update_allocated_audio_bandwidth(LinphoneCore *lc){
const MSList *elem;
PayloadType *max=NULL;
for(elem=linphone_core_get_audio_codecs(lc);elem!=NULL;elem=elem->next){
PayloadType *pt=(PayloadType*)elem->data;
if (payload_type_enabled(pt)){
if (max==NULL) max=pt;
else if (max->normal_bitrate<pt->normal_bitrate){
max=pt;
}
}
}
if (max) {
linphone_core_update_allocated_audio_bandwidth(lc,max);
}
}
/* return TRUE if codec can be used with bandwidth, FALSE else*/
bool_t linphone_core_check_payload_type_usability(LinphoneCore *lc, PayloadType *pt)
{
double codec_band;
int min_audio_bw;
int min_video_bw;
bool_t ret=FALSE;
/*
update allocated audio bandwidth to allocate the remaining to video.
This must be done outside calls, because after sdp negociation
the audio bandwidth is refined to the selected codec
*/
if (!linphone_core_in_call(lc)) update_allocated_audio_bandwidth(lc);
min_audio_bw=get_min_bandwidth(linphone_core_get_download_bandwidth(lc),
linphone_core_get_upload_bandwidth(lc));
if (min_audio_bw==0) min_audio_bw=-1;
min_video_bw=get_min_bandwidth(lc->dw_video_bw,lc->up_video_bw);
switch (pt->type){
case PAYLOAD_AUDIO_CONTINUOUS:
case PAYLOAD_AUDIO_PACKETIZED:
codec_band=get_audio_payload_bandwidth(pt);
ret=bandwidth_is_greater(min_audio_bw*1000,codec_band);
//ms_message("Payload %s: %g",pt->mime_type,codec_band);
break;
case PAYLOAD_VIDEO:
if (min_video_bw!=0) {/* infinite (-1) or strictly positive*/
/*let the video use all the bandwidth minus the maximum bandwidth used by audio */
if (min_video_bw>0)
pt->normal_bitrate=min_video_bw*1000;
else
pt->normal_bitrate=512000;
ret=TRUE;
}
else ret=FALSE;
break;
}
/*if (!ret) ms_warning("Payload %s is not usable with your internet connection.",pt->mime_type);*/
return ret;
}
static PayloadType * find_payload(RtpProfile *prof, PayloadType *pt /*from config*/){
PayloadType *candidate=NULL;
int i;
PayloadType *it;
for(i=0;i<127;++i){
it=rtp_profile_get_payload(prof,i);
if (it!=NULL && strcasecmp(pt->mime_type,it->mime_type)==0
&& (pt->clock_rate==it->clock_rate || pt->clock_rate<=0)
&& payload_type_get_user_data(it)==NULL ){
if ( (pt->recv_fmtp && it->recv_fmtp && strcasecmp(pt->recv_fmtp,it->recv_fmtp)==0) ||
(pt->recv_fmtp==NULL && it->recv_fmtp==NULL) ){
/*exact match*/
return it;
}else candidate=it;
}
}
return candidate;
}
static MSList *fix_codec_list(RtpProfile *prof, MSList *conflist)
{
MSList *elem;
MSList *newlist=NULL;
PayloadType *payload,*confpayload;
for (elem=conflist;elem!=NULL;elem=ms_list_next(elem))
{
confpayload=(PayloadType*)elem->data;
payload=find_payload(prof,confpayload);
if (payload!=NULL){
if (ms_filter_codec_supported(confpayload->mime_type)){
MSFilterDesc *desc=ms_filter_get_encoder(confpayload->mime_type);
payload_type_set_user_data(payload,(void*)desc->text);
payload_type_set_enable(payload,payload_type_enabled(confpayload));
newlist=ms_list_append(newlist,payload);
}
}
else{
ms_warning("Cannot support %s/%i: does not exist.",confpayload->mime_type,
confpayload->clock_rate);
}
}
return newlist;
}
void linphone_core_setup_local_rtp_profile(LinphoneCore *lc)
{
int i;
MSList *audiopt,*videopt;
PayloadType *payload;
bool_t prepend;
lc->local_profile=rtp_profile_clone_full(&av_profile);
/* first look at the list given by configuration file to see if
it is correct */
audiopt=fix_codec_list(lc->local_profile,lc->codecs_conf.audio_codecs);
videopt=fix_codec_list(lc->local_profile,lc->codecs_conf.video_codecs);
/* now find and add payloads that are not listed in the configuration
codec list */
for (i=0;i<127;i++)
{
payload=rtp_profile_get_payload(lc->local_profile,i);
if (payload!=NULL){
if (payload_type_get_user_data(payload)!=NULL) continue;
/* find a mediastreamer codec for this payload type */
if (ms_filter_codec_supported(payload->mime_type)){
MSFilterDesc *desc=ms_filter_get_encoder(payload->mime_type);
ms_message("Adding new codec %s/%i",payload->mime_type,payload->clock_rate);
payload_type_set_enable(payload,1);
payload_type_set_user_data(payload,(void *)desc->text);
prepend=FALSE;
/* by default, put speex, mpeg4, or h264 on top of list*/
if (strcmp(payload->mime_type,"speex")==0)
prepend=TRUE;
if (strcmp(payload->mime_type,"MP4V-ES")==0)
prepend=TRUE;
if (strcmp(payload->mime_type,"H264")==0)
prepend=TRUE;
switch (payload->type){
case PAYLOAD_AUDIO_CONTINUOUS:
case PAYLOAD_AUDIO_PACKETIZED:
if (prepend)
audiopt=ms_list_prepend(audiopt,(void *)payload);
else
audiopt=ms_list_append(audiopt,(void *)payload);
break;
case PAYLOAD_VIDEO:
if (prepend)
videopt=ms_list_prepend(videopt,(void *)payload);
else
videopt=ms_list_append(videopt,(void *)payload);
break;
default:
ms_error("Unsupported rtp media type.");
}
}
}
}
ms_list_for_each(lc->codecs_conf.audio_codecs,(void (*)(void*))payload_type_destroy);
ms_list_for_each(lc->codecs_conf.video_codecs,(void (*)(void *))payload_type_destroy);
ms_list_free(lc->codecs_conf.audio_codecs);
ms_list_free(lc->codecs_conf.video_codecs);
/* set the fixed lists instead:*/
lc->codecs_conf.audio_codecs=audiopt;
lc->codecs_conf.video_codecs=videopt;
}
int from_2char_without_params(osip_from_t *from,char **str)
{
osip_from_t *tmpfrom=NULL;
osip_from_clone(from,&tmpfrom);
if (tmpfrom!=NULL){
while(!osip_list_eol(&tmpfrom->gen_params,0)){
osip_generic_param_t *param=(osip_generic_param_t*)osip_list_get(&tmpfrom->gen_params,0);
osip_generic_param_free(param);
osip_list_remove(&tmpfrom->gen_params,0);
}
}else return -1;
osip_from_to_str(tmpfrom,str);
osip_from_free(tmpfrom);
return 0;
}
bool_t lp_spawn_command_line_sync(const char *command, char **result,int *command_ret){
FILE *f=popen(command,"r");
if (f!=NULL){
int err;
*result=ms_malloc(4096);
err=fread(*result,1,4096-1,f);
if (err<0){
ms_warning("Error reading command output:%s",strerror(errno));
ms_free(result);
return FALSE;
}
(*result)[err]=0;
err=pclose(f);
if (command_ret!=NULL) *command_ret=err;
return TRUE;
}
return FALSE;
}
#if defined(HAVE_GETIFADDRS) && defined(INET6)
#include <sys/types.h>
#include <sys/socket.h>
#include <ifaddrs.h>
bool_t host_has_ipv6_network()
{
struct ifaddrs *ifp;
struct ifaddrs *ifpstart;
bool_t ipv6_present=FALSE;
if (getifaddrs (&ifpstart) < 0)
{
return FALSE;
}
for (ifp=ifpstart; ifp != NULL; ifp = ifp->ifa_next)
{
if (!ifp->ifa_addr)
continue;
switch (ifp->ifa_addr->sa_family) {
case AF_INET:
break;
case AF_INET6:
ipv6_present=TRUE;
break;
default:
continue;
}
}
freeifaddrs (ifpstart);
return ipv6_present;
}
#else
bool_t host_has_ipv6_network()
{
return FALSE;
}
#endif

208
linphone/coreapi/presence.c Normal file
View file

@ -0,0 +1,208 @@
/*
linphone
Copyright (C) 2000 Simon MORLAT (simon.morlat@linphone.org)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "linphonecore.h"
#include <eXosip2/eXosip.h>
#include <osipparser2/osip_message.h>
#include "private.h"
extern const char *__policy_enum_to_str(LinphoneSubscribePolicy pol);
void linphone_core_add_subscriber(LinphoneCore *lc, const char *subscriber, int did, int nid){
LinphoneFriend *fl=linphone_friend_new_with_addr(subscriber);
if (fl==NULL) return ;
fl->in_did=did;
linphone_friend_set_nid(fl,nid);
linphone_friend_set_inc_subscribe_policy(fl,LinphoneSPAccept);
fl->inc_subscribe_pending=TRUE;
lc->subscribers=ms_list_append(lc->subscribers,(void *)fl);
if (lc->vtable.new_unknown_subscriber!=NULL) {
char *clean_subscriber; /* we need to remove tags...*/
from_2char_without_params(fl->url,&clean_subscriber);
lc->vtable.new_unknown_subscriber(lc,fl,clean_subscriber);
ms_free(clean_subscriber);
}
}
void linphone_core_reject_subscriber(LinphoneCore *lc, LinphoneFriend *lf){
linphone_friend_set_inc_subscribe_policy(lf,LinphoneSPDeny);
}
static void __do_notify(void * data, void * user_data){
int *tab=(int*)user_data;
LinphoneFriend *lf=(LinphoneFriend*)data;
linphone_friend_notify(lf,tab[0],tab[1]);
}
void __linphone_core_notify_all_friends(LinphoneCore *lc, int ss, int os){
int tab[2];
tab[0]=ss;
tab[1]=os;
ms_list_for_each2(lc->friends,__do_notify,(void *)tab);
}
void linphone_core_notify_all_friends(LinphoneCore *lc, LinphoneOnlineStatus os){
ms_message("Notifying all friends that we are in status %i",os);
__linphone_core_notify_all_friends(lc,EXOSIP_SUBCRSTATE_ACTIVE,os);
}
/* check presence state before answering to call; returns TRUE if we can proceed, else answer the appropriate answer
to close the dialog*/
bool_t linphone_core_check_presence(LinphoneCore *lc){
return TRUE;
}
void linphone_subscription_new(LinphoneCore *lc, eXosip_event_t *ev){
LinphoneFriend *lf=NULL;
osip_from_t *from=ev->request->from;
char *tmp;
osip_message_t *msg=NULL;
osip_from_to_str(ev->request->from,&tmp);
ms_message("Receiving new subscription from %s.",tmp);
/* check if we answer to this subscription */
if (find_friend(lc->friends,from,&lf)!=NULL){
lf->in_did=ev->did;
linphone_friend_set_nid(lf,ev->nid);
eXosip_insubscription_build_answer(ev->tid,202,&msg);
eXosip_insubscription_send_answer(ev->tid,202,msg);
__eXosip_wakeup_event();
linphone_friend_done(lf); /*this will do all necessary actions */
}else{
/* check if this subscriber is in our black list */
if (find_friend(lc->subscribers,from,&lf)){
if (lf->pol==LinphoneSPDeny){
ms_message("Rejecting %s because we already rejected it once.",from);
eXosip_insubscription_send_answer(ev->tid,401,NULL);
}
else {
/* else it is in wait for approval state, because otherwise it is in the friend list.*/
ms_message("New subscriber found in friend list, in %s state.",__policy_enum_to_str(lf->pol));
}
}else {
eXosip_insubscription_build_answer(ev->tid,202,&msg);
eXosip_insubscription_send_answer(ev->tid,202,msg);
linphone_core_add_subscriber(lc,tmp,ev->did,ev->nid);
}
}
osip_free(tmp);
}
void linphone_notify_recv(LinphoneCore *lc, eXosip_event_t *ev)
{
const char *status=_("Gone");
const char *img="sip-closed.png";
char *tmp;
LinphoneFriend *lf;
osip_from_t *friend=NULL;
osip_from_t *from=NULL;
osip_body_t *body=NULL;
LinphoneOnlineStatus estatus=LINPHONE_STATUS_UNKNOWN;
ms_message("Receiving notify with sid=%i,nid=%i",ev->sid,ev->nid);
if (ev->request!=NULL){
from=ev->request->from;
osip_message_get_body(ev->request,0,&body);
if (body==NULL){
ms_error("No body in NOTIFY");
return;
}
if (strstr(body->body,"pending")!=NULL){
status=_("Waiting for Approval");
img="sip-wfa.png";
estatus=LINPHONE_STATUS_PENDING;
}else if ((strstr(body->body,"online")!=NULL) || (strstr(body->body,"open")!=NULL)) {
status=_("Online");
img="sip-online.png";
estatus=LINPHONE_STATUS_ONLINE;
}else if (strstr(body->body,"busy")!=NULL){
status=_("Busy");
img="sip-busy.png";
estatus=LINPHONE_STATUS_BUSY;
}else if (strstr(body->body,"berightback")!=NULL
|| strstr(body->body,"in-transit")!=NULL ){
status=_("Be Right Back");
img="sip-bifm.png";
estatus=LINPHONE_STATUS_BERIGHTBACK;
}else if (strstr(body->body,"away")!=NULL){
status=_("Away");
img="sip-away.png";
estatus=LINPHONE_STATUS_AWAY;
}else if (strstr(body->body,"onthephone")!=NULL
|| strstr(body->body,"on-the-phone")!=NULL){
status=_("On The Phone");
img="sip-otp.png";
estatus=LINPHONE_STATUS_ONTHEPHONE;
}else if (strstr(body->body,"outtolunch")!=NULL
|| strstr(body->body,"meal")!=NULL){
status=_("Out To Lunch");
img="sip-otl.png";
estatus=LINPHONE_STATUS_OUTTOLUNCH;
}else if (strstr(body->body,"closed")!=NULL){
status=_("Closed");
img="sip-away.png";
estatus=LINPHONE_STATUS_CLOSED;
}else{
status=_("Gone");
img="sip-closed.png";
estatus=LINPHONE_STATUS_OFFLINE;
}
ms_message("We are notified that sip:%s@%s has online status %s",from->url->username,from->url->host,status);
}
lf=linphone_find_friend_by_sid(lc->friends,ev->sid);
if (lf!=NULL){
friend=lf->url;
from_2char_without_params(friend,&tmp);
lf->status=estatus;
lc->vtable.notify_recv(lc,(LinphoneFriend*)lf,tmp,status,img);
ms_free(tmp);
if (ev->ss_status==EXOSIP_SUBCRSTATE_TERMINATED) {
lf->sid=-1;
lf->out_did=-1;
ms_message("Outgoing subscription terminated by remote.");
}
}else{
ms_message("But this person is not part of our friend list, so we don't care.");
}
}
void linphone_subscription_answered(LinphoneCore *lc, eXosip_event_t *ev){
LinphoneFriend *lf;
osip_from_t *from=ev->response->to;
find_friend(lc->friends,from,&lf);
if (lf!=NULL){
lf->out_did=ev->did;
linphone_friend_set_sid(lf,ev->sid);
}else{
ms_warning("Receiving answer for unknown subscribe sip:%s@%s", from->url->username,from->url->host);
}
}
void linphone_subscription_closed(LinphoneCore *lc,eXosip_event_t *ev){
LinphoneFriend *lf;
osip_from_t *from=ev->request->from;
lf=linphone_find_friend_by_nid(lc->friends,ev->nid);
if (lf!=NULL){
lf->in_did=-1;
linphone_friend_set_nid(lf,-1);
}else{
ms_warning("Receiving unsuscribe for unknown in-subscribtion from sip:%s@%s", from->url->username, from->url->host);
}
}

121
linphone/coreapi/private.h Normal file
View file

@ -0,0 +1,121 @@
/***************************************************************************
* private.h
*
* Mon Jun 13 14:23:23 2005
* Copyright 2005 Simon Morlat
* Email simon dot morlat at linphone dot org
****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _PRIVATE_H
#define _PRIVATE_H
#include "linphonecore.h"
#include <eXosip2/eXosip.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifndef LINPHONE_VERSION
#define LINPHONE_VERSION "2.99.4"
#endif
#ifndef LIBLINPHONE_VERSION
#define LIBLINPHONE_VERSION LINPHONE_VERSION
#endif
#ifndef PACKAGE_SOUND_DIR
#define PACKAGE_SOUND_DIR "."
#endif
#ifdef WIN32
#include <io.h> /* for access() */
#endif
#ifdef HAVE_GETTEXT
#include <libintl.h>
#ifndef _
#define _(String) gettext(String)
#endif
#else
#define _(something) (something)
#endif
void linphone_core_init_media_streams(LinphoneCore *lc);
void linphone_auth_info_write_config(struct _LpConfig *config, LinphoneAuthInfo *obj, int pos);
void linphone_core_update_proxy_register(LinphoneCore *lc);
void linphone_core_refresh_subscribes(LinphoneCore *lc);
int linphone_proxy_config_send_publish(LinphoneProxyConfig *cfg, LinphoneOnlineStatus os);
int linphone_online_status_to_eXosip(LinphoneOnlineStatus os);
void linphone_friend_set_sid(LinphoneFriend *lf, int sid);
void linphone_friend_set_nid(LinphoneFriend *lf, int nid);
void linphone_friend_notify(LinphoneFriend *lf, int ss, LinphoneOnlineStatus os);
int set_lock_file();
int get_lock_file();
int remove_lock_file();
int do_registration(LinphoneCore *lc, bool_t doit);
void check_for_registration(LinphoneCore *lc);
char *int2str(int number);
int from_2char_without_params(osip_from_t *from,char **str);
void check_sound_device(LinphoneCore *lc);
void linphone_core_setup_local_rtp_profile(LinphoneCore *lc);
void linphone_core_get_local_ip(LinphoneCore *lc, const char *to, char *result);
bool_t host_has_ipv6_network();
bool_t lp_spawn_command_line_sync(const char *command, char **result,int *command_ret);
static inline int get_min_bandwidth(int dbw, int ubw){
if (dbw<0) return ubw;
if (ubw<0) return dbw;
return MIN(dbw,ubw);
}
static inline bool_t bandwidth_is_greater(int bw1, int bw2){
if (bw1<0) return TRUE;
else if (bw2<0) return FALSE;
else return bw1>=bw2;
}
#define PAYLOAD_TYPE_ENABLED PAYLOAD_TYPE_USER_FLAG_0
void linphone_process_authentication(LinphoneCore* lc, eXosip_event_t *ev);
void linphone_authentication_ok(LinphoneCore *lc, eXosip_event_t *ev);
void linphone_subscription_new(LinphoneCore *lc, eXosip_event_t *ev);
void linphone_notify_recv(LinphoneCore *lc,eXosip_event_t *ev);
LinphoneProxyConfig *linphone_core_get_proxy_config_from_rid(LinphoneCore *lc, int rid);
void linphone_subscription_answered(LinphoneCore *lc, eXosip_event_t *ev);
void linphone_subscription_closed(LinphoneCore *lc, eXosip_event_t *ev);
void linphone_call_init_media_params(LinphoneCall *call);
void linphone_set_sdp(osip_message_t *sip, const char *sdp);
MSList *find_friend(MSList *fl, const osip_from_t *friend, LinphoneFriend **lf);
LinphoneFriend *linphone_find_friend_by_nid(MSList *l, int nid);
LinphoneFriend *linphone_find_friend_by_sid(MSList *l, int sid);
void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc, const PayloadType *pt);
#endif /* _PRIVATE_H */

512
linphone/coreapi/proxy.c Normal file
View file

@ -0,0 +1,512 @@
/*
linphone
Copyright (C) 2000 Simon MORLAT (simon.morlat@linphone.org)
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "linphonecore.h"
#include <eXosip2/eXosip.h>
#include <osipparser2/osip_message.h>
#include "lpconfig.h"
#include "private.h"
void linphone_proxy_config_init(LinphoneProxyConfig *obj){
memset(obj,0,sizeof(LinphoneProxyConfig));
obj->rid=-1;
obj->expires=3600;
}
LinphoneProxyConfig *linphone_proxy_config_new(){
LinphoneProxyConfig *obj=NULL;
obj=ms_new(LinphoneProxyConfig,1);
linphone_proxy_config_init(obj);
return obj;
}
void linphone_proxy_config_destroy(LinphoneProxyConfig *obj){
if (obj->reg_proxy!=NULL) ms_free(obj->reg_proxy);
if (obj->reg_identity!=NULL) ms_free(obj->reg_identity);
if (obj->reg_route!=NULL) ms_free(obj->reg_route);
}
static void linphone_proxy_config_register(LinphoneProxyConfig *obj){
osip_message_t *msg;
eXosip_lock();
eXosip_register_build_register(obj->rid,obj->expires,&msg);
eXosip_register_send_register(obj->rid,msg);
eXosip_unlock();
}
int linphone_proxy_config_set_server_addr(LinphoneProxyConfig *obj, const char *server_addr){
int err;
osip_from_t *url;
if (obj->reg_proxy!=NULL) ms_free(obj->reg_proxy);
obj->reg_proxy=NULL;
if (server_addr!=NULL && strlen(server_addr)>0){
osip_from_init(&url);
err=osip_from_parse(url,server_addr);
if (err==0 && url->url->host!=NULL){
obj->reg_proxy=ms_strdup(server_addr);
}else{
ms_warning("Could not parse %s",server_addr);
}
osip_from_free(url);
}
return 0;
}
void linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *identity){
int err=0;
osip_from_t *url;
if (identity!=NULL && strlen(identity)>0){
osip_from_init(&url);
err=osip_from_parse(url,identity);
if (err<0 || url->url->host==NULL || url->url->username==NULL){
ms_warning("Could not parse %s",identity);
osip_from_free(url);
return;
}
osip_from_free(url);
} else err=-2;
if (obj->reg_identity!=NULL) {
ms_free(obj->reg_identity);
obj->reg_identity=NULL;
}
if (err==-2) obj->reg_identity=NULL;
else obj->reg_identity=ms_strdup(identity);
}
void linphone_proxy_config_set_route(LinphoneProxyConfig *obj, const char *route)
{
int err;
osip_uri_param_t *lr_param=NULL;
osip_route_t *rt=NULL;
char *tmproute=NULL;
if (route!=NULL && strlen(route)>0){
osip_route_init(&rt);
err=osip_route_parse(rt,route);
if (err<0){
ms_warning("Could not parse %s",route);
osip_route_free(rt);
return ;
}
if (obj->reg_route!=NULL) {
ms_free(obj->reg_route);
obj->reg_route=NULL;
}
/* check if the lr parameter is set , if not add it */
osip_uri_uparam_get_byname(rt->url, "lr", &lr_param);
if (lr_param==NULL){
osip_uri_uparam_add(rt->url,osip_strdup("lr"),NULL);
osip_route_to_str(rt,&tmproute);
obj->reg_route=ms_strdup(tmproute);
osip_free(tmproute);
}else obj->reg_route=ms_strdup(route);
}else{
if (obj->reg_route!=NULL) ms_free(obj->reg_route);
obj->reg_route=NULL;
}
}
bool_t linphone_proxy_config_check(LinphoneCore *lc, LinphoneProxyConfig *obj){
if (obj->reg_proxy==NULL){
if (lc->vtable.display_warning)
lc->vtable.display_warning(lc,_("The sip proxy address you entered is invalid, it must start with \"sip:\""
" followed by a hostname."));
return FALSE;
}
if (obj->reg_identity==NULL){
if (lc->vtable.display_warning)
lc->vtable.display_warning(lc,_("The sip identity you entered is invalid.\nIt should look like "
"sip:username@proxydomain, such as sip:alice@example.net"));
return FALSE;
}
return TRUE;
}
void linphone_proxy_config_enableregister(LinphoneProxyConfig *obj, bool_t val){
obj->reg_sendregister=val;
}
void linphone_proxy_config_expires(LinphoneProxyConfig *obj, int val){
if (val<=0) val=600;
obj->expires=val;
}
void linphone_proxy_config_enable_publish(LinphoneProxyConfig *obj, bool_t val){
obj->publish=val;
}
void linphone_proxy_config_edit(LinphoneProxyConfig *obj){
obj->frozen=TRUE;
if (obj->reg_sendregister){
/* unregister */
if (obj->registered) {
osip_message_t *msg;
eXosip_lock();
eXosip_register_build_register(obj->rid,0,&msg);
eXosip_register_send_register(obj->rid,msg);
eXosip_unlock();
obj->registered=FALSE;
}
}
}
void linphone_proxy_config_apply(LinphoneProxyConfig *obj,LinphoneCore *lc)
{
obj->lc=lc;
linphone_proxy_config_done(obj);
}
int linphone_proxy_config_done(LinphoneProxyConfig *obj)
{
const char *id_str;
if (!linphone_proxy_config_check(obj->lc,obj)) return -1;
if (obj->reg_identity!=NULL) id_str=obj->reg_identity;
else id_str=linphone_core_get_primary_contact(obj->lc);
obj->frozen=FALSE;
if (obj->reg_sendregister){
char *ct=NULL;
osip_message_t *msg=NULL;
obj->rid=eXosip_register_build_initial_register(id_str,obj->reg_proxy,NULL,obj->expires,&msg);
eXosip_register_send_register(obj->rid,msg);
if (ct!=NULL) osip_free(ct);
}
return 0;
}
void linphone_proxy_config_set_realm(LinphoneProxyConfig *cfg, const char *realm)
{
if (cfg->realm!=NULL) {
ms_free(cfg->realm);
cfg->realm=NULL;
}
if (realm!=NULL) cfg->realm=ms_strdup(realm);
}
int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy,
LinphoneOnlineStatus presence_mode)
{
osip_message_t *pub;
int i;
const char *from=NULL;
char buf[5000];
if (proxy->publish==FALSE) return 0;
if (proxy!=NULL) {
from=linphone_proxy_config_get_identity(proxy);
}
if (from==NULL) from=linphone_core_get_primary_contact(proxy->lc);
if (presence_mode==LINPHONE_STATUS_ONLINE)
{
snprintf(buf, 5000, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>online</note>\n\
</tuple>\n\
</presence>",
from, from);
}
else if (presence_mode==LINPHONE_STATUS_BUSY
||presence_mode==LINPHONE_STATUS_NOT_DISTURB)
{
snprintf(buf, 5000, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>busy</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>busy</note>\n\
</tuple>\n\
</presence>",
from, from);
}
else if (presence_mode==LINPHONE_STATUS_BERIGHTBACK)
{
snprintf(buf, 5000, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>in-transit</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>be right back</note>\n\
</tuple>\n\
</presence>",
from,from);
}
else if (presence_mode==LINPHONE_STATUS_AWAY
||presence_mode==LINPHONE_STATUS_MOVED
||presence_mode==LINPHONE_STATUS_ALT_SERVICE)
{
snprintf(buf, 5000, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>away</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>away</note>\n\
</tuple>\n\
</presence>",
from, from);
}
else if (presence_mode==LINPHONE_STATUS_ONTHEPHONE)
{
snprintf(buf, 5000, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>on-the-phone</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>on the phone</note>\n\
</tuple>\n\
</presence>",
from, from);
}
else if (presence_mode==LINPHONE_STATUS_OUTTOLUNCH)
{
snprintf(buf, 5000, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>meal</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>out to lunch</note>\n\
</tuple>\n\
</presence>",
from, from);
}
else if (presence_mode==LINPHONE_STATUS_OFFLINE)
{
/* */
snprintf(buf, 5000, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n%s",
from,
"<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>closed</basic>\n\
<es:activities>\n\
<es:activity>permanent-absence</e:activity>\n\
</es:activities>\n\
</status>\n\
</tuple>\n\
\n</presence>\n");
}
i = eXosip_build_publish(&pub, (char *)from, (char *)from, NULL, "presence", "1800", "application/pidf+xml", buf);
if (i<0)
{
ms_message("Failed to build publish request.");
return -1;
}
eXosip_lock();
i = eXosip_publish(pub, from); /* should update the sip-if-match parameter
from sip-etag from last 200ok of PUBLISH */
eXosip_unlock();
if (i<0)
{
ms_message("Failed to send publish request.");
return -1;
}
return 0;
}
int linphone_core_add_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *cfg){
if (!linphone_proxy_config_check(lc,cfg)) return -1;
lc->sip_conf.proxies=ms_list_append(lc->sip_conf.proxies,(void *)cfg);
linphone_proxy_config_apply(cfg,lc);
return 0;
}
extern void linphone_friend_check_for_removed_proxy(LinphoneFriend *lf, LinphoneProxyConfig *cfg);
void linphone_core_remove_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *cfg){
MSList *elem;
lc->sip_conf.proxies=ms_list_remove(lc->sip_conf.proxies,(void *)cfg);
/* add to the list of destroyed proxies, so that the possible unREGISTER request can succeed authentication */
lc->sip_conf.deleted_proxies=ms_list_append(lc->sip_conf.deleted_proxies,(void *)cfg);
/* this will unREGISTER */
linphone_proxy_config_edit(cfg);
if (lc->default_proxy==cfg){
lc->default_proxy=NULL;
}
/* invalidate all references to this proxy in our friend list */
for (elem=lc->friends;elem!=NULL;elem=ms_list_next(elem)){
linphone_friend_check_for_removed_proxy((LinphoneFriend*)elem->data,cfg);
}
}
void linphone_core_set_default_proxy(LinphoneCore *lc, LinphoneProxyConfig *config){
/* check if this proxy is in our list */
if (config!=NULL){
if (ms_list_find(lc->sip_conf.proxies,config)==NULL){
ms_warning("Bad proxy address: it is not in the list !");
lc->default_proxy=NULL;
return ;
}
}
lc->default_proxy=config;
}
void linphone_core_set_default_proxy_index(LinphoneCore *lc, int index){
if (index<0) linphone_core_set_default_proxy(lc,NULL);
else linphone_core_set_default_proxy(lc,ms_list_nth_data(lc->sip_conf.proxies,index));
}
int linphone_core_get_default_proxy(LinphoneCore *lc, LinphoneProxyConfig **config){
int pos=-1;
if (config!=NULL) *config=lc->default_proxy;
if (lc->default_proxy!=NULL){
pos=ms_list_position(lc->sip_conf.proxies,ms_list_find(lc->sip_conf.proxies,(void *)lc->default_proxy));
}
return pos;
}
static int rid_compare(const void *pcfg,const void *prid){
const LinphoneProxyConfig *cfg=(const LinphoneProxyConfig*)pcfg;
const int *rid=(const int*)prid;
ms_message("cfg= %s, cfg->rid=%i, rid=%i",cfg->reg_proxy, cfg->rid, *rid);
return cfg->rid-(*rid);
}
LinphoneProxyConfig *linphone_core_get_proxy_config_from_rid(LinphoneCore *lc, int rid){
MSList *elem=ms_list_find_custom(lc->sip_conf.proxies,rid_compare, &rid);
if (elem==NULL){
ms_message("linphone_core_get_proxy_config_from_rid: searching in deleted proxies...");
elem=ms_list_find_custom(lc->sip_conf.deleted_proxies,rid_compare, &rid);
}
if (elem==NULL) return NULL;
else return (LinphoneProxyConfig*)elem->data;
}
void linphone_core_retry_proxy_register(LinphoneCore *lc, const char *realm)
{
MSList *elem;
for (elem=lc->sip_conf.proxies;elem!=NULL;elem=ms_list_next(elem)){
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data;
/*ms_message("linphone_core_retry_proxy_register: cfg->auth_pending=%i, cfg->realm=%s, realm=%s",
cfg->auth_pending,cfg->realm,realm);*/
if (cfg->auth_pending && cfg->realm!=NULL && strcmp(cfg->realm,realm)==0){
ms_message("Restarting REGISTER request for %s.",cfg->reg_proxy);
linphone_proxy_config_register(cfg);
}
}
}
const MSList *linphone_core_get_proxy_config_list(const LinphoneCore *lc){
return lc->sip_conf.proxies;
}
void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyConfig *obj, int index)
{
char key[50];
sprintf(key,"proxy_%i",index);
lp_config_clean_section(config,key);
if (obj==NULL){
return;
}
if (obj->reg_proxy!=NULL){
lp_config_set_string(config,key,"reg_proxy",obj->reg_proxy);
}
if (obj->reg_route!=NULL){
lp_config_set_string(config,key,"reg_route",obj->reg_route);
}
if (obj->reg_identity!=NULL){
lp_config_set_string(config,key,"reg_identity",obj->reg_identity);
}
lp_config_set_int(config,key,"reg_expires",obj->expires);
lp_config_set_int(config,key,"reg_sendregister",obj->reg_sendregister);
lp_config_set_int(config,key,"publish",obj->publish);
}
LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LpConfig *config, int index)
{
const char *tmp;
LinphoneProxyConfig *cfg;
char key[50];
sprintf(key,"proxy_%i",index);
if (!lp_config_has_section(config,key)){
return NULL;
}
tmp=lp_config_get_string(config,key,"reg_proxy",NULL);
if (tmp==NULL) return NULL;
cfg=linphone_proxy_config_new();
linphone_proxy_config_set_server_addr(cfg,tmp);
tmp=lp_config_get_string(config,key,"reg_route",NULL);
if (tmp!=NULL) linphone_proxy_config_set_route(cfg,tmp);
tmp=lp_config_get_string(config,key,"reg_identity",NULL);
if (tmp!=NULL) linphone_proxy_config_set_identity(cfg,tmp);
linphone_proxy_config_expires(cfg,lp_config_get_int(config,key,"reg_expires",600));
linphone_proxy_config_enableregister(cfg,lp_config_get_int(config,key,"reg_sendregister",0));
linphone_proxy_config_enable_publish(cfg,lp_config_get_int(config,key,"publish",0));
return cfg;
}

View file

@ -0,0 +1,682 @@
/*
* Linphone is sip (RFC3261) compatible internet phone.
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "sdphandler.h"
#include <osipparser2/osip_port.h>
#include <osipparser2/sdp_message.h>
#include <eXosip2/eXosip.h>
#include "linphonecore.h"
#include "ortp/b64.h"
#define keywordcmp(key,str) strncmp(key,str,strlen(key))
#define sstrdup_sprintf ms_strdup_printf
#define eXosip_trace(loglevel,args) do \
{ \
char *__strmsg; \
__strmsg=ms_strdup_printf args ; \
OSIP_TRACE(osip_trace(__FILE__,__LINE__,(loglevel),NULL,"%s\n",__strmsg)); \
osip_free (__strmsg); \
}while (0);
static char *make_relay_session_id(const char *username, const char *relay){
/*ideally this should be a hash of the parameters with a random part*/
char tmp[128];
int s1=(int)random();
int s2=(int)random();
long long int res=((long long int)s1)<<32 | (long long int) s2;
void *src=&res;
b64_encode(src, sizeof(long long int), tmp, sizeof(tmp));
return osip_strdup(tmp);
}
char * int_2char(int a){
char *p=osip_malloc(16);
snprintf(p,16,"%i",a);
return p;
}
/* return the value of attr "field" for payload pt at line pos (field=rtpmap,fmtp...)*/
char *sdp_message_a_attr_value_get_with_pt(sdp_message_t *sdp,int pos,int pt,const char *field)
{
int i,tmppt=0,scanned=0;
char *tmp;
sdp_attribute_t *attr;
for (i=0;(attr=sdp_message_attribute_get(sdp,pos,i))!=NULL;i++){
if (keywordcmp(field,attr->a_att_field)==0 && attr->a_att_value!=NULL){
int nb = sscanf(attr->a_att_value,"%i %n",&tmppt,&scanned);
/* the return value may depend on how %n is interpreted by the libc: see manpage*/
if (nb == 1 || nb==2 ){
if (pt==tmppt){
tmp=attr->a_att_value+scanned;
if (strlen(tmp)>0)
return tmp;
}
}else eXosip_trace(OSIP_WARNING,("sdp has a strange a= line (%s) nb=%i",attr->a_att_value,nb));
}
}
return NULL;
}
/* return the value of attr "field" */
char *sdp_message_a_attr_value_get(sdp_message_t *sdp,int pos,const char *field)
{
int i;
sdp_attribute_t *attr;
for (i=0;(attr=sdp_message_attribute_get(sdp,pos,i))!=NULL;i++){
if (keywordcmp(field,attr->a_att_field)==0 && attr->a_att_value!=NULL){
return attr->a_att_value;
}
}
return NULL;
}
static int _sdp_message_get_a_ptime(sdp_message_t *sdp, int mline){
int i,ret;
sdp_attribute_t *attr;
for (i=0;(attr=sdp_message_attribute_get(sdp,mline,i))!=NULL;i++){
if (keywordcmp("ptime",attr->a_att_field)==0){
int nb = sscanf(attr->a_att_value,"%i",&ret);
/* the return value may depend on how %n is interpreted by the libc: see manpage*/
if (nb == 1){
return ret;
}else eXosip_trace(OSIP_WARNING,("sdp has a strange a=ptime line (%s) ",attr->a_att_value));
}
}
return 0;
}
int
sdp_payload_init (sdp_payload_t * payload)
{
memset (payload, 0, sizeof (sdp_payload_t));
return 0;
}
sdp_context_t *sdp_handler_create_context(sdp_handler_t *handler, const char *localip, const char *username, const char *relay){
sdp_context_t *ctx=osip_malloc(sizeof(sdp_context_t));
memset(ctx,0,sizeof(sdp_context_t));
if (localip!=NULL) ctx->localip=osip_strdup(localip);
ctx->username=osip_strdup(username);
ctx->handler=handler;
if (relay){
ctx->relay=osip_strdup(relay);
ctx->relay_session_id=make_relay_session_id(username,relay);
}
return ctx;
}
void sdp_context_set_user_pointer(sdp_context_t * ctx, void* up){
ctx->reference=up;
}
void *sdp_context_get_user_pointer(sdp_context_t * ctx){
return ctx->reference;
}
int sdp_context_get_status(sdp_context_t* ctx){
return ctx->negoc_status;
}
/* generate a template sdp */
sdp_message_t *
sdp_context_generate_template (sdp_context_t * ctx)
{
sdp_message_t *local;
int inet6;
sdp_message_init (&local);
if (strchr(ctx->localip,':')!=NULL){
inet6=1;
}else inet6=0;
if (!inet6){
sdp_message_v_version_set (local, osip_strdup ("0"));
sdp_message_o_origin_set (local, osip_strdup (ctx->username),
osip_strdup ("123456"), osip_strdup ("654321"),
osip_strdup ("IN"), osip_strdup ("IP4"),
osip_strdup (ctx->localip));
sdp_message_s_name_set (local, osip_strdup ("A conversation"));
sdp_message_c_connection_add (local, -1,
osip_strdup ("IN"), osip_strdup ("IP4"),
osip_strdup (ctx->localip), NULL, NULL);
sdp_message_t_time_descr_add (local, osip_strdup ("0"), osip_strdup ("0"));
}else{
sdp_message_v_version_set (local, osip_strdup ("0"));
sdp_message_o_origin_set (local, osip_strdup (ctx->username),
osip_strdup ("123456"), osip_strdup ("654321"),
osip_strdup ("IN"), osip_strdup ("IP6"),
osip_strdup (ctx->localip));
sdp_message_s_name_set (local, osip_strdup ("A conversation"));
sdp_message_c_connection_add (local, -1,
osip_strdup ("IN"), osip_strdup ("IP6"),
osip_strdup (ctx->localip), NULL, NULL);
sdp_message_t_time_descr_add (local, osip_strdup ("0"), osip_strdup ("0"));
}
return local;
}
static void add_relay_info(sdp_message_t *sdp, int mline, const char *relay, const char *relay_session_id){
if (relay) sdp_message_a_attribute_add(sdp, mline,
osip_strdup ("relay-addr"),osip_strdup(relay));
if (relay_session_id) sdp_message_a_attribute_add(sdp, mline,
osip_strdup ("relay-session-id"), osip_strdup(relay_session_id));
}
/* to add payloads to the offer, must be called inside the write_offer callback */
void
sdp_context_add_payload (sdp_context_t * ctx, sdp_payload_t * payload, char *media)
{
sdp_message_t *offer = ctx->offer;
char *attr_field;
if (!ctx->incb)
{
eXosip_trace (OSIP_ERROR,
("You must not call sdp_context_add_*_payload outside the write_offer callback\n"));
abort ();
}
if (payload->proto == NULL)
payload->proto = "RTP/AVP";
/*printf("payload->line=%i payload->pt=%i\n",payload->line, payload->pt);*/
if (sdp_message_m_media_get (offer, payload->line) == NULL)
{
/*printf("Adding new mline %s \n",media);*/
/* need a new line */
sdp_message_m_media_add (offer, osip_strdup (media),
int_2char (payload->localport), NULL,
osip_strdup (payload->proto));
if (ctx->relay){
add_relay_info(offer,payload->line,ctx->relay,ctx->relay_session_id);
}
}
sdp_message_m_payload_add (offer, payload->line, int_2char (payload->pt));
if (payload->a_rtpmap != NULL)
{
attr_field =
sstrdup_sprintf ("%i %s", payload->pt,
payload->a_rtpmap);
sdp_message_a_attribute_add (offer, payload->line,
osip_strdup ("rtpmap"), attr_field);
}
if (payload->a_fmtp != NULL)
{
attr_field =
sstrdup_sprintf ("%i %s", payload->pt,
payload->a_fmtp);
sdp_message_a_attribute_add (offer, payload->line, osip_strdup ("fmtp"),
attr_field);
}
if (payload->b_as_bandwidth != 0)
{
if (sdp_message_bandwidth_get(offer,payload->line,0)==NULL){
attr_field =
sstrdup_sprintf ("%i", payload->b_as_bandwidth);
sdp_message_b_bandwidth_add (offer, payload->line, osip_strdup ("AS"),
attr_field);
}
}
}
void
sdp_context_add_audio_payload (sdp_context_t * ctx, sdp_payload_t * payload)
{
sdp_context_add_payload (ctx, payload, "audio");
}
void
sdp_context_add_video_payload (sdp_context_t * ctx, sdp_payload_t * payload)
{
sdp_context_add_payload (ctx, payload, "video");
}
char *
sdp_context_get_offer ( sdp_context_t * ctx)
{
sdp_message_t *offer;
sdp_handler_t *sdph=ctx->handler;
char *tmp;
offer = sdp_context_generate_template (ctx);
/* add audio codecs */
ctx->offer = offer;
ctx->incb = 1;
if (sdph->set_audio_codecs != NULL)
sdph->set_audio_codecs (ctx);
if (sdph->set_video_codecs != NULL)
sdph->set_video_codecs (ctx);
ctx->incb = 0;
sdp_message_to_str(offer,&tmp);
ctx->offerstr=tmp;
return tmp;
}
/* refuse the line */
static void refuse_mline(sdp_message_t *answer,char *mtype,char *proto, int mline)
{
sdp_message_m_media_add (answer,
osip_strdup (mtype),
int_2char (0), NULL,
osip_strdup (proto));
/* add a payload just to comply with sdp RFC.*/
sdp_message_m_payload_add(answer,mline,int_2char(0));
}
static char * parse_relay_addr(char *addr, int *port)
{
char *semicolon=NULL;
char *p;
*port=56789;
semicolon=strchr(addr,':');
for (p=addr+strlen(addr)-1;p>addr;p--){
if (*p==':') {
semicolon=p;
break;
}
}
if (semicolon){
*port=atoi(semicolon+1);
*semicolon='\0';
}
return addr;
}
char *
sdp_context_get_answer ( sdp_context_t *ctx,sdp_message_t *remote)
{
sdp_message_t *answer=NULL;
char *mtype=NULL, *tmp=NULL;
char *proto=NULL, *port=NULL, *pt=NULL;
int i, j, ncodec, m_lines_accepted = 0;
int err;
sdp_payload_t payload;
sdp_handler_t *sdph=ctx->handler;
sdp_bandwidth_t *sbw=NULL;
char *relay;
tmp = sdp_message_c_addr_get (remote, 0, 0);
if (tmp == NULL)
tmp = sdp_message_c_addr_get (remote, -1, 0);
if (ctx->localip==NULL) {
/* NULL means guess, otherwise we use the address given as localip */
ctx->localip=osip_malloc(128);
eXosip_guess_localip(strchr(tmp,':') ? AF_INET6 : AF_INET,ctx->localip,128);
}
else eXosip_trace(OSIP_INFO1,("Using firewall address in sdp."));
answer = sdp_context_generate_template (ctx);
/* for each m= line */
for (i = 0; !sdp_message_endof_media (remote, i); i++)
{
sdp_payload_init(&payload);
mtype = sdp_message_m_media_get (remote, i);
proto = sdp_message_m_proto_get (remote, i);
port = sdp_message_m_port_get (remote, i);
payload.remoteport = osip_atoi (port);
payload.proto = proto;
payload.line = i;
payload.c_addr = sdp_message_c_addr_get (remote, i, 0);
if (payload.c_addr == NULL)
payload.c_addr = sdp_message_c_addr_get (remote, -1, 0);
/*parse relay address if given*/
relay=sdp_message_a_attr_value_get(remote,i,"relay-addr");
if (relay){
payload.relay_host=parse_relay_addr(relay,&payload.relay_port);
}
payload.relay_session_id=sdp_message_a_attr_value_get(remote,i,"relay-session-id");
/* get application specific bandwidth, if any */
for(j=0;(sbw=sdp_message_bandwidth_get(remote,i,j))!=NULL;j++){
if (strcasecmp(sbw->b_bwtype,"AS")==0) payload.b_as_bandwidth=atoi(sbw->b_bandwidth);
}
payload.a_ptime=_sdp_message_get_a_ptime(remote,i);
if (keywordcmp ("audio", mtype) == 0)
{
if (sdph->accept_audio_codecs != NULL)
{
ncodec = 0;
/* for each payload type */
for (j = 0;
((pt =
sdp_message_m_payload_get (remote, i,
j)) != NULL); j++)
{
payload.pt = osip_atoi (pt);
/* get the rtpmap associated to this codec, if any */
payload.a_rtpmap =
sdp_message_a_attr_value_get_with_pt
(remote, i, payload.pt,
"rtpmap");
/* get the fmtp, if any */
payload.a_fmtp =
sdp_message_a_attr_value_get_with_pt
(remote, i, payload.pt,
"fmtp");
/* ask the application if this codec is supported */
err = sdph->accept_audio_codecs (ctx,
&payload);
if (err == 0 && payload.localport > 0)
{
ncodec++;
/* codec accepted */
if (ncodec == 1)
{
/* first codec accepted, setup the line */
sdp_message_m_media_add
(answer,
osip_strdup
(mtype),
int_2char
(payload.
localport),
NULL,
osip_strdup
(proto));
/* and accept the remote relay addr if we planned to use our own */
if (ctx->relay!=NULL && relay){
add_relay_info(answer,i,relay,payload.relay_session_id);
}
}
/* add the payload, rtpmap, fmtp */
sdp_message_m_payload_add (answer, i,
int_2char
(payload.
pt));
if (payload.a_rtpmap != NULL)
{
sdp_message_a_attribute_add
(answer, i,
osip_strdup
("rtpmap"),
sstrdup_sprintf
("%i %s",
payload.pt,
payload.
a_rtpmap));
}
if (payload.a_fmtp != NULL)
{
sdp_message_a_attribute_add
(answer, i,
osip_strdup
("fmtp"),
sstrdup_sprintf
("%i %s",
payload.pt,
payload.
a_fmtp));
}
if (payload.b_as_bandwidth !=
0)
{
if (sdp_message_bandwidth_get(answer,i,0)==NULL)
sdp_message_b_bandwidth_add
(answer, i,
osip_strdup
("AS"),
sstrdup_sprintf
("%i",
payload.
b_as_bandwidth));
}
}
}
if (ncodec == 0)
{
/* refuse the line */
refuse_mline(answer,mtype,proto,i);
}
else
m_lines_accepted++;
}
else
{
/* refuse this line (leave port to 0) */
refuse_mline(answer,mtype,proto,i);
}
}
else if (keywordcmp ("video", mtype) == 0)
{
if (sdph->accept_video_codecs != NULL)
{
ncodec = 0;
/* for each payload type */
for (j = 0;
((pt =
sdp_message_m_payload_get (remote, i,
j)) != NULL); j++)
{
payload.pt = osip_atoi (pt);
/* get the rtpmap associated to this codec, if any */
payload.a_rtpmap =
sdp_message_a_attr_value_get_with_pt
(remote, i, payload.pt,
"rtpmap");
/* get the fmtp, if any */
payload.a_fmtp =
sdp_message_a_attr_value_get_with_pt
(remote, i, payload.pt,
"fmtp");
/* ask the application if this codec is supported */
err = sdph->accept_video_codecs (ctx,
&payload);
if (err == 0 && payload.localport > 0)
{
ncodec++;
/* codec accepted */
if (ncodec == 1)
{
/* first codec accepted, setup the line */
sdp_message_m_media_add
(answer,
osip_strdup
(mtype),
int_2char
(payload.localport), NULL,
osip_strdup
(proto));
/* and accept the remote relay addr if we planned to use our own */
if (ctx->relay!=NULL && relay){
add_relay_info(answer,i,relay,payload.relay_session_id);
}
}
/* add the payload, rtpmap, fmtp */
sdp_message_m_payload_add (answer, i,
int_2char
(payload.
pt));
if (payload.a_rtpmap != NULL)
{
sdp_message_a_attribute_add
(answer, i,
osip_strdup
("rtpmap"),
sstrdup_sprintf
("%i %s",
payload.pt,
payload.
a_rtpmap));
}
if (payload.a_fmtp != NULL)
{
sdp_message_a_attribute_add
(answer, i,
osip_strdup
("fmtp"),
sstrdup_sprintf
("%i %s",
payload.pt,
payload.
a_fmtp));
}
if (payload.b_as_bandwidth !=0)
{
if (sdp_message_bandwidth_get(answer,i,0)==NULL)
sdp_message_b_bandwidth_add
(answer, i,
osip_strdup
("AS"),
sstrdup_sprintf
("%i",
payload.
b_as_bandwidth));
}
}
}
if (ncodec == 0)
{
/* refuse the line */
refuse_mline(answer,mtype,proto,i);
}
else
m_lines_accepted++;
}
else
{
/* refuse the line */
refuse_mline(answer,mtype,proto,i);
}
}
}
if (ctx->answer!=NULL)
sdp_message_free(ctx->answer);
ctx->answer = answer;
if (m_lines_accepted > 0){
ctx->negoc_status = 200;
sdp_message_to_str(answer,&tmp);
if (ctx->answerstr!=NULL)
osip_free(ctx->answerstr);
ctx->answerstr=tmp;
return tmp;
}else{
ctx->negoc_status = 415;
return NULL;
}
}
void
sdp_context_read_answer (sdp_context_t *ctx, sdp_message_t *remote)
{
char *mtype;
char *proto, *port, *pt;
int i, j,err;
char *relay;
sdp_payload_t payload,arg_payload;
sdp_handler_t *sdph=ctx->handler;
sdp_bandwidth_t *sbw=NULL;
/* for each m= line */
for (i = 0; !sdp_message_endof_media (remote, i); i++)
{
sdp_payload_init(&payload);
mtype = sdp_message_m_media_get (remote, i);
proto = sdp_message_m_proto_get (remote, i);
port = sdp_message_m_port_get (remote, i);
payload.remoteport = osip_atoi (port);
payload.localport = osip_atoi (sdp_message_m_port_get (ctx->offer, i));
payload.proto = proto;
payload.line = i;
payload.c_addr = sdp_message_c_addr_get (remote, i, 0);
if (payload.c_addr == NULL)
payload.c_addr = sdp_message_c_addr_get (remote, -1, 0);
/*parse relay address if given*/
relay=sdp_message_a_attr_value_get(remote,i,"relay-addr");
if (relay){
payload.relay_host=parse_relay_addr(relay,&payload.relay_port);
}
payload.relay_session_id=sdp_message_a_attr_value_get(remote,i,"relay-session-id");
for(j=0;(sbw=sdp_message_bandwidth_get(remote,i,j))!=NULL;++j){
if (strcasecmp(sbw->b_bwtype,"AS")==0) payload.b_as_bandwidth=atoi(sbw->b_bandwidth);
}
payload.a_ptime=_sdp_message_get_a_ptime(remote,i);
if (keywordcmp ("audio", mtype) == 0)
{
if (sdph->get_audio_codecs != NULL)
{
/* for each payload type */
for (j = 0;
((pt =
sdp_message_m_payload_get (remote, i,
j)) != NULL); j++)
{
payload.pt = osip_atoi (pt);
/* get the rtpmap associated to this codec, if any */
payload.a_rtpmap =
sdp_message_a_attr_value_get_with_pt
(remote, i, payload.pt,
"rtpmap");
/* get the fmtp, if any */
payload.a_fmtp =
sdp_message_a_attr_value_get_with_pt
(remote, i, payload.pt,
"fmtp");
/* ask the application if this codec is supported */
memcpy(&arg_payload,&payload,sizeof(payload));
err = sdph->get_audio_codecs (ctx,
&arg_payload);
}
}
}
else if (keywordcmp ("video", mtype) == 0)
{
if (sdph->get_video_codecs != NULL)
{
/* for each payload type */
for (j = 0;
((pt =
sdp_message_m_payload_get (remote, i,
j)) != NULL); j++)
{
payload.pt = osip_atoi (pt);
/* get the rtpmap associated to this codec, if any */
payload.a_rtpmap =
sdp_message_a_attr_value_get_with_pt
(remote, i, payload.pt,
"rtpmap");
/* get the fmtp, if any */
payload.a_fmtp =
sdp_message_a_attr_value_get_with_pt
(remote, i, payload.pt,
"fmtp");
/* ask the application if this codec is supported */
memcpy(&arg_payload,&payload,sizeof(payload));
err = sdph->get_video_codecs (ctx,
&arg_payload);
}
}
}
}
}
void sdp_context_free(sdp_context_t *ctx){
osip_free(ctx->localip);
osip_free(ctx->username);
if (ctx->offer!=NULL) sdp_message_free(ctx->offer);
if (ctx->answer!=NULL) sdp_message_free(ctx->answer);
if (ctx->offerstr!=NULL) osip_free(ctx->offerstr);
if (ctx->answerstr!=NULL) osip_free(ctx->answerstr);
if (ctx->relay!=NULL) osip_free(ctx->relay);
if (ctx->relay_session_id!=NULL) osip_free(ctx->relay_session_id);
osip_free(ctx);
}

View file

@ -0,0 +1,101 @@
/*
* Linphone is sip (RFC3261) compatible internet phone.
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef SDP_HANDLER_H
#define SDP_HANDLER_H
#include <osipparser2/sdp_message.h>
#include "linphonecore.h"
typedef struct _sdp_payload
{
int line; /* the index of the m= line */
int pt; /*payload type */
int localport;
int remoteport;
int b_as_bandwidth; /* application specific bandwidth */
char *proto;
char *c_nettype;
char *c_addrtype;
char *c_addr;
char *c_addr_multicast_ttl;
char *c_addr_multicast_int;
char *a_rtpmap;
char *a_fmtp;
char *relay_host;
int relay_port;
char *relay_session_id;
int a_ptime;
} sdp_payload_t;
typedef struct _sdp_context sdp_context_t;
typedef int (*sdp_handler_read_codec_func_t) (struct _sdp_context *,
sdp_payload_t *);
typedef int (*sdp_handler_write_codec_func_t) (struct _sdp_context *);
typedef struct _sdp_handler
{
sdp_handler_read_codec_func_t accept_audio_codecs; /*from remote sdp */
sdp_handler_read_codec_func_t accept_video_codecs; /*from remote sdp */
sdp_handler_write_codec_func_t set_audio_codecs; /*to local sdp */
sdp_handler_write_codec_func_t set_video_codecs; /*to local sdp */
sdp_handler_read_codec_func_t get_audio_codecs; /*from incoming answer */
sdp_handler_read_codec_func_t get_video_codecs; /*from incoming answer */
} sdp_handler_t;
typedef enum _sdp_context_state
{
SDP_CONTEXT_STATE_INIT,
SDP_CONTEXT_STATE_NEGOCIATION_OPENED,
SDP_CONTEXT_STATE_NEGOCIATION_CLOSED
} sdp_context_state_t;
struct _sdp_context
{
sdp_handler_t *handler;
char *localip;
char *username;
void *reference;
sdp_message_t *offer; /* the local sdp to be used for outgoing request */
char *offerstr;
sdp_message_t *answer; /* the local sdp generated from an inc request */
char *answerstr;
char *relay;
char *relay_session_id;
int negoc_status; /* in sip code */
int incb;
sdp_context_state_t state;
};
/* create a context for a sdp negociation: localip is the ip address to be used in the sdp message, can
be a firewall address.
It can be null when negociating for an incoming offer; In that case it will be guessed. */
sdp_context_t *sdp_handler_create_context(sdp_handler_t *handler, const char *localip, const char *username, const char *relay);
void sdp_context_set_user_pointer(sdp_context_t * ctx, void* up);
void *sdp_context_get_user_pointer(sdp_context_t * ctx);
void sdp_context_add_audio_payload( sdp_context_t * ctx, sdp_payload_t * payload);
void sdp_context_add_video_payload( sdp_context_t * ctx, sdp_payload_t * payload);
char * sdp_context_get_offer(sdp_context_t *ctx);
char * sdp_context_get_answer(sdp_context_t* ctx, sdp_message_t *remote_offer);
int sdp_context_get_status(sdp_context_t* ctx);
void sdp_context_read_answer(sdp_context_t *ctx, sdp_message_t *remote_answer);
void sdp_context_free(sdp_context_t *ctx);
int sdp_payload_init (sdp_payload_t * payload);
#endif

View file

@ -0,0 +1,2 @@
Makefile
Makefile.in

View file

@ -0,0 +1,15 @@
EXTRA_DIST= copyright dirs manpage.sgml.ex rules \
control docs manpage.1.ex menu watch.ex changelog
changelog: changelog.stamp
echo -n -e "linphone (">changelog
echo -n -e $(VERSION)>>changelog
echo -n -e "-1) unstable; urgency=low\n\n">>changelog
echo -n -e " * New Release.\n\n">>changelog
echo -n -e " -- Simon Morlat <simon.morlat@linphone.org> ">>changelog
date -R >>changelog
touch changelog.stamp
changelog.stamp:
touch changelog.stamp

14
linphone/debian/control Normal file
View file

@ -0,0 +1,14 @@
Source: linphone
Section: sound
Priority: optional
Maintainer: Uwe Steinmann <uwe@steinmann.cx>
Build-Depends: debhelper (>> 3.0.0), libosip0-dev (>= 0.9.6), libasound2-dev (>=0.9.4)
Standards-Version: 3.5.2
Package: linphone
Architecture: any
Depends: ${shlibs:Depends}, libosip0 (>= 0.9.6), libspeex1, libasound2 (>=0.9.4)
Description: A sip phone
Linphone is a web phone: it let you phone to your friends anywhere in the
whole world, freely, simply by using the internet. It is compatible with the
well known SIP protocol.

10
linphone/debian/copyright Normal file
View file

@ -0,0 +1,10 @@
This package was debianized by Uwe Steinmann <uwe@steinmann.cx> on
Thu, 28 Feb 2002 08:29:57 +0100.
It was downloaded from http://www.linphone.org
Upstream Author(s): Simon Morlat <simon.morlat@linphone.org>
Copyright:
GPL

2
linphone/debian/dirs Normal file
View file

@ -0,0 +1,2 @@
usr/bin
usr/sbin

3
linphone/debian/docs Normal file
View file

@ -0,0 +1,3 @@
BUGS
NEWS
README

View file

@ -0,0 +1,60 @@
.\" Hey, EMACS: -*- nroff -*-
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
.TH LINPHONE SECTION "February 28, 2002"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
.\" .nh disable hyphenation
.\" .hy enable hyphenation
.\" .ad l left justify
.\" .ad b justify to both left and right margins
.\" .nf disable filling
.\" .fi enable filling
.\" .br insert line break
.\" .sp <n> insert n+1 empty lines
.\" for manpage-specific macros, see man(7)
.SH NAME
linphone \- program to do something
.SH SYNOPSIS
.B linphone
.RI [ options ] " files" ...
.br
.B bar
.RI [ options ] " files" ...
.SH DESCRIPTION
This manual page documents briefly the
.B linphone
and
.B bar
commands.
This manual page was written for the Debian distribution
because the original program does not have a manual page.
Instead, it has documentation in the GNU Info format; see below.
.PP
.\" TeX users may be more comfortable with the \fB<whatever>\fP and
.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
.\" respectively.
\fBlinphone\fP is a program that...
.SH OPTIONS
These programs follow the usual GNU command line syntax, with long
options starting with two dashes (`-').
A summary of options is included below.
For a complete description, see the Info files.
.TP
.B \-h, \-\-help
Show summary of options.
.TP
.B \-v, \-\-version
Show version of program.
.SH SEE ALSO
.BR bar (1),
.BR baz (1).
.br
The programs are documented fully by
.IR "The Rise and Fall of a Fooish Bar" ,
available via the Info system.
.SH AUTHOR
This manual page was written by Uwe Steinmann <uwe@steinmann.cx>,
for the Debian GNU/Linux system (but may be used by others).

View file

@ -0,0 +1,152 @@
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [
<!-- Process this file with docbook-to-man to generate an nroff manual
page: `docbook-to-man manpage.sgml > manpage.1'. You may view
the manual page with: `docbook-to-man manpage.sgml | nroff -man |
less'. A typical entry in a Makefile or Makefile.am is:
manpage.1: manpage.sgml
docbook-to-man $< > $@
The docbook-to-man binary is found in the docbook-to-man package.
Please remember that if you create the nroff version in one of the
debian/rules file targets (such as build), you will need to include
docbook-to-man in your Build-Depends control field.
-->
<!-- Fill in your name for FIRSTNAME and SURNAME. -->
<!ENTITY dhfirstname "<firstname>FIRSTNAME</firstname>">
<!ENTITY dhsurname "<surname>SURNAME</surname>">
<!-- Please adjust the date whenever revising the manpage. -->
<!ENTITY dhdate "<date>February 28, 2002</date>">
<!-- SECTION should be 1-8, maybe w/ subsection other parameters are
allowed: see man(7), man(1). -->
<!ENTITY dhsection "<manvolnum>SECTION</manvolnum>">
<!ENTITY dhemail "<email>uwe@steinmann.cx</email>">
<!ENTITY dhusername "Uwe Steinmann">
<!ENTITY dhucpackage "<refentrytitle>LINPHONE</refentrytitle>">
<!ENTITY dhpackage "linphone">
<!ENTITY debian "<productname>Debian</productname>">
<!ENTITY gnu "<acronym>GNU</acronym>">
]>
<refentry>
<refentryinfo>
<address>
&dhemail;
</address>
<author>
&dhfirstname;
&dhsurname;
</author>
<copyright>
<year>2001</year>
<holder>&dhusername;</holder>
</copyright>
&dhdate;
</refentryinfo>
<refmeta>
&dhucpackage;
&dhsection;
</refmeta>
<refnamediv>
<refname>&dhpackage;</refname>
<refpurpose>program to do something</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>&dhpackage;</command>
<arg><option>-e <replaceable>this</replaceable></option></arg>
<arg><option>--example <replaceable>that</replaceable></option></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>DESCRIPTION</title>
<para>This manual page documents briefly the
<command>&dhpackage;</command> and <command>bar</command>
commands.</para>
<para>This manual page was written for the &debian; distribution
because the original program does not have a manual page.
Instead, it has documentation in the &gnu;
<application>Info</application> format; see below.</para>
<para><command>&dhpackage;</command> is a program that...</para>
</refsect1>
<refsect1>
<title>OPTIONS</title>
<para>These programs follow the usual GNU command line syntax,
with long options starting with two dashes (`-'). A summary of
options is included below. For a complete description, see the
<application>Info</application> files.</para>
<variablelist>
<varlistentry>
<term><option>-h</option>
<option>--help</option>
</term>
<listitem>
<para>Show summary of options.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-v</option>
<option>--version</option>
</term>
<listitem>
<para>Show version of program.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>SEE ALSO</title>
<para>bar (1), baz (1).</para>
<para>The programs are documented fully by <citetitle>The Rise and
Fall of a Fooish Bar</citetitle> available via the
<application>Info</application> system.</para>
</refsect1>
<refsect1>
<title>AUTHOR</title>
<para>This manual page was written by &dhusername; &dhemail; for
the &debian; system (but may be used by others). Permission is
granted to copy, distribute and/or modify this document under
the terms of the <acronym>GNU</acronym> Free Documentation
License, Version 1.1 or any later version published by the Free
Software Foundation; with no Invariant Sections, no Front-Cover
Texts and no Back-Cover Texts.</para>
</refsect1>
</refentry>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:2
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:nil
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
-->

3
linphone/debian/menu Normal file
View file

@ -0,0 +1,3 @@
?package(linphone):needs=X11 section=Apps/Net \
title="Linphone" command="/usr/bin/linphone" hints="Telephony"\
icon="/usr/share/pixmaps/linphone/linphone2.xpm"

107
linphone/debian/rules Executable file
View file

@ -0,0 +1,107 @@
#!/usr/bin/make -f
# Sample debian/rules that uses debhelper.
# GNU copyright 1997 to 1999 by Joey Hess.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
# This is the debhelper compatibility version to use.
export DH_COMPAT=3
# These are used for cross-compiling and for saving the configure script
# from having to guess our platform (since we know it already)
DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS)))
CFLAGS += -g
endif
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
INSTALL_PROGRAM += -s
endif
configure: configure-stamp
configure-stamp:
dh_testdir
# Add here commands to configure the package.
./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --disable-static --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info --sysconfdir=/etc
touch configure-stamp
build: build-stamp
build-stamp: configure-stamp
dh_testdir
# Add here commands to compile the package.
$(MAKE)
#/usr/bin/docbook-to-man debian/linphone.sgml > linphone.1
touch build-stamp
clean:
dh_testdir
dh_testroot
rm -f build-stamp configure-stamp
# Add here commands to clean up after the build process.
-make clean
-make distclean
-test -r /usr/share/misc/config.sub && \
-cp -f /usr/share/misc/config.sub config.sub
-test -r /usr/share/misc/config.guess && \
-cp -f /usr/share/misc/config.guess config.guess
dh_clean
install: build
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
# Add here commands to install the package into debian/linphone.
$(MAKE) install PIXDESTDIR=$(CURDIR)/debian/linphone prefix=$(CURDIR)/debian/linphone/usr sysconfdir=$(CURDIR)/debian/linphone/etc
# remove speex libs, in order to not to conflict with speex debian package.
rm -f $(CURDIR)/debian/linphone/usr/lib/libspeex* \
$(CURDIR)/debian/linphone/usr/bin/speex* \
$(CURDIR)/debian/linphone/usr/include/speex* \
$(CURDIR)/debian/linphone/usr/share/man/man1/speex*
# Build architecture-independent files here.
binary-indep: build install
# We have nothing to do by default.
# Build architecture-dependent files here.
binary-arch: build install
dh_testdir
dh_testroot
# dh_installdebconf
dh_installdocs
dh_installexamples
dh_installmenu
# dh_installlogrotate
# dh_installemacsen
# dh_installpam
# dh_installmime
# dh_installinit
dh_installcron
dh_installman
dh_installinfo
# dh_undocumented
dh_installchangelogs ChangeLog
dh_link
dh_strip
dh_compress
dh_fixperms
# dh_makeshlibs
dh_installdeb
# dh_perl
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install configure

5
linphone/debian/watch.ex Normal file
View file

@ -0,0 +1,5 @@
# Example watch control file for uscan
# Rename this file to "watch" and then you can run the "uscan" command
# to check for upstream updates and more.
# Site Directory Pattern Version Script
sunsite.unc.edu /pub/Linux/Incoming linphone-(.*)\.tar\.gz debian uupdate

View file

@ -0,0 +1,2 @@
Makefile
Makefile.in

View file

@ -0,0 +1,2 @@
Makefile.in
Makefile

View file

@ -0,0 +1,6 @@
.deps
.libs
Makefile
Makefile.in
*.lo
*.la

View file

@ -0,0 +1,16 @@
noinst_LTLIBRARIES = libeXosip.la
AM_CFLAGS = $(EXOSIP_CFLAGS)
libeXosip_la_SOURCES = eXosip.c \
jrequest.c jresponse.c jcallback.c jdialog.c udp.c \
jcall.c jreg.c jfreinds.c jidentity.c eXutils.c \
jnotify.c jsubscribers.c jsubscribe.c jevents.c \
sdp_offans.c misc.c eXosip2.h \
jpipe.c jpipe.h jauth.c jpublish.c \
eXosip.h eXosip_cfg.h
libeXosip_la_LIBADD = $(EXOSIP_LIBS)
INCLUDES = -I$(top_srcdir)

3192
linphone/exosip/eXosip.c Normal file

File diff suppressed because it is too large Load diff

752
linphone/exosip/eXosip.h Normal file
View file

@ -0,0 +1,752 @@
/*
eXosip - This is the eXtended osip library.
Copyright (C) 2002, 2003 Aymeric MOIZARD - jack@atosc.org
eXosip is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
eXosip is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef ENABLE_MPATROL
#include <mpatrol.h>
#endif
#ifndef __EXOSIP_H__
#define __EXOSIP_H__
#include <osipparser2/osip_parser.h>
#include <osip2/osip_negotiation.h>
#include <time.h>
/**
* @file eXosip.h
* @brief eXosip API
*
* eXosip is a high layer library for rfc3261: the SIP protocol.
* It has limited API and functionnalities to make it easy to use.
* If you need complexity in your SIP applications, you may prefer
* to use directly osip.
*
* eXosip capabilities:
* REGISTER to handle mobility.
* INVITE/BYE/OPTIONS to start/stop VoIP sessions.
* re-INVITE to modify VoIP sessions (On-hold/Off-hold)
* MESSAGE to send Instant Message.
* SUBSCRIBE/NOTIFY to handle presence capabilities.
*
* <P>
*/
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @defgroup eXosip eXosip Management
* @ingroup eXosip
* @{
*/
/**
* Use IPv6 instead of IPv4.
*
* @param ipv6_enable This paramter should be set to 1 to enable IPv6.
*/
void eXosip_enable_ipv6(int ipv6_enable);
/**
* Initiate the eXtented oSIP library.
*
* @param input command input (RESERVED FOR FUTUR USE).
* @param output resulting output (RESERVED FOR FUTUR USE).
* @param port The SIP port to use. (5060 is the default)
*/
int eXosip_init(FILE *input, FILE *output, int port);
/**
* Force eXosip to use a specific local ip address in all its SIP message.
*
* @param localip the ip address.
*
* If set to NULL, then the local ip address will be guessed
* automatically (returns to default mode).
*/
int eXosip_force_localip(const char *localip);
/**
* Release ressource used by the eXtented oSIP library.
*
*/
void eXosip_quit(void);
/**
* Automatic refresh of subscription and register
* send subscribe refresh when subscription is close to expiration.
* send register refresh when registration is close to expiration.
*
*/
void eXosip_automatic_refresh(void);
/**
* Wake Up the eXosip_event_wait method.
*
*/
void __eXosip_wakeup_event(void);
/**
* This method is used to modify the sdp connection address
* When you are behind a NAT. (EXPERIMENTAL)
*
*/
void eXosip_set_firewallip(const char *firewall_address);
/**
* This method is used to modify NAT firewall type
* When you are behind a NAT. (EXPERIMENTAL)
* @param nat type ("", "fcone", "rcone", "prcone", "sym")
*/
void eXosip_set_nattype(const char *nat_type);
/**
* This method is used to force ALL SIP packets to go through given proxy
* @param proxyurl - when empty disable forced proxy behaviour
*/
void eXosip_force_proxy(const char *proxyurl);
/**
* This method is used to set contact header on answers which establishes dialogs
* @param contacturl - the url to use for conatct SIP header,
* when empty - the contact header will be generated from 'to'
* header of the incoming request
*/
void eXosip_set_answer_contact(const char *contacturl);
/**
* This method is used to build a contact header for SIP packets
* @param url url from wich username part will be extracted
* @param strbuf buffer where the result will be stored
* @param bufsize size of the 'strbuf'
* @param public_net when TRUE use firewall ip (if defined) as hostname part
* else use local host ip
*
*/
void eXosip_guess_contact_uri(const char *url, char *strbuf, int bufsize, int public_net);
/**
* Find the current localip (interface with default route).
* ****DEPRECATED**** Use eXosip_guess_localip
*
* @param ip a string containing the local IP address.
*/
void eXosip_get_localip(char *ip);
/**
* Find the current localip (interface with default route).
*
* @param family AF_INET or AF_INET6
* @param address a string containing the local IP address.
* @param size The size of the string
*/
int eXosip_guess_localip(int family, char *address, int size);
/**
* Find the interface to be used to reach the specified host.
*
* @param ip a string containing the local IP address.
* @param localip the local ip address to be used to reach host.
*
* You usually don't need this function at all.
*/
void eXosip_get_localip_for(char *host, char **localip);
/**
* Add authentication credentials. These are used when an outgoing
* request comes back with an authorization required response.
*
* @param username username
* @param userid not sure what this is for
* @param passwd password
* @param ha1 currently ignored
* @param realm realm within which credentials apply, or NULL
* to apply credentials to unrecognized realms
*/
int eXosip_add_authentication_info(const char *username, const char *userid,
const char *passwd, const char *ha1,
const char *realm);
/**
* Clear all authentication credentials stored in eXosip.
*
*/
int eXosip_clear_authentication_info(void);
/**
* Remove an audio payload.
*
*/
void eXosip_sdp_negotiation_remove_audio_payloads(void);
/**
* Remove an audio payload.
*
* @param payload The payload
* @param number_of_port The number of port
* @param proto The protocol
* @param c_nettype The connection type of network
* @param c_addrtype The connection type of address
* @param c_addr The connection address
* @param c_addr_multicast_ttl The multicast TTL value
* @param c_addr_multicast_int ?
* @param a_rtpmap The rtpmap of element.
*/
void eXosip_sdp_negotiation_add_codec(char *payload, char *number_of_port,
char *proto, char *c_nettype,
char *c_addrtype, char *c_addr,
char *c_addr_multicast_ttl,
char *c_addr_multicast_int,
char *a_rtpmap);
/**
* Replace the internal SDP negociator facility.
*
* @param sn The new negociator context
*/
int eXosip_sdp_negotiation_replace(osip_negotiation_t *sn);
struct eXosip_call_t;
/**
* Set the reference element to be used in callback for the negociator.
* This must be done only if eXosip_sdp_negotiation_replace has been
* used and must not be done if this method has not been used.
*
* @param jc The related call.
* @param sn The new negociator context.
*/
void eXosip_sdp_negotiation_ctx_set_mycontext(struct eXosip_call_t *jc, void *arg);
#define DEFAULT_MODE 2
#define CALLBACK_MODE 1
#define EVENT_MODE 2
/**
* Set the functionnal mode of eXosip.
* The default mode is the EVENT_MODE.
*
* @param mode mode to use.
*/
void eXosip_set_mode(int mode);
/**
* Set the SIP User-Agent: header string.
*/
void eXosip_set_user_agent(const char *user_agent);
/**
* Lock the eXtented oSIP library.
*
*/
int eXosip_lock(void);
/**
* UnLock the eXtented oSIP library.
*
*/
int eXosip_unlock(void);
/** @} */
/**
* @defgroup eXosip_call eXosip Call Management
* @ingroup eXosip
* @{
*/
/**
* Build a default INVITE message for a new call.
*
* @param invite Pointer for the SIP element to hold.
* @param to SIP url for callee.
* @param from SIP url for caller.
* @param route Route header for INVITE. (optionnal)
* @param subject Subject for the call.
*/
int eXosip_build_initial_invite(osip_message_t **invite, char *to,
char *from, char *route, char *subject);
/**
* Initiate a call.
*
* @param invite SIP INVITE message to send.
* @param reference Application context. (optionnal)
* @param sdp_reference_context Sdp Application context. (optionnal)
* @param local_sdp_port The port to be used for this call.
*/
int eXosip_initiate_call (osip_message_t *invite, void *reference,
void *sdp_context_reference, char *local_sdp_port);
/**
* Initiate a call with the specified body-type and body
*
* @param invite SIP INVITE message to send.
* @param body_type body type (ex: "application/sdp")
* @param body The body.
*/
int eXosip_initiate_call_with_body (osip_message_t *invite, const char *body_type, const char *body, void *reference);
/**
* When a call failed to initiate due to authorization reasons (407), retry the call using the authentication information
* previously stored in eXosip using eXosip_add_authentication_info()
*
* @param cid The eXosip call id as returned by eXosip_initiate_call*()
*/
int eXosip_retry_call (int cid);
/**
* Initiate a blind transfer outside of a call.
* (probably not supported by many softphone...)
*
* @param refer_to SIP url for transfer.
* @param from SIP url for caller.
* @param to SIP url for callee.
* @param route Route header for REFER. (optionnal)
*/
int eXosip_transfer_call_out_of_dialog(char *refer_to, char *from, char *to, char *route);
/**
* Set redirection url before a call to eXosip_answer_call.
*
* @param jid dialog id of call.
* @param contact contact address.
*/
int eXosip_set_redirection_address (int jid, char *contact);
/**
* Answer call.
*
* @param jid dialog id of call.
* @param status Status code to use.
*/
int eXosip_answer_call (int jid, int status, char *local_sdp_port);
/**
* Answer call.
*
* @param jid dialog id of call.
* @param status Status code to use.
* @param answer The resulting sip answer to send.
*/
int eXosip2_answer (int jid, int status, osip_message_t **answer);
/**
* Answer call.
*
* @param jid dialog id of call.
* @param answer The sip answer to send.
*/
int eXosip2_answer_send(int jid, osip_message_t *answer);
/**
* Answer call with the specified body.
*
* @param jid dialog id of call.
* @param status Status code to use.
* @param body_type body type (ex: "application/sdp")
* @param body The body.
*/
int eXosip_answer_call_with_body (int jid, int status,const char *body_type, const char*body);
/**
* Retreive payload negotiated for this dialog
*
* @param jid dialog id of call.
* @param payload will hold the negotited payload code
* @param payload_name will hold negotioated payload mime string
* @param pnsize size of the payload_name buffer
*/
int eXosip_retrieve_negotiated_payload(int jid, int *payload, char *payload_name, int pnsize);
/**
* Set a new application context for an existing call
*
* @param jc Pointer to the call to modify
* @param reference New application context.
*/
int eXosip_set_call_reference(int jid, void *reference);
/**
* Put a call on hold.
*
* @param jid dialog id of call.
*/
int eXosip_on_hold_call (int jid);
int eXosip_off_hold_call (int jid, char *rtp_ip, int port);
/**
* Tranfer a call.
*
* @param jid dialog id of call.
* @param refer_to SIP Url for transfer.
*/
int eXosip_transfer_call(int jid, char *refer_to);
/**
* Tranfer a call.
*
* @param jid dialog id of call.
* @param refer_to SIP Url for transfer.
*/
int eXosip_transfer_send_notify(int jid, int subscription_status, char *body);
/**
* Terminate a call.
*
* @param cid call id of call.
* @param jid dialog id of call.
*/
int eXosip_terminate_call(int cid, int jid);
/**
* Send an OPTIONS message within a call.
*
* @param cid call id of call.
* @param jid dialog id of call.
*/
int eXosip_options_call (int jid);
/**
* Send an INFO message within a call.
*
* @param jid dialog id of call.
* @param content_type content-type of body.
* @param body body to attach.
*/
int eXosip_info_call(int jid, char *content_type, char *body);
/**
* Answer an OPTIONS message.
*
* @param cid call id of call.
* @param jid dialog id of call.
*/
int eXosip_answer_options(int cid, int jid, int status);
/** @} */
/**
* @defgroup eXosip_registration eXosip Registration Management
* @ingroup eXosip
* @{
*/
/**
* Send initial registration to a server. (REGISTER request)
*
* @param from SIP url for caller.
* @param proxy Proxy used for registration.
* @param contact Contact address. (optionnal)
* @param route Outbound proxy address. (optionnal)
*/
int eXosip_register_init (char *from, char *proxy, char *contact, char* route);
/**
* Update the registration. (REGISTER request)
*
* @param rid .
* @param expires The expires value for registration.
*/
int eXosip_register (int rid, int expires);
/** @} */
/**
* @defgroup eXosip_impp eXosip Instant Messaging and Presence Management
* @ingroup eXosip
* @{
*/
/**
* Send an Instant Message (MESSAGE request).
*
* @param rid .
*/
int eXosip_message (char *to, char *from, char *route, char *buff);
/**
* build publication for a user. (PUBLISH request)
*
* @param message returned published request.
* @param to SIP url for callee.
* @param from SIP url for caller.
* @param route Route used for publication.
* @param event SIP Event header.
* @param expires SIP Expires header.
* @param ctype Content-Type of body.
* @param body body for publication.
*/
int eXosip_build_publish(osip_message_t **message,
char *to,
char *from,
char *route,
const char *event,
const char *expires,
const char *ctype,
const char *body);
/**
* Send an Publication Message (PUBLISH request).
*
* @param message is a ready to be sent publish message .
* @param sip_if_match is the SIP-If-Match header. (NULL for initial publication)
*/
int eXosip_publish (osip_message_t *message, const char *sip_if_match);
/**
* Send initial subscription to a user. (SUBSCRIBE request)
*
* @param to SIP url for callee.
* @param from SIP url for caller.
* @param route Route used for registration.
*/
int eXosip_subscribe(char *to, char *from, char *route);
/**
* Update a subscription (SUBSCRIBE request).
*
* @param sid id of subscription.
* @param expires Time between updates.
*/
int eXosip_subscribe_refresh(int sid, char *expires);
/**
* Close a subscription (SUBSCRIBE request).
*
* @param sid id of subscription.
*/
int eXosip_subscribe_close(int sid);
typedef enum eXosip_ss {
EXOSIP_SUBCRSTATE_UNKNOWN,
EXOSIP_SUBCRSTATE_PENDING,
EXOSIP_SUBCRSTATE_ACTIVE,
EXOSIP_SUBCRSTATE_TERMINATED
} eXosip_ss_t;
typedef enum eXosip_ss_reason {
DEACTIVATED,
PROBATION,
REJECTED,
TIMEOUT,
GIVEUP,
NORESOURCE
} eXosip_ss_reason_t;
/* typo error */
#define NORESSOURCE NORESOURCE
typedef enum eXosip_ss_status {
EXOSIP_NOTIFY_UNKNOWN,
EXOSIP_NOTIFY_PENDING, /* subscription not yet accepted */
EXOSIP_NOTIFY_ONLINE,
EXOSIP_NOTIFY_BUSY,
EXOSIP_NOTIFY_BERIGHTBACK,
EXOSIP_NOTIFY_AWAY,
EXOSIP_NOTIFY_ONTHEPHONE,
EXOSIP_NOTIFY_OUTTOLUNCH,
EXOSIP_NOTIFY_CLOSED
} eXosip_ss_status_t;
/**
* Accept a subscription and notify state (NOTIFY request).
*
* @param nid call id of call.
* @param code code for answer to subscribe.
* @param subscription_status subscription status.
* @param online_status online status to send.
*/
int eXosip_notify_accept_subscribe (int nid, int code, int subscription_status, int online_status);
/**
* Update a subscription and notify state (NOTIFY request).
*
* @param nid call id of call.
* @param subscription_status subscription status.
* @param online_status online status to send.
*/
int eXosip_notify(int nid, int subscription_status, int online_status);
/** @} */
int eXosip_send_ack(int did);
/**
* @defgroup eXosip_event eXosip event Management
* @ingroup eXosip
* @{
*/
typedef enum eXosip_event_type_t {
/* Registration Info */
EXOSIP_REGISTRATION_NEW, /* announce new registration. */
EXOSIP_REGISTRATION_SUCCESS, /* user is successfully registred. */
EXOSIP_REGISTRATION_FAILURE, /* user is not registred. */
EXOSIP_REGISTRATION_REFRESHED, /* registration has been refreshed. */
EXOSIP_REGISTRATION_TERMINATED, /* UA is not registred any more. */
/* for UAC events */
EXOSIP_CALL_NOANSWER, /* announce no answer within the timeout */
EXOSIP_CALL_PROCEEDING, /* announce processing by a remote app */
EXOSIP_CALL_RINGING, /* announce ringback */
EXOSIP_CALL_ANSWERED, /* announce start of call */
EXOSIP_CALL_REDIRECTED, /* announce a redirection */
EXOSIP_CALL_REQUESTFAILURE, /* announce a request failure */
EXOSIP_CALL_SERVERFAILURE, /* announce a server failure */
EXOSIP_CALL_GLOBALFAILURE, /* announce a global failure */
/* for UAS events */
EXOSIP_CALL_NEW, /* announce a new call */
EXOSIP_CALL_ACK, /* ACK received for 200ok to INVITE */
EXOSIP_CALL_CANCELLED, /* announce that call has been cancelled */
EXOSIP_CALL_TIMEOUT, /* announce that call has failed */
EXOSIP_CALL_HOLD, /* audio must be stopped */
EXOSIP_CALL_OFFHOLD, /* audio must be restarted */
EXOSIP_CALL_CLOSED, /* a BYE was received for this call */
/* for both UAS & UAC events */
EXOSIP_CALL_STARTAUDIO, /* audio must be established */
EXOSIP_CALL_RELEASED, /* call context is cleared. */
/* for UAC events */
EXOSIP_OPTIONS_NOANSWER, /* announce no answer within the timeout */
EXOSIP_OPTIONS_PROCEEDING, /* announce processing by a remote app */
EXOSIP_OPTIONS_ANSWERED, /* announce a 200ok */
EXOSIP_OPTIONS_REDIRECTED, /* announce a redirection */
EXOSIP_OPTIONS_REQUESTFAILURE, /* announce a request failure */
EXOSIP_OPTIONS_SERVERFAILURE, /* announce a server failure */
EXOSIP_OPTIONS_GLOBALFAILURE, /* announce a global failure */
EXOSIP_INFO_NOANSWER, /* announce no answer within the timeout */
EXOSIP_INFO_PROCEEDING, /* announce processing by a remote app */
EXOSIP_INFO_ANSWERED, /* announce a 200ok */
EXOSIP_INFO_REDIRECTED, /* announce a redirection */
EXOSIP_INFO_REQUESTFAILURE, /* announce a request failure */
EXOSIP_INFO_SERVERFAILURE, /* announce a server failure */
EXOSIP_INFO_GLOBALFAILURE, /* announce a global failure */
/* for UAS events */
EXOSIP_OPTIONS_NEW, /* announce a new options method */
EXOSIP_INFO_NEW, /* new info request received */
EXOSIP_MESSAGE_NEW, /* announce new incoming MESSAGE. */
EXOSIP_MESSAGE_SUCCESS, /* announce a 200ok to a previous sent */
EXOSIP_MESSAGE_FAILURE, /* announce a failure. */
/* Presence and Instant Messaging */
EXOSIP_SUBSCRIPTION_NEW, /* announce new incoming SUBSCRIBE. */
EXOSIP_SUBSCRIPTION_UPDATE, /* announce incoming SUBSCRIBE. */
EXOSIP_SUBSCRIPTION_CLOSED, /* announce end of subscription. */
EXOSIP_SUBSCRIPTION_NOANSWER, /* announce no answer */
EXOSIP_SUBSCRIPTION_PROCEEDING, /* announce a 1xx */
EXOSIP_SUBSCRIPTION_ANSWERED, /* announce a 200ok */
EXOSIP_SUBSCRIPTION_REDIRECTED, /* announce a redirection */
EXOSIP_SUBSCRIPTION_REQUESTFAILURE, /* announce a request failure */
EXOSIP_SUBSCRIPTION_SERVERFAILURE, /* announce a server failure */
EXOSIP_SUBSCRIPTION_GLOBALFAILURE, /* announce a global failure */
EXOSIP_SUBSCRIPTION_NOTIFY, /* announce new NOTIFY request */
EXOSIP_SUBSCRIPTION_RELEASED, /* call context is cleared. */
EXOSIP_IN_SUBSCRIPTION_NEW, /* announce new incoming SUBSCRIBE.*/
EXOSIP_IN_SUBSCRIPTION_RELEASED, /* announce end of subscription. */
EXOSIP_CALL_REFERED, /* announce incoming REFER */
EXOSIP_CALL_REFER_STATUS, /* announce incoming NOTIFY */
EXOSIP_CALLBACK_COUNT
} eXosip_event_type_t;
typedef struct eXosip_event {
eXosip_event_type_t type;
void *external_reference;
char reason_phrase[50];
int status_code;
char textinfo[256];
char req_uri[256];
char local_uri[256];
char remote_uri[256];
char remote_contact[256];
char refer_to[256];
char subject[256];
osip_content_type_t *i_ctt;
osip_list_t *i_bodies;
char remote_sdp_audio_ip[50];
int remote_sdp_audio_port;
int local_sdp_audio_port;
int payload;
char payload_name[50];
char sdp_body[1000]; /* The whole SDP body */
int online_status;
int ss_status;
int ss_reason;
/* For a high level usage of the eXosip stack? (API is enough?) */
int did;
int cid;
int rid;
int sid;
int nid;
/* For a low level usage of the eXosip stack */
struct eXosip_dialog_t *jd;
struct eXosip_call_t *jc;
struct eXosip_reg_t *jr;
struct eXosip_subscribe_t *js;
struct eXosip_notify_t *jn;
} eXosip_event_t;
/**
* Free ressource in an eXosip event.
*
* @param je event to work on.
*/
void eXosip_event_free(eXosip_event_t *je);
/**
* Wait for an eXosip event. (FUTURE USE)
*
* @param tv_s timeout value (seconds).
* @param tv_ms timeout value (mseconds).
*/
eXosip_event_t *eXosip_event_wait(int tv_s, int tv_ms);
/**
* Wait for next eXosip event.
*
*/
eXosip_event_t *eXosip_event_get(void);
#ifdef __cplusplus
}
#endif
#endif

510
linphone/exosip/eXosip2.h Normal file
View file

@ -0,0 +1,510 @@
/*
eXosip - This is the eXtended osip library.
Copyright (C) 2002, 2003 Aymeric MOIZARD - jack@atosc.org
eXosip is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
eXosip is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef ENABLE_MPATROL
#include <mpatrol.h>
#endif
#ifndef __EXOSIP2_H__
#define __EXOSIP2_H__
#ifdef WIN32
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#define snprintf _snprintf
#define close(s) closesocket(s)
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#endif
#include <stdio.h>
#include <osip2/osip.h>
#include <osip2/osip_dialog.h>
#include <osip2/osip_negotiation.h>
#include <eXosip_cfg.h>
#include <eXosip.h>
#include "jpipe.h"
#ifndef JD_EMPTY
#define JD_EMPTY 0
#define JD_INITIALIZED 1
#define JD_TRYING 2
#define JD_QUEUED 3
#define JD_RINGING 4
#define JD_ESTABLISHED 5
#define JD_REDIRECTED 6
#define JD_AUTH_REQUIRED 7
#define JD_CLIENTERROR 8
#define JD_SERVERERROR 9
#define JD_GLOBALFAILURE 10
#define JD_TERMINATED 11
#define JD_MAX 11
#endif
#define EXOSIP_VERSION "0.1"
#ifdef __cplusplus
extern "C"
{
#endif
void eXosip_update(void);
void __eXosip_wakeup(void);
typedef struct eXosip_dialog_t eXosip_dialog_t;
struct eXosip_dialog_t {
int d_id;
int d_STATE;
osip_dialog_t *d_dialog; /* active dialog */
int d_timer;
osip_message_t *d_200Ok;
osip_message_t *d_ack;
osip_list_t *media_lines;
osip_list_t *d_inc_trs;
osip_list_t *d_out_trs;
/* struct _BodyHandler *d_bh; */
eXosip_dialog_t *next;
eXosip_dialog_t *parent;
};
typedef struct eXosip_subscribe_t eXosip_subscribe_t;
struct eXosip_subscribe_t {
int s_id;
char s_uri[255];
int s_online_status;
int s_ss_status;
int s_ss_reason;
int s_ss_expires;
eXosip_dialog_t *s_dialogs;
osip_transaction_t *s_inc_tr;
osip_transaction_t *s_out_tr;
eXosip_subscribe_t *next;
eXosip_subscribe_t *parent;
};
typedef struct eXosip_notify_t eXosip_notify_t;
struct eXosip_notify_t {
int n_id;
char n_uri[255];
int n_online_status;
char *n_contact_info;
int n_ss_status;
int n_ss_reason;
int n_ss_expires;
eXosip_dialog_t *n_dialogs;
osip_transaction_t *n_inc_tr;
osip_transaction_t *n_out_tr;
eXosip_notify_t *next;
eXosip_notify_t *parent;
};
typedef struct eXosip_call_t eXosip_call_t;
struct eXosip_call_t {
int c_id;
char c_subject[100];
int c_ack_sdp; /* flag for alternative SDP offer-response model */
eXosip_dialog_t *c_dialogs;
osip_transaction_t *c_inc_tr;
osip_transaction_t *c_out_tr;
osip_transaction_t *c_inc_options_tr;
osip_transaction_t *c_out_options_tr;
void *external_reference;
osip_negotiation_ctx_t *c_ctx;
char c_sdp_port[10];
char c_redirection[1024]; /* contact for 3xx answers */
eXosip_call_t *next;
eXosip_call_t *parent;
};
#if 0
typedef struct eXosip_realm_t eXosip_realm_t;
struct eXosip_realm_t {
int r_id;
char *r_realm;
char *r_username;
char *r_passwd;
eXosip_realm_t *next;
eXosip_realm_t *parent;
};
#endif
typedef struct eXosip_reg_t eXosip_reg_t;
struct eXosip_reg_t {
int r_id;
int r_reg_period; /* delay between registration */
char *r_aor; /* sip identity */
char *r_registrar; /* registrar */
char *r_route; /* outbound proxy */
#if 0
eXosip_realm_t *r_realms; /* list of realms */
#endif
char *r_contact; /* list of contacts string */
osip_transaction_t *r_last_tr;
eXosip_reg_t *next;
eXosip_reg_t *parent;
};
typedef struct eXosip_pub_t eXosip_pub_t;
struct eXosip_pub_t {
int p_id;
time_t p_expires; /* expiration date (started+period) */
int p_period; /* delay between registration */
char p_aor[256]; /* sip identity */
char p_sip_etag[64]; /* sip_etag from 200ok */
osip_transaction_t *p_last_tr;
eXosip_pub_t *next;
eXosip_pub_t *parent;
};
int _eXosip_pub_update(eXosip_pub_t **pub, osip_transaction_t *tr, osip_message_t *answer);
int _eXosip_pub_find_by_aor(eXosip_pub_t **pub, const char *aor);
int _eXosip_pub_init(eXosip_pub_t **pub, const char *aor, const char *exp);
void _eXosip_pub_free(eXosip_pub_t *pub);
typedef struct jauthinfo_t jauthinfo_t;
struct jauthinfo_t {
char username[50];
char userid[50];
char passwd[50];
char ha1[50];
char realm[50];
jauthinfo_t *parent;
jauthinfo_t *next;
};
int
__eXosip_create_authorization_header(osip_message_t *previous_answer,
const char *rquri, const char *username,
const char *passwd,
osip_authorization_t **auth);
int
__eXosip_create_proxy_authorization_header(osip_message_t *previous_answer,
const char *rquri,
const char *username,
const char *passwd,
osip_proxy_authorization_t **auth);
eXosip_event_t *eXosip_event_init_for_call(int type, eXosip_call_t *jc,
eXosip_dialog_t *jd);
int eXosip_event_add_sdp_info(eXosip_event_t *je, osip_message_t *message);
int eXosip_event_add_status(eXosip_event_t *je, osip_message_t *response);
eXosip_event_t *eXosip_event_init_for_subscribe(int type,
eXosip_subscribe_t *js,
eXosip_dialog_t *jd);
eXosip_event_t *eXosip_event_init_for_notify(int type, eXosip_notify_t *jn,
eXosip_dialog_t *jd);
eXosip_event_t *eXosip_event_init_for_reg(int type, eXosip_reg_t *jr);
eXosip_event_t *eXosip_event_init_for_message(int type, osip_transaction_t
*tr, osip_message_t *sip);
int eXosip_event_init(eXosip_event_t **je, int type);
eXosip_call_t *eXosip_event_get_callinfo(eXosip_event_t *je);
eXosip_dialog_t *eXosip_event_get_dialoginfo(eXosip_event_t *je);
eXosip_reg_t *eXosip_event_get_reginfo(eXosip_event_t *je);
eXosip_notify_t *eXosip_event_get_notifyinfo(eXosip_event_t *je);
eXosip_subscribe_t *eXosip_event_get_subscribeinfo(eXosip_event_t *je);
int eXosip_event_add(eXosip_event_t *je);
eXosip_event_t *eXosip_event_wait(int tv_s, int tv_ms);
eXosip_event_t *eXosip_event_get(void);
typedef void (* eXosip_callback_t) (int type, eXosip_event_t *);
char *strdup_printf(const char *fmt, ...);
jfriend_t *jfriend_get(void);
jsubscriber_t *jsubscriber_get(void);
jidentity_t *jidentity_get(void);
int jfriend_get_and_set_next_token (char **dest, char *buf,
char **next);
#define eXosip_trace(loglevel,args) do \
{ \
char *__strmsg; \
__strmsg=strdup_printf args ; \
OSIP_TRACE(osip_trace(__FILE__,__LINE__,(loglevel),NULL,"%s\n",__strmsg)); \
osip_free (__strmsg); \
}while (0);
typedef struct eXosip_t eXosip_t;
struct eXosip_t {
int forced_localip; /* set to 1 when we must always use the default local ip */
char *localip; /* default local ip */
char *localport;
char *user_agent;
FILE *j_input;
FILE *j_output;
eXosip_call_t *j_calls; /* my calls */
eXosip_subscribe_t *j_subscribes; /* my friends */
eXosip_notify_t *j_notifies; /* my susbscribers */
osip_list_t *j_transactions;
eXosip_reg_t *j_reg; /* my registrations */
eXosip_pub_t *j_pub; /* my publications */
void *j_cond;
void *j_mutexlock;
osip_t *j_osip;
int j_socket;
int j_stop_ua;
void *j_thread;
jpipe_t *j_socketctl;
jpipe_t *j_socketctl_event;
jsubscriber_t *j_subscribers;
jfriend_t *j_friends;
jidentity_t *j_identitys;
int j_runtime_mode;
eXosip_callback_t j_call_callbacks[EXOSIP_CALLBACK_COUNT];
osip_fifo_t *j_events;
osip_negotiation_t *osip_negotiation;
char j_firewall_ip[50];
jauthinfo_t *authinfos;
int ip_family; /* AF_INET6 or AF_INET */
char nat_type[16];
char forced_proxy[256];
char answer_contact[256]; /* conatact header value to use in answers */
};
typedef struct jinfo_t jinfo_t;
struct jinfo_t {
eXosip_dialog_t *jd;
eXosip_call_t *jc;
eXosip_subscribe_t *js;
eXosip_notify_t *jn;
};
int eXosip_guess_ip_for_via (int family, char *address, int size);
int eXosip_sdp_negotiation_init(osip_negotiation_t **sn);
void eXosip_sdp_negotiation_free(osip_negotiation_t *sn);
int eXosip_retrieve_sdp_negotiation_result(osip_negotiation_ctx_t *ctx, char *payload_name, int pnsize);
sdp_message_t *eXosip_get_local_sdp_info(osip_transaction_t *invite_tr);
sdp_message_t *eXosip_get_remote_sdp_info(osip_transaction_t *invite_tr);
sdp_message_t *eXosip_get_local_sdp(osip_transaction_t *transaction);
sdp_message_t *eXosip_get_remote_sdp(osip_transaction_t *transaction);
int eXosip_set_callbacks(osip_t *osip);
char *osip_call_id_new_random(void);
char *osip_to_tag_new_random(void);
char *osip_from_tag_new_random(void);
unsigned int via_branch_new_random(void);
void __eXosip_delete_jinfo(osip_transaction_t *transaction);
jinfo_t *__eXosip_new_jinfo(eXosip_call_t *jc, eXosip_dialog_t *jd,
eXosip_subscribe_t *js, eXosip_notify_t *jn);
int eXosip_dialog_init_as_uac(eXosip_dialog_t **jd, osip_message_t *_200Ok);
int eXosip_dialog_init_as_uas(eXosip_dialog_t **jd, osip_message_t *_invite, osip_message_t *_200Ok);
void eXosip_dialog_free(eXosip_dialog_t *jd);
void eXosip_dialog_set_state(eXosip_dialog_t *jd, int state);
void eXosip_delete_early_dialog(eXosip_dialog_t *jd);
struct __eXosip_sockaddr {
u_char ss_len;
u_char ss_family;
u_char padding[128 - 2];
};
int eXosip_get_addrinfo (struct addrinfo **addrinfo,
char *hostname, int service);
int isrfc1918(char *ipaddr);
void eXosip_get_localip_from_via(osip_message_t *,char**localip);
int generating_initial_subscribe(osip_message_t **message, char *to,
char *from, char *route);
int generating_message(osip_message_t **message, char *to, char *from,
char *route, char *buff);
int generating_publish(osip_message_t **message, char *to, char *from,
char *route);
int generating_cancel(osip_message_t **dest, osip_message_t *request_cancelled);
int generating_options_within_dialog(osip_message_t **info, osip_dialog_t *dialog);
int generating_info_within_dialog(osip_message_t **info, osip_dialog_t *dialog);
int generating_bye(osip_message_t **bye, osip_dialog_t *dialog);
int generating_refer(osip_message_t **refer, osip_dialog_t *dialog, char *refer_to);
int generating_refer_outside_dialog(osip_message_t **refer, char *refer_to, char *from, char *to, char *proxy);
int generating_invite_on_hold(osip_message_t **invite, osip_dialog_t *dialog,
char *subject, char *sdp);
int generating_invite_off_hold(osip_message_t **invite, osip_dialog_t *dialog,
char *subject, char *sdp);
int generating_options(osip_message_t **options, char *from, char *to, char *proxy);
int generating_ack_for_2xx(osip_message_t **ack, osip_dialog_t *dialog);
int generating_info(osip_message_t **info, char *from, char *to, char *proxy);
int _eXosip_reg_find(eXosip_reg_t **reg, osip_transaction_t *tr);
int eXosip_reg_init(eXosip_reg_t **jr, char *from, char *proxy, char *contact, char* route);
void eXosip_reg_free(eXosip_reg_t *jreg);
int generating_register(osip_message_t **reg, char *transport, char *from, char *proxy, int expires);
char *generating_sdp_answer(osip_message_t *request, osip_negotiation_ctx_t *context);
int eXosip_call_dialog_find(int jid, eXosip_call_t **jc, eXosip_dialog_t **jd);
int eXosip_notify_dialog_find(int nid, eXosip_notify_t **jn, eXosip_dialog_t **jd);
int eXosip_subscribe_dialog_find(int nid, eXosip_subscribe_t **js, eXosip_dialog_t **jd);
int eXosip_call_find(int cid, eXosip_call_t **jc);
int eXosip_dialog_set_200ok(eXosip_dialog_t *_jd, osip_message_t *_200Ok);
int _eXosip2_answer_invite_3456xx(eXosip_call_t *jc, eXosip_dialog_t *jd, int code, osip_message_t **answer);
int _eXosip2_answer_invite_2xx(eXosip_call_t *jc, eXosip_dialog_t *jd, int code, osip_message_t **answer);
int _eXosip2_answer_invite_1xx(eXosip_call_t *jc, eXosip_dialog_t *jd, int code, osip_message_t **answer);
int eXosip_answer_invite_1xx(eXosip_call_t *jc, eXosip_dialog_t *jd, int code);
int eXosip_answer_invite_2xx(eXosip_call_t *jc, eXosip_dialog_t *jd, int code, char *local_sdp_port);
int eXosip_answer_invite_2xx_with_body(eXosip_call_t *jc, eXosip_dialog_t *jd, int code,const char*, const char*);
int eXosip_answer_invite_3456xx(eXosip_call_t *jc, eXosip_dialog_t *jd, int code);
int eXosip_answer_options_1xx(eXosip_call_t *jc, eXosip_dialog_t *jd, int code);
int eXosip_answer_options_2xx(eXosip_call_t *jc, eXosip_dialog_t *jd, int code);
int eXosip_answer_options_3456xx(eXosip_call_t *jc, eXosip_dialog_t *jd, int code);
void eXosip_notify_answer_subscribe_1xx(eXosip_notify_t *jc,
eXosip_dialog_t *jd, int code);
void eXosip_notify_answer_subscribe_2xx(eXosip_notify_t *jn,
eXosip_dialog_t *jd, int code);
void eXosip_notify_answer_subscribe_3456xx(eXosip_notify_t *jn,
eXosip_dialog_t *jd, int code);
int eXosip_build_response_default(int jid, int status);
int _eXosip_build_response_default(osip_message_t **dest, osip_dialog_t *dialog,
int status, osip_message_t *request);
int complete_answer_that_establish_a_dialog(osip_message_t *response, osip_message_t *request);
int _eXosip_build_request_within_dialog(osip_message_t **dest, char *method_name,
osip_dialog_t *dialog, char *transport);
int eXosip_build_initial_options(osip_message_t **options, char *to, char *from,
char *route);
void eXosip_kill_transaction(osip_list_t * transactions);
int eXosip_remove_transaction_from_call(osip_transaction_t *tr, eXosip_call_t *jc);
osip_transaction_t *eXosip_find_last_inc_notify(eXosip_subscribe_t *jn, eXosip_dialog_t *jd);
osip_transaction_t *eXosip_find_last_out_notify(eXosip_notify_t *jn, eXosip_dialog_t *jd);
osip_transaction_t *eXosip_find_last_inc_subscribe(eXosip_notify_t *jn, eXosip_dialog_t *jd);
osip_transaction_t *eXosip_find_last_out_subscribe(eXosip_subscribe_t *js, eXosip_dialog_t *jd );
osip_transaction_t *eXosip_find_last_out_options(eXosip_call_t *jc, eXosip_dialog_t *jd );
osip_transaction_t *eXosip_find_last_inc_options(eXosip_call_t *jc, eXosip_dialog_t *jd );
osip_transaction_t *eXosip_find_last_options(eXosip_call_t *jc, eXosip_dialog_t *jd );
osip_transaction_t *eXosip_find_last_out_info(eXosip_call_t *jc, eXosip_dialog_t *jd );
osip_transaction_t *eXosip_find_last_inc_info(eXosip_call_t *jc, eXosip_dialog_t *jd );
osip_transaction_t *eXosip_find_last_info(eXosip_call_t *jc, eXosip_dialog_t *jd );
osip_transaction_t *eXosip_find_last_invite(eXosip_call_t *jc, eXosip_dialog_t *jd );
osip_transaction_t *eXosip_find_last_inc_invite(eXosip_call_t *jc, eXosip_dialog_t *jd);
osip_transaction_t *eXosip_find_last_out_invite(eXosip_call_t *jc, eXosip_dialog_t *jd);
osip_transaction_t *eXosip_find_last_refer(eXosip_call_t *jc, eXosip_dialog_t *jd );
osip_transaction_t *eXosip_find_last_inc_notify_for_refer(eXosip_call_t *jc, eXosip_dialog_t *jd);
osip_transaction_t *eXosip_find_last_out_notify_for_refer(eXosip_call_t *jc, eXosip_dialog_t *jd);
osip_transaction_t *eXosip_find_last_inc_bye(eXosip_call_t *jc, eXosip_dialog_t *jd);
osip_transaction_t *eXosip_find_last_out_bye(eXosip_call_t *jc, eXosip_dialog_t *jd);
osip_transaction_t *eXosip_find_last_inc_refer(eXosip_call_t *jc, eXosip_dialog_t *jd);
osip_transaction_t *eXosip_find_last_out_refer(eXosip_call_t *jc, eXosip_dialog_t *jd);
int eXosip_call_init(eXosip_call_t **jc);
void eXosip_call_free(eXosip_call_t *jc);
void __eXosip_call_remove_dialog_reference_in_call(eXosip_call_t *jc, eXosip_dialog_t *jd);
void eXosip_call_set_subject(eXosip_call_t *jc, char *subject);
int eXosip_read_message(int max_message_nb, int sec_max, int usec_max);
void eXosip_release_terminated_calls ( void );
int eXosip_subscribe_init(eXosip_subscribe_t **js, char *uri);
void eXosip_subscribe_free(eXosip_subscribe_t *js);
int _eXosip_subscribe_set_refresh_interval(eXosip_subscribe_t *js, osip_message_t *inc_subscribe);
int eXosip_subscribe_need_refresh(eXosip_subscribe_t *js, int now);
int eXosip_subscribe_send_subscribe(eXosip_subscribe_t *js,
eXosip_dialog_t *jd, const char *expires);
int eXosip_notify_init(eXosip_notify_t **jn, osip_message_t *inc_subscribe);
void eXosip_notify_free(eXosip_notify_t *jn);
int _eXosip_notify_set_contact_info(eXosip_notify_t *jn, char *uri);
int _eXosip_notify_set_refresh_interval(eXosip_notify_t *jn,
osip_message_t *inc_subscribe);
void _eXosip_notify_add_expires_in_2XX_for_subscribe(eXosip_notify_t *jn,
osip_message_t *answer);
int _eXosip_notify_add_body(eXosip_notify_t *jn, osip_message_t *notify);
int eXosip_notify_add_allowed_subscriber(char *sip_url);
int _eXosip_notify_is_a_known_subscriber(osip_message_t *sip);
int eXosip_notify_send_notify(eXosip_notify_t *jn, eXosip_dialog_t *jd,
int subsciption_status,
int online_status);
int _eXosip_transfer_send_notify(eXosip_call_t *jc,
eXosip_dialog_t *jd,
int subscription_status,
char *body);
int eXosip_is_public_address(const char *addr);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,150 @@
/*
eXosip - This is the eXtended osip library.
Copyright (C) 2002, 2003 Aymeric MOIZARD - jack@atosc.org
eXosip is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
eXosip is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef ENABLE_MPATROL
#include <mpatrol.h>
#endif
#ifndef __EXOSIP_CFG_H__
#define __EXOSIP_CFG_H__
/**
* @defgroup eXosip_cfg eXosip Configuration Management
* @ingroup eXosip
* @{
*/
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct jfriend_t jfriend_t;
struct jfriend_t {
int f_id;
char *f_nick;
char *f_home;
char *f_work;
char *f_email;
char *f_e164;
jfriend_t *next;
jfriend_t *parent;
};
typedef struct jidentity_t jidentity_t;
struct jidentity_t {
int i_id;
char *i_identity;
char *i_registrar;
char *i_realm;
char *i_userid;
char *i_pwd;
jidentity_t *next;
jidentity_t *parent;
};
typedef struct jsubscriber_t jsubscriber_t;
struct jsubscriber_t {
int s_id;
char *s_nick;
char *s_uri;
char *s_allow;
jsubscriber_t *next;
jsubscriber_t *parent;
};
jfriend_t *jfriend_get(void);
void jfriend_remove(jfriend_t *fr);
jsubscriber_t *jsubscriber_get(void);
jidentity_t *jidentity_get(void);
int jfriend_load(void);
void jfriend_unload(void);
void jfriend_add(char *nickname, char *home,
char *work, char *email, char *e164);
char *jfriend_get_home(int fid);
int jsubscriber_load(void);
void jsubscriber_unload(void);
void subscribers_add(char *nickname, char *uri, int black_list);
char *jsubscriber_get_uri(int fid);
int jidentity_load(void);
void jidentity_unload(void);
void identitys_add(char *identity, char *registrar, char *realm,
char *userid, char *password);
char *jidentity_get_identity(int fid);
char *jidentity_get_registrar(int fid);
#define REMOVE_ELEMENT(first_element, element) \
if (element->parent==NULL) \
{ first_element = element->next; \
if (first_element!=NULL) \
first_element->parent = NULL; } \
else \
{ element->parent->next = element->next; \
if (element->next!=NULL) \
element->next->parent = element->parent; \
element->next = NULL; \
element->parent = NULL; }
#define ADD_ELEMENT(first_element, element) \
if (first_element==NULL) \
{ \
first_element = element; \
element->next = NULL; \
element->parent = NULL; \
} \
else \
{ \
element->next = first_element; \
element->parent = NULL; \
element->next->parent = element; \
first_element = element; \
}
#define APPEND_ELEMENT(type_of_element_t, first_element, element) \
if (first_element==NULL) \
{ first_element = element; \
element->next = NULL; /* useless */ \
element->parent = NULL; /* useless */ } \
else \
{ type_of_element_t *f; \
for (f=first_element; f->next!=NULL; f=f->next) \
{ } \
f->next = element; \
element->parent = f; \
element->next = NULL; \
}
#ifdef __cplusplus
}
#endif
/** @} */
#endif

278
linphone/exosip/eXutils.c Normal file
View file

@ -0,0 +1,278 @@
/*
eXosip - This is the eXtended osip library.
Copyright (C) 2002, 2003 Aymeric MOIZARD - jack@atosc.org
eXosip is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
eXosip is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef ENABLE_MPATROL
#include <mpatrol.h>
#endif
#include <osipparser2/osip_port.h>
#include "eXosip2.h"
extern eXosip_t eXosip;
#ifdef WIN32
/* You need the Platform SDK to compile this. */
#include <Windows.h>
#else /* sun, *BSD, linux, and other? */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <unistd.h>
#include <sys/param.h>
#include <stdio.h>
#endif
int
eXosip_guess_ip_for_via (int family, char *address, int size){
char *res=NULL;
if (family==AF_INET6)
eXosip_get_localip_for("2001:638:500:101:2e0:81ff:fe24:37c6",&res);
else
eXosip_get_localip_for("15.128.128.93",&res);
strncpy(address,res,size);
osip_free(res);
return 0;
}
#ifdef SM
void eXosip_get_localip_from_via(osip_message_t *mesg,char **locip){
osip_via_t *via=NULL;
char *host;
via=(osip_via_t*)osip_list_get(mesg->vias,0);
if (via==NULL) {
host="15.128.128.93";
eXosip_trace(OSIP_ERROR,("Could not get via:%s"));
}else host=via->host;
eXosip_get_localip_for(host,locip);
}
#endif
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 1024
#endif
void eXosip_get_localip_for(char *address_to_reach,char **loc){
int err,tmp;
struct addrinfo hints;
struct addrinfo *res=NULL,*res0=NULL;
struct sockaddr_storage addr;
int sock;
#ifdef __APPLE_CC__
int s;
#else
socklen_t s;
#endif
if (eXosip.forced_localip){
*loc=osip_strdup(eXosip.localip);
return;
}
*loc=osip_malloc(MAXHOSTNAMELEN);
if (eXosip.ip_family==AF_INET)
strcpy(*loc,"127.0.0.1"); /* always fallback to local loopback */
else strcpy(*loc,"::1");
memset(&hints,0,sizeof(hints));
hints.ai_family=(eXosip.ip_family==AF_INET) ? PF_INET:PF_INET6;
hints.ai_socktype=SOCK_DGRAM;
/*hints.ai_flags=AI_NUMERICHOST|AI_CANONNAME;*/
err=getaddrinfo(address_to_reach,"5060",&hints,&res0);
if (err!=0){
eXosip_trace(OSIP_ERROR,("Error in getaddrinfo for %s: %s\n",address_to_reach,gai_strerror(err)));
return ;
}
if (res0==NULL){
eXosip_trace(OSIP_ERROR,("getaddrinfo reported nothing !"));
abort();
return ;
}
for (res=res0;res!=NULL;res=res->ai_next){
sock=socket(res->ai_family,SOCK_DGRAM,0);
tmp=1;
err=setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof(int));
if (err<0){
eXosip_trace(OSIP_ERROR,("Error in setsockopt: %s\n",strerror(errno)));
abort();
return ;
}
err=connect(sock,res->ai_addr,res->ai_addrlen);
if (err<0) {
eXosip_trace(OSIP_ERROR,("Error in connect: %s\n",strerror(errno)));
close(sock);
sock=-1;
continue;
}else break;
}
freeaddrinfo(res0);
if (sock==-1){
eXosip_trace(OSIP_WARNING,("Could not find interface to reach %s\n",address_to_reach));
return;
}
res0=NULL;
res=NULL;
s=sizeof(addr);
err=getsockname(sock,(struct sockaddr*)&addr,&s);
if (err!=0) {
eXosip_trace(OSIP_ERROR,("Error in getsockname: %s\n",strerror(errno)));
close(sock);
return ;
}
err=getnameinfo((struct sockaddr *)&addr,s,*loc,MAXHOSTNAMELEN,NULL,0,NI_NUMERICHOST);
if (err!=0){
eXosip_trace(OSIP_ERROR,("getnameinfo error:%s ; while finding local address for %s",strerror(errno), address_to_reach));
abort();
return ;
}
close(sock);
eXosip_trace(OSIP_INFO1,("Outgoing interface to reach %s is %s.\n",address_to_reach,*loc));
return ;
}
char *strdup_printf(const char *fmt, ...)
{
/* Guess we need no more than 100 bytes. */
int n, size = 100;
char *p;
va_list ap;
if ((p = osip_malloc (size)) == NULL)
return NULL;
while (1)
{
/* Try to print in the allocated space. */
va_start (ap, fmt);
#ifdef WIN32
n = _vsnprintf (p, size, fmt, ap);
#else
n = vsnprintf (p, size, fmt, ap);
#endif
va_end (ap);
/* If that worked, return the string. */
if (n > -1 && n < size)
return p;
/* Else try again with more space. */
if (n > -1) /* glibc 2.1 */
size = n + 1; /* precisely what is needed */
else /* glibc 2.0 */
size *= 2; /* twice the old size */
if ((p = realloc (p, size)) == NULL)
return NULL;
}
}
int
eXosip_get_addrinfo (struct addrinfo **addrinfo, char *hostname, int service)
{
#ifndef WIN32
struct in_addr addr;
struct in6_addr addrv6;
#else
unsigned long int one_inet_addr;
#endif
struct addrinfo hints;
int error;
char portbuf[10];
if (service!=0)
snprintf(portbuf, sizeof(portbuf), "%i", service);
memset (&hints, 0, sizeof (hints));
#ifndef WIN32
if (inet_pton(AF_INET, hostname, &addr)>0)
{
/* ipv4 address detected */
hints.ai_flags = AI_NUMERICHOST;
hints.ai_family = PF_INET;
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_INFO2, NULL,
"IPv4 address detected: %s\n", hostname));
}
else if (inet_pton(AF_INET6, hostname, &addrv6)>0)
{
/* ipv6 address detected */
/* Do the resolution anyway */
hints.ai_flags = AI_CANONNAME;
hints.ai_family = PF_INET6;
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_INFO2, NULL,
"IPv6 address detected: %s\n", hostname));
}
else
{
/* hostname must be resolved */
hints.ai_flags = 0;
hints.ai_family = (eXosip.ip_family==AF_INET) ? PF_INET:PF_INET6;
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_INFO2, NULL,
"Not an IPv4 or IPv6 address: %s\n", hostname));
}
#else
if ((int)(one_inet_addr = inet_addr(hostname)) == -1)
hints.ai_flags = AI_CANONNAME;
else
hints.ai_flags = AI_NUMERICHOST;
#ifdef IPV6_SUPPORT
hints.ai_family = PF_UNSPEC; /* ipv6 support */
#else
hints.ai_family = PF_INET; /* ipv4 only support */
#endif
#endif
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
if (service==0)
{
error = getaddrinfo (hostname, "sip", &hints, addrinfo);
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_INFO2, NULL,
"SRV resolution with udp-sip-%s\n", hostname));
}
else
{
error = getaddrinfo (hostname, portbuf, &hints, addrinfo);
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_INFO2, NULL,
"DNS resolution with %s:%i\n", hostname, service));
}
if (error || *addrinfo == NULL)
{
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_INFO2, NULL,
"getaddrinfo failure. %s:%s (%s)\n", hostname, portbuf, gai_strerror(error)));
return -1;
}
return 0;
}

289
linphone/exosip/exosip.dev Executable file
View file

@ -0,0 +1,289 @@
[Project]
FileName=exosip.dev
Name=exosip
UnitCount=24
Type=2
Ver=1
ObjFiles=
Includes=.
Libs=
PrivateResource=
ResourceIncludes=
MakeIncludes=
Compiler=-D_WIN32_WINNT=0x501_@@_-DSM_@@_-g_@@_
CppCompiler=
Linker=
IsCpp=0
Icon=
ExeOutput=
ObjectOutput=
OverrideOutput=1
OverrideOutputName=libexosip.a
HostApplication=
Folders=
CommandLine=
UseCustomMakefile=0
CustomMakefile=
IncludeVersionInfo=0
SupportXPThemes=0
CompilerSet=0
CompilerSettings=0000000000000000000000
[Unit1]
FileName=udp.c
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit2]
FileName=eXosip2.h
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit3]
FileName=eXosip.c
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit4]
FileName=eXosip.h
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit5]
FileName=eXosip_cfg.h
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit6]
FileName=eXutils.c
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit7]
FileName=jauth.c
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit8]
FileName=jcall.c
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit9]
FileName=jcallback.c
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit10]
FileName=jdialog.c
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit11]
FileName=jevents.c
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit12]
FileName=jfreinds.c
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit13]
FileName=jidentity.c
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit14]
FileName=jnotify.c
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit15]
FileName=jpipe.c
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit16]
FileName=jpipe.h
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit17]
FileName=jpublish.c
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit18]
FileName=jreg.c
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit19]
FileName=jrequest.c
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit20]
FileName=jresponse.c
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit21]
FileName=jsubscribe.c
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit22]
FileName=jsubscribers.c
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit23]
FileName=misc.c
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit24]
FileName=sdp_offans.c
CompileCpp=0
Folder=exosip
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[VersionInfo]
Major=0
Minor=1
Release=1
Build=1
LanguageID=1033
CharsetID=1252
CompanyName=
FileVersion=
FileDescription=Developed using the Dev-C++ IDE
InternalName=
LegalCopyright=
LegalTrademarks=
OriginalFilename=
ProductName=
ProductVersion=
AutoIncBuildNr=0

453
linphone/exosip/jauth.c Normal file
View file

@ -0,0 +1,453 @@
/*
eXosip - This is the eXtended osip library.
Copyright (C) 2002, 2003 Aymeric MOIZARD - jack@atosc.org
eXosip is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
eXosip is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef ENABLE_MPATROL
#include <mpatrol.h>
#endif
#include "eXosip2.h"
#include <eXosip.h>
#include <eXosip_cfg.h>
#include <osip2/osip_mt.h>
#include <osip2/osip_condv.h>
/* #include <osip2/global.h> */
#include <osipparser2/osip_md5.h>
/* TAKEN from rcf2617.txt */
#define HASHLEN 16
typedef char HASH[HASHLEN];
#define HASHHEXLEN 32
typedef char HASHHEX[HASHHEXLEN+1];
#define IN
#define OUT
extern eXosip_t eXosip;
/* Private functions */
static void CvtHex(IN HASH Bin, OUT HASHHEX Hex);
static void DigestCalcHA1(IN const char * pszAlg, IN const char * pszUserName,
IN const char * pszRealm, IN const char * pszPassword,
IN const char * pszNonce, IN const char * pszCNonce,
OUT HASHHEX SessionKey);
static void DigestCalcResponse(IN HASHHEX HA1,
IN const char * pszNonce,
IN const char * pszNonceCount,
IN const char * pszCNonce,
IN const char * pszQop,
IN const char * pszMethod,
IN const char * pszDigestUri,
IN HASHHEX HEntity, OUT HASHHEX Response);
static void CvtHex(IN HASH Bin,
OUT HASHHEX Hex)
{
unsigned short i;
unsigned char j;
for (i = 0; i < HASHLEN; i++) {
j = (Bin[i] >> 4) & 0xf;
if (j <= 9)
Hex[i*2] = (j + '0');
else
Hex[i*2] = (j + 'a' - 10);
j = Bin[i] & 0xf;
if (j <= 9)
Hex[i*2+1] = (j + '0');
else
Hex[i*2+1] = (j + 'a' - 10);
};
Hex[HASHHEXLEN] = '\0';
}
/* calculate H(A1) as per spec */
static void DigestCalcHA1(IN const char * pszAlg,
IN const char * pszUserName,
IN const char * pszRealm,
IN const char * pszPassword,
IN const char * pszNonce,
IN const char * pszCNonce,
OUT HASHHEX SessionKey)
{
MD5_CTX Md5Ctx;
HASH HA1;
MD5Init(&Md5Ctx);
MD5Update(&Md5Ctx, (unsigned char *)pszUserName, strlen(pszUserName));
MD5Update(&Md5Ctx, (unsigned char *)":", 1);
MD5Update(&Md5Ctx, (unsigned char *)pszRealm, strlen(pszRealm));
MD5Update(&Md5Ctx, (unsigned char *)":", 1);
MD5Update(&Md5Ctx, (unsigned char *)pszPassword, strlen(pszPassword));
MD5Final((unsigned char *)HA1, &Md5Ctx);
if ((pszAlg!=NULL)&&osip_strcasecmp(pszAlg, "md5-sess") == 0)
{
MD5Init(&Md5Ctx);
MD5Update(&Md5Ctx, (unsigned char *)HA1, HASHLEN);
MD5Update(&Md5Ctx, (unsigned char *)":", 1);
MD5Update(&Md5Ctx, (unsigned char *)pszNonce, strlen(pszNonce));
MD5Update(&Md5Ctx, (unsigned char *)":", 1);
MD5Update(&Md5Ctx, (unsigned char *)pszCNonce, strlen(pszCNonce));
MD5Final((unsigned char *)HA1, &Md5Ctx);
}
CvtHex(HA1, SessionKey);
}
/* calculate request-digest/response-digest as per HTTP Digest spec */
static void DigestCalcResponse(IN HASHHEX HA1, /* H(A1) */
IN const char * pszNonce, /* nonce from server */
IN const char * pszNonceCount,/* 8 hex digits */
IN const char * pszCNonce, /* client nonce */
IN const char * pszQop, /* qop-value: "", "auth", "auth-int" */
IN const char * pszMethod, /* method from the request */
IN const char * pszDigestUri, /* requested URL */
IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */
OUT HASHHEX Response /* request-digest or response-digest */)
{
MD5_CTX Md5Ctx;
HASH HA2;
HASH RespHash;
HASHHEX HA2Hex;
int auth_int_flag = 0;
/* calculate H(A2) */
MD5Init(&Md5Ctx);
MD5Update(&Md5Ctx, (unsigned char *)pszMethod, strlen(pszMethod));
MD5Update(&Md5Ctx, (unsigned char *)":", 1);
MD5Update(&Md5Ctx, (unsigned char *)pszDigestUri, strlen(pszDigestUri));
if (pszQop!=NULL)
{
char *index = strchr(pszQop,'i');
while (index!=NULL&&index-pszQop>=5&&strlen(index)>=3)
{
if (osip_strncasecmp(index-5, "auth-int",8) == 0)
{
auth_int_flag = 1;
goto auth_withqop;
}
index = strchr(index+1,'i');
}
index = strchr(pszQop,'a');
while (index!=NULL&&strlen(index)>=4)
{
if (osip_strncasecmp(index, "auth",4) == 0)
{
/* and in the case of a unknown token
like auth1. It is not auth, but this
implementation will think it is!??
This is may not happen but it's a bug!
*/
goto auth_withqop;
}
index = strchr(index+1,'a');
}
goto auth_withoutqop;
}
auth_withoutqop:
MD5Final((unsigned char*)HA2, &Md5Ctx);
CvtHex(HA2, HA2Hex);
/* calculate response */
MD5Init(&Md5Ctx);
MD5Update(&Md5Ctx, (unsigned char*)HA1, HASHHEXLEN);
MD5Update(&Md5Ctx, (unsigned char*)":", 1);
MD5Update(&Md5Ctx, (unsigned char*)pszNonce, strlen(pszNonce));
MD5Update(&Md5Ctx, (unsigned char*)":", 1);
goto end;
auth_withqop:
if (auth_int_flag)
{
MD5Update(&Md5Ctx, (unsigned char*)":", 1);
MD5Update(&Md5Ctx, (unsigned char*)HEntity, HASHHEXLEN);
}
MD5Final((unsigned char*)HA2, &Md5Ctx);
CvtHex(HA2, HA2Hex);
/* calculate response */
MD5Init(&Md5Ctx);
MD5Update(&Md5Ctx, (unsigned char*)HA1, HASHHEXLEN);
MD5Update(&Md5Ctx, (unsigned char*)":", 1);
MD5Update(&Md5Ctx, (unsigned char*)pszNonce, strlen(pszNonce));
MD5Update(&Md5Ctx, (unsigned char*)":", 1);
MD5Update(&Md5Ctx, (unsigned char*)pszNonceCount, strlen(pszNonceCount));
MD5Update(&Md5Ctx, (unsigned char*)":", 1);
MD5Update(&Md5Ctx, (unsigned char*)pszCNonce, strlen(pszCNonce));
MD5Update(&Md5Ctx, (unsigned char*)":", 1);
MD5Update(&Md5Ctx, (unsigned char*)pszQop, strlen(pszQop));
MD5Update(&Md5Ctx, (unsigned char*)":", 1);
end:
MD5Update(&Md5Ctx, (unsigned char*)HA2Hex, HASHHEXLEN);
MD5Final((unsigned char*)RespHash, &Md5Ctx);
CvtHex(RespHash, Response);
}
int
__eXosip_create_authorization_header(osip_message_t *previous_answer,
const char *rquri, const char *username,
const char *passwd,
osip_authorization_t **auth)
{
static int nc = 1;
osip_authorization_t *aut;
osip_www_authenticate_t *wa=NULL;
osip_message_get_www_authenticate(previous_answer,0,&wa);
/* make some test */
if (passwd==NULL)
return -1;
if (wa==NULL||wa->auth_type==NULL
||(wa->realm==NULL)||(wa->nonce==NULL)) {
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_ERROR, NULL,
"www_authenticate header is not acceptable.\n"));
return -1;
}
if (0!=osip_strcasecmp("Digest",wa->auth_type))
{
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_ERROR, NULL,
"Authentication method not supported. (Digest only).\n"));
return -1;
}
/* "MD5" is invalid, but some servers use it. */
if (wa->algorithm!=NULL&&0!=osip_strcasecmp("MD5",wa->algorithm)&&0!=osip_strcasecmp("\"MD5\"",wa->algorithm))
{
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_ERROR, NULL,
"Authentication method not supported. (Digest only).\n"));
return -1;
}
if (0!=osip_authorization_init(&aut))
{
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_ERROR, NULL,
"allocation with authorization_init failed.\n"));
return -1;
}
/* just copy some feilds from response to new request */
osip_authorization_set_auth_type(aut,osip_strdup("Digest"));
osip_authorization_set_realm(aut,osip_strdup(osip_www_authenticate_get_realm(wa)));
osip_authorization_set_nonce(aut,osip_strdup(osip_www_authenticate_get_nonce(wa)));
if (osip_www_authenticate_get_opaque(wa)!=NULL)
osip_authorization_set_opaque(aut,osip_strdup(osip_www_authenticate_get_opaque(wa)));
/* copy the username field in new request */
aut->username = osip_malloc(strlen(username)+3);
sprintf(aut->username,"\"%s\"",username);
{
char *tmp = osip_malloc(strlen(rquri)+3);
sprintf(tmp,"\"%s\"",rquri);
osip_authorization_set_uri(aut,tmp);
}
osip_authorization_set_algorithm(aut,osip_strdup("MD5"));
{
char * pszNonce = osip_strdup_without_quote(osip_www_authenticate_get_nonce(wa));
char * pszCNonce = osip_strdup_without_quote("abcdefghi");
char * pszUser = osip_strdup_without_quote(username);
char * pszRealm = osip_strdup_without_quote(osip_authorization_get_realm(aut));
const char * pszPass=NULL;
char * pszAlg = osip_strdup("MD5");
char *szNonceCount = NULL;
char * pszMethod = osip_strdup_without_quote(previous_answer->cseq->method);
char * pszQop = NULL;
char * pszURI = osip_strdup_without_quote(rquri);
szNonceCount = osip_strdup("00000000");
sprintf(szNonceCount, "%08d", nc++);
HASHHEX HA1;
HASHHEX HA2 = "";
HASHHEX Response;
pszPass=passwd;
if (osip_www_authenticate_get_qop_options(wa)!=NULL)
{
pszQop = osip_strdup_without_quote(osip_www_authenticate_get_qop_options(wa));
osip_authorization_set_message_qop(aut,osip_strdup(pszQop));
osip_authorization_set_nonce_count(aut,osip_strdup(szNonceCount));
osip_authorization_set_cnonce(aut,osip_strdup("\"abcdefghi\""));
osip_authorization_set_algorithm(aut,osip_strdup(pszAlg));
}
DigestCalcHA1(pszAlg, pszUser, pszRealm, pszPass, pszNonce,
pszCNonce, HA1);
DigestCalcResponse(HA1, pszNonce, szNonceCount, pszCNonce, pszQop,
pszMethod, pszURI, HA2, Response);
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_INFO4, NULL,
"Response in authorization |%s|\n", Response));
{
char *resp = osip_malloc(35);
sprintf(resp,"\"%s\"",Response);
osip_authorization_set_response(aut,resp);
}
osip_free(pszAlg); /* xkd, 2004-5-13*/
osip_free(pszNonce);
osip_free(pszCNonce);
osip_free(pszRealm);
osip_free(pszQop);
osip_free(szNonceCount);
osip_free(pszUser);
osip_free(pszMethod);
osip_free(pszURI);
}
*auth = aut;
return 0;
}
int
__eXosip_create_proxy_authorization_header(osip_message_t *previous_answer,
const char *rquri,
const char *username,
const char *passwd,
osip_proxy_authorization_t **auth)
{
osip_proxy_authorization_t *aut;
osip_proxy_authenticate_t *wa;
osip_message_get_proxy_authenticate(previous_answer,0,&wa);
/* make some test */
if (passwd==NULL)
return -1;
if (wa==NULL||wa->auth_type==NULL
||(wa->realm==NULL)||(wa->nonce==NULL))
{
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_ERROR, NULL,
"www_authenticate header is not acceptable.\n"));
return -1;
}
if (0!=osip_strcasecmp("Digest",wa->auth_type))
{
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_ERROR, NULL,
"Authentication method not supported. (Digest only).\n"));
return -1;
}
/* "MD5" is invalid, but some servers use it. */
if (wa->algorithm!=NULL&&0!=osip_strcasecmp("MD5",wa->algorithm)&&0!=osip_strcasecmp("\"MD5\"",wa->algorithm))
{
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_ERROR, NULL,
"Authentication method not supported. (MD5 Digest only).\n"));
return -1;
}
if (0!=osip_proxy_authorization_init(&aut))
{
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_ERROR, NULL,
"allocation with authorization_init failed.\n"));
return -1;
}
/* just copy some feilds from response to new request */
osip_proxy_authorization_set_auth_type(aut,osip_strdup("Digest"));
osip_proxy_authorization_set_realm(aut,osip_strdup(osip_proxy_authenticate_get_realm(wa)));
osip_proxy_authorization_set_nonce(aut,osip_strdup(osip_proxy_authenticate_get_nonce(wa)));
if (osip_proxy_authenticate_get_opaque(wa)!=NULL)
osip_proxy_authorization_set_opaque(aut,osip_strdup(osip_proxy_authenticate_get_opaque(wa)));
/* copy the username field in new request */
aut->username = osip_malloc(strlen(username)+3);
sprintf(aut->username,"\"%s\"",username);
{
char *tmp = osip_malloc(strlen(rquri)+3);
sprintf(tmp,"\"%s\"",rquri);
osip_proxy_authorization_set_uri(aut,tmp);
}
osip_proxy_authorization_set_algorithm(aut,osip_strdup("MD5"));
{
char * pszNonce = NULL;
char * pszCNonce= NULL ;
const char * pszUser = username;
char * pszRealm = osip_strdup_without_quote(osip_proxy_authorization_get_realm(aut));
const char * pszPass = NULL;
char * pszAlg = osip_strdup("MD5");
char *szNonceCount = NULL;
char * pszMethod = previous_answer->cseq->method;
char * pszQop = NULL;
const char * pszURI = rquri;
HASHHEX HA1;
HASHHEX HA2 = "";
HASHHEX Response;
pszPass=passwd;
if (osip_www_authenticate_get_nonce(wa)==NULL)
return -1;
pszNonce = osip_strdup_without_quote(osip_www_authenticate_get_nonce(wa));
/* should upgrade szNonceCount */
/* should add szNonceCount in aut*/
/* should upgrade pszCNonce */
/* should add pszCNonce in aut */
if (osip_proxy_authenticate_get_qop_options(wa)!=NULL)
{
szNonceCount = osip_strdup("00000001");
/* MUST be incremented on each */
pszQop = osip_strdup(osip_proxy_authenticate_get_qop_options(wa));
pszCNonce = osip_strdup("234abcc436e2667097e7fe6eia53e8dd");
}
DigestCalcHA1(pszAlg, pszUser, pszRealm, pszPass, pszNonce,
pszCNonce, HA1);
DigestCalcResponse(HA1, pszNonce, szNonceCount, pszCNonce, pszQop,
pszMethod, pszURI, HA2, Response);
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_INFO4, NULL,
"Response in proxy_authorization |%s|\n", Response));
{
char *resp = osip_malloc(35);
sprintf(resp,"\"%s\"",Response);
osip_proxy_authorization_set_response(aut,resp);
}
osip_free(pszAlg); /* xkd, 2004-5-13*/
osip_free(pszNonce);
osip_free(pszCNonce);
osip_free(pszRealm);
osip_free(pszQop);
osip_free(szNonceCount);
}
*auth = aut;
return 0;
}

122
linphone/exosip/jcall.c Normal file
View file

@ -0,0 +1,122 @@
/*
eXosip - This is the eXtended osip library.
Copyright (C) 2002, 2003 Aymeric MOIZARD - jack@atosc.org
eXosip is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
eXosip is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef ENABLE_MPATROL
#include <mpatrol.h>
#endif
#include "eXosip2.h"
#include <eXosip_cfg.h>
extern eXosip_t eXosip;
int eXosip_call_find(int cid, eXosip_call_t **jc)
{
for (*jc=eXosip.j_calls; *jc!=NULL; *jc=(*jc)->next)
{
if ((*jc)->c_id==cid)
{
return 0;
}
}
*jc = NULL;
return -1;
}
int
eXosip_call_init(eXosip_call_t **jc)
{
*jc = (eXosip_call_t *)osip_malloc(sizeof(eXosip_call_t));
if (*jc == NULL) return -1;
memset(*jc, 0, sizeof(eXosip_call_t));
(*jc)->c_id = -1; /* make sure the eXosip_update will assign a valid id to the call */
osip_negotiation_ctx_init(&(*jc)->c_ctx);
return 0;
}
void
__eXosip_call_remove_dialog_reference_in_call(eXosip_call_t *jc, eXosip_dialog_t *jd)
{
eXosip_dialog_t *_jd;
jinfo_t *ji;
if (jc==NULL) return;
if (jd==NULL) return;
for (_jd = jc->c_dialogs; _jd!=NULL; _jd=jc->c_dialogs)
{
if (jd==_jd)
break;
}
if (_jd==NULL)
{
/* dialog not found??? */
}
ji = osip_transaction_get_your_instance(jc->c_inc_tr);
if (ji!=NULL && ji->jd==jd)
ji->jd=NULL;
ji = osip_transaction_get_your_instance(jc->c_out_tr);
if (ji!=NULL && ji->jd==jd)
ji->jd=NULL;
}
void
eXosip_call_free(eXosip_call_t *jc)
{
/* ... */
eXosip_dialog_t *jd;
for (jd = jc->c_dialogs; jd!=NULL; jd=jc->c_dialogs)
{
REMOVE_ELEMENT(jc->c_dialogs, jd);
eXosip_dialog_free(jd);
}
__eXosip_delete_jinfo(jc->c_inc_tr);
__eXosip_delete_jinfo(jc->c_out_tr);
if (jc->c_inc_tr!=NULL)
osip_list_add(eXosip.j_transactions, jc->c_inc_tr, 0);
if (jc->c_out_tr!=NULL)
osip_list_add(eXosip.j_transactions, jc->c_out_tr, 0);
__eXosip_delete_jinfo(jc->c_inc_options_tr);
__eXosip_delete_jinfo(jc->c_out_options_tr);
if (jc->c_inc_options_tr!=NULL)
osip_list_add(eXosip.j_transactions, jc->c_inc_options_tr, 0);
if (jc->c_out_options_tr!=NULL)
osip_list_add(eXosip.j_transactions, jc->c_out_options_tr, 0);
osip_negotiation_ctx_free(jc->c_ctx);
osip_free(jc);
}
void
eXosip_call_set_subject(eXosip_call_t *jc, char *subject)
{
if (jc==NULL||subject==NULL||subject[0]=='\0') return;
snprintf(jc->c_subject, 99, "%s", subject);
}

1972
linphone/exosip/jcallback.c Normal file

File diff suppressed because it is too large Load diff

209
linphone/exosip/jdialog.c Normal file
View file

@ -0,0 +1,209 @@
/*
eXosip - This is the eXtended osip library.
Copyright (C) 2002, 2003 Aymeric MOIZARD - jack@atosc.org
eXosip is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
eXosip is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef ENABLE_MPATROL
#include <mpatrol.h>
#endif
#include "eXosip2.h"
extern eXosip_t eXosip;
void eXosip_dialog_set_state(eXosip_dialog_t *jd, int state)
{
jd->d_STATE = state;
}
int eXosip_call_dialog_find(int jid, eXosip_call_t **jc, eXosip_dialog_t **jd)
{
for (*jc=eXosip.j_calls; *jc!=NULL; *jc=(*jc)->next)
{
for (*jd=(*jc)->c_dialogs; *jd!=NULL; *jd=(*jd)->next)
{
if ((*jd)->d_id==jid)
return 0;
}
}
*jd = NULL;
*jc = NULL;
return -1;
}
int eXosip_notify_dialog_find(int nid, eXosip_notify_t **jn, eXosip_dialog_t **jd)
{
for (*jn=eXosip.j_notifies; *jn!=NULL; *jn=(*jn)->next)
{
for (*jd=(*jn)->n_dialogs; *jd!=NULL; *jd=(*jd)->next)
{
if ((*jd)->d_id==nid)
return 0;
}
}
*jd = NULL;
*jn = NULL;
return -1;
}
int eXosip_subscribe_dialog_find(int sid, eXosip_subscribe_t **js, eXosip_dialog_t **jd)
{
for (*js=eXosip.j_subscribes; *js!=NULL; *js=(*js)->next)
{
*jd=NULL;
if ((*js)->s_id==sid)
return 0;
for (*jd=(*js)->s_dialogs; *jd!=NULL; *jd=(*jd)->next)
{
if ((*jd)->d_id==sid)
return 0;
}
}
*jd = NULL;
*js = NULL;
return -1;
}
int eXosip_dialog_set_200ok(eXosip_dialog_t *jd, osip_message_t *_200Ok)
{
int i;
if (jd==NULL) return -1;
i = osip_message_clone(_200Ok, &(jd->d_200Ok));
if (i!=0) {
return -1;
}
return 0;
}
int eXosip_dialog_init_as_uac(eXosip_dialog_t **_jd, osip_message_t *_200Ok)
{
int i;
eXosip_dialog_t *jd;
*_jd = NULL;
jd = (eXosip_dialog_t *) osip_malloc(sizeof(eXosip_dialog_t));
jd->d_id = -1; /* not yet available to user */
jd->d_STATE = JD_EMPTY;
if (MSG_IS_REQUEST(_200Ok))
{
i = osip_dialog_init_as_uac_with_remote_request(&(jd->d_dialog), _200Ok, -1);
}
else
{ /* normal usage with response */
i = osip_dialog_init_as_uac(&(jd->d_dialog), _200Ok);
}
if (i!=0)
{
osip_free(jd);
return -1;
}
jd->media_lines = (osip_list_t*) osip_malloc(sizeof(osip_list_t));
osip_list_init(jd->media_lines);
jd->d_timer = time(NULL);
jd->d_200Ok = NULL;
jd->d_ack = NULL;
jd->next = NULL;
jd->parent = NULL;
jd->d_out_trs = (osip_list_t*) osip_malloc(sizeof(osip_list_t));
osip_list_init(jd->d_out_trs);
jd->d_inc_trs = (osip_list_t*) osip_malloc(sizeof(osip_list_t));
osip_list_init(jd->d_inc_trs);
/* jd->d_bh = sdp_handler_new(); */
*_jd = jd;
return 0;
}
int eXosip_dialog_init_as_uas(eXosip_dialog_t **_jd, osip_message_t *_invite, osip_message_t *_200Ok)
{
int i;
eXosip_dialog_t *jd;
*_jd = NULL;
jd = (eXosip_dialog_t *) osip_malloc(sizeof(eXosip_dialog_t));
jd->d_id = -1; /* not yet available to user */
jd->d_STATE = JD_EMPTY;
i = osip_dialog_init_as_uas(&(jd->d_dialog), _invite, _200Ok);
if (i!=0)
{
osip_free(jd);
return -1;
}
jd->media_lines = (osip_list_t*) osip_malloc(sizeof(osip_list_t));
osip_list_init(jd->media_lines);
jd->d_timer = time(NULL);
jd->d_200Ok = NULL;
jd->d_ack = NULL;
jd->next = NULL;
jd->parent = NULL;
jd->d_out_trs = (osip_list_t*) osip_malloc(sizeof(osip_list_t));
osip_list_init(jd->d_out_trs);
jd->d_inc_trs = (osip_list_t*) osip_malloc(sizeof(osip_list_t));
osip_list_init(jd->d_inc_trs);
#ifdef SUPPORT_MSN
/* bugguy MSN */
jd->d_dialog->local_cseq = 1;
#endif
/* jd->d_bh = sdp_handler_new(); */
*_jd = jd;
return 0;
}
void eXosip_dialog_free(eXosip_dialog_t *jd)
{
while (!osip_list_eol(jd->d_inc_trs, 0))
{
osip_transaction_t *tr;
tr = (osip_transaction_t*) osip_list_get(jd->d_inc_trs, 0);
osip_list_remove(jd->d_inc_trs, 0);
__eXosip_delete_jinfo(tr);
osip_list_add(eXosip.j_transactions, tr, 0);
}
while (!osip_list_eol(jd->d_out_trs, 0))
{
osip_transaction_t *tr;
tr = (osip_transaction_t*) osip_list_get(jd->d_out_trs, 0);
osip_list_remove(jd->d_out_trs, 0);
__eXosip_delete_jinfo(tr);
osip_list_add(eXosip.j_transactions, tr, 0);
}
osip_message_free(jd->d_200Ok);
osip_message_free(jd->d_ack);
osip_dialog_free(jd->d_dialog);
while (!osip_list_eol(jd->media_lines, 0))
{
char *tmp = osip_list_get(jd->media_lines, 0);
osip_list_remove(jd->media_lines, 0);
osip_free(tmp);
}
osip_free(jd->media_lines);
osip_free(jd->d_out_trs);
osip_free(jd->d_inc_trs);
osip_free(jd);
}

949
linphone/exosip/jevents.c Normal file
View file

@ -0,0 +1,949 @@
/*
eXosip - This is the eXtended osip library.
Copyright (C) 2002, 2003 Aymeric MOIZARD - jack@atosc.org
eXosip is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
eXosip is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef ENABLE_MPATROL
#include <mpatrol.h>
#endif
#include "eXosip2.h"
#include <eXosip.h>
#include <osip2/osip_condv.h>
extern eXosip_t eXosip;
static void fill_dialog_params(eXosip_event_t *je, osip_dialog_t *dialog)
{
char *tmp;
if (dialog->remote_uri!=NULL){
osip_to_to_str(dialog->remote_uri, &tmp);
if (tmp!=NULL)
{
snprintf(je->remote_uri, 255, "%s", tmp);
osip_free(tmp);
}
}
if (dialog->local_uri!=NULL)
{
osip_to_to_str(dialog->local_uri, &tmp);
if (tmp!=NULL)
{
snprintf(je->local_uri, 255, "%s", tmp);
osip_free(tmp);
}
}
if (dialog->remote_contact_uri!=NULL){
osip_contact_to_str(dialog->remote_contact_uri,&tmp);
if (tmp!=NULL){
snprintf(je->remote_contact,255,"%s",tmp);
osip_free(tmp);
}
}
}
eXosip_event_t *
eXosip_event_init_for_call(int type,
eXosip_call_t *jc,
eXosip_dialog_t *jd)
{
eXosip_event_t *je;
eXosip_event_init(&je, type);
if (je==NULL) return NULL;
je->jc = jc;
je->jd = jd;
je->cid = jc->c_id;
if (jd!=NULL)
je->did = jd->d_id;
je->external_reference = jc->external_reference;
/* fill in usefull info */
if (type==EXOSIP_CALL_NEW
|| type==EXOSIP_CALL_ACK
|| type==EXOSIP_CALL_NOANSWER
|| type==EXOSIP_CALL_PROCEEDING
|| type==EXOSIP_CALL_RINGING
|| type==EXOSIP_CALL_ANSWERED
|| type==EXOSIP_CALL_REDIRECTED
|| type==EXOSIP_CALL_REQUESTFAILURE
|| type==EXOSIP_CALL_SERVERFAILURE
|| type==EXOSIP_CALL_GLOBALFAILURE
|| type==EXOSIP_OPTIONS_NOANSWER
|| type==EXOSIP_OPTIONS_PROCEEDING
|| type==EXOSIP_OPTIONS_ANSWERED
|| type==EXOSIP_OPTIONS_REDIRECTED
|| type==EXOSIP_OPTIONS_REQUESTFAILURE
|| type==EXOSIP_OPTIONS_SERVERFAILURE
|| type==EXOSIP_OPTIONS_GLOBALFAILURE
|| type==EXOSIP_OPTIONS_NEW
|| type==EXOSIP_INFO_NOANSWER
|| type==EXOSIP_INFO_PROCEEDING
|| type==EXOSIP_INFO_ANSWERED
|| type==EXOSIP_INFO_REDIRECTED
|| type==EXOSIP_INFO_REQUESTFAILURE
|| type==EXOSIP_INFO_SERVERFAILURE
|| type==EXOSIP_INFO_GLOBALFAILURE
|| type==EXOSIP_INFO_NEW
|| type==EXOSIP_CALL_CANCELLED
|| type==EXOSIP_CALL_TIMEOUT
|| type==EXOSIP_CALL_HOLD
|| type==EXOSIP_CALL_OFFHOLD
|| type==EXOSIP_CALL_CLOSED
|| type==EXOSIP_CALL_STARTAUDIO
|| type==EXOSIP_CALL_REFERED
|| type==EXOSIP_CALL_REFER_STATUS
|| type==EXOSIP_CALL_RELEASED)
{
if (jc->c_sdp_port[0]!='\0')
je->local_sdp_audio_port = osip_atoi(jc->c_sdp_port);
if (jd!=NULL&&jd->d_dialog!=NULL)
{
osip_transaction_t *tr;
osip_header_t *subject;
char *tmp;
fill_dialog_params(je,jd->d_dialog);
if (type==EXOSIP_OPTIONS_NOANSWER
|| type==EXOSIP_OPTIONS_PROCEEDING
|| type==EXOSIP_OPTIONS_ANSWERED
|| type==EXOSIP_OPTIONS_REDIRECTED
|| type==EXOSIP_OPTIONS_REQUESTFAILURE
|| type==EXOSIP_OPTIONS_SERVERFAILURE
|| type==EXOSIP_OPTIONS_GLOBALFAILURE
|| type==EXOSIP_OPTIONS_NEW)
tr = eXosip_find_last_options(jc, jd);
else if (type==EXOSIP_INFO_NOANSWER
|| type==EXOSIP_INFO_PROCEEDING
|| type==EXOSIP_INFO_ANSWERED
|| type==EXOSIP_INFO_REDIRECTED
|| type==EXOSIP_INFO_REQUESTFAILURE
|| type==EXOSIP_INFO_SERVERFAILURE
|| type==EXOSIP_INFO_GLOBALFAILURE
|| type==EXOSIP_INFO_NEW)
tr = eXosip_find_last_info(jc, jd);
else if (type==EXOSIP_CALL_REFERED)
tr = eXosip_find_last_refer(jc, jd);
else if (type==EXOSIP_CALL_REFER_STATUS)
tr = eXosip_find_last_inc_notify_for_refer(jc, jd);
else
tr = eXosip_find_last_invite(jc, jd);
if (tr!=NULL && tr->orig_request!=NULL)
{
osip_message_get_subject(tr->orig_request, 0, &subject);
if (subject!=NULL && subject->hvalue!=NULL && subject->hvalue[0]!='\0')
snprintf(je->subject, 255, "%s", subject->hvalue);
osip_message_header_get_byname(tr->orig_request, "refer-to", 0,
&subject);
if (subject!=NULL && subject->hvalue!=NULL && subject->hvalue[0]!='\0')
snprintf(je->refer_to, 255, "%s", subject->hvalue);
osip_uri_to_str(tr->orig_request->req_uri, &tmp);
if (tmp!=NULL)
{
snprintf(je->req_uri, 255, "%s", tmp);
osip_free(tmp);
}
}
}else{
osip_transaction_t *tr;
char *tmp;
tr=eXosip_find_last_invite(jc,NULL);
/* no dialog established but we need to fill remote_contact */
if (tr!=NULL && tr->last_response!=NULL)
{
osip_contact_t *ctt=NULL;
snprintf(je->reason_phrase, 49, "%s", tr->last_response->reason_phrase);
je->status_code = tr->last_response->status_code;
osip_message_get_contact(tr->last_response,0,&ctt);
if (ctt){
tmp=NULL;
osip_contact_to_str(ctt,&tmp);
if (tmp){
strncpy(je->remote_contact,tmp,255);
}
}
}
}
}
return je;
}
int
eXosip_event_add_status(eXosip_event_t *je, osip_message_t *response)
{
if (response!=NULL && response->reason_phrase!=NULL)
{
snprintf(je->reason_phrase, 49, "%s", response->reason_phrase);
je->status_code = response->status_code;
}
return 0;
}
int
eXosip_event_add_sdp_info(eXosip_event_t *je, osip_message_t *message)
{
osip_content_type_t *ctt;
osip_mime_version_t *mv;
sdp_message_t *sdp;
osip_body_t *oldbody;
int pos;
int gotpayload = 0;
/*
search for remote_sdp_audio_port & remote_sdp_audio_ip
in the last SIP message
extract the payload to be used for connection either from negotioation context
or from the last SIP message
*/
if (message==NULL) return -1;
/* get content-type info */
ctt = osip_message_get_content_type(message);
mv = osip_message_get_mime_version(message);
if (mv==NULL && ctt==NULL)
return 0; /* previous message was not correct or empty */
if (mv!=NULL)
{
/* look for the SDP body */
/* ... */
}
else if (ctt!=NULL)
{
if (ctt->type==NULL || ctt->subtype==NULL)
/* it can be application/sdp or mime... */
return -1;
if (osip_strcasecmp(ctt->type, "application")!=0 ||
osip_strcasecmp(ctt->subtype, "sdp")!=0 )
{ return -1; }
}
if (je->jc)
{
int pl = eXosip_retrieve_sdp_negotiation_result(je->jc->c_ctx, je->payload_name, sizeof(je->payload_name));
if (pl >= 0)
{
je->payload = pl;
gotpayload = 1;
}
}
sdp = NULL;
pos = 0;
while (!osip_list_eol(message->bodies, pos))
{
int i;
oldbody = (osip_body_t *)osip_list_get(message->bodies, pos);
pos++;
sdp_message_init(&sdp);
i = sdp_message_parse(sdp,oldbody->body);
if (i==0)
{
int len = strlen(oldbody->body);
if (len<999)
osip_strncpy(je->sdp_body, oldbody->body, len);
else
osip_strncpy(je->sdp_body, oldbody->body, 999);
break;
}
sdp_message_free(sdp);
sdp = NULL;
}
if (sdp!=NULL)
{
int j=0;
if (sdp->c_connection !=NULL
&& sdp->c_connection->c_addr !=NULL )
{
snprintf(je->remote_sdp_audio_ip, 49, "%s",
sdp->c_connection->c_addr);
}
for (j=0; !osip_list_eol(sdp->m_medias, j); j++)
{
sdp_media_t *med = (sdp_media_t*) osip_list_get(sdp->m_medias, j);
if (med==NULL)
{
snprintf(je->remote_sdp_audio_ip, 49, "Y a probleme!");
}
if (med->m_media!=NULL &&
0==osip_strcasecmp(med->m_media, "audio"))
{
sdp_connection_t *conn;
int pos_attr;
char *payload = (char *) osip_list_get (med->m_payloads, 0);
if (!gotpayload)
je->payload = 0;
if (!gotpayload && payload!=NULL)
{
je->payload = osip_atoi(payload);
/* copy payload name! */
for (pos_attr=0;
!osip_list_eol(med->a_attributes, pos_attr);
pos_attr++)
{
sdp_attribute_t *attr;
attr = (sdp_attribute_t *)osip_list_get(med->a_attributes, pos_attr);
if (0==osip_strncasecmp(attr->a_att_field, "rtpmap", 6))
{
if ((je->payload<10 &&
0==osip_strncasecmp(attr->a_att_value, payload, 1))
||(je->payload>9 && je->payload<100 &&
0==osip_strncasecmp(attr->a_att_value, payload, 2))
||(je->payload>100 && je->payload<128 &&
0==osip_strncasecmp(attr->a_att_value, payload, 3)))
{
snprintf(je->payload_name, 49, "%s", attr->a_att_value);
}
}
}
}
je->remote_sdp_audio_port = osip_atoi(med->m_port);
conn = (sdp_connection_t*) osip_list_get(med->c_connections, 0);
if (conn!=NULL && conn->c_addr!=NULL)
{
snprintf(je->remote_sdp_audio_ip, 49, "%s",
conn->c_addr);
}
sdp_message_free(sdp);
return 0;
}
}
sdp_message_free(sdp);
}
return -1;
}
eXosip_event_t *
eXosip_event_init_for_subscribe(int type,
eXosip_subscribe_t *js,
eXosip_dialog_t *jd)
{
char *tmp;
eXosip_event_t *je;
eXosip_event_init(&je, type);
if (je==NULL) return NULL;
je->js = js;
je->jd = jd;
je->sid = js->s_id;
if (jd!=NULL)
je->did = jd->d_id;
je->ss_status = js->s_ss_status;
je->online_status = js->s_online_status;
je->ss_reason = js->s_ss_reason;
/* je->external_reference = js->external_reference; */
if (jd!=NULL&&jd->d_dialog!=NULL)
{
fill_dialog_params(je,jd->d_dialog);
}
/* fill in usefull info */
if (type==EXOSIP_SUBSCRIPTION_NEW
|| type==EXOSIP_SUBSCRIPTION_NOANSWER
|| type==EXOSIP_SUBSCRIPTION_PROCEEDING
|| type==EXOSIP_SUBSCRIPTION_ANSWERED
|| type==EXOSIP_SUBSCRIPTION_REDIRECTED
|| type==EXOSIP_SUBSCRIPTION_REQUESTFAILURE
|| type==EXOSIP_SUBSCRIPTION_SERVERFAILURE
|| type==EXOSIP_SUBSCRIPTION_GLOBALFAILURE
|| type==EXOSIP_SUBSCRIPTION_RELEASED)
{
if (jd!=NULL&&jd->d_dialog!=NULL)
{
osip_transaction_t *tr;
tr = eXosip_find_last_out_subscribe(js, jd);
if (tr!=NULL && tr->orig_request!=NULL)
{
osip_uri_to_str(tr->orig_request->req_uri, &tmp);
if (tmp!=NULL)
{
snprintf(je->req_uri, 255, "%s", tmp);
osip_free(tmp);
}
}
if (tr!=NULL && tr->last_response!=NULL)
{
snprintf(je->reason_phrase, 49, "%s", tr->last_response->reason_phrase);
je->status_code = tr->last_response->status_code;
}
}
}
else if (type==EXOSIP_SUBSCRIPTION_NOTIFY)
{
if (jd!=NULL&&jd->d_dialog!=NULL)
{
osip_transaction_t *tr;
tr = eXosip_find_last_inc_notify(js, jd);
if (tr!=NULL && tr->orig_request!=NULL)
{
osip_uri_to_str(tr->orig_request->req_uri, &tmp);
if (tmp!=NULL)
{
snprintf(je->req_uri, 255, "%s", tmp);
osip_free(tmp);
}
}
if (tr!=NULL && tr->last_response!=NULL)
{
snprintf(je->reason_phrase, 49, "%s", tr->last_response->reason_phrase);
je->status_code = tr->last_response->status_code;
}
}
}
return je;
}
eXosip_event_t *
eXosip_event_init_for_notify(int type,
eXosip_notify_t *jn,
eXosip_dialog_t *jd)
{
eXosip_event_t *je;
eXosip_event_init(&je, type);
if (je==NULL) return NULL;
je->jn = jn;
je->jd = jd;
je->nid = jn->n_id;
if (jd!=NULL)
je->did = jd->d_id;
je->ss_status = jn->n_ss_status;
je->online_status = jn->n_online_status;
je->ss_reason = jn->n_ss_reason;
/*je->external_reference = jc->external_reference; */
/* fill in usefull info */
if (type==EXOSIP_IN_SUBSCRIPTION_NEW
|| type==EXOSIP_IN_SUBSCRIPTION_RELEASED)
{
if (jd!=NULL&&jd->d_dialog!=NULL)
{
osip_transaction_t *tr;
char *tmp;
fill_dialog_params(je,jd->d_dialog);
tr = eXosip_find_last_inc_subscribe(jn, jd);
if (tr!=NULL && tr->orig_request!=NULL)
{
osip_uri_to_str(tr->orig_request->req_uri, &tmp);
if (tmp!=NULL)
{
snprintf(je->req_uri, 255, "%s", tmp);
osip_free(tmp);
}
}
if (tr!=NULL && tr->last_response!=NULL)
{
snprintf(je->reason_phrase, 49, "%s", tr->last_response->reason_phrase);
je->status_code = tr->last_response->status_code;
}
}
}
return je;
}
eXosip_event_t *
eXosip_event_init_for_reg(int type,
eXosip_reg_t *jr)
{
eXosip_event_t *je;
eXosip_event_init(&je, type);
if (je==NULL) return NULL;
je->jr = jr;
je->rid = jr->r_id;
snprintf(je->remote_uri, 255, "%s", jr->r_aor);
snprintf(je->req_uri, 255, "%s", jr->r_registrar);
return je;
}
eXosip_event_t *
eXosip_event_init_for_message(int type, osip_transaction_t *tr,
osip_message_t *sip)
{
eXosip_event_t *je;
eXosip_event_init(&je, type);
if (je==NULL) return NULL;
/* fill in usefull info */
{
char *tmp;
/* Request URI */
osip_uri_to_str(sip->req_uri, &tmp);
if (tmp!=NULL)
{
snprintf(je->req_uri, 255, "%s", tmp);
osip_free(tmp);
}
/* FROM & TO */
if (sip->from != NULL)
{
osip_from_to_str(sip->from, &tmp);
if (tmp!=NULL)
{
snprintf(je->remote_uri, 255, "%s", tmp);
osip_free(tmp);
}
}
if (sip->to != NULL)
{
osip_to_to_str(sip->to, &tmp);
if (tmp!=NULL)
{
snprintf(je->local_uri, 255, "%s", tmp);
osip_free(tmp);
}
}
}
return je;
}
int
eXosip_event_init(eXosip_event_t **je, int type)
{
*je = (eXosip_event_t *) osip_malloc(sizeof(eXosip_event_t));
if (*je==NULL) return -1;
memset(*je, 0, sizeof(eXosip_event_t));
(*je)->type = type;
if (type==EXOSIP_CALL_NOANSWER)
{
sprintf((*je)->textinfo, "No answer for this Call!");
}
else if (type==EXOSIP_CALL_PROCEEDING)
{
sprintf((*je)->textinfo, "Call is being processed!");
}
else if (type==EXOSIP_CALL_RINGING)
{
sprintf((*je)->textinfo, "Remote phone is ringing!");
}
else if (type==EXOSIP_CALL_ANSWERED)
{
sprintf((*je)->textinfo, "Remote phone has answered!");
}
else if (type==EXOSIP_CALL_REDIRECTED)
{
sprintf((*je)->textinfo, "Call is redirected!");
}
else if (type==EXOSIP_CALL_REQUESTFAILURE)
{
sprintf((*je)->textinfo, "4xx received for Call!");
}
else if (type==EXOSIP_CALL_SERVERFAILURE)
{
sprintf((*je)->textinfo, "5xx received for Call!");
}
else if (type==EXOSIP_CALL_GLOBALFAILURE)
{
sprintf((*je)->textinfo, "6xx received for Call!");
}
else if (type==EXOSIP_CALL_NEW)
{
sprintf((*je)->textinfo, "New call received!");
}
else if (type==EXOSIP_CALL_ACK)
{
sprintf((*je)->textinfo, "ACK received!");
}
else if (type==EXOSIP_CALL_CANCELLED)
{
sprintf((*je)->textinfo, "Call has been cancelled!");
}
else if (type==EXOSIP_CALL_TIMEOUT)
{
sprintf((*je)->textinfo, "Timeout. Gived up!");
}
else if (type==EXOSIP_CALL_HOLD)
{
sprintf((*je)->textinfo, "Call is on Hold!");
}
else if (type==EXOSIP_CALL_OFFHOLD)
{
sprintf((*je)->textinfo, "Call is off Hold!");
}
else if (type==EXOSIP_CALL_CLOSED)
{
sprintf((*je)->textinfo, "Bye Received!");
}
else if (type==EXOSIP_CALL_RELEASED)
{
sprintf((*je)->textinfo, "Call Context is released!");
}
else if (type==EXOSIP_REGISTRATION_SUCCESS)
{
sprintf((*je)->textinfo, "User is successfully registred!");
}
else if (type==EXOSIP_REGISTRATION_FAILURE)
{
sprintf((*je)->textinfo, "Registration failed!");
}
else if (type==EXOSIP_OPTIONS_NEW)
{
sprintf((*je)->textinfo, "New OPTIONS received!");
}
else if (type==EXOSIP_OPTIONS_NOANSWER)
{
sprintf((*je)->textinfo, "No answer for this OPTIONS!");
}
else if (type==EXOSIP_OPTIONS_PROCEEDING)
{
sprintf((*je)->textinfo, "OPTIONS is being processed!");
}
else if (type==EXOSIP_OPTIONS_ANSWERED)
{
sprintf((*je)->textinfo, "2xx received for OPTIONS!");
}
else if (type==EXOSIP_OPTIONS_REDIRECTED)
{
sprintf((*je)->textinfo, "3xx received for OPTIONS!");
}
else if (type==EXOSIP_OPTIONS_REQUESTFAILURE)
{
sprintf((*je)->textinfo, "4xx received for OPTIONS!");
}
else if (type==EXOSIP_OPTIONS_SERVERFAILURE)
{
sprintf((*je)->textinfo, "5xx received for OPTIONS!");
}
else if (type==EXOSIP_OPTIONS_GLOBALFAILURE)
{
sprintf((*je)->textinfo, "5xx received for OPTIONS!");
}
else if (type==EXOSIP_INFO_NEW)
{
sprintf((*je)->textinfo, "New INFO received!");
}
else if (type==EXOSIP_INFO_NOANSWER)
{
sprintf((*je)->textinfo, "No answer for this INFO!");
}
else if (type==EXOSIP_INFO_PROCEEDING)
{
sprintf((*je)->textinfo, "INFO is being processed!");
}
else if (type==EXOSIP_INFO_ANSWERED)
{
sprintf((*je)->textinfo, "2xx received for INFO!");
}
else if (type==EXOSIP_INFO_REDIRECTED)
{
sprintf((*je)->textinfo, "3xx received for INFO!");
}
else if (type==EXOSIP_INFO_REQUESTFAILURE)
{
sprintf((*je)->textinfo, "4xx received for INFO!");
}
else if (type==EXOSIP_INFO_SERVERFAILURE)
{
sprintf((*je)->textinfo, "5xx received for INFO!");
}
else if (type==EXOSIP_INFO_GLOBALFAILURE)
{
sprintf((*je)->textinfo, "6xx received for INFO!");
}
else if (type==EXOSIP_MESSAGE_NEW)
{
sprintf((*je)->textinfo, "New MESSAGE received!");
}
else if (type==EXOSIP_MESSAGE_SUCCESS)
{
sprintf((*je)->textinfo, "User has successfully received our MESSAGE!");
}
else if (type==EXOSIP_MESSAGE_FAILURE)
{
sprintf((*je)->textinfo, "Error received for our MESSAGE!");
}
else if (type==EXOSIP_SUBSCRIPTION_NEW)
{
sprintf((*je)->textinfo, "New SUBSCRIBE received!");
}
else if (type==EXOSIP_SUBSCRIPTION_NOANSWER)
{
sprintf((*je)->textinfo, "No answer for this SUBSCRIBE!");
}
else if (type==EXOSIP_SUBSCRIPTION_PROCEEDING)
{
sprintf((*je)->textinfo, "SUBSCRIBE is being processed!");
}
else if (type==EXOSIP_SUBSCRIPTION_ANSWERED)
{
sprintf((*je)->textinfo, "2xx received for SUBSCRIBE!");
}
else if (type==EXOSIP_SUBSCRIPTION_REDIRECTED)
{
sprintf((*je)->textinfo, "3xx received for SUBSCRIBE!");
}
else if (type==EXOSIP_SUBSCRIPTION_REQUESTFAILURE)
{
sprintf((*je)->textinfo, "4xx received for SUBSCRIBE!");
}
else if (type==EXOSIP_SUBSCRIPTION_SERVERFAILURE)
{
sprintf((*je)->textinfo, "5xx received for SUBSCRIBE!");
}
else if (type==EXOSIP_SUBSCRIPTION_GLOBALFAILURE)
{
sprintf((*je)->textinfo, "5xx received for SUBSCRIBE!");
}
else if (type==EXOSIP_SUBSCRIPTION_NOTIFY)
{
sprintf((*je)->textinfo, "NOTIFY request for subscription!");
}
else if (type==EXOSIP_SUBSCRIPTION_RELEASED)
{
sprintf((*je)->textinfo, "Subscription has terminate!");
}
else if (type==EXOSIP_IN_SUBSCRIPTION_NEW)
{
sprintf((*je)->textinfo, "New incoming SUBSCRIBE!");
}
else if (type==EXOSIP_IN_SUBSCRIPTION_RELEASED)
{
sprintf((*je)->textinfo, "Incoming Subscription has terminate!");
}
else
{
(*je)->textinfo[0] = '\0';
}
return 0;
}
void
eXosip_event_free(eXosip_event_t *je)
{
if (je==NULL) return;
if (je->i_ctt!=NULL)
osip_content_type_free(je->i_ctt);
if (je->i_bodies!=NULL)
{
int pos;
for (pos=0;!osip_list_eol(je->i_bodies, pos);)
{
osip_body_t *body;
body = (osip_body_t *)osip_list_get(je->i_bodies, pos);
osip_list_remove(je->i_bodies, pos);
osip_body_free(body);
}
}
osip_free(je);
}
eXosip_call_t *
eXosip_event_get_callinfo(eXosip_event_t *je)
{
return je->jc;
}
eXosip_dialog_t *
eXosip_event_get_dialoginfo(eXosip_event_t *je)
{
return je->jd;
}
eXosip_reg_t *
eXosip_event_get_reginfo(eXosip_event_t *je)
{
return je->jr;
}
eXosip_notify_t *
eXosip_event_get_notifyinfo(eXosip_event_t *je)
{
return je->jn;
}
eXosip_subscribe_t *
eXosip_event_get_subscribeinfo(eXosip_event_t *je)
{
return je->js;
}
int
eXosip_event_add(eXosip_event_t *je)
{
int i = osip_fifo_add(eXosip.j_events, (void *) je);
osip_cond_signal((struct osip_cond *)eXosip.j_cond);
__eXosip_wakeup_event();
return i;
}
#if 0
#ifdef CLOCK_REALTIME
/* if CLOCK_REALTIME exist, then clock_gettime should be defined */
#define OSIP_CLOCK_REALTIME CLOCK_REALTIME
void
__eXosip_clock_gettime(clockid_t cid, struct timespec *time)
{
clock_gettime(cid, time);
}
#elif defined (WIN32) || defined (_WIN32_WCE)
#include <sys/types.h>
#include <sys/timeb.h>
#define OSIP_CLOCK_REALTIME 4002
void
__eXosip_clock_gettime(unsigned int clock_id, struct timespec *time)
{
struct _timeb time_val;
if (clock_id != OSIP_CLOCK_REALTIME)
return;
_ftime (&time_val);
time->tv_sec = time_val.time;
time->tv_nsec = time_val.millitm * 1000000;
return;
}
#endif
#endif
eXosip_event_t *
eXosip_event_wait(int tv_s, int tv_ms)
{
eXosip_event_t *je = NULL;
#if 0 /* this does not seems to work. by now */
#if defined (CLOCK_REALTIME) || defined (WIN32) || defined (_WIN32_WCE)
int i;
struct timespec deadline;
struct timespec interval;
long tot_ms = (tv_s*1000) + tv_ms;
static struct osip_mutex *mlock = NULL;
if (mlock==NULL) mlock = osip_mutex_init();
je = (eXosip_event_t *) osip_fifo_tryget(eXosip.j_events);
if(je) return je;
interval.tv_sec = tot_ms / 1000;
interval.tv_nsec = (tot_ms % 1000) * 1000000L;
__eXosip_clock_gettime(OSIP_CLOCK_REALTIME, &deadline);
if ((deadline.tv_nsec += interval.tv_nsec) >= 1000000000L)
{
deadline.tv_nsec -= 1000000000L;
deadline.tv_sec += 1;
}
else
deadline.tv_nsec += interval.tv_nsec;
deadline.tv_sec += interval.tv_sec;
i = osip_cond_timedwait ((struct osip_cond *)eXosip.j_cond,
(struct osip_mutex *)mlock,
&deadline);
#endif
#else
/* basic replacement */
{
fd_set fdset;
struct timeval tv;
int max, i;
FD_ZERO(&fdset);
#if defined (WIN32) || defined (_WIN32_WCE)
FD_SET((unsigned int)jpipe_get_read_descr(eXosip.j_socketctl_event), &fdset);
#else
FD_SET(jpipe_get_read_descr(eXosip.j_socketctl_event), &fdset);
#endif
max = jpipe_get_read_descr(eXosip.j_socketctl_event);
tv.tv_sec = tv_s;
tv.tv_usec = tv_ms*1000;
je = (eXosip_event_t *) osip_fifo_tryget(eXosip.j_events);
if (je!=NULL) return je;
if (tv_s==0 && tv_ms==0)
return NULL;
i = select(max+1, &fdset, NULL, NULL, &tv);
if (i <= 0)
return 0;
if (FD_ISSET (jpipe_get_read_descr(eXosip.j_socketctl_event), &fdset))
{
char buf[500];
jpipe_read (eXosip.j_socketctl_event, buf, 499);
}
je = (eXosip_event_t *) osip_fifo_tryget(eXosip.j_events);
if (je!=NULL) return je;
}
#endif
return je;
}
eXosip_event_t *
eXosip_event_get()
{
eXosip_event_t *je;
je = (eXosip_event_t *) osip_fifo_get(eXosip.j_events);
return je;
}

311
linphone/exosip/jfreinds.c Normal file
View file

@ -0,0 +1,311 @@
/*
eXosip - This is the eXtended osip library.
Copyright (C) 2002, 2003 Aymeric MOIZARD - jack@atosc.org
eXosip is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
eXosip is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef ENABLE_MPATROL
#include <mpatrol.h>
#endif
#include "eXosip2.h"
#include <eXosip_cfg.h>
extern eXosip_t eXosip;
#ifndef EXOSIP_ETC_DIR
#define EXOSIP_ETC_DIR ".eXosip"
#endif
#ifndef EXOSIP_ADDFRIENDS_SH
#define EXOSIP_ADDFRIENDS_SH "eXosip_addfriend.sh"
#endif
static int jfriend_init(jfriend_t **fr, char *ch)
{
char *next;
int i;
*fr = (jfriend_t *)osip_malloc(sizeof(jfriend_t));
if (*fr==NULL) return -1;
i = jfriend_get_and_set_next_token(&((*fr)->f_nick), ch, &next);
if (i != 0)
goto jf_error1;
osip_clrspace ((*fr)->f_nick);
ch = next;
i = jfriend_get_and_set_next_token(&((*fr)->f_home), next, &next);
if (i != 0)
goto jf_error2;
osip_clrspace ((*fr)->f_home);
ch = next;
i = jfriend_get_and_set_next_token(&((*fr)->f_work), ch, &next);
if (i != 0)
goto jf_error3;
osip_clrspace ((*fr)->f_work);
ch = next;
i = jfriend_get_and_set_next_token(&((*fr)->f_email), ch, &next);
if (i != 0)
goto jf_error4;
osip_clrspace ((*fr)->f_email);
(*fr)->f_e164 = osip_strdup(next);
osip_clrspace ((*fr)->f_e164);
return 0;
jf_error4:
osip_free((*fr)->f_work);
jf_error3:
osip_free((*fr)->f_home);
jf_error2:
osip_free((*fr)->f_nick);
jf_error1:
osip_free(*fr);
*fr = NULL;
return -1;
}
int
jfriend_get_and_set_next_token (char **dest, char *buf, char **next)
{
char *end;
char *start;
*next = NULL;
/* find first non space and tab element */
start = buf;
while (((*start == ' ') || (*start == '\t')) && (*start != '\0')
&& (*start != '\r') && (*start != '\n') )
start++;
end = start+1;
while ((*end != '\0') && (*end != '\r') && (*end != '\n')
&& (*end != '\t') && (*end != '|'))
end++;
if ((*end == '\r') || (*end == '\n'))
/* we should continue normally only if this is the separator asked! */
return -1;
if (end == start)
return -1; /* empty value (or several space!) */
*dest = osip_malloc (end - (start) + 1);
osip_strncpy (*dest, start, end - start);
*next = end + 1; /* return the position right after the separator
*/
return 0;
}
void __jfriend_remove(char *nickname, char *home)
{
char *Home;
char command[256];
char *tmp = command;
int length = 0;
if (nickname!=NULL)
length = strlen(nickname);
Home = getenv("HOME");
if (Home==NULL)
return;
length = length + strlen(Home);
osip_clrspace(nickname);
osip_clrspace(home);
if (home!=NULL)
length = length + strlen(home);
else
return; /* MUST be set */
length = length + strlen(EXOSIP_ETC_DIR);
length = length + strlen("/jm_contact");
if (length>235) /* leave some room for SPACEs and \r\n */
return ;
sprintf(tmp , "%s %s/%s/jm_contact", EXOSIP_ADDFRIENDS_SH,
Home, EXOSIP_ETC_DIR);
tmp = tmp + strlen(tmp);
if (nickname!=NULL)
sprintf(tmp , " %s", nickname);
else
sprintf(tmp , " \"\"");
tmp = tmp + strlen(tmp);
if (home!=NULL)
sprintf(tmp , " %s", home);
else
sprintf(tmp , " \"\"");
sprintf(tmp , "delete");
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_ERROR, NULL,
"%s", command));
system(command);
}
void jfriend_add(char *nickname, char *home,
char *work, char *email, char *e164)
{
char *Home;
char command[256];
char *tmp = command;
int length = 0;
if (nickname!=NULL)
length = strlen(nickname);
Home = getenv("HOME");
if (Home==NULL)
return;
length = length + strlen(Home);
osip_clrspace(nickname);
osip_clrspace(home);
osip_clrspace(work);
osip_clrspace(email);
osip_clrspace(e164);
if (home!=NULL)
length = length + strlen(home);
else
return; /* MUST be set */
if (work!=NULL)
length = length + strlen(work);
if (email!=NULL)
length = length + strlen(email);
if (e164!=NULL)
length = length + strlen(e164);
length = length + strlen(EXOSIP_ETC_DIR);
length = length + strlen("/jm_contact");
if (length>235) /* leave some room for SPACEs and \r\n */
return ;
sprintf(tmp , "%s %s/%s/jm_contact", EXOSIP_ADDFRIENDS_SH,
Home, EXOSIP_ETC_DIR);
tmp = tmp + strlen(tmp);
if (nickname!=NULL)
sprintf(tmp , " %s", nickname);
else
sprintf(tmp , " \"\"");
tmp = tmp + strlen(tmp);
if (home!=NULL)
sprintf(tmp , " %s", home);
else
sprintf(tmp , " \"\"");
tmp = tmp + strlen(tmp);
if (work!=NULL)
sprintf(tmp , " %s", work);
else
sprintf(tmp , " \"\"");
tmp = tmp + strlen(tmp);
if (email!=NULL)
sprintf(tmp , " %s", email);
else
sprintf(tmp , " \"\"");
tmp = tmp + strlen(tmp);
if (e164!=NULL)
sprintf(tmp , " %s", e164);
else
sprintf(tmp , " \"\"");
/* fprintf(stderr, "%s", command); */
system(command);
}
void
jfriend_unload()
{
jfriend_t *fr;
if (eXosip.j_friends==NULL) return;
for (fr=eXosip.j_friends; fr!=NULL; fr=eXosip.j_friends)
{
REMOVE_ELEMENT(eXosip.j_friends,fr);
osip_free(fr->f_nick);
osip_free(fr->f_home);
osip_free(fr->f_work);
osip_free(fr->f_email);
osip_free(fr->f_e164);
osip_free(fr);
}
osip_free(eXosip.j_friends);
eXosip.j_friends=NULL;
return;
}
int
jfriend_load()
{
FILE *file;
char *s;
jfriend_t *fr;
int pos;
char *home;
char filename[255];
jfriend_unload();
home = getenv("HOME");
sprintf(filename, "%s/%s/%s", home, EXOSIP_ETC_DIR, "jm_contact");
file = fopen(filename, "r");
if (file==NULL) return -1;
s = (char *)osip_malloc(255*sizeof(char));
pos = 0;
while (NULL!=fgets(s, 254, file))
{
char *tmp = s;
while (*tmp!='\0' && *tmp!=' ') tmp++;
while (*tmp!='\0' && *tmp==' ') tmp++;
while (*tmp!='\0' && *tmp!=' ') tmp++;
tmp++; /* first usefull characters */
pos++;
jfriend_init(&fr, tmp);
if (fr!=NULL)
{ ADD_ELEMENT(eXosip.j_friends, fr); }
}
osip_free(s);
fclose(file);
return 0; /* ok */
}
char *
jfriend_get_home(int fid)
{
jfriend_t *fr;
for (fr = eXosip.j_friends; fr!=NULL ; fr=fr->next)
{
if (fid==0)
return osip_strdup(fr->f_home);
fid--;
}
return NULL;
}

277
linphone/exosip/jidentity.c Normal file
View file

@ -0,0 +1,277 @@
/*
eXosip - This is the eXtended osip library.
Copyright (C) 2002, 2003 Aymeric MOIZARD - jack@atosc.org
eXosip is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
eXosip is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef ENABLE_MPATROL
#include <mpatrol.h>
#endif
#include "eXosip2.h"
#include <eXosip_cfg.h>
extern eXosip_t eXosip;
#ifndef EXOSIP_ETC_DIR
#define EXOSIP_ETC_DIR ".eXosip"
#endif
#ifndef EXOSIP_ADDIDENTITYS_SH
#define EXOSIP_ADDIDENTITYS_SH "eXosip_addidentity.sh"
#endif
static int
jidentity_get_and_set_next_token (char **dest, char *buf, char **next)
{
char *end;
char *start;
*next = NULL;
/* find first non space and tab element */
start = buf;
while (((*start == ' ') || (*start == '\t')) && (*start != '\0')
&& (*start != '\r') && (*start != '\n') )
start++;
end = start+1;
while ((*end != '\0') && (*end != '\r') && (*end != '\n')
&& (*end != '\t') && (*end != '|'))
end++;
if ((*end == '\r') || (*end == '\n'))
/* we should continue normally only if this is the separator asked! */
return -1;
if (end == start)
return -1; /* empty value (or several space!) */
*dest = osip_malloc (end - (start) + 1);
osip_strncpy (*dest, start, end - start);
*next = end + 1; /* return the position right after the separator
*/
return 0;
}
static int jidentity_init(jidentity_t **fr, char *ch)
{
char *next;
int i;
*fr = (jidentity_t *)osip_malloc(sizeof(jidentity_t));
if (*fr==NULL) return -1;
i = jidentity_get_and_set_next_token(&((*fr)->i_identity), ch, &next);
if (i != 0)
goto ji_error1;
osip_clrspace ((*fr)->i_identity);
ch = next;
i = jidentity_get_and_set_next_token(&((*fr)->i_registrar), next, &next);
if (i != 0)
goto ji_error2;
osip_clrspace ((*fr)->i_registrar);
ch = next;
i = jidentity_get_and_set_next_token(&((*fr)->i_realm), ch, &next);
if (i != 0)
goto ji_error3;
osip_clrspace ((*fr)->i_realm);
ch = next;
i = jidentity_get_and_set_next_token(&((*fr)->i_userid), ch, &next);
if (i != 0)
goto ji_error4;
osip_clrspace ((*fr)->i_userid);
(*fr)->i_pwd = osip_strdup(next);
osip_clrspace ((*fr)->i_pwd);
if ((*fr)->i_pwd!=NULL && (*fr)->i_pwd[0]!='\0')
{
eXosip_add_authentication_info((*fr)->i_userid, (*fr)->i_userid,
(*fr)->i_pwd, NULL,
(*fr)->i_realm);
}
return 0;
ji_error4:
osip_free((*fr)->i_realm);
ji_error3:
osip_free((*fr)->i_registrar);
ji_error2:
osip_free((*fr)->i_identity);
ji_error1:
osip_free(*fr);
*fr = NULL;
return -1;
}
void identitys_add(char *identity, char *registrar,
char *realm, char *userid, char *pwd)
{
char command[256];
char *tmp = command;
char *home;
int length = 0;
if (identity==NULL)
return ;
if (registrar==NULL)
return ;
if (realm!=NULL && *realm=='\0')
realm = NULL;
if (userid!=NULL && *userid=='\0')
userid = NULL;
if (pwd!=NULL && *pwd=='\0')
pwd = NULL;
length = strlen(identity) +3;
length = length + strlen(registrar) +3;
if (realm!=NULL && userid!=NULL && pwd!=NULL)
{
length = length + strlen(realm) +3;
length = length + strlen(userid) +3;
length = length + strlen(pwd) +3;
}
else if (realm==NULL && userid==NULL && pwd==NULL)
{}
else
return ;
home = getenv("HOME");
length = length + strlen(home);
length = length + strlen(EXOSIP_ETC_DIR) + 3;
length = length + strlen("/jm_identity") + 1;
if (length>235) /* leave some room for SPACEs and \r\n */
return ;
sprintf(tmp , "%s \"%s/%s/jm_identity\"", EXOSIP_ADDIDENTITYS_SH,
home, EXOSIP_ETC_DIR);
tmp = tmp + strlen(tmp);
sprintf(tmp , " \"%s\"", identity);
tmp = tmp + strlen(tmp);
sprintf(tmp , " \"%s\"", registrar);
tmp = tmp + strlen(tmp);
if (realm!=NULL && userid!=NULL && pwd!=NULL)
{
sprintf(tmp , " \"%s\"", realm);
tmp = tmp + strlen(tmp);
sprintf(tmp , " \"%s\"", userid);
tmp = tmp + strlen(tmp);
sprintf(tmp , " \"%s\"", pwd);
}
else if (realm==NULL && userid==NULL && pwd==NULL)
{
sprintf(tmp , " \"\"");
tmp = tmp + strlen(tmp);
sprintf(tmp , " \"\"");
tmp = tmp + strlen(tmp);
sprintf(tmp , " \"\"");
}
system(command);
}
void
jidentity_unload()
{
jidentity_t *fr;
if (eXosip.j_identitys==NULL) return;
for (fr=eXosip.j_identitys; fr!=NULL; fr=eXosip.j_identitys)
{
REMOVE_ELEMENT(eXosip.j_identitys,fr);
osip_free(fr->i_identity);
osip_free(fr->i_registrar);
osip_free(fr->i_realm);
osip_free(fr->i_userid);
osip_free(fr->i_pwd);
osip_free(fr);
}
osip_free(eXosip.j_identitys);
eXosip.j_identitys=NULL;
return;
}
int
jidentity_load()
{
FILE *file;
char *s;
jidentity_t *fr;
int pos;
char *home;
char filename[255];
jidentity_unload();
home = getenv("HOME");
sprintf(filename, "%s/%s/%s", home, EXOSIP_ETC_DIR, "jm_identity");
file = fopen(filename, "r");
if (file==NULL) return -1;
s = (char *)osip_malloc(255*sizeof(char));
pos = 0;
while (NULL!=fgets(s, 254, file))
{
char *tmp = s;
while (*tmp!='\0' && *tmp!=' ') tmp++;
while (*tmp!='\0' && *tmp==' ') tmp++;
while (*tmp!='\0' && *tmp!=' ') tmp++;
tmp++; /* first usefull characters */
pos++;
jidentity_init(&fr, tmp);
if (fr!=NULL)
{ ADD_ELEMENT(eXosip.j_identitys, fr); }
}
osip_free(s);
fclose(file);
return 0; /* ok */
}
char *
jidentity_get_registrar(int fid)
{
jidentity_t *fr;
for (fr = eXosip.j_identitys; fr!=NULL ; fr=fr->next)
{
if (fid==0)
return osip_strdup(fr->i_registrar);
fid--;
}
return NULL;
}
char *
jidentity_get_identity(int fid)
{
jidentity_t *fr;
for (fr = eXosip.j_identitys; fr!=NULL ; fr=fr->next)
{
if (fid==0)
return osip_strdup(fr->i_identity);
fid--;
}
return NULL;
}

528
linphone/exosip/jnotify.c Normal file
View file

@ -0,0 +1,528 @@
/*
eXosip - This is the eXtended osip library.
Copyright (C) 2002, 2003 Aymeric MOIZARD - jack@atosc.org
eXosip is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
eXosip is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef ENABLE_MPATROL
#include <mpatrol.h>
#endif
#include "eXosip2.h"
#include <eXosip_cfg.h>
extern eXosip_t eXosip;
#if 0
int eXosip_notify_find(int sid, eXosip_notify_t **jn)
{
for (*jn=eXosip.j_notifies; *jn!=NULL; *jn=(*jn)->next)
{
if ((*jn)->n_id==sid)
return 0;
}
*jn = NULL;
return -1;
}
#endif
osip_transaction_t *
eXosip_find_last_inc_subscribe(eXosip_notify_t *jn, eXosip_dialog_t *jd )
{
osip_transaction_t *inc_tr;
int pos;
inc_tr = NULL;
pos=0;
if (jd!=NULL)
{
while (!osip_list_eol(jd->d_inc_trs, pos))
{
inc_tr = osip_list_get(jd->d_inc_trs, pos);
if (0==strcmp(inc_tr->cseq->method, "SUBSCRIBE"))
break;
else inc_tr = NULL;
pos++;
}
}
else
inc_tr = NULL;
if (inc_tr==NULL)
return jn->n_inc_tr; /* can be NULL */
return inc_tr;
}
osip_transaction_t *
eXosip_find_last_out_notify(eXosip_notify_t *jn, eXosip_dialog_t *jd )
{
osip_transaction_t *out_tr;
int pos;
out_tr = NULL;
pos=0;
if (jd!=NULL)
{
while (!osip_list_eol(jd->d_out_trs, pos))
{
out_tr = osip_list_get(jd->d_out_trs, pos);
if (0==strcmp(out_tr->cseq->method, "NOTIFY"))
return out_tr;
pos++;
}
}
return NULL;
}
int
eXosip_notify_init(eXosip_notify_t **jn, osip_message_t *inc_subscribe)
{
osip_contact_t *co;
char *uri;
int i;
#ifdef SM
char *locip;
eXosip_get_localip_from_via(inc_subscribe,&locip);
#else
char locip[50];
eXosip_guess_ip_for_via(eXosip.ip_family, locip, 49);
#endif
if (inc_subscribe==NULL
||inc_subscribe->to==NULL
||inc_subscribe->to->url==NULL)
return -1;
co = (osip_contact_t *) osip_list_get(inc_subscribe->contacts, 0);
if (co==NULL || co->url==NULL)
return -1;
*jn = (eXosip_notify_t *)osip_malloc(sizeof(eXosip_notify_t));
if (*jn == NULL) return -1;
memset(*jn, 0, sizeof(eXosip_notify_t));
i = osip_uri_to_str(co->url, &uri);
if (i!=0)
{
osip_free(*jn);
*jn=NULL;
return -1;
}
osip_strncpy((*jn)->n_uri, uri, 254);
osip_free(uri);
if (inc_subscribe->to->url->username!=NULL)
{
/* SM: allocate a string instead of risking a buffer overflow */
if (eXosip.localport==NULL)
(*jn)->n_contact_info=strdup_printf("sip:%s@%s",
inc_subscribe->to->url->username,
locip);
else
(*jn)->n_contact_info= strdup_printf("sip:%s@%s:%s",
inc_subscribe->to->url->username,
locip, eXosip.localport);
}
else
{
if (eXosip.localport==NULL)
(*jn)->n_contact_info=strdup_printf("sip:%s", locip);
else
(*jn)->n_contact_info=strdup_printf("sip:%s:%s", locip,
eXosip.localport);
}
#ifdef SM
osip_free(locip);
#endif
return 0;
}
#if 0
void
__eXosip_notify_remove_dialog_reference_in_notify(eXosip_notify_t *jn, eXosip_dialog_t *jd)
{
eXosip_dialog_t *_jd;
jinfo_t *ji;
if (jn==NULL) return;
if (jd==NULL) return;
for (_jd = jn->n_dialogs; _jd!=NULL; _jd=jn->n_dialogs)
{
if (jd==_jd)
break;
}
if (_jd==NULL)
{
/* dialog not found??? */
}
ji = osip_transaction_get_your_instance(jn->n_inc_tr);
if (ji!=NULL && ji->jd==jd)
ji->jd=NULL;
ji = osip_transaction_get_your_instance(jn->n_out_tr);
if (ji!=NULL && ji->jd==jd)
ji->jd=NULL;
}
#endif
void
eXosip_notify_free(eXosip_notify_t *jn)
{
/* ... */
eXosip_dialog_t *jd;
for (jd = jn->n_dialogs; jd!=NULL; jd=jn->n_dialogs)
{
REMOVE_ELEMENT(jn->n_dialogs, jd);
eXosip_dialog_free(jd);
}
__eXosip_delete_jinfo(jn->n_inc_tr);
__eXosip_delete_jinfo(jn->n_out_tr);
if (jn->n_inc_tr!=NULL)
osip_list_add(eXosip.j_transactions, jn->n_inc_tr, 0);
if (jn->n_out_tr!=NULL)
osip_list_add(eXosip.j_transactions, jn->n_out_tr, 0);
if (jn->n_contact_info!=NULL) osip_free(jn->n_contact_info);
osip_free(jn);
}
int
_eXosip_notify_set_refresh_interval(eXosip_notify_t *jn,
osip_message_t *inc_subscribe)
{
osip_header_t *exp;
int now;
now = time(NULL);
if (jn==NULL || inc_subscribe==NULL)
return -1;
osip_message_get_expires(inc_subscribe, 0, &exp);
if (exp==NULL || exp->hvalue==NULL)
jn->n_ss_expires = now + 600;
else
{
jn->n_ss_expires = osip_atoi(exp->hvalue);
if (jn->n_ss_expires!=-1)
jn->n_ss_expires = now + jn->n_ss_expires;
else /* on error, set it to default */
jn->n_ss_expires = now + 600;
}
return 0;
}
int
eXosip_notify_add_allowed_subscriber(char *sip_url)
{
/* TODO */
return -1;
}
int
_eXosip_notify_is_a_known_subscriber(osip_message_t *sip)
{
/* */
return -1;
}
int
_eXosip_notify_add_body(eXosip_notify_t *jn, osip_message_t *notify)
{
char buf[1000];
#ifdef SUPPORT_MSN
int atom_id = 1000;
#endif
if (jn->n_ss_status!=EXOSIP_SUBCRSTATE_ACTIVE
|| jn->n_contact_info==NULL || jn->n_contact_info=='\0') /* mandatory! */
return 0; /* don't need a body? */
#ifdef SUPPORT_MSN
if (jn->n_online_status==EXOSIP_NOTIFY_ONLINE)
{
sprintf(buf, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence\n\
PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
<status status=\"open\" />\n\
<msnsubstatus substatus=\"online\" />\n\
</address>\n\
</atom>\n\
</presence>", jn->n_contact_info, atom_id, jn->n_contact_info);
}
else if (jn->n_online_status==EXOSIP_NOTIFY_BUSY)
{
sprintf(buf, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence\n\
PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
<status status=\"inuse\" />\n\
<msnsubstatus substatus=\"busy\" />\n\
</address>\n\
</atom>\n\
</presence>", jn->n_contact_info, atom_id, jn->n_contact_info);
}
else if (jn->n_online_status==EXOSIP_NOTIFY_BERIGHTBACK)
{
sprintf(buf, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence\n\
PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
<status status=\"inactive\" />\n\
<msnsubstatus substatus=\"berightback\" />\n\
</address>\n\
</atom>\n\
</presence>", jn->n_contact_info, atom_id, jn->n_contact_info);
}
else if (jn->n_online_status==EXOSIP_NOTIFY_AWAY)
{
sprintf(buf, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence\n\
PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
<status status=\"inactive\" />\n\
<msnsubstatus substatus=\"away\" />\n\
</address>\n\
</atom>\n\
</presence>", jn->n_contact_info, atom_id, jn->n_contact_info);
}
else if (jn->n_online_status==EXOSIP_NOTIFY_ONTHEPHONE)
{
sprintf(buf, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence\n\
PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
<status status=\"inuse\" />\n\
<msnsubstatus substatus=\"onthephone\" />\n\
</address>\n\
</atom>\n\
</presence>", jn->n_contact_info, atom_id, jn->n_contact_info);
}
else if (jn->n_online_status==EXOSIP_NOTIFY_OUTTOLUNCH)
{
sprintf(buf, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence\n\
PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
<status status=\"inactive\" />\n\
<msnsubstatus substatus=\"outtolunch\" />\n\
</address>\n\
</atom>\n\
</presence>", jn->n_contact_info, atom_id, jn->n_contact_info);
}
else
{
sprintf(buf, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence\n\
PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
<status status=\"inactive\" />\n\
<msnsubstatus substatus=\"away\" />\n\
</address>\n\
</atom>\n\
</presence>", jn->n_contact_info, atom_id, jn->n_contact_info);
}
osip_message_set_body(notify, buf, strlen(buf));
osip_message_set_content_type(notify, "application/xpidf+xml");
#else
if (jn->n_online_status==EXOSIP_NOTIFY_ONLINE)
{
sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>online</note>\n\
</tuple>\n\
</presence>",
jn->n_contact_info, jn->n_contact_info);
}
else if (jn->n_online_status==EXOSIP_NOTIFY_BUSY)
{
sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>busy</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>busy</note>\n\
</tuple>\n\
</presence>",
jn->n_contact_info, jn->n_contact_info);
}
else if (jn->n_online_status==EXOSIP_NOTIFY_BERIGHTBACK)
{
sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>in-transit</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>be right back</note>\n\
</tuple>\n\
</presence>",
jn->n_contact_info, jn->n_contact_info);
}
else if (jn->n_online_status==EXOSIP_NOTIFY_AWAY)
{
sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>away</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>away</note>\n\
</tuple>\n\
</presence>",
jn->n_contact_info, jn->n_contact_info);
}
else if (jn->n_online_status==EXOSIP_NOTIFY_ONTHEPHONE)
{
sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>on-the-phone</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>on the phone</note>\n\
</tuple>\n\
</presence>",
jn->n_contact_info, jn->n_contact_info);
}
else if (jn->n_online_status==EXOSIP_NOTIFY_OUTTOLUNCH)
{
sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>meal</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>out to lunch</note>\n\
</tuple>\n\
</presence>",
jn->n_contact_info, jn->n_contact_info);
}
else
{
/* */
sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n%s",
jn->n_contact_info,
"<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>closed</basic>\n\
<es:activities>\n\
<es:activity>permanent-absence</e:activity>\n\
</es:activities>\n\
</status>\n\
</tuple>\n\
\n</presence>\n");
}
osip_message_set_body(notify, buf, strlen(buf));
osip_message_set_content_type(notify, "application/pidf+xml");
#endif
return 0;
}
void
_eXosip_notify_add_expires_in_2XX_for_subscribe(eXosip_notify_t *jn, osip_message_t *answer)
{
char tmp[20];
int now;
now = time(NULL);
if (jn->n_ss_expires-now<0)
{
tmp[0] = '0';
tmp[1] = '\0';
}
else
{
sprintf(tmp, "%i", jn->n_ss_expires-now);
}
osip_message_set_expires(answer, tmp);
}

221
linphone/exosip/jpipe.c Normal file
View file

@ -0,0 +1,221 @@
/*
eXosip - This is the eXtended osip library.
Copyright (C) 2002, 2003 Aymeric MOIZARD - jack@atosc.org
eXosip is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
eXosip is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef ENABLE_MPATROL
#include <mpatrol.h>
#endif
#include "jpipe.h"
#ifndef WIN32
jpipe_t * jpipe ()
{
jpipe_t *my_pipe = (jpipe_t *) osip_malloc (sizeof (jpipe_t));
if (my_pipe==NULL) return NULL;
if (0 != pipe (my_pipe->pipes))
{
osip_free (my_pipe);
return NULL;
}
return my_pipe;
}
int jpipe_close (jpipe_t * apipe)
{
if (apipe == NULL)
return -1;
close (apipe->pipes[0]);
close (apipe->pipes[1]);
osip_free (apipe);
return 0;
}
/**
* Write in a pipe.
*/
int
jpipe_write (jpipe_t * apipe, const void *buf, int count)
{
if (apipe == NULL)
return -1;
return write (apipe->pipes[1], buf, count);
}
/**
* Read in a pipe.
*/
int jpipe_read (jpipe_t * apipe, void *buf, int count)
{
if (apipe == NULL)
return -1;
return read (apipe->pipes[0], buf, count);
}
/**
* Get descriptor of reading pipe.
*/
int jpipe_get_read_descr (jpipe_t * apipe)
{
if (apipe == NULL)
return -1;
return apipe->pipes[0];
}
#else
jpipe_t * jpipe ()
{
int s = 0;
int timeout = 0;
static int aport = 10500;
struct sockaddr_in raddr;
int j;
jpipe_t *my_pipe = (jpipe_t *) osip_malloc (sizeof (jpipe_t));
if (my_pipe==NULL)
return NULL;
s = (int) socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (0 > s)
{
osip_free (my_pipe);
return NULL;
}
my_pipe->pipes[1] = (int) socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (0 > my_pipe->pipes[1])
{
closesocket(s);
osip_free (my_pipe);
return NULL;
}
raddr.sin_addr.s_addr = inet_addr ("127.0.0.1");
raddr.sin_family = AF_INET;
j = 50;
while (aport++ && j-- > 0)
{
raddr.sin_port = htons ((short) aport);
if (bind (s, (struct sockaddr *) &raddr, sizeof (raddr)) < 0)
{
OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL,
"Failed to bind one local socket %i!\n",
aport));
}
else
break;
}
if (j == 0)
{
OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
"Failed to bind a local socket, aborting!\n"));
closesocket (s);
closesocket (my_pipe->pipes[1]);
osip_free (my_pipe);
}
j = listen(s,1);
if (j != 0)
{
OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
"Failed to listen on a local socket, aborting!\n"));
closesocket(s);
closesocket(my_pipe->pipes[1]);
osip_free (my_pipe);
}
j = setsockopt (my_pipe->pipes[1],
SOL_SOCKET,
SO_RCVTIMEO, (const char*) &timeout, sizeof (timeout));
if (j != NO_ERROR)
{
/* failed for some reason... */
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_ERROR, NULL,
"udp plugin; cannot set O_NONBLOCK to the file desciptor!\n"));
closesocket(s);
closesocket(my_pipe->pipes[1]);
osip_free (my_pipe);
}
connect (my_pipe->pipes[1], (struct sockaddr *) &raddr, sizeof (raddr));
my_pipe->pipes[0] = accept (s, NULL, NULL);
if (my_pipe->pipes[0]<=0)
{
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_ERROR, NULL,
"udp plugin; Failed to call accept!\n"));
closesocket(s);
closesocket(my_pipe->pipes[1]);
osip_free (my_pipe);
}
return my_pipe;
}
int jpipe_close (jpipe_t * apipe)
{
if (apipe == NULL)
return -1;
closesocket (apipe->pipes[0]);
closesocket (apipe->pipes[1]);
osip_free (apipe);
return 0;
}
/**
* Write in a pipe.
*/
int
jpipe_write (jpipe_t * apipe, const void *buf, int count)
{
if (apipe == NULL)
return -1;
return send (apipe->pipes[1], buf, count, 0);
}
/**
* Read in a pipe.
*/
int jpipe_read (jpipe_t * apipe, void *buf, int count)
{
if (apipe == NULL)
return -1;
return recv (apipe->pipes[0], buf, count, 0 /* MSG_DONTWAIT */ ); /* BUG?? */
}
/**
* Get descriptor of reading pipe.
*/
int jpipe_get_read_descr (jpipe_t * apipe)
{
if (apipe == NULL)
return -1;
return apipe->pipes[0];
}
#endif

111
linphone/exosip/jpipe.h Normal file
View file

@ -0,0 +1,111 @@
/*
eXosip - This is the eXtended osip library.
Copyright (C) 2002, 2003 Aymeric MOIZARD - jack@atosc.org
eXosip is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
eXosip is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _JPIPE_H_
#define _JPIPE_H_
#include <eXosip.h>
#ifndef WIN32
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#endif
#ifdef WIN32
#include <windows.h>
#endif
/**
* @file jpipe.h
* @brief PPL Pipe Handling Routines
*/
/**
* @defgroup JPIPE Pipe Handling
* @ingroup PPL
* @{
*/
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef WIN32
/**
* Structure for storing a pipe descriptor
* @defvar jpipe_t
*/
typedef struct jpipe_t jpipe_t;
struct jpipe_t
{
int pipes[2];
};
#else
/**
* Structure for storing a pipe descriptor
* @defvar ppl_pipe_t
*/
typedef struct jpipe_t jpipe_t;
struct jpipe_t
{
int pipes[2];
};
#endif
/**
* Get New pipe pair.
*/
jpipe_t * jpipe (void);
/**
* Close pipe
*/
int jpipe_close (jpipe_t * apipe);
/**
* Write in a pipe.
*/
int jpipe_write (jpipe_t * pipe, const void *buf,
int count);
/**
* Read in a pipe.
*/
int jpipe_read (jpipe_t * pipe, void *buf,
int count);
/**
* Get descriptor of reading pipe.
*/
int jpipe_get_read_descr (jpipe_t * pipe);
#ifdef __cplusplus
}
#endif
/** @} */
#endif

118
linphone/exosip/jpublish.c Normal file
View file

@ -0,0 +1,118 @@
/*
eXosip - This is the eXtended osip library.
Copyright (C) 2002, 2003 Aymeric MOIZARD - jack@atosc.org
eXosip is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
eXosip is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef ENABLE_MPATROL
#include <mpatrol.h>
#endif
#include "eXosip2.h"
extern eXosip_t eXosip;
int _eXosip_pub_update(eXosip_pub_t **pub, osip_transaction_t *tr, osip_message_t *answer)
{
eXosip_pub_t *jpub;
*pub = NULL;
for (jpub = eXosip.j_pub; jpub!=NULL; jpub = jpub->next)
{
if (jpub->p_last_tr==NULL)
{ /*bug? */ }
else if (tr==jpub->p_last_tr)
{
/* update the sip_etag parameter */
if (answer==NULL)
{ /* bug? */
}
else if (MSG_IS_STATUS_2XX(answer))
{
osip_header_t *sip_etag=NULL;
osip_message_header_get_byname(answer, "SIP-ETag", 0, &sip_etag);
if (sip_etag!=NULL && sip_etag->hvalue!=NULL)
snprintf(jpub->p_sip_etag, 64, "%s", sip_etag->hvalue);
}
*pub=jpub;
return 0;
}
}
return -1;
}
int _eXosip_pub_find_by_aor(eXosip_pub_t **pub, const char *aor)
{
eXosip_pub_t *jpub;
eXosip_pub_t *ptr;
time_t now;
*pub = NULL;
/* delete expired publications */
now = time(NULL);
ptr = eXosip.j_pub;
for (jpub = ptr; jpub!=NULL; jpub = ptr)
{
ptr = jpub->next;
if (now-jpub->p_expires>60)
{
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_WARNING, NULL,
"eXosip: removing expired publication!"));
REMOVE_ELEMENT(eXosip.j_pub, jpub);
_eXosip_pub_free(jpub);
}
}
for (jpub = eXosip.j_pub; jpub!=NULL; jpub = jpub->next)
{
if (osip_strcasecmp(aor, jpub->p_aor)==0)
{
*pub=jpub;
return 0;
}
}
return -1;
}
int _eXosip_pub_init(eXosip_pub_t **pub, const char *aor, const char *exp)
{
eXosip_pub_t *jpub;
*pub = NULL;
jpub = (eXosip_pub_t*) osip_malloc(sizeof(eXosip_pub_t));
if (jpub==0)
return -1;
memset(jpub, 0, sizeof(eXosip_pub_t));
snprintf(jpub->p_aor, 256, "%s", aor);
jpub->p_expires = atoi(exp) + time(NULL);
jpub->p_period = atoi(exp);
*pub = jpub;
return 0;
}
void _eXosip_pub_free(eXosip_pub_t *pub)
{
if (pub->p_last_tr!=NULL)
osip_list_add(eXosip.j_transactions, pub->p_last_tr, 0);
osip_free(pub);
}

106
linphone/exosip/jreg.c Normal file
View file

@ -0,0 +1,106 @@
/*
eXosip - This is the eXtended osip library.
Copyright (C) 2002, 2003 Aymeric MOIZARD - jack@atosc.org
eXosip is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
eXosip is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef ENABLE_MPATROL
#include <mpatrol.h>
#endif
#include "eXosip2.h"
extern eXosip_t eXosip;
int eXosip_reg_init(eXosip_reg_t **jr, char *from, char *proxy, char *contact, char* route)
{
static int r_id;
*jr = (eXosip_reg_t*) osip_malloc(sizeof(eXosip_reg_t));
if (*jr==NULL) return -1;
if (r_id > 1000000) /* keep it non-negative */
r_id = 0;
(*jr)->r_id = ++r_id;
(*jr)->r_reg_period = 3600; /* delay between registration */
(*jr)->r_aor = osip_strdup(from); /* sip identity */
(*jr)->r_contact = osip_strdup(contact); /* sip identity */
(*jr)->r_registrar = osip_strdup(proxy); /* registrar */
(*jr)->r_route = osip_strdup(route); /* outbound proxy */
#if 0
(*jr)->r_realms = NULL; /* list of realms */
#endif
(*jr)->r_last_tr = NULL;
(*jr)->next = NULL;
(*jr)->parent = NULL;
return 0;
}
void eXosip_reg_free(eXosip_reg_t *jreg)
{
osip_free(jreg->r_aor);
osip_free(jreg->r_contact);
osip_free(jreg->r_registrar);
#if 0
osip_free(jreg->r_realms);
#endif
if (jreg->r_last_tr != NULL)
{
if (jreg->r_last_tr->state==IST_TERMINATED ||
jreg->r_last_tr->state==ICT_TERMINATED ||
jreg->r_last_tr->state== NICT_TERMINATED ||
jreg->r_last_tr->state==NIST_TERMINATED)
{
OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_INFO1,NULL,
"Release a terminated transaction\n"));
__eXosip_delete_jinfo(jreg->r_last_tr);
if (jreg->r_last_tr!=NULL)
osip_list_add(eXosip.j_transactions, jreg->r_last_tr, 0);
}
else
{
OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_INFO1,NULL,
"Release a non-terminated transaction\n"));
__eXosip_delete_jinfo(jreg->r_last_tr);
if (jreg->r_last_tr!=NULL)
osip_list_add(eXosip.j_transactions, jreg->r_last_tr, 0);
}
}
osip_free(jreg);
}
int _eXosip_reg_find(eXosip_reg_t **reg, osip_transaction_t *tr)
{
eXosip_reg_t *jreg;
*reg = NULL;
if (tr==NULL) return -1;
for (jreg = eXosip.j_reg; jreg!=NULL; jreg = jreg->next)
{
if (jreg->r_last_tr==tr)
{
*reg = jreg;
return 0;
}
}
return -1;
}

1158
linphone/exosip/jrequest.c Normal file

File diff suppressed because it is too large Load diff

1264
linphone/exosip/jresponse.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,231 @@
/*
eXosip - This is the eXtended osip library.
Copyright (C) 2002, 2003 Aymeric MOIZARD - jack@atosc.org
eXosip is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
eXosip is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef ENABLE_MPATROL
#include <mpatrol.h>
#endif
#include "eXosip2.h"
#include <eXosip_cfg.h>
extern eXosip_t eXosip;
#if 0
int eXosip_subscribe_find(int sid, eXosip_subscribe_t **js)
{
for (*js=eXosip.j_subscribes; *js!=NULL; *js=(*js)->next)
{
if ((*js)->s_id==sid)
return 0;
}
*js = NULL;
return -1;
}
#endif
osip_transaction_t *
eXosip_find_last_out_subscribe(eXosip_subscribe_t *js, eXosip_dialog_t *jd )
{
osip_transaction_t *out_tr;
int pos;
out_tr = NULL;
pos=0;
if (jd!=NULL)
{
while (!osip_list_eol(jd->d_out_trs, pos))
{
out_tr = osip_list_get(jd->d_out_trs, pos);
if (0==strcmp(out_tr->cseq->method, "SUBSCRIBE"))
break;
else out_tr = NULL;
pos++;
}
}
else
out_tr = NULL;
if (out_tr==NULL)
return js->s_out_tr; /* can be NULL */
return out_tr;
}
osip_transaction_t *
eXosip_find_last_inc_notify(eXosip_subscribe_t *js, eXosip_dialog_t *jd )
{
osip_transaction_t *out_tr;
int pos;
out_tr = NULL;
pos=0;
if (jd!=NULL)
{
while (!osip_list_eol(jd->d_out_trs, pos))
{
out_tr = osip_list_get(jd->d_out_trs, pos);
if (0==strcmp(out_tr->cseq->method, "NOTIFY"))
return out_tr;
pos++;
}
}
return NULL;
}
#if 0
void
__eXosip_subscribe_remove_dialog_reference_in_subscribe(eXosip_subscribe_t *js, eXosip_dialog_t *jd)
{
eXosip_dialog_t *_jd;
jinfo_t *ji;
if (js==NULL) return;
if (jd==NULL) return;
for (_jd = js->s_dialogs; _jd!=NULL; _jd=js->s_dialogs)
{
if (jd==_jd)
break;
}
if (_jd==NULL)
{
/* dialog not found??? */
}
ji = osip_transaction_get_your_instance(js->s_inc_tr);
if (ji!=NULL && ji->jd==jd)
ji->jd=NULL;
ji = osip_transaction_get_your_instance(js->s_out_tr);
if (ji!=NULL && ji->jd==jd)
ji->jd=NULL;
}
#endif
int
eXosip_subscribe_init(eXosip_subscribe_t **js, char *uri)
{
if (uri==NULL) return -1;
*js = (eXosip_subscribe_t *)osip_malloc(sizeof(eXosip_subscribe_t));
if (*js == NULL) return -1;
memset(*js, 0, sizeof(eXosip_subscribe_t));
osip_strncpy((*js)->s_uri, uri, strlen(uri));
return 0;
}
void
eXosip_subscribe_free(eXosip_subscribe_t *js)
{
/* ... */
eXosip_dialog_t *jd;
for (jd = js->s_dialogs; jd!=NULL; jd=js->s_dialogs)
{
REMOVE_ELEMENT(js->s_dialogs, jd);
eXosip_dialog_free(jd);
}
__eXosip_delete_jinfo(js->s_inc_tr);
__eXosip_delete_jinfo(js->s_out_tr);
if (js->s_inc_tr!=NULL)
osip_list_add(eXosip.j_transactions, js->s_inc_tr, 0);
if (js->s_out_tr!=NULL)
osip_list_add(eXosip.j_transactions, js->s_out_tr, 0);
osip_free(js);
}
int
_eXosip_subscribe_set_refresh_interval(eXosip_subscribe_t *js,
osip_message_t *out_subscribe)
{
osip_header_t *exp;
int now = time(NULL);
if (js==NULL || out_subscribe==NULL)
return -1;
osip_message_get_expires(out_subscribe, 0, &exp);
if (exp==NULL || exp->hvalue==NULL)
js->s_ss_expires = now + 600;
else
{
js->s_ss_expires = osip_atoi(exp->hvalue);
if (js->s_ss_expires!=-1)
js->s_ss_expires = now + js->s_ss_expires;
else /* on error, set it to default */
js->s_ss_expires = now + 600;
}
return 0;
}
int eXosip_subscribe_need_refresh(eXosip_subscribe_t *js, int now)
{
if (now-js->s_ss_expires>-120)
return 0;
return -1;
}
int eXosip_subscribe_send_subscribe(eXosip_subscribe_t *js,
eXosip_dialog_t *jd, const char *expires)
{
osip_transaction_t *transaction;
osip_message_t *subscribe;
osip_event_t *sipevent;
int i;
transaction = eXosip_find_last_out_subscribe(js, jd);
if (transaction!=NULL)
{
if (transaction->state!=NICT_TERMINATED &&
transaction->state!=NIST_TERMINATED)
return -1;
}
i = _eXosip_build_request_within_dialog(&subscribe, "SUBSCRIBE",
jd->d_dialog, "UDP");
if (i!=0)
return -2;
osip_message_set_expires(subscribe, expires);
i = osip_transaction_init(&transaction,
NICT,
eXosip.j_osip,
subscribe);
if (i!=0)
{
/* TODO: release the j_call.. */
osip_message_free(subscribe);
return -1;
}
_eXosip_subscribe_set_refresh_interval(js, subscribe);
osip_list_add(jd->d_out_trs, transaction, 0);
sipevent = osip_new_outgoing_sipmessage(subscribe);
sipevent->transactionid = transaction->transactionid;
osip_transaction_add_event(transaction, sipevent);
osip_transaction_set_your_instance(transaction, __eXosip_new_jinfo(NULL, jd, js, NULL));
__eXosip_wakeup();
return 0;
}

View file

@ -0,0 +1,185 @@
/*
eXosip - This is the eXtended osip library.
Copyright (C) 2002, 2003 Aymeric MOIZARD - jack@atosc.org
eXosip is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
eXosip is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef ENABLE_MPATROL
#include <mpatrol.h>
#endif
#include "eXosip2.h"
#include <eXosip.h>
#include <eXosip_cfg.h>
extern eXosip_t eXosip;
#ifndef EXOSIP_ETC_DIR
#define EXOSIP_ETC_DIR ".eXosip"
#endif
#ifndef EXOSIP_ADDSUBSCRIBERS_SH
#define EXOSIP_ADDSUBSCRIBERS_SH "eXosip_addsubscriber.sh"
#endif
static int jsubscriber_init(jsubscriber_t **js, char *ch)
{
char *next;
int i;
*js = (jsubscriber_t *)osip_malloc(sizeof(jsubscriber_t));
if (*js==NULL) return -1;
i = jfriend_get_and_set_next_token(&((*js)->s_nick), ch, &next);
if (i != 0)
goto js_error1;
osip_clrspace ((*js)->s_nick);
ch = next;
i = jfriend_get_and_set_next_token(&((*js)->s_uri), ch, &next);
if (i != 0)
goto js_error2;
osip_clrspace ((*js)->s_uri);
ch = next;
(*js)->s_allow = osip_strdup(next);
osip_clrspace ((*js)->s_allow);
return 0;
js_error2:
osip_free((*js)->s_nick);
js_error1:
osip_free(*js);
*js = NULL;
return -1;
}
void
jsubscriber_unload()
{
jsubscriber_t *js;
if (eXosip.j_subscribers==NULL) return;
for (js=eXosip.j_subscribers; js!=NULL; js=eXosip.j_subscribers)
{
REMOVE_ELEMENT(eXosip.j_subscribers,js);
osip_free(js->s_nick);
osip_free(js->s_uri);
osip_free(js->s_allow);
osip_free(js);
}
osip_free(eXosip.j_subscribers);
eXosip.j_subscribers=NULL;
return;
}
int
jsubscriber_load()
{
FILE *file;
char *s;
jsubscriber_t *js;
int pos;
char *home;
char filename[255];
jsubscriber_unload();
home = getenv("HOME");
sprintf(filename, "%s/%s/%s", home, EXOSIP_ETC_DIR, "jm_subscriber");
file = fopen(filename, "r");
if (file==NULL) return -1;
s = (char *)osip_malloc(255*sizeof(char));
pos = 0;
while (NULL!=fgets(s, 254, file))
{
char *tmp = s;
while (*tmp!='\0' && *tmp!=' ') tmp++;
while (*tmp!='\0' && *tmp==' ') tmp++;
while (*tmp!='\0' && *tmp!=' ') tmp++;
tmp++; /* first usefull characters */
pos++;
jsubscriber_init(&js, tmp);
if (js!=NULL)
{ ADD_ELEMENT(eXosip.j_subscribers, js); }
}
osip_free(s);
fclose(file);
return 0; /* ok */
}
void subscribers_add(char *nickname, char *uri, int black_list)
{
char *home;
char command[256];
char *tmp = command;
int length = 0;
if (nickname!=NULL)
length = strlen(nickname);
if (uri==NULL)
return ;
home = getenv("HOME");
length = length + strlen(home);
length = length + strlen(uri);
length = length + 10; /* for black_list info */
length = length + strlen(EXOSIP_ETC_DIR);
length = length + strlen("/jm_subscriber");
if (length>235) /* leave some room for SPACEs and \r\n */
return ;
sprintf(tmp , "%s %s/%s/jm_subscriber", EXOSIP_ADDSUBSCRIBERS_SH, home, EXOSIP_ETC_DIR);
tmp = tmp + strlen(tmp);
if (nickname!=NULL)
sprintf(tmp , " %s", nickname);
else
sprintf(tmp , " \"\"");
tmp = tmp + strlen(tmp);
sprintf(tmp , " %s", uri);
tmp = tmp + strlen(tmp);
if (black_list==0) /* allowed */
sprintf(tmp , " allow");
else
sprintf(tmp , " reject");
system(command);
jsubscriber_load();
}
char *
jsubscriber_get_uri(int fid)
{
jsubscriber_t *js;
for (js = eXosip.j_subscribers; js!=NULL ; js=js->next)
{
if (fid==0)
return osip_strdup(js->s_uri);
fid--;
}
return NULL;
}

436
linphone/exosip/misc.c Normal file
View file

@ -0,0 +1,436 @@
/*
eXosip - This is the eXtended osip library.
Copyright (C) 2002, 2003 Aymeric MOIZARD - jack@atosc.org
eXosip is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
eXosip is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef ENABLE_MPATROL
#include <mpatrol.h>
#endif
#include "eXosip2.h"
extern eXosip_t eXosip;
/* some methods to extract transaction information from a eXosip_call_t */
int
eXosip_remove_transaction_from_call(osip_transaction_t *tr, eXosip_call_t *jc)
{
osip_transaction_t *inc_tr;
osip_transaction_t *out_tr;
eXosip_dialog_t *jd;
int pos=0;
if (jc->c_inc_tr==tr)
{
jc->c_inc_tr = NULL; /* can be NULL */
return 0;
}
for (jd=jc->c_dialogs;jd!=NULL;jd=jd->next)
{
pos=0;
while (!osip_list_eol(jd->d_inc_trs, pos))
{
inc_tr = osip_list_get(jd->d_inc_trs, pos);
if (inc_tr==tr)
{
osip_list_remove(jd->d_inc_trs, pos);
return 0;
}
pos++;
}
}
if (jc->c_out_tr==tr)
{
jc->c_out_tr = NULL; /* can be NULL */
return 0;
}
for (jd=jc->c_dialogs;jd!=NULL;jd=jd->next)
{
pos=0;
while (!osip_list_eol(jd->d_out_trs, pos))
{
out_tr = osip_list_get(jd->d_out_trs, pos);
if (out_tr==tr)
{
osip_list_remove(jd->d_out_trs, pos);
return 0;
}
pos++;
}
}
OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_INFO1,NULL,
"eXosip: No information.\n"));
return -1;
}
osip_transaction_t *
eXosip_find_last_options(eXosip_call_t *jc, eXosip_dialog_t *jd )
{
osip_transaction_t *inc_tr;
osip_transaction_t *out_tr;
inc_tr = eXosip_find_last_inc_options(jc, jd);
out_tr = eXosip_find_last_out_options(jc, jd);
if (inc_tr==NULL)
return out_tr;
if (out_tr==NULL)
return inc_tr;
if (inc_tr->birth_time>out_tr->birth_time)
return inc_tr;
return out_tr;
}
osip_transaction_t *
eXosip_find_last_inc_options(eXosip_call_t *jc, eXosip_dialog_t *jd )
{
osip_transaction_t *inc_tr;
int pos;
inc_tr = NULL;
pos=0;
if (jd!=NULL)
{
while (!osip_list_eol(jd->d_inc_trs, pos))
{
inc_tr = osip_list_get(jd->d_inc_trs, pos);
if (0==strcmp(inc_tr->cseq->method, "OPTIONS"))
break;
else inc_tr = NULL;
pos++;
}
}
else
inc_tr = NULL;
if (inc_tr==NULL)
return jc->c_inc_options_tr; /* can be NULL */
return inc_tr;
}
osip_transaction_t *
eXosip_find_last_out_options(eXosip_call_t *jc, eXosip_dialog_t *jd )
{
osip_transaction_t *out_tr;
int pos;
out_tr = NULL;
pos=0;
if (jd==NULL && jc==NULL) return NULL;
if (jd!=NULL)
{
while (!osip_list_eol(jd->d_out_trs, pos))
{
out_tr = osip_list_get(jd->d_out_trs, pos);
if (0==strcmp(out_tr->cseq->method, "OPTIONS"))
break;
else out_tr = NULL;
pos++;
}
}
if (out_tr==NULL)
return jc->c_out_options_tr; /* can be NULL */
return out_tr;
}
osip_transaction_t *
eXosip_find_last_info(eXosip_call_t *jc, eXosip_dialog_t *jd )
{
osip_transaction_t *inc_tr;
osip_transaction_t *out_tr;
inc_tr = eXosip_find_last_inc_info(jc, jd);
out_tr = eXosip_find_last_out_info(jc, jd);
if (inc_tr==NULL)
return out_tr;
if (out_tr==NULL)
return inc_tr;
if (inc_tr->birth_time>out_tr->birth_time)
return inc_tr;
return out_tr;
}
osip_transaction_t *
eXosip_find_last_inc_info(eXosip_call_t *jc, eXosip_dialog_t *jd )
{
osip_transaction_t *inc_tr;
int pos;
inc_tr = NULL;
pos=0;
if (jd!=NULL)
{
while (!osip_list_eol(jd->d_inc_trs, pos))
{
inc_tr = osip_list_get(jd->d_inc_trs, pos);
if (0==strcmp(inc_tr->cseq->method, "INFO"))
break;
else inc_tr = NULL;
pos++;
}
}
else
inc_tr = NULL;
return inc_tr;
}
osip_transaction_t *
eXosip_find_last_out_info(eXosip_call_t *jc, eXosip_dialog_t *jd )
{
osip_transaction_t *out_tr;
int pos;
out_tr = NULL;
pos=0;
if (jd==NULL && jc==NULL) return NULL;
if (jd!=NULL)
{
while (!osip_list_eol(jd->d_out_trs, pos))
{
out_tr = osip_list_get(jd->d_out_trs, pos);
if (0==strcmp(out_tr->cseq->method, "INFO"))
break;
else out_tr = NULL;
pos++;
}
}
return out_tr;
}
osip_transaction_t *
eXosip_find_last_refer(eXosip_call_t *jc, eXosip_dialog_t *jd )
{
osip_transaction_t *inc_tr;
osip_transaction_t *out_tr;
inc_tr = eXosip_find_last_inc_refer(jc, jd);
out_tr = eXosip_find_last_out_refer(jc, jd);
if (inc_tr==NULL)
return out_tr;
if (out_tr==NULL)
return inc_tr;
if (inc_tr->birth_time>out_tr->birth_time)
return inc_tr;
return out_tr;
}
osip_transaction_t *
eXosip_find_last_invite(eXosip_call_t *jc, eXosip_dialog_t *jd )
{
osip_transaction_t *inc_tr;
osip_transaction_t *out_tr;
inc_tr = eXosip_find_last_inc_invite(jc, jd);
out_tr = eXosip_find_last_out_invite(jc, jd);
if (inc_tr==NULL)
return out_tr;
if (out_tr==NULL)
return inc_tr;
if (inc_tr->birth_time>out_tr->birth_time)
return inc_tr;
return out_tr;
}
osip_transaction_t *
eXosip_find_last_inc_invite(eXosip_call_t *jc, eXosip_dialog_t *jd )
{
osip_transaction_t *inc_tr;
int pos;
inc_tr = NULL;
pos=0;
if (jd!=NULL)
{
while (!osip_list_eol(jd->d_inc_trs, pos))
{
inc_tr = osip_list_get(jd->d_inc_trs, pos);
if (0==strcmp(inc_tr->cseq->method, "INVITE"))
break;
else inc_tr = NULL;
pos++;
}
}
else
inc_tr = NULL;
if (inc_tr==NULL)
return jc->c_inc_tr; /* can be NULL */
return inc_tr;
}
osip_transaction_t *
eXosip_find_last_out_invite(eXosip_call_t *jc, eXosip_dialog_t *jd )
{
osip_transaction_t *out_tr;
int pos;
out_tr = NULL;
pos=0;
if (jd==NULL && jc==NULL) return NULL;
if (jd!=NULL)
{
while (!osip_list_eol(jd->d_out_trs, pos))
{
out_tr = osip_list_get(jd->d_out_trs, pos);
if (0==strcmp(out_tr->cseq->method, "INVITE"))
break;
else out_tr = NULL;
pos++;
}
}
if (out_tr==NULL)
return jc->c_out_tr; /* can be NULL */
return out_tr;
}
osip_transaction_t *
eXosip_find_last_inc_bye(eXosip_call_t *jc, eXosip_dialog_t *jd )
{
osip_transaction_t *inc_tr;
int pos;
inc_tr = NULL;
pos=0;
if (jd!=NULL)
{
while (!osip_list_eol(jd->d_inc_trs, pos))
{
inc_tr = osip_list_get(jd->d_inc_trs, pos);
if (0==strcmp(inc_tr->cseq->method, "BYE"))
return inc_tr;
pos++;
}
}
return NULL;
}
osip_transaction_t *
eXosip_find_last_out_bye(eXosip_call_t *jc, eXosip_dialog_t *jd )
{
osip_transaction_t *out_tr;
int pos;
out_tr = NULL;
pos=0;
if (jd!=NULL)
{
while (!osip_list_eol(jd->d_out_trs, pos))
{
out_tr = osip_list_get(jd->d_out_trs, pos);
if (0==strcmp(out_tr->cseq->method, "BYE"))
return out_tr;
pos++;
}
}
return NULL;
}
osip_transaction_t *
eXosip_find_last_inc_refer(eXosip_call_t *jc, eXosip_dialog_t *jd )
{
osip_transaction_t *inc_tr;
int pos;
inc_tr = NULL;
pos=0;
if (jd!=NULL)
{
while (!osip_list_eol(jd->d_inc_trs, pos))
{
inc_tr = osip_list_get(jd->d_inc_trs, pos);
if (0==strcmp(inc_tr->cseq->method, "REFER"))
return inc_tr;
pos++;
}
}
return NULL;
}
osip_transaction_t *
eXosip_find_last_out_refer(eXosip_call_t *jc, eXosip_dialog_t *jd )
{
osip_transaction_t *out_tr;
int pos;
out_tr = NULL;
pos=0;
if (jd!=NULL)
{
while (!osip_list_eol(jd->d_out_trs, pos))
{
out_tr = osip_list_get(jd->d_out_trs, pos);
if (0==strcmp(out_tr->cseq->method, "REFER"))
return out_tr;
pos++;
}
}
return NULL;
}
osip_transaction_t *
eXosip_find_last_inc_notify_for_refer(eXosip_call_t *jc, eXosip_dialog_t *jd )
{
osip_transaction_t *inc_tr;
int pos;
inc_tr = NULL;
pos=0;
if (jd!=NULL)
{
while (!osip_list_eol(jd->d_inc_trs, pos))
{
inc_tr = osip_list_get(jd->d_inc_trs, pos);
if (0==strcmp(inc_tr->cseq->method, "NOTIFY"))
return inc_tr;
pos++;
}
}
return NULL;
}
osip_transaction_t *
eXosip_find_last_out_notify_for_refer(eXosip_call_t *jc, eXosip_dialog_t *jd )
{
osip_transaction_t *out_tr;
int pos;
out_tr = NULL;
pos=0;
if (jd!=NULL)
{
while (!osip_list_eol(jd->d_out_trs, pos))
{
out_tr = osip_list_get(jd->d_out_trs, pos);
if (0==strcmp(out_tr->cseq->method, "NOTIFY"))
return out_tr;
pos++;
}
}
return NULL;
}

View file

@ -0,0 +1,333 @@
/*
eXosip - This is the eXtended osip library.
Copyright (C) 2002, 2003 Aymeric MOIZARD - jack@atosc.org
eXosip is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
eXosip is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef ENABLE_MPATROL
#include <mpatrol.h>
#endif
#include "eXosip2.h"
extern eXosip_t eXosip;
osip_list_t *supported_codec = NULL;
int eXosip_sdp_accept_audio_codec(osip_negotiation_ctx_t *context,
char *port, char *number_of_port,
int audio_qty, char *payload);
int eXosip_sdp_accept_video_codec(osip_negotiation_ctx_t *context,
char *port, char *number_of_port,
int video_qty, char *payload);
int eXosip_sdp_accept_other_codec(osip_negotiation_ctx_t *context,
char *type, char *port,
char *number_of_port, char *payload);
char *eXosip_sdp_get_audio_port(osip_negotiation_ctx_t *context, int pos_media);
int eXosip_sdp_accept_audio_codec(osip_negotiation_ctx_t *context,
char *port, char *number_of_port,
int audio_qty, char *payload)
{
int pos;
for (pos=0;!osip_list_eol(supported_codec, pos);pos++)
{
char *_payload;
_payload = osip_list_get(supported_codec, pos);
if (0==strcmp(payload,_payload))
{
/*
We have to look at the rtpmap attributes in context->remote
to check if we support this stuff.
*/
return 0;
}
}
return -1;
}
int eXosip_sdp_accept_video_codec(osip_negotiation_ctx_t *context,
char *port, char *number_of_port,
int video_qty, char *payload)
{
return -1;
}
int eXosip_sdp_accept_other_codec(osip_negotiation_ctx_t *context,
char *type, char *port,
char *number_of_port, char *payload)
{
/* ... */
return -1;
}
char *eXosip_sdp_get_audio_port(osip_negotiation_ctx_t *context, int pos_media)
{
eXosip_call_t *jc = (eXosip_call_t*)osip_negotiation_ctx_get_mycontext(context);
if (jc==NULL)
return osip_strdup("10500");
else if (jc->c_sdp_port[0]=='\0')
return osip_strdup("10500");
else return osip_strdup(jc->c_sdp_port);
}
int eXosip_sdp_negotiation_replace(osip_negotiation_t *sn)
{
if (eXosip.osip_negotiation!=NULL)
osip_negotiation_free(eXosip.osip_negotiation);
eXosip.osip_negotiation = sn;
return 0;
}
void
eXosip_sdp_negotiation_ctx_set_mycontext(struct eXosip_call_t *jc, void *arg)
{
osip_negotiation_ctx_set_mycontext(jc->c_ctx, arg);
}
void eXosip_sdp_negotiation_remove_audio_payloads()
{
if (supported_codec==NULL)
return;
for (;!osip_list_eol(supported_codec, 0);)
{
char *p;
p = (char *) osip_list_get(supported_codec, 0);
osip_free(p);
osip_list_remove(supported_codec, 0);
}
osip_negotiation_remove_audio_payloads(eXosip.osip_negotiation);
}
void eXosip_sdp_negotiation_add_codec(char *payload, char *number_of_port,
char *proto, char *c_nettype,
char *c_addrtype, char *c_addr,
char *c_addr_multicast_ttl,
char *c_addr_multicast_int,
char *a_rtpmap)
{
osip_negotiation_add_support_for_audio_codec(eXosip.osip_negotiation,
payload,
number_of_port,
proto,
c_nettype,
c_addrtype,
c_addr,
c_addr_multicast_ttl,
c_addr_multicast_int,
a_rtpmap);
osip_list_add(supported_codec, osip_strdup(payload), -1);
}
int eXosip_sdp_negotiation_init(osip_negotiation_t **sn)
{
int i = osip_negotiation_init(sn);
if (i!=0) {
return -1;
}
if (supported_codec==NULL)
{
supported_codec = (osip_list_t*) osip_malloc(sizeof(osip_list_t));
osip_list_init(supported_codec);
}
osip_negotiation_set_o_username(*sn, osip_strdup("userX"));
osip_negotiation_set_o_session_id(*sn, osip_strdup("20000001"));
osip_negotiation_set_o_session_version(*sn, osip_strdup("20000001"));
osip_negotiation_set_o_nettype(*sn, osip_strdup("IN"));
osip_negotiation_set_o_addrtype(*sn, osip_strdup("IP4"));
osip_negotiation_set_o_addr(*sn, osip_strdup(eXosip.localip));
osip_negotiation_set_c_nettype(*sn, osip_strdup("IN"));
osip_negotiation_set_c_addrtype(*sn, osip_strdup("IP4"));
osip_negotiation_set_c_addr(*sn, osip_strdup(eXosip.localip));
/* ALL CODEC MUST SHARE THE SAME "C=" line and proto as the media
will appear on the same "m" line... */
osip_negotiation_set_fcn_accept_audio_codec(*sn, &eXosip_sdp_accept_audio_codec);
osip_negotiation_set_fcn_accept_video_codec(*sn, &eXosip_sdp_accept_video_codec);
osip_negotiation_set_fcn_accept_other_codec(*sn, &eXosip_sdp_accept_other_codec);
osip_negotiation_set_fcn_get_audio_port(*sn, &eXosip_sdp_get_audio_port);
return 0;
}
void eXosip_sdp_negotiation_free(osip_negotiation_t *sn)
{
if (sn==NULL)
return;
osip_list_ofchar_free(supported_codec);
supported_codec = NULL;
osip_negotiation_free(sn);
}
sdp_message_t *
eXosip_get_local_sdp_info(osip_transaction_t *invite_tr)
{
osip_content_type_t *ctt;
osip_mime_version_t *mv;
osip_message_t *message;
sdp_message_t *sdp;
osip_body_t *oldbody;
int pos;
if (invite_tr->ctx_type == IST)
message = invite_tr->last_response;
else if (invite_tr->ctx_type == ICT)
message = invite_tr->orig_request;
else return NULL; /* BUG -> NOT AN INVITE TRANSACTION!! */
if (message==NULL) return NULL;
/* get content-type info */
ctt = osip_message_get_content_type(message);
mv = osip_message_get_mime_version(message);
if (mv==NULL && ctt==NULL)
return NULL; /* previous message was not correct or empty */
if (mv!=NULL)
{
/* look for the SDP body */
/* ... */
}
else if (ctt!=NULL)
{
if (ctt->type==NULL || ctt->subtype==NULL)
/* it can be application/sdp or mime... */
return NULL;
if (osip_strcasecmp(ctt->type, "application")!=0 ||
osip_strcasecmp(ctt->subtype, "sdp")!=0 )
{ return NULL; }
}
pos=0;
while (!osip_list_eol(message->bodies, pos))
{
int i;
oldbody = (osip_body_t *) osip_list_get(message->bodies, pos);
pos++;
sdp_message_init(&sdp);
i = sdp_message_parse(sdp,oldbody->body);
if (i==0) return sdp;
sdp_message_free(sdp);
sdp = NULL;
}
return NULL;
}
sdp_message_t *
eXosip_get_remote_sdp_info(osip_transaction_t *invite_tr)
{
osip_content_type_t *ctt;
osip_mime_version_t *mv;
osip_message_t *message;
sdp_message_t *sdp;
osip_body_t *oldbody;
int pos;
if (invite_tr->ctx_type == IST)
message = invite_tr->orig_request;
else if (invite_tr->ctx_type == ICT)
message = invite_tr->last_response;
else return NULL; /* BUG -> NOT AN INVITE TRANSACTION!! */
if (message==NULL) return NULL;
/* get content-type info */
ctt = osip_message_get_content_type(message);
mv = osip_message_get_mime_version(message);
if (mv==NULL && ctt==NULL)
return NULL; /* previous message was not correct or empty */
if (mv!=NULL)
{
/* look for the SDP body */
/* ... */
}
else if (ctt!=NULL)
{
if (ctt->type==NULL || ctt->subtype==NULL)
/* it can be application/sdp or mime... */
return NULL;
if (osip_strcasecmp(ctt->type, "application")!=0 ||
osip_strcasecmp(ctt->subtype, "sdp")!=0 )
{ return NULL; }
}
pos=0;
while (!osip_list_eol(message->bodies, pos))
{
int i;
oldbody = (osip_body_t *) osip_list_get(message->bodies, pos);
pos++;
sdp_message_init(&sdp);
i = sdp_message_parse(sdp,oldbody->body);
if (i==0) return sdp;
sdp_message_free(sdp);
sdp = NULL;
}
return NULL;
}
int eXosip_retrieve_sdp_negotiation_result(osip_negotiation_ctx_t *ctx, char *payload_name, int pnsize)
{
sdp_message_t *local_sdp = 0;
int payload_result = -1;
if (!ctx)
return payload_result;
local_sdp = osip_negotiation_ctx_get_local_sdp(ctx);
if (local_sdp != NULL)
{
sdp_media_t *med = (sdp_media_t*) osip_list_get(local_sdp->m_medias, 0);
char *payload = (char *) osip_list_get (med->m_payloads, 0);
int pos_attr;
if (payload!=NULL)
{
payload_result = osip_atoi(payload);
/* copy payload name! */
for (pos_attr=0;
!osip_list_eol(med->a_attributes, pos_attr);
pos_attr++)
{
sdp_attribute_t *attr;
attr = (sdp_attribute_t *)osip_list_get(med->a_attributes, pos_attr);
if (0==osip_strncasecmp(attr->a_att_field, "rtpmap", 6))
{
if ((payload_result <10 &&
0==osip_strncasecmp(attr->a_att_value, payload, 1))
||(payload_result>9 && payload_result<100 &&
0==osip_strncasecmp(attr->a_att_value, payload, 2))
||(payload_result >100 && payload_result<128 &&
0==osip_strncasecmp(attr->a_att_value, payload, 3)))
{
snprintf(payload_name, pnsize, "%s", attr->a_att_value);
return payload_result;
}
}
}
}
}
return payload_result;
}

2635
linphone/exosip/udp.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,8 @@
.deps
.libs
Makefile
Makefile.in
linphone
linphone_applet
GNOME_LinphoneApplet.server
GNOME_LinphoneApplet.server.in

View file

@ -0,0 +1,32 @@
<oaf_info>
<oaf_server iid="OAFIID:GNOME_LinphoneApplet_Factory"
type="exe"
location="@LIBEXECDIR@/linphone_applet">
<oaf_attribute name="repo_ids" type="stringv">
<item value="IDL:Bonobo/GenericFactory:1.0"/>
<item value="IDL:Bonobo/Unknown:1.0"/>
</oaf_attribute>
<oaf_attribute name="name" type="string" value="Linphone Applet Factory"/>
<oaf_attribute name="description" type="string" value="Linphone Applet Factory"/>
</oaf_server>
<oaf_server iid="OAFIID:GNOME_LinphoneApplet"
type="factory"
location="OAFIID:GNOME_LinphoneApplet_Factory">
<oaf_attribute name="repo_ids" type="stringv">
<item value="IDL:GNOME/Vertigo/PanelAppletShell:1.0"/>
<item value="IDL:Bonobo/Control:1.0"/>
<item value="IDL:Bonobo/Unknown:1.0"/>
</oaf_attribute>
<oaf_attribute name="name" type="string" _value="Linphone"/>
<oaf_attribute name="description" type="string" _value="Linphone"/>
<oaf_attribute name="panel:category" type="string" _value="Internet"/>
<oaf_attribute name="panel:icon" type="string" value="linphone/linphone2.png"/>
</oaf_server>
</oaf_info>

View file

@ -0,0 +1,7 @@
<Root>
<popups>
<popup name="button3">
<menuitem name="About" verb="About" _label="_About..." pixtype="stock" pixname="gnome-stock-about"/>
</popup>
</popups>
</Root>

View file

@ -0,0 +1,80 @@
## Process this file with automake to produce Makefile.in
linphone_common_sources=\
linphone.c linphone.h \
gui_utils.c gui_utils.h \
support.c support.h \
interface.c interface.h \
callbacks.c callbacks.h \
presence.c presence.h \
propertybox.c propertybox.h \
addressbook.c addressbook.h \
friends.c friends.h
if BUILD_GNOME
INCLUDES = \
-I$(top_srcdir)\
-I$(top_srcdir)/intl \
$(ORTP_CFLAGS) \
-I$(top_srcdir)/coreapi \
-I$(top_srcdir)/mediastreamer2/include \
$(OSIP_CFLAGS)
bin_PROGRAMS = linphone
linphone_SOURCES = \
main.c \
$(linphone_common_sources)
linphone_LDADD = $(LIBGNOMEUI_LIBS) $(INTLLIBS) \
$(LIBGNOME_LIBS) \
$(top_builddir)/coreapi/liblinphone.la \
$(OSIP_LIBS)
endif
AM_CFLAGS=$(STRICT_OPTIONS) $(LIBGNOMEUI_CFLAGS) $(LIBGNOME_CFLAGS) $(GNOME_APPLETS_CFLAGS) $(IPV6_CFLAGS)
@INTLTOOL_SERVER_RULE@
if BUILD_GNOME_APPLET
gnome_appletdir=$(libexecdir)
gnome_applet_PROGRAMS = linphone_applet
linphone_applet_SOURCES = \
$(linphone_common_sources)\
applet.c
linphone_applet_CFLAGS=$(AM_CFLAGS) -DLINPHONE_APPLET
linphone_applet_LDADD = \
$(GNOME_APPLETS_LIBS) \
$(top_builddir)/coreapi/liblinphone.la \
$(OSIP_LIBS)
serverdir = $(libdir)/bonobo/servers
server_in_files = GNOME_LinphoneApplet.server.in
server_DATA = $(server_in_files:.server.in=.server)
$(server_in_files): $(server_in_files:.server.in=.server.in.in)
sed -e "s|\@LIBEXECDIR\@|$(libexecdir)|" $< > $@
uidir = $(datadir)/gnome-2.0/ui
ui_DATA = GNOME_LinphoneApplet.xml
endif
EXTRA_DIST = \
GNOME_LinphoneApplet.server.in.in \
applet.c \
$(ui_DATA)
DISTCLEANFILES=GNOME_LinphoneApplet.server.in GNOME_LinphoneApplet.server

View file

@ -0,0 +1,306 @@
/***************************************************************************
addressbook.c -
-------------------
begin : Wed Jan 30 2002
copyright : (C) 2002 by Simon Morlat
email : simon.morlat@linphone.org
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "linphone.h"
#define get_address_book() (&uiobj->addressbook)
#define get_main_window() (&uiobj->main_window)
#define get_core() (uiobj->core)
#define get_uiobj() (uiobj)
void fill_address_book(GtkWidget *address_list);
void ab_destroyed(){
get_uiobj()->ab=NULL;
}
void show_address_book(){
if (get_uiobj()->ab!=NULL){
gtk_window_present(GTK_WINDOW(get_uiobj()->ab));
}else{
get_uiobj()->ab=create_and_fill_address_book();
g_signal_connect(G_OBJECT(get_uiobj()->ab),"destroy",G_CALLBACK(ab_destroyed),NULL);
gtk_widget_show(get_uiobj()->ab);
}
}
#define GLADE_HOOKUP_OBJECT(component,widget,name) \
g_object_set_data_full (G_OBJECT (component), name, \
gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref)
void contact_draw(GtkWidget *w, LinphoneProxyConfig *cfg){
GtkWidget *table=lookup_widget(w,"table10");
GtkWidget *combo;
combo=proxy_combo_box_new(cfg);
gtk_widget_show(combo);
gtk_table_attach(GTK_TABLE(table),combo,1,2,2,3, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
(GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
GLADE_HOOKUP_OBJECT(w,combo,"proxy");
combo=gtk_combo_box_new_text();
gtk_combo_box_append_text(GTK_COMBO_BOX(combo),_("Wait"));
gtk_combo_box_append_text(GTK_COMBO_BOX(combo),_("Deny"));
gtk_combo_box_append_text(GTK_COMBO_BOX(combo),_("Accept"));
gtk_widget_show(combo);
gtk_table_attach(GTK_TABLE(table),combo,1,2,3,4, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
(GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
GLADE_HOOKUP_OBJECT(w,combo,"pol");
}
GtkWidget * contact_new(LinphoneFriend *lf, GtkWidget *ab){
GtkWidget *w=create_contact_box();
contact_draw(w,NULL);
gtk_widget_show(w);
g_object_set_data(G_OBJECT(w),"friend_ref",(gpointer)lf);
g_object_set_data(G_OBJECT(w),"address_book",(gpointer)ab);
g_object_set_data(G_OBJECT(w),"add",GINT_TO_POINTER(TRUE));
gtk_combo_box_set_active(GTK_COMBO_BOX(lookup_widget(w,"pol")),lf->pol);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(w,"send_subscribe")),lf->subscribe);
return w;
}
GtkWidget * contact_edit(LinphoneFriend *lf, GtkWidget *ab){
GtkWidget *w=create_contact_box();
gchar *tmpstr;
contact_draw(w,lf->proxy);
g_object_set_data(G_OBJECT(w),"friend_ref",(gpointer)lf);
linphone_friend_edit(lf);
tmpstr=linphone_friend_get_name(lf);
if (tmpstr!=NULL) {
gtk_entry_set_text(GTK_ENTRY(lookup_widget(w,"name")),tmpstr);
g_free(tmpstr);
}
tmpstr=linphone_friend_get_addr(lf);
gtk_entry_set_text(GTK_ENTRY(lookup_widget(w,"sipaddr")),tmpstr);
g_free(tmpstr);
gtk_combo_box_set_active(GTK_COMBO_BOX(lookup_widget(w,"pol")),lf->pol);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(w,"send_subscribe")),lf->subscribe);
gtk_widget_show(w);
if (ab!=NULL) g_object_set_data(G_OBJECT(w),"address_book",(gpointer)ab);
return w;
}
GtkWidget * subscriber_edit(LinphoneFriend *lf){
GtkWidget *w=contact_edit(lf,NULL);
g_object_set_data(G_OBJECT(w),"add",GINT_TO_POINTER(TRUE));
return w;
}
gint contact_ok(GtkWidget *dialog){
gchar *name,*sipaddr;
gchar *url;
gboolean add=FALSE;
GtkWidget *ab;
LinphoneFriend *lf;
int err;
lf=(LinphoneFriend*)g_object_get_data(G_OBJECT(dialog),"friend_ref");
add=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(dialog),"add"));
name=gtk_editable_get_chars(GTK_EDITABLE(lookup_widget(dialog,"name")),0,-1);
sipaddr=gtk_editable_get_chars(GTK_EDITABLE(lookup_widget(dialog,"sipaddr")),0,-1);
url=g_strdup_printf("%s <%s>",name,sipaddr);
/* workaround a bug in osip ? */
/* something doesn't like addresses like "machin <<sip:truc@bidule>>" */
if (strchr(sipaddr,'<')==NULL){
err=linphone_friend_set_sip_addr(lf,url);
}else err=-1;
if (err<0){
linphone_gnome_ui_display_something(get_uiobj(),GTK_MESSAGE_WARNING,_("Bad sip address: a sip address looks like sip:user@domain"));
linphone_friend_destroy(lf);
g_free(name);
g_free(sipaddr);
g_free(url);
return -1;
}
g_free(name);
g_free(sipaddr);
g_free(url);
linphone_friend_set_proxy(lf,proxy_combo_box_get_selected(lookup_widget(dialog,"proxy")));
linphone_friend_set_inc_subscribe_policy(lf,gtk_combo_box_get_active(GTK_COMBO_BOX(lookup_widget(dialog,"pol"))));
linphone_friend_send_subscribe(lf,gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog,"send_subscribe"))));
if (add){
linphone_core_add_friend(get_core(),lf);
}
else linphone_friend_done(lf);
/* ask the address book to redraw itself */
ab=g_object_get_data(G_OBJECT(dialog),"address_book");
if (ab!=NULL) fill_address_book(lookup_widget(ab,"address_list"));
return 0;
}
enum{
SIP_ADDRESS_COLUMN,
FRIEND_REFERENCE,
AB_NCOLUMNS
};
void choose_address_and_close(GtkWidget *ab){
GtkTreeSelection *select;
GtkWidget *addressentry=get_main_window()->addressentry;
GtkTreeIter iter;
GtkTreeModel *model;
gchar *address=NULL;
GtkWidget *address_list=lookup_widget(ab,"address_list");
select = gtk_tree_view_get_selection (GTK_TREE_VIEW (address_list));
if (select==NULL) return;
if (gtk_tree_selection_get_selected (select, &model, &iter))
{
gtk_tree_model_get (model, &iter,SIP_ADDRESS_COLUMN , &address, -1);
}
if (address!=NULL){
gtk_entry_set_text (GTK_ENTRY(addressentry),address);
g_free(address);
}
gtk_widget_destroy(ab);
}
void
address_book_close (GtkWidget *object,
gpointer user_data)
{
gtk_widget_destroy(gtk_widget_get_toplevel(object));
}
void address_selection_changed_cb(GtkTreeSelection *selection, gpointer data)
{
}
gboolean address_button_press(GtkWidget *widget,GdkEventButton *event,gpointer user_data)
{
GtkWidget *ab=(GtkWidget*)user_data;
if (event->type==GDK_2BUTTON_PRESS){
choose_address_and_close(ab);
return TRUE;
}
return FALSE;
}
void fill_address_book(GtkWidget *address_list){
GtkListStore *store;
GtkTreeIter iter;
GtkTreeModel *model;
MSList *elem;
gchar *tmpstr;
/* fill the store */
elem=linphone_core_get_friend_list(get_core());
model=gtk_tree_view_get_model(GTK_TREE_VIEW(address_list));
store=GTK_LIST_STORE(model);
gtk_list_store_clear(store);
for(;elem!=NULL;elem=ms_list_next(elem)){
LinphoneFriend *lf=(LinphoneFriend*)elem->data;
tmpstr=linphone_friend_get_url(lf);
gtk_list_store_append(store,&iter);
gtk_list_store_set(store,&iter,SIP_ADDRESS_COLUMN,tmpstr,FRIEND_REFERENCE,(gpointer)lf,-1);
ms_free(tmpstr);
}
}
GtkWidget *create_and_fill_address_book(){
GtkListStore *store;
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
GtkTreeSelection *select;
GtkWidget *address_list;
GtkWidget *ret=create_address_book();
address_list=lookup_widget(ret,"address_list");
store = gtk_list_store_new (AB_NCOLUMNS, G_TYPE_STRING,G_TYPE_POINTER);
gtk_tree_view_set_model(GTK_TREE_VIEW(address_list),GTK_TREE_MODEL(store));
g_object_unref(G_OBJECT(store));
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes (_("Contact list"),
renderer,
"text", SIP_ADDRESS_COLUMN,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (address_list), column);
/* Setup the selection handler */
select = gtk_tree_view_get_selection (GTK_TREE_VIEW (address_list));
gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
g_signal_connect (G_OBJECT (select), "changed",
G_CALLBACK (address_selection_changed_cb),
NULL);
/* setup handler for double click */
g_signal_connect(G_OBJECT(address_list),"button-press-event",G_CALLBACK(address_button_press),(gpointer)ret);
fill_address_book(address_list);
return ret;
}
void
on_modify_address_clicked (GtkButton *button,
gpointer user_data)
{
GtkTreeSelection *select;
GtkTreeIter iter;
GtkTreeModel *model;
GtkWidget *address_list=lookup_widget(gtk_widget_get_toplevel(GTK_WIDGET(button)),"address_list");
/* change the address in the view */
select = gtk_tree_view_get_selection (GTK_TREE_VIEW (address_list));
if (gtk_tree_selection_get_selected (select, &model, &iter))
{
LinphoneFriend *lf=NULL;
gtk_tree_model_get(model,&iter,FRIEND_REFERENCE,&lf,-1);
contact_edit(lf,gtk_widget_get_toplevel(GTK_WIDGET(button)));
}
}
void on_add_address_clicked(GtkButton *button,gpointer user_data)
{
LinphoneFriend *lf=linphone_friend_new();
contact_new(lf,gtk_widget_get_toplevel(GTK_WIDGET(button)));
}
void on_remove_address_clicked(GtkButton *button,gpointer user_data)
{
GtkTreeSelection *select;
GtkTreeIter iter;
GtkTreeModel *model;
GtkWidget *address_list=lookup_widget(gtk_widget_get_toplevel(GTK_WIDGET(button)),"address_list");
select = gtk_tree_view_get_selection (GTK_TREE_VIEW (address_list));
if (gtk_tree_selection_get_selected (select, &model, &iter))
{
LinphoneFriend *lf=NULL;
gtk_tree_model_get(model,&iter,FRIEND_REFERENCE,&lf,-1);
linphone_core_remove_friend(get_core(),lf);
gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
}
}
void on_select_address_clicked(GtkButton *button,gpointer user_data)
{
choose_address_and_close(gtk_widget_get_toplevel(GTK_WIDGET(button)));
}
void
on_contact_box_response (GtkDialog *dialog,
gint response_id,
gpointer user_data)
{
switch (response_id){
case GTK_RESPONSE_OK:
contact_ok(GTK_WIDGET(dialog));
break;
default:
break;
}
gtk_widget_destroy(GTK_WIDGET(dialog));
}

View file

@ -0,0 +1,28 @@
/***************************************************************************
addressbook.h -
-------------------
begin : Wed Jan 30 2002
copyright : (C) 2002 by Simon Morlat
email : simon.morlat@linphone.org
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef ADDRESSBOOK_H
#define ADDRESSBOOK_H
GtkWidget *create_and_fill_address_book();
void show_address_book();
GtkWidget * contact_new(LinphoneFriend *lf, GtkWidget *ab);
GtkWidget * contact_edit(LinphoneFriend *lf, GtkWidget *ab);
GtkWidget * subscriber_edit(LinphoneFriend *lf);
#endif

182
linphone/gnome/applet.c Normal file
View file

@ -0,0 +1,182 @@
/***************************************************************************
applet.c - Applet code for linphone's gnome
interface
-------------------
begin : Sat Dec 14 2002
copyright : (C) 2001 by Simon Morlat
email : simon.morlat@linphone.org
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "linphone.h"
#include <panel-applet.h>
#define get_uiobj() (uiobj)
LinphoneCore core;
LinphoneGnomeUI ui;
static int show=0;
static gulong signal_ref;
static GtkWidget *applet_button=NULL;
static GdkPixbuf *original_icon=NULL;
static GtkWidget *icon=NULL;
void draw_icon(GtkWidget *button, int size)
{
GdkPixbuf *resized;
if (original_icon==NULL){
original_icon=gdk_pixbuf_new_from_file(PACKAGE_DATA_DIR "/pixmaps/linphone/linphone2.xpm",
NULL);
g_return_if_fail( original_icon!=NULL);
}
if (icon!=NULL){
gtk_container_remove(GTK_CONTAINER(button),icon);
gtk_widget_destroy(icon);
}
resized=gdk_pixbuf_scale_simple(original_icon,size,size,GDK_INTERP_BILINEAR);
g_return_if_fail(resized!=NULL);
icon=gtk_image_new_from_pixbuf(resized);
g_return_if_fail(icon!=NULL);
gdk_pixbuf_unref(resized);
gtk_container_add(GTK_CONTAINER(button),icon);
gtk_widget_show(icon);
}
void linphone_applet_about_cb(gpointer p)
{
GtkWidget *about2;
about2 = create_about2 ();
gtk_widget_show (about2);
}
static void applet_change_pixel_size(GtkWidget *applet, int size)
{
g_return_if_fail(applet_button!=NULL);
draw_icon(applet_button,size);
}
static void applet_destroy_cb(GtkWidget *widget, gpointer data)
{
if (get_uiobj()->main_window.window!=NULL){
gtk_widget_destroy(get_uiobj()->main_window.window);
}
linphone_gnome_uninit(get_uiobj());
}
static gboolean
gui_destroy_cb (GtkWidget *widget, gpointer data)
{
linphone_gnome_ui_uninit(get_uiobj());
show=0;
return FALSE;
}
static gboolean button_press_cb(GtkWidget *applet, GdkEventButton* event, gpointer data)
{
if (event->button!=1) return FALSE;
if (show){
g_signal_handlers_disconnect_by_func(G_OBJECT(get_uiobj()->main_window.window),
G_CALLBACK(gui_destroy_cb),NULL);
linphone_gnome_ui_hide(get_uiobj());
show=0;
}else {
linphone_gnome_ui_show(get_uiobj());
signal_ref=g_signal_connect(G_OBJECT(get_uiobj()->main_window.window),
"destroy",
G_CALLBACK(gui_destroy_cb),NULL);
show=1;
}
return FALSE;
}
const BonoboUIVerb linphone_applet_menu_verbs [] = {
BONOBO_UI_UNSAFE_VERB ("About", linphone_applet_about_cb),
BONOBO_UI_VERB_END
};
static gboolean
linphone_applet_fill (PanelApplet *applet)
{
gint size=panel_applet_get_size(applet);
applet_button=gtk_frame_new(NULL);
gtk_container_add(GTK_CONTAINER(applet),applet_button);
gtk_widget_show(applet_button);
draw_icon(applet_button,size);
g_signal_connect(G_OBJECT(applet),"button-press-event",G_CALLBACK(button_press_cb),NULL);
g_signal_connect(G_OBJECT(applet),"change_size",
G_CALLBACK(applet_change_pixel_size),
NULL);
g_signal_connect (G_OBJECT (applet), "destroy",
G_CALLBACK (applet_destroy_cb), NULL);
//sizehint = panel_applet_get_size (PANEL_APPLET (applet));
panel_applet_setup_menu_from_file (applet,
NULL,
"GNOME_LinphoneApplet.xml",
NULL,
linphone_applet_menu_verbs,
NULL);
/* tracing for osip */
TRACE_INITIALIZE(5,stdout);
linphone_gnome_init(&ui,&core);
gtk_widget_show_all (GTK_WIDGET (applet));
return TRUE;
}
static gboolean
linphone_applet_factory (PanelApplet *applet,
const gchar *iid,
gpointer data)
{
static int instances=0;
GtkWidget *dialog;
if (!strcmp (iid, "OAFIID:GNOME_LinphoneApplet")){
if (instances>0){
dialog = gtk_message_dialog_new (GTK_WINDOW(applet),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_WARNING,
GTK_BUTTONS_CLOSE,
(const gchar*) _("Cannot run multiples instances of the linphone applet."));
/* Destroy the dialog when the user responds to it (e.g. clicks a button) */
g_signal_connect_swapped (G_OBJECT (dialog), "response",
G_CALLBACK (gtk_widget_destroy),
G_OBJECT (dialog));
gtk_widget_show(GTK_WIDGET(dialog));
return FALSE;
}
return linphone_applet_fill (applet);
}
return FALSE;
}
#define GNOMELOCALEDIR PACKAGE_LOCALE_DIR
PANEL_APPLET_BONOBO_FACTORY ("OAFIID:GNOME_LinphoneApplet_Factory",
PANEL_TYPE_APPLET,
"linphone_applet",
"0",
linphone_applet_factory,
NULL)

695
linphone/gnome/callbacks.c Normal file
View file

@ -0,0 +1,695 @@
/*
linphone
Copyright (C) 2000 Simon MORLAT (simon.morlat@free.fr)
callbacks.c -- gtk callbacks, and osipua callbacks.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "linphone.h"
#include <gdk/gdkkeysyms.h>
#define get_core() (uiobj->core)
#define get_main_window() (&uiobj->main_window)
#define get_uiobj() (uiobj)
void
on_about1_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
GtkWidget *about2;
about2 = create_about2 ();
gtk_widget_show (about2);
}
gint
on_prop1_close (GnomeDialog *gnomedialog,
gpointer user_data)
{
LinphoneMainWindow *obj=get_main_window();
gnome_appbar_clear_stack( GNOME_APPBAR(obj->status_bar));
return(FALSE);
}
void
on_parametres1_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
LinphoneGnomeUI *ui=get_uiobj();
linphone_property_box_init(&ui->propbox);
}
void
on_user_manual1_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
gnome_help_display("index.xml",NULL,NULL);
}
gboolean
on_play_vol_button_release_event (GtkWidget *widget,
GdkEventButton *event,
gpointer user_data)
{
int vol;
vol=(gtk_range_get_adjustment(GTK_RANGE(widget)))->value;
linphone_core_set_play_level(get_core(),vol);
return FALSE;
}
gboolean
on_rec_vol_button_release_event (GtkWidget *widget,
GdkEventButton *event,
gpointer user_data)
{
int vol;
vol=(gtk_range_get_adjustment(GTK_RANGE(widget)))->value;
linphone_core_set_rec_level(get_core(),vol);
return FALSE;
}
gboolean
on_ring_vol_button_release_event (GtkWidget *widget,
GdkEventButton *event,
gpointer user_data)
{
int vol;
vol=(gtk_range_get_adjustment(GTK_RANGE(widget)))->value;
linphone_core_set_ring_level(get_core(),vol);
return FALSE;
}
void
on_prop1_help (GnomePropertyBox *gnomepropertybox,
gint arg1,
gpointer user_data)
{
gnome_help_display("index.html",NULL,NULL);
}
void
on_fermer1_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
linphone_gnome_ui_hide(get_uiobj());
}
#if 0
/*this is when the panel size changes*/
void applet_change_pixel_size(GtkWidget *w, int size, gpointer data)
{
GtkWidget *pixmap,*button;
pixmap=gtk_object_get_data(GTK_OBJECT(applet),"applet_pixmap");
button=(GtkWidget*)gtk_object_get_data(GTK_OBJECT(applet),"applet_button");
if (button==NULL)
{
printf("Cannot find applet button\n");
return;
}
if (pixmap!=NULL) gtk_widget_destroy(pixmap);
pixmap = gnome_pixmap_new_from_xpm_d_at_size(linphone2_xpm,
size-4, size-4);
gtk_object_set_data(GTK_OBJECT(applet),"applet_pixmap",pixmap);
gtk_widget_show(pixmap);
gtk_container_add(GTK_CONTAINER(button), pixmap);
}
#endif
void
on_adresse_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
show_address_book();
}
void on_address_book_show(GtkWidget *widget,gpointer user_data)
{
}
void
on_showmore_toggled (GtkToggleButton *togglebutton,
gpointer user_data)
{
gint state;
GtkWidget *optioncontrols=get_main_window()->optioncontrols;
state=gtk_toggle_button_get_active(togglebutton);
if (state) gtk_widget_show(optioncontrols);
else {
gtk_widget_hide(optioncontrols);
}
}
void
on_useRPC_toggled (GtkToggleButton *togglebutton,
gpointer user_data)
{
#ifdef VINCENT_MAURY_RSVP
LinphoneCore *lc=get_core();
gboolean state;
state=gtk_toggle_button_get_active(togglebutton);
/* change RPC settings according to state */
if (state)
{
if (linphone_core_set_rpc_mode(lc,1)!=0) /* set rpc on */
{
printf("RPC error. unable to set rpc on !\n");
printf("Check to see if RPC server is running\n");
gtk_toggle_button_set_active(togglebutton,FALSE);
/*linphone_core_set_rpc_mode(lc,0);*/
}
}
else
{
if (linphone_core_set_rpc_mode(lc,0)!=0) /* set rpc off */
printf("RPC error. That's impossible !!\n");
}
#endif
}
void
on_useRSVP_toggled (GtkToggleButton *togglebutton,
gpointer user_data)
{
#ifdef VINCENT_MAURY_RSVP
LinphoneCore *lc=get_core();
LinphoneGnomeUI *ui=get_uiobj();
gboolean state;
state=gtk_toggle_button_get_active(togglebutton);
/* change the QoS settings function of the state */
if (state)
{
linphone_core_set_rsvp_mode(lc,1); /* set RSVP on */
gtk_widget_show(lookup_widget(ui->propbox.prop,"useRPC")); /* show RPC checkbox */
}
else
{
linphone_core_set_rsvp_mode(lc,0); /* set RSVP off */
/* uncheck RPC if necessary and hide RPC checkbox */
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
lookup_widget(ui->propbox.prop,"useRPC")),FALSE);
gtk_widget_hide(lookup_widget(ui->propbox.prop,"useRPC"));
}
#endif
}
#ifdef VINCENT_MAURY_RSVP
/* callback called when you click the yes/no dialog box
* send yes or no to the core_change_qos which knows the question
* and will be able to ajust qos */
void dialog_click (GtkDialog *dialog,gint arg1,gpointer user_data)
{
LinphoneCore *lc=get_core();
if (lc->call==NULL)
return;
if (arg1==GTK_RESPONSE_YES)
{
printf("YES\n");
linphone_core_change_qos(lc, 1); /* 1 = yes */
}
else
{
printf("NO\n");
linphone_core_change_qos(lc, 0); /* 0 = no */
}
gtk_widget_destroy((GtkWidget*)dialog);
}
#endif
void
on_alt_href_clicked (GtkButton *button,
gpointer user_data)
{
gchar *url;
GtkWidget *label;
osip_from_t * from;
LinphoneGnomeUI *ui=get_uiobj();
label=GTK_BIN(button)->child;
gtk_label_get(GTK_LABEL(label),&url);
osip_from_init(&from);
if ( osip_from_parse(from,url) <0){
/* do something here */
}else
{ /* it was a sip url, so display it in the entry*/
gtk_entry_set_text(GTK_ENTRY(gnome_entry_gtk_entry(GNOME_ENTRY(ui->main_window.addressentry))),url);
}
osip_from_free(from);
}
void
on_alt_href_realize (GtkWidget *widget,
gpointer user_data)
{
GdkCursor *cursor = gdk_cursor_new(GDK_HAND2);
gdk_window_set_cursor(widget->window, cursor);
gdk_cursor_destroy(cursor);
}
void
on_dtmf_3_clicked (GtkButton *button,
gpointer user_data)
{
GtkWidget *dtmf_entry=get_main_window()->dtmfentry;
gtk_entry_append_text(GTK_ENTRY(dtmf_entry),"3");
}
void
on_dmtf_2_clicked (GtkButton *button,
gpointer user_data)
{
GtkWidget *dtmf_entry=get_main_window()->dtmfentry;
gtk_entry_append_text(GTK_ENTRY(dtmf_entry),"2");
}
void
on_dtmf_1_clicked (GtkButton *button,
gpointer user_data)
{
GtkWidget *dtmf_entry=get_main_window()->dtmfentry;
gtk_entry_append_text(GTK_ENTRY(dtmf_entry),"1");
}
void
on_dtmf_4_clicked (GtkButton *button,
gpointer user_data)
{
GtkWidget *dtmf_entry=get_main_window()->dtmfentry;
gtk_entry_append_text(GTK_ENTRY(dtmf_entry),"4");
}
void
on_dtmf_5_clicked (GtkButton *button,
gpointer user_data)
{
GtkWidget *dtmf_entry=get_main_window()->dtmfentry;
gtk_entry_append_text(GTK_ENTRY(dtmf_entry),"5");
}
void
on_dtmf_6_clicked (GtkButton *button,
gpointer user_data)
{
GtkWidget *dtmf_entry=get_main_window()->dtmfentry;
gtk_entry_append_text(GTK_ENTRY(dtmf_entry),"6");
}
void
on_dtmf_7_clicked (GtkButton *button,
gpointer user_data)
{
GtkWidget *dtmf_entry=get_main_window()->dtmfentry;
gtk_entry_append_text(GTK_ENTRY(dtmf_entry),"7");
}
void
on_dtmf_8_clicked (GtkButton *button,
gpointer user_data)
{
GtkWidget *dtmf_entry=get_main_window()->dtmfentry;
gtk_entry_append_text(GTK_ENTRY(dtmf_entry),"8");
}
void
on_dtmf_9_clicked (GtkButton *button,
gpointer user_data)
{
GtkWidget *dtmf_entry=get_main_window()->dtmfentry;
gtk_entry_append_text(GTK_ENTRY(dtmf_entry),"9");
}
void
on_dtmf_star_clicked (GtkButton *button,
gpointer user_data)
{
GtkWidget *dtmf_entry=get_main_window()->dtmfentry;
gtk_entry_append_text(GTK_ENTRY(dtmf_entry),"*");
}
void
on_dtmf_0_clicked (GtkButton *button,
gpointer user_data)
{
GtkWidget *dtmf_entry=get_main_window()->dtmfentry;
gtk_entry_append_text(GTK_ENTRY(dtmf_entry),"0");
}
void
on_dtmf_pound_clicked (GtkButton *button,
gpointer user_data)
{
GtkWidget *dtmf_entry=get_main_window()->dtmfentry;
gtk_entry_append_text(GTK_ENTRY(dtmf_entry),"#");
}
void
on_dtmf_entry_changed (GtkEditable *editable,
gpointer user_data)
{
gchar *dtmfs;
gint len;
/* get the last entry in the text box and plays it */
dtmfs=gtk_editable_get_chars(editable,0,-1);
g_return_if_fail(dtmfs!=NULL);
len=strlen(dtmfs);
if (len>0){
g_message("Sending dtmf %c",dtmfs[len-1]);
linphone_core_send_dtmf(get_uiobj()->core,dtmfs[len-1]);
}
g_free(dtmfs);
}
void
on_exit1_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
#ifdef LINPHONE_APPLET
#else
gtk_widget_destroy(get_uiobj()->main_window.window);
#endif
}
void on_app1_destroy(GtkWidget *app1, gpointer user_data)
{
#ifdef LINPHONE_APPLET
#else
gtk_main_quit();
#endif
}
void
on_display_ab_clicked (GtkButton *button,
gpointer user_data)
{
show_address_book();
}
void
on_inc_subscr_dialog_response (GtkDialog *dialog,
gint response_id,
gpointer user_data)
{
LinphoneFriend *lf=(LinphoneFriend*)g_object_get_data(G_OBJECT(dialog),"friend_ref");
switch(response_id){
case GTK_RESPONSE_ACCEPT:
subscriber_edit(lf);
break;
case GTK_RESPONSE_REJECT:
linphone_core_reject_subscriber(get_core(),lf);
break;
}
gtk_widget_destroy(GTK_WIDGET(dialog));
}
void authentication_dialog_ok(GtkWidget *w)
{
gchar *realm,*username,*userid,*passwd;
LinphoneAuthInfo *info;
realm=gtk_editable_get_chars(GTK_EDITABLE(lookup_widget(w,"realm")),0,-1);
username=gtk_editable_get_chars(GTK_EDITABLE(lookup_widget(w,"username")),0,-1);
userid=gtk_editable_get_chars(GTK_EDITABLE(lookup_widget(w,"userid")),0,-1);
passwd=gtk_editable_get_chars(GTK_EDITABLE(lookup_widget(w,"passwd")),0,-1);
info=linphone_auth_info_new(username,userid,passwd,NULL,realm);
linphone_core_add_auth_info(get_core(),info);
g_free(username);
g_free(userid);
g_free(passwd);
g_free(realm);
}
void
on_authentication_dialog_response (GtkDialog *dialog,
gint response_id,
gpointer user_data)
{
switch(response_id){
case GTK_RESPONSE_OK:
authentication_dialog_ok(GTK_WIDGET(dialog));
gtk_widget_destroy(GTK_WIDGET(dialog));
break;
}
}
void
on_clear_auth_info_clicked (GtkButton *button,
gpointer user_data)
{
linphone_core_clear_all_auth_info(get_core());
}
void
on_call_history_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
linphone_gnome_show_call_logs_window(get_uiobj());
}
void
on_call_logs_response (GtkDialog *dialog,
gint response_id,
gpointer user_data)
{
gtk_widget_destroy(GTK_WIDGET(dialog));
}
void
on_call_logs_destroy (GtkObject *object,
gpointer user_data)
{
get_uiobj()->logs=NULL;
}
static void completion_add_text(GtkEntry *entry, const char *text){
GtkTreeIter iter;
GtkTreeModel *model=gtk_entry_completion_get_model(gtk_entry_get_completion(entry));
if (gtk_tree_model_get_iter_first(model,&iter)){
do {
gchar *uri=NULL;
gtk_tree_model_get(model,&iter,0,&uri,-1);
if (uri!=NULL){
if (strcmp(uri,text)==0) {
/*remove text */
gtk_list_store_remove(GTK_LIST_STORE(model),&iter);
g_free(uri);
break;
}
g_free(uri);
}
}while (gtk_tree_model_iter_next(model,&iter));
}
/* and prepend it on top of the list */
gtk_list_store_prepend(GTK_LIST_STORE(model),&iter);
gtk_list_store_set(GTK_LIST_STORE(model),&iter,0,text,-1);
}
void
on_callbutton_clicked (GtkButton *button,
gpointer user_data)
{
LinphoneGnomeUI *ui=get_uiobj();
LinphoneCore *lc=get_core();
GtkEntry *entry=GTK_ENTRY(ui->main_window.addressentry);
if (lc->call==NULL){
const gchar *sipurl=NULL;
int err;
/* we have no dialog in progress */
/* get the url to call */
sipurl=gtk_entry_get_text(entry);
err=linphone_core_invite(lc,sipurl);
if (err==0) completion_add_text(entry,sipurl);
}else {
linphone_core_accept_call(lc,NULL);
}
}
void
on_hangup_clicked (GtkButton *button,
gpointer user_data)
{
LinphoneGnomeUI *ui=get_uiobj();
LinphoneCore *lc=get_core();
if (lc->call!=NULL){
/* same trick here as for linphone_core_accept_dialog: defer it to gtk's idle loop */
gtk_window_set_title(GTK_WINDOW(ui->main_window.window),"linphone");
linphone_core_terminate_call(lc,NULL);
}
}
GtkWidget *chatroom_new(const gchar *url, LinphoneChatRoom *cr){
GtkWidget *gcr=NULL;
if (cr==NULL)
cr=linphone_core_create_chat_room(get_core(),url);
if (cr!=NULL){
gchar *tmp;
gcr=create_chatroom();
g_object_set_data(G_OBJECT(gcr),"chatroom",(gpointer)cr);
linphone_chat_room_set_user_data(cr,(gpointer)gcr);
tmp=g_strdup_printf(_("Chat with %s"),url);
gtk_window_set_title(GTK_WINDOW(gcr),tmp);
g_free(tmp);
}
return gcr;
}
void chatroom_append(GtkWidget *gcr, const gchar *from, const gchar *message){
GtkTextBuffer *tb;
gchar *str;
GtkTextIter enditer;
GtkTextView *tv=GTK_TEXT_VIEW(lookup_widget(gcr,"chattext"));
tb=gtk_text_view_get_buffer(tv);
g_return_if_fail(tb!=NULL);
gtk_text_buffer_get_end_iter(tb,&enditer);
str=g_strdup_printf("[%s]\t:%s\n",from,message);
gtk_text_buffer_insert(tb,&enditer,str,strlen(str));
g_free(str);
}
void chatroom_close(GtkWidget *gcr){
LinphoneChatRoom *cr;
cr=(LinphoneChatRoom*)g_object_get_data(G_OBJECT(gcr),"chatroom");
linphone_chat_room_destroy(cr);
}
void
on_chat_clicked (GtkButton *button,
gpointer user_data)
{
gchar *sipurl;
sipurl=gtk_editable_get_chars(GTK_EDITABLE(get_main_window()->addressentry),0,-1);
GtkWidget *gcr=chatroom_new(sipurl,NULL);
if (gcr!=NULL) gtk_widget_show(gcr);
g_free(sipurl);
}
void
on_chatbox_clicked (GtkButton *button,
gpointer user_data)
{
gtk_widget_destroy(gtk_widget_get_toplevel(GTK_WIDGET(button)));
}
void
on_chatentry_activate (GtkEntry *entry,
gpointer user_data)
{
LinphoneChatRoom *cr;
gchar *text;
text=gtk_editable_get_chars(GTK_EDITABLE(entry),0,-1);
if (strlen(text)>0){
GtkWidget *gcr=gtk_widget_get_toplevel(GTK_WIDGET(entry));
cr=(LinphoneChatRoom*)g_object_get_data(G_OBJECT(gcr),"chatroom");
linphone_chat_room_send_message(cr,text);
chatroom_append(gcr,linphone_core_get_primary_contact(get_core()),text);
gtk_editable_delete_text(GTK_EDITABLE(entry),0,-1);
}
}
void
on_chatroom_destroy (GtkObject *object,
gpointer user_data)
{
chatroom_close(GTK_WIDGET(object));
}
void
on_addressentry_activate (GtkEntry *entry,
gpointer user_data)
{
on_callbutton_clicked(NULL,NULL);
}
void
on_addressentry_destroy (GtkObject *object,
gpointer user_data)
{
linphone_gnome_save_uri_history(get_uiobj());
}
void
on_video_enabled_toggled (GtkToggleButton *togglebutton,
gpointer user_data)
{
linphone_core_enable_video(get_core(),gtk_toggle_button_get_active(togglebutton));
}
void
on_echocancelation_toggled (GtkToggleButton *togglebutton,
gpointer user_data)
{
linphone_core_enable_echo_cancelation(get_core(),
gtk_toggle_button_get_active(togglebutton));
}

540
linphone/gnome/callbacks.h Normal file
View file

@ -0,0 +1,540 @@
#include <gnome.h>
void
on_app1_destroy (GtkObject *object,
gpointer user_data);
void
on_adresse_activate (GtkMenuItem *menuitem,
gpointer user_data);
void
on_parametres1_activate (GtkMenuItem *menuitem,
gpointer user_data);
void
on_fermer1_activate (GtkMenuItem *menuitem,
gpointer user_data);
void
on_exit1_activate (GtkMenuItem *menuitem,
gpointer user_data);
void
on_about1_activate (GtkMenuItem *menuitem,
gpointer user_data);
void
on_user_manual1_activate (GtkMenuItem *menuitem,
gpointer user_data);
void
on_greenbutton_clicked (GtkButton *button,
gpointer user_data);
void
on_redbutton_clicked (GtkButton *button,
gpointer user_data);
void
on_showmore_toggled (GtkToggleButton *togglebutton,
gpointer user_data);
gboolean
on_play_vol_button_release_event (GtkWidget *widget,
GdkEventButton *event,
gpointer user_data);
gboolean
on_rec_vol_button_release_event (GtkWidget *widget,
GdkEventButton *event,
gpointer user_data);
gboolean
on_ring_vol_button_release_event (GtkWidget *widget,
GdkEventButton *event,
gpointer user_data);
void
on_reachable (GtkToggleButton *togglebutton,
gpointer user_data);
void
on_busy (GtkToggleButton *togglebutton,
gpointer user_data);
void
on_minutesaway_changed (GtkEditable *editable,
gpointer user_data);
void
on_away (GtkToggleButton *togglebutton,
gpointer user_data);
void
on_do_not_disturb (GtkToggleButton *togglebutton,
gpointer user_data);
void
on_moved_tmply (GtkToggleButton *togglebutton,
gpointer user_data);
void
on_alt_serv (GtkToggleButton *togglebutton,
gpointer user_data);
void
on_contact_field_changed (GtkEditable *editable,
gpointer user_data);
void
on_presence_validate_clicked (GtkButton *button,
gpointer user_data);
void
on_dtmf_entry_changed (GtkEditable *editable,
gpointer user_data);
void
on_dtmf_3_clicked (GtkButton *button,
gpointer user_data);
void
on_dmtf_2_clicked (GtkButton *button,
gpointer user_data);
void
on_dtmf_1_clicked (GtkButton *button,
gpointer user_data);
void
on_dtmf_4_clicked (GtkButton *button,
gpointer user_data);
void
on_dtmf_5_clicked (GtkButton *button,
gpointer user_data);
void
on_dtmf_6_clicked (GtkButton *button,
gpointer user_data);
void
on_dtmf_7_clicked (GtkButton *button,
gpointer user_data);
void
on_dtmf_8_clicked (GtkButton *button,
gpointer user_data);
void
on_dtmf_9_clicked (GtkButton *button,
gpointer user_data);
void
on_dtmf_star_clicked (GtkButton *button,
gpointer user_data);
void
on_dtmf_0_clicked (GtkButton *button,
gpointer user_data);
void
on_dtmf_pound_clicked (GtkButton *button,
gpointer user_data);
void
on_propertybox1_apply (GnomePropertyBox *propertybox,
gint page_num,
gpointer user_data);
gboolean
on_prop1_close (GnomeDialog *gnomedialog,
gpointer user_data);
void
on_prop1_help (GnomePropertyBox *propertybox,
gint page_num,
gpointer user_data);
gboolean
on_hscale1_button_release_event (GtkWidget *widget,
GdkEventButton *event,
gpointer user_data);
void
on_audioport_changed (GtkEditable *editable,
gpointer user_data);
void
on_sipport_changed (GtkEditable *editable,
gpointer user_data);
void
on_user_name_changed (GtkEditable *editable,
gpointer user_data);
void
on_domain_name_changed (GtkEditable *editable,
gpointer user_data);
void
on_registrar_checked_toggled (GtkToggleButton *togglebutton,
gpointer user_data);
void
on_rsvp_checked_toggled (GtkToggleButton *togglebutton,
gpointer user_data);
void
on_redirect_button_toggled (GtkToggleButton *togglebutton,
gpointer user_data);
void
on_proxy_button_toggled (GtkToggleButton *togglebutton,
gpointer user_data);
void
on_obproxy_button_toggled (GtkToggleButton *togglebutton,
gpointer user_data);
void
on_registrar_addr_changed (GtkEditable *editable,
gpointer user_data);
void
on_reg_passwd_changed (GtkEditable *editable,
gpointer user_data);
void
on_address_of_record_changed (GtkEditable *editable,
gpointer user_data);
void
on_aucodec_up_clicked (GtkButton *button,
gpointer user_data);
void
on_aucodec_down_clicked (GtkButton *button,
gpointer user_data);
void
on_aucodec_enable_clicked (GtkButton *button,
gpointer user_data);
void
on_aucodec_disable_clicked (GtkButton *button,
gpointer user_data);
void
on_sounddriver_changed (GtkEditable *editable,
gpointer user_data);
void
on_source_changed (GtkEditable *editable,
gpointer user_data);
void
on_autokill_button1_toggled (GtkToggleButton *togglebutton,
gpointer user_data);
void
on_address_book_show (GtkWidget *widget,
gpointer user_data);
void
on_add_address_clicked (GtkButton *button,
gpointer user_data);
void
on_remove_address_clicked (GtkButton *button,
gpointer user_data);
void
on_select_address_clicked (GtkButton *button,
gpointer user_data);
void
on_modify_address_clicked (GtkButton *button,
gpointer user_data);
void
on_alt_href_clicked (GtkButton *button,
gpointer user_data);
void
on_alt_href_realize (GtkWidget *widget,
gpointer user_data);
void
on_exit1_activate (GtkMenuItem *menuitem,
gpointer user_data);
void
address_book_close (GtkButton *button,
gpointer user_data);
void
on_card_changed (GtkEditable *editable,
gpointer user_data);
void
on_audio_jittcomp_value_changed (GtkRange *range,
gpointer user_data);
void
on_enable_nat_toggled (GtkToggleButton *togglebutton,
gpointer user_data);
void
on_nat_address_changed (GtkEditable *editable,
gpointer user_data);
void
on_display_ab_clicked (GtkButton *button,
gpointer user_data);
void
on_ringfileentry_changed (GtkEditable *editable,
gpointer user_data);
void
on_ringpreview_clicked (GtkButton *button,
gpointer user_data);
gboolean
on_property_box_closed (GnomeDialog *gnomedialog,
gpointer user_data);
void
on_address_book_close (GtkObject *object,
gpointer user_data);
#ifndef VERSION
# define VERSION LINPHONE_VERSION
#endif
void
on_addfriend_clicked (GtkButton *button,
gpointer user_data);
void
on_removefriend_clicked (GtkButton *button,
gpointer user_data);
void
on_add_adbk_clicked (GtkButton *button,
gpointer user_data);
void
on_addfriend_dialog_response (GtkDialog *dialog,
gint response_id,
gpointer user_data);
void
on_friendlist_row_activated (GtkTreeView *treeview,
GtkTreePath *path,
GtkTreeViewColumn *column,
gpointer user_data);
void
on_useRSVP_toggled (GtkToggleButton *togglebutton,
gpointer user_data);
void
on_useRPC_toggled (GtkToggleButton *togglebutton,
gpointer user_data);
#ifdef VINCENT_MAURY_RSVP
void
dialog_click (GtkDialog *dialog,
gint arg1,
gpointer user_data);
#endif
void
on_proxy_config_box_response (GtkDialog *dialog,
gint response_id,
gpointer user_data);
void
on_removeproxy_button_clicked (GtkButton *button,
gpointer user_data);
void
on_addproxy_button_clicked (GtkButton *button,
gpointer user_data);
void
on_editproxy_button_clicked (GtkButton *button,
gpointer user_data);
void
on_contact_box_response (GtkDialog *dialog,
gint response_id,
gpointer user_data);
void
on_inc_subscr_dialog_response (GtkDialog *dialog,
gint response_id,
gpointer user_data);
void
on_ob_proxy_changed (GtkComboBox *combobox,
gpointer user_data);
void
on_authentication_dialog_response (GtkDialog *dialog,
gint response_id,
gpointer user_data);
void
on_clear_auth_info_clicked (GtkButton *button,
gpointer user_data);
void
on_use_sipinfo_toggled (GtkToggleButton *togglebutton,
gpointer user_data);
void
on_guess_hostname_toggled (GtkToggleButton *togglebutton,
gpointer user_data);
void
on_call_history_activate (GtkMenuItem *menuitem,
gpointer user_data);
void
on_call_logs_response (GtkDialog *dialog,
gint response_id,
gpointer user_data);
void
on_call_logs_destroy (GtkObject *object,
gpointer user_data);
void
on_enable_ipv6_toggled (GtkToggleButton *togglebutton,
gpointer user_data);
void
on_play_card_changed (GtkComboBox *combobox,
gpointer user_data);
void
on_capt_card_changed (GtkComboBox *combobox,
gpointer user_data);
void
on_ring_card_changed (GtkComboBox *combobox,
gpointer user_data);
void
on_callbutton_clicked (GtkButton *button,
gpointer user_data);
void
on_chatbox_clicked (GtkButton *button,
gpointer user_data);
void
on_chatentry_activate (GtkEntry *entry,
gpointer user_data);
void
on_hangup_clicked (GtkButton *button,
gpointer user_data);
void
on_chat_clicked (GtkButton *button,
gpointer user_data);
void
on_chatroom_destroy (GtkObject *object,
gpointer user_data);
void
on_ring_card_changed (GtkComboBox *combobox,
gpointer user_data);
void
on_addressentry_editing_done (GtkCellEditable *celleditable,
gpointer user_data);
void
on_addressentry_destroy (GtkObject *object,
gpointer user_data);
gboolean
on_addressentry_key_pressed (GtkWidget *widget,
GdkEventKey *event,
gpointer user_data);
void
on_addressentry_changed (GtkComboBox *combobox,
gpointer user_data);
void
on_addressentry_activate (GtkEntry *entry,
gpointer user_data);
void
on_addressentry_destroy (GtkObject *object,
gpointer user_data);
void
on_download_bw_value_changed (GtkSpinButton *spinbutton,
gpointer user_data);
void
on_download_bw_editing_done (GtkCellEditable *celleditable,
gpointer user_data);
void
on_download_bw_changed (GtkEditable *editable,
gpointer user_data);
gboolean
on_upload_bw_output (GtkSpinButton *spinbutton,
gpointer user_data);
void
on_upload_bw_change_value (GtkSpinButton *spinbutton,
GtkScrollType scroll,
gpointer user_data);
void
on_upload_bw_value_changed (GtkSpinButton *spinbutton,
gpointer user_data);
gboolean
on_upload_bw_leave_notify_event (GtkWidget *widget,
GdkEventCrossing *event,
gpointer user_data);
void
on_video_enabled_toggled (GtkToggleButton *togglebutton,
gpointer user_data);
void
on_echocancelation_toggled (GtkToggleButton *togglebutton,
gpointer user_data);
void
on_no_nat_toggled (GtkToggleButton *togglebutton,
gpointer user_data);
void
on_use_stun_toggled (GtkToggleButton *togglebutton,
gpointer user_data);
void
on_static_nat_toggled (GtkToggleButton *togglebutton,
gpointer user_data);
void
on_stun_server_changed (GtkEditable *editable,
gpointer user_data);

127
linphone/gnome/friends.c Normal file
View file

@ -0,0 +1,127 @@
/***************************************************************************
friends.c - display of friend's list
-------------------
begin : Mon Dec 17 2001
copyright : (C) 2001 by Simon Morlat
email : simon.morlat@linphone.org
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "linphone.h"
#define get_friend_list() (&uiobj->main_window.friendlist)
#define get_core() (uiobj->core)
#define get_main_window() (&uiobj->main_window)
enum{
FRIEND_PRESENCE_IMG,
FRIEND_SIP_ADDRESS,
FRIEND_PRESENCE_STATUS,
FRIEND_ID,
FRIEND_LIST_NCOL
};
void friend_list_set_friend_status(FriendList *fl, LinphoneFriend * fid, const gchar *url, const gchar *status, const gchar *img){
GtkTreeIter iter;
LinphoneFriend *tmp=0;
gboolean found=FALSE;
GtkTreeModel *model=gtk_tree_view_get_model(GTK_TREE_VIEW(fl->friendlist));
if (gtk_tree_model_get_iter_first(model,&iter)) {
do{
gtk_tree_model_get(model,&iter,FRIEND_ID,&tmp,-1);
//printf("tmp=%i, fid=%i",tmp,fid);
if (fid==tmp) {
GdkPixbuf *pixbuf;
gtk_list_store_set(GTK_LIST_STORE(model),&iter,FRIEND_PRESENCE_STATUS,status,-1);
pixbuf = create_pixbuf(img);
if (pixbuf)
{
gtk_list_store_set(GTK_LIST_STORE(model),&iter,FRIEND_PRESENCE_IMG, pixbuf,-1);
}
found=TRUE;
}
}while(gtk_tree_model_iter_next(model,&iter));
}
if (found==FALSE){
//printf("Adding new notifier\n");
GdkPixbuf *pixbuf;
gtk_list_store_append(GTK_LIST_STORE(model),&iter);
gtk_list_store_set(GTK_LIST_STORE(model),&iter,FRIEND_SIP_ADDRESS, url, FRIEND_PRESENCE_STATUS,status,FRIEND_ID,fid,-1);
pixbuf = create_pixbuf(img);
if (pixbuf) gtk_list_store_set(GTK_LIST_STORE(model),&iter,FRIEND_PRESENCE_IMG, pixbuf,-1);
}
}
void
on_friendlist_row_activated (GtkTreeView *treeview,
GtkTreePath *path,
GtkTreeViewColumn *column,
gpointer user_data)
{
GtkTreeSelection *select;
GtkTreeIter iter;
GtkTreeModel *model;
gchar* friend;
select = gtk_tree_view_get_selection (treeview);
if (gtk_tree_selection_get_selected (select, &model, &iter))
{
gtk_tree_model_get (model, &iter,FRIEND_SIP_ADDRESS , &friend, -1);
gtk_entry_set_text(GTK_ENTRY(get_main_window()->addressentry),friend);
g_free(friend);
}
}
void friend_list_init(FriendList *fl,LinphoneCore *lc,GtkWidget *mainwidget)
{
GtkListStore *store;
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
GtkTreeSelection *select;
store = gtk_list_store_new (FRIEND_LIST_NCOL, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
fl->lc=lc;
fl->friendlist=lookup_widget(mainwidget,"friendlist");
/* need to add friends to the store here ...*/
gtk_tree_view_set_model(GTK_TREE_VIEW(fl->friendlist),GTK_TREE_MODEL(store));
g_object_unref(G_OBJECT(store));
renderer = gtk_cell_renderer_pixbuf_new();
column = gtk_tree_view_column_new_with_attributes (NULL,
renderer,
"pixbuf", FRIEND_PRESENCE_IMG,
NULL);
gtk_tree_view_column_set_min_width (column, 29);
gtk_tree_view_append_column (GTK_TREE_VIEW (fl->friendlist), column);
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes (_("Name"),
renderer,
"text", FRIEND_SIP_ADDRESS,
NULL);
g_object_set (G_OBJECT(column), "resizable", TRUE, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (fl->friendlist), column);
column = gtk_tree_view_column_new_with_attributes (_("Presence status"),
renderer,
"text", FRIEND_PRESENCE_STATUS,
NULL);
g_object_set (G_OBJECT(column), "resizable", TRUE, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (fl->friendlist), column);
select = gtk_tree_view_get_selection (GTK_TREE_VIEW (fl->friendlist));
gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
}

29
linphone/gnome/friends.h Normal file
View file

@ -0,0 +1,29 @@
/***************************************************************************
friends.h - display of friend's list
-------------------
begin : Mon Dec 17 2001
copyright : (C) 2001 by Simon Morlat
email : simon.morlat@linphone.org
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <interface.h>
struct _FriendList {
LinphoneCore *lc;
GtkWidget *friendlist;
};
typedef struct _FriendList FriendList;
void friend_list_init(FriendList *fl,LinphoneCore *lc,GtkWidget *mainwidget);
void friend_list_set_friend_status(FriendList *fl, LinphoneFriend * fid, const gchar *url, const gchar *status, const gchar *img);

102
linphone/gnome/gui_utils.c Normal file
View file

@ -0,0 +1,102 @@
/*
applet.c - some utils functions that cannot be set in interface.c.
Copyright (C) 2000 Simon MORLAT (simon.morlat@free.fr)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "linphone.h"
/* creates the applet button*
GtkWidget *create_applet()
{
GtkWidget *frame;
GtkWidget *button;
GtkWidget *vbox;
GtkWidget *applet;
applet = applet_widget_new("linphone_applet");
frame = gtk_frame_new(NULL);
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
gtk_widget_show(frame);
vbox = gtk_vbox_new(FALSE, FALSE);
gtk_container_add(GTK_CONTAINER(frame), vbox);
gtk_widget_show(vbox);
button = gtk_button_new();
gtk_widget_ref(button);
GTK_WIDGET_UNSET_FLAGS(button, GTK_CAN_DEFAULT);
GTK_WIDGET_UNSET_FLAGS(button, GTK_CAN_FOCUS);
gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, TRUE, 0);
gtk_widget_show(button);
applet_widget_add (APPLET_WIDGET (applet), frame);
gtk_object_set_data_full(GTK_OBJECT(applet),"applet_button",button,(GtkDestroyNotify)gtk_widget_unref);
gtk_signal_connect(GTK_OBJECT(button), "button_press_event",
GTK_SIGNAL_FUNC(on_applet_clicked), NULL);
gtk_signal_connect(GTK_OBJECT(applet), "change_pixel_size",
GTK_SIGNAL_FUNC(applet_change_pixel_size), NULL);
applet_widget_set_tooltip( APPLET_WIDGET (applet),_("linphone"));
gtk_widget_show(applet);
return(applet);
};
*/
/* this just sets level adjustements for startup*/
void set_levels(LinphoneGnomeUI *ui,gint reclev, gint playlev, gint ringlev)
{
GtkWidget *range;
GtkWidget *window=ui->main_window.window;
return;
if (window)
{
range=lookup_widget(window,"rec_vol");
gtk_adjustment_set_value (gtk_range_get_adjustment(GTK_RANGE(range)),(gfloat)reclev);
range=lookup_widget(window,"play_vol");
gtk_adjustment_set_value (gtk_range_get_adjustment(GTK_RANGE(range)),(gfloat)playlev);
range=lookup_widget(window,"ring_vol");
gtk_adjustment_set_value (gtk_range_get_adjustment(GTK_RANGE(range)),(gfloat)ringlev);
}
}
void alt_ressource_display(LinphoneGnomeUI *ui,const gchar *url)
{
GtkWidget *href;
GtkWidget *altdisplay;
GtkLabel *label;
gchar *pattern;
altdisplay=create_altressource();
g_object_set_data(G_OBJECT(altdisplay),"ui",(gpointer)ui);
href=lookup_widget(altdisplay,"alt_href");
label=GTK_LABEL(GTK_BIN(href)->child);
gtk_label_set_text(label,url);
/* pattern used to set underline for string */
pattern = g_strnfill(strlen(url), '_');
gtk_label_set_pattern(label,pattern);
g_free(pattern);
gtk_widget_show(altdisplay);
}

Some files were not shown because too many files have changed in this diff Show more