summaryrefslogtreecommitdiff
path: root/pjsip/src/pjsua
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2006-02-27 00:00:30 +0000
committerBenny Prijono <bennylp@teluu.com>2006-02-27 00:00:30 +0000
commit887750106a0999aca4638c31d01ffa89eb3d4a74 (patch)
treef32476008af99f7a6be473ecc86166d76a0a1e20 /pjsip/src/pjsua
parente74059628256afdb725c367d23b9503f011b0d0c (diff)
Moved pjsua framework to pjsua-lib
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@238 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjsip/src/pjsua')
-rw-r--r--pjsip/src/pjsua/getopt.c751
-rw-r--r--pjsip/src/pjsua/getopt.h136
-rw-r--r--pjsip/src/pjsua/main.c2
-rw-r--r--pjsip/src/pjsua/pjsua.h468
-rw-r--r--pjsip/src/pjsua/pjsua_call.c1090
-rw-r--r--pjsip/src/pjsua/pjsua_core.c910
-rw-r--r--pjsip/src/pjsua/pjsua_opt.c860
-rw-r--r--pjsip/src/pjsua/pjsua_pres.c504
-rw-r--r--pjsip/src/pjsua/pjsua_reg.c167
9 files changed, 1 insertions, 4887 deletions
diff --git a/pjsip/src/pjsua/getopt.c b/pjsip/src/pjsua/getopt.c
deleted file mode 100644
index 30f45381..00000000
--- a/pjsip/src/pjsua/getopt.c
+++ /dev/null
@@ -1,751 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.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
- */
-
-/*
- * getopt entry points
- *
- * modified by Mike Borella <mike_borella@mw.3com.com>
- *
- * $Id$
- */
-
-#include "getopt.h"
-#include <pj/string.h>
-
-/* Internal only. Users should not call this directly. */
-static
-int _getopt_internal (int argc, char *const *argv,
- const char *shortopts,
- const struct option *longopts, int *longind,
- int long_only);
-
-/* getopt_long and getopt_long_only entry points for GNU getopt.
- Copyright (C) 1987,88,89,90,91,92,93,94,96,97 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The GNU C 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-
-/* Comment out all this code if we are using the GNU C Library, and are not
- actually compiling the library itself. This code is part of the GNU C
- Library, but also included in many other GNU distributions. Compiling
- and linking in this code is a waste when using the GNU C library
- (especially if it is a shared library). Rather than having every GNU
- program understand `configure --with-gnu-libc' and omit the object files,
- it is simpler to just do this in the source for each such file. */
-
-# define GETOPT_INTERFACE_VERSION 2
-
-
-int
-getopt_long (int argc, char *const *argv, const char *options,
- const struct option *long_options, int *opt_index)
-{
- return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
-}
-
-/* Like getopt_long, but '-' as well as '--' can indicate a long option.
- If an option that starts with '-' (not '--') doesn't match a long option,
- but does match a short option, it is parsed as a short option
- instead. */
-
-int
-getopt (int argc, char * const * argv, const char * optstring)
-{
- return _getopt_internal (argc, argv, optstring,
- (const struct option *) 0,
- (int *) 0,
- 0);
-}
-
-
-#define _(msgid) (msgid)
-
-/* This version of `getopt' appears to the caller like standard Unix `getopt'
- but it behaves differently for the user, since it allows the user
- to intersperse the options with the other arguments.
-
- As `getopt' works, it permutes the elements of ARGV so that,
- when it is done, all the options precede everything else. Thus
- all application programs are extended to handle flexible argument order.
-
- Setting the environment variable POSIXLY_CORRECT disables permutation.
- Then the behavior is completely standard.
-
- GNU application programs can use a third alternative mode in which
- they can distinguish the relative order of options and other arguments. */
-
-/* For communication from `getopt' to the caller.
- When `getopt' finds an option that takes an argument,
- the argument value is returned here.
- Also, when `ordering' is RETURN_IN_ORDER,
- each non-option ARGV-element is returned here. */
-
-char *optarg = NULL;
-
-/* Index in ARGV of the next element to be scanned.
- This is used for communication to and from the caller
- and for communication between successive calls to `getopt'.
-
- On entry to `getopt', zero means this is the first call; initialize.
-
- When `getopt' returns -1, this is the index of the first of the
- non-option elements that the caller should itself scan.
-
- Otherwise, `optind' communicates from one call to the next
- how much of ARGV has been scanned so far. */
-
-/* 1003.2 says this must be 1 before any call. */
-int optind = 1;
-
-/* Formerly, initialization of getopt depended on optind==0, which
- causes problems with re-calling getopt as programs generally don't
- know that. */
-
-int __getopt_initialized = 0;
-
-/* The next char to be scanned in the option-element
- in which the last option character we returned was found.
- This allows us to pick up the scan where we left off.
-
- If this is zero, or a null string, it means resume the scan
- by advancing to the next ARGV-element. */
-
-static char *nextchar;
-
-/* Set to an option character which was unrecognized.
- This must be initialized on some systems to avoid linking in the
- system's own getopt implementation. */
-
-int optopt = '?';
-
-/* Describe how to deal with options that follow non-option ARGV-elements.
-
- If the caller did not specify anything,
- the default is REQUIRE_ORDER if the environment variable
- POSIXLY_CORRECT is defined, PERMUTE otherwise.
-
- REQUIRE_ORDER means don't recognize them as options;
- stop option processing when the first non-option is seen.
- This is what Unix does.
- This mode of operation is selected by either setting the environment
- variable POSIXLY_CORRECT, or using `+' as the first character
- of the list of option characters.
-
- PERMUTE is the default. We permute the contents of ARGV as we scan,
- so that eventually all the non-options are at the end. This allows options
- to be given in any order, even with programs that were not written to
- expect this.
-
- RETURN_IN_ORDER is an option available to programs that were written
- to expect options and other ARGV-elements in any order and that care about
- the ordering of the two. We describe each non-option ARGV-element
- as if it were the argument of an option with character code 1.
- Using `-' as the first character of the list of option characters
- selects this mode of operation.
-
- The special argument `--' forces an end of option-scanning regardless
- of the value of `ordering'. In the case of RETURN_IN_ORDER, only
- `--' can cause `getopt' to return -1 with `optind' != ARGC. */
-
-static enum
-{
- REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
-} ordering;
-
-/* Value of POSIXLY_CORRECT environment variable. */
-static char *posixly_correct;
-
-static char *
-my_index (const char *str, int chr)
-{
- while (*str)
- {
- if (*str == chr)
- return (char *) str;
- str++;
- }
- return 0;
-}
-
-
-/* Handle permutation of arguments. */
-
-/* Describe the part of ARGV that contains non-options that have
- been skipped. `first_nonopt' is the index in ARGV of the first of them;
- `last_nonopt' is the index after the last of them. */
-
-static int first_nonopt;
-static int last_nonopt;
-
-# define SWAP_FLAGS(ch1, ch2)
-
-/* Exchange two adjacent subsequences of ARGV.
- One subsequence is elements [first_nonopt,last_nonopt)
- which contains all the non-options that have been skipped so far.
- The other is elements [last_nonopt,optind), which contains all
- the options processed since those non-options were skipped.
-
- `first_nonopt' and `last_nonopt' are relocated so that they describe
- the new indices of the non-options in ARGV after they are moved. */
-
-static void
-exchange (char **argv)
-{
- int bottom = first_nonopt;
- int middle = last_nonopt;
- int top = optind;
- char *tem;
-
- /* Exchange the shorter segment with the far end of the longer segment.
- That puts the shorter segment into the right place.
- It leaves the longer segment in the right place overall,
- but it consists of two parts that need to be swapped next. */
-
- while (top > middle && middle > bottom)
- {
- if (top - middle > middle - bottom)
- {
- /* Bottom segment is the short one. */
- int len = middle - bottom;
- register int i;
-
- /* Swap it with the top part of the top segment. */
- for (i = 0; i < len; i++)
- {
- tem = argv[bottom + i];
- argv[bottom + i] = argv[top - (middle - bottom) + i];
- argv[top - (middle - bottom) + i] = tem;
- SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
- }
- /* Exclude the moved bottom segment from further swapping. */
- top -= len;
- }
- else
- {
- /* Top segment is the short one. */
- int len = top - middle;
- register int i;
-
- /* Swap it with the bottom part of the bottom segment. */
- for (i = 0; i < len; i++)
- {
- tem = argv[bottom + i];
- argv[bottom + i] = argv[middle + i];
- argv[middle + i] = tem;
- SWAP_FLAGS (bottom + i, middle + i);
- }
- /* Exclude the moved top segment from further swapping. */
- bottom += len;
- }
- }
-
- /* Update records for the slots the non-options now occupy. */
-
- first_nonopt += (optind - last_nonopt);
- last_nonopt = optind;
-}
-
-/* Initialize the internal data when the first call is made. */
-
-static const char *_getopt_initialize (int argc, char *const *argv,
- const char *optstring)
-{
- PJ_UNUSED_ARG(argc);
- PJ_UNUSED_ARG(argv);
-
- /* Start processing options with ARGV-element 1 (since ARGV-element 0
- is the program name); the sequence of previously skipped
- non-option ARGV-elements is empty. */
-
- first_nonopt = last_nonopt = optind;
-
- nextchar = NULL;
-
- //posixly_correct = getenv ("POSIXLY_CORRECT");
- posixly_correct = NULL;
-
- /* Determine how to handle the ordering of options and nonoptions. */
-
- if (optstring[0] == '-')
- {
- ordering = RETURN_IN_ORDER;
- ++optstring;
- }
- else if (optstring[0] == '+')
- {
- ordering = REQUIRE_ORDER;
- ++optstring;
- }
- else if (posixly_correct != NULL)
- ordering = REQUIRE_ORDER;
- else
- ordering = PERMUTE;
-
- return optstring;
-}
-
-/* Scan elements of ARGV (whose length is ARGC) for option characters
- given in OPTSTRING.
-
- If an element of ARGV starts with '-', and is not exactly "-" or "--",
- then it is an option element. The characters of this element
- (aside from the initial '-') are option characters. If `getopt'
- is called repeatedly, it returns successively each of the option characters
- from each of the option elements.
-
- If `getopt' finds another option character, it returns that character,
- updating `optind' and `nextchar' so that the next call to `getopt' can
- resume the scan with the following option character or ARGV-element.
-
- If there are no more option characters, `getopt' returns -1.
- Then `optind' is the index in ARGV of the first ARGV-element
- that is not an option. (The ARGV-elements have been permuted
- so that those that are not options now come last.)
-
- OPTSTRING is a string containing the legitimate option characters.
- If an option character is seen that is not listed in OPTSTRING,
- return '?' after printing an error message. If you set `opterr' to
- zero, the error message is suppressed but we still return '?'.
-
- If a char in OPTSTRING is followed by a colon, that means it wants an arg,
- so the following text in the same ARGV-element, or the text of the following
- ARGV-element, is returned in `optarg'. Two colons mean an option that
- wants an optional arg; if there is text in the current ARGV-element,
- it is returned in `optarg', otherwise `optarg' is set to zero.
-
- If OPTSTRING starts with `-' or `+', it requests different methods of
- handling the non-option ARGV-elements.
- See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
-
- Long-named options begin with `--' instead of `-'.
- Their names may be abbreviated as long as the abbreviation is unique
- or is an exact match for some defined option. If they have an
- argument, it follows the option name in the same ARGV-element, separated
- from the option name by a `=', or else the in next ARGV-element.
- When `getopt' finds a long-named option, it returns 0 if that option's
- `flag' field is nonzero, the value of the option's `val' field
- if the `flag' field is zero.
-
- The elements of ARGV aren't really const, because we permute them.
- But we pretend they're const in the prototype to be compatible
- with other systems.
-
- LONGOPTS is a vector of `struct option' terminated by an
- element containing a name which is zero.
-
- LONGIND returns the index in LONGOPT of the long-named option found.
- It is only valid when a long-named option has been found by the most
- recent call.
-
- If LONG_ONLY is nonzero, '-' as well as '--' can introduce
- long-named options. */
-
-static int
-_getopt_internal (int argc, char *const *argv, const char *optstring,
- const struct option *longopts, int *longind,
- int long_only)
-{
- optarg = NULL;
-
- if (optind == 0 || !__getopt_initialized)
- {
- if (optind == 0)
- optind = 1; /* Don't scan ARGV[0], the program name. */
- optstring = _getopt_initialize (argc, argv, optstring);
- __getopt_initialized = 1;
- }
-
- /* Test whether ARGV[optind] points to a non-option argument.
- Either it does not have option syntax, or there is an environment flag
- from the shell indicating it is not an option. The later information
- is only used when the used in the GNU libc. */
-#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
-
- if (nextchar == NULL || *nextchar == '\0')
- {
- /* Advance to the next ARGV-element. */
-
- /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
- moved back by the user (who may also have changed the arguments). */
- if (last_nonopt > optind)
- last_nonopt = optind;
- if (first_nonopt > optind)
- first_nonopt = optind;
-
- if (ordering == PERMUTE)
- {
- /* If we have just processed some options following some non-options,
- exchange them so that the options come first. */
-
- if (first_nonopt != last_nonopt && last_nonopt != optind)
- exchange ((char **) argv);
- else if (last_nonopt != optind)
- first_nonopt = optind;
-
- /* Skip any additional non-options
- and extend the range of non-options previously skipped. */
-
- while (optind < argc && NONOPTION_P)
- optind++;
- last_nonopt = optind;
- }
-
- /* The special ARGV-element `--' means premature end of options.
- Skip it like a null option,
- then exchange with previous non-options as if it were an option,
- then skip everything else like a non-option. */
-
- if (optind != argc && !pj_ansi_strcmp(argv[optind], "--"))
- {
- optind++;
-
- if (first_nonopt != last_nonopt && last_nonopt != optind)
- exchange ((char **) argv);
- else if (first_nonopt == last_nonopt)
- first_nonopt = optind;
- last_nonopt = argc;
-
- optind = argc;
- }
-
- /* If we have done all the ARGV-elements, stop the scan
- and back over any non-options that we skipped and permuted. */
-
- if (optind == argc)
- {
- /* Set the next-arg-index to point at the non-options
- that we previously skipped, so the caller will digest them. */
- if (first_nonopt != last_nonopt)
- optind = first_nonopt;
- return -1;
- }
-
- /* If we have come to a non-option and did not permute it,
- either stop the scan or describe it to the caller and pass it by. */
-
- if (NONOPTION_P)
- {
- if (ordering == REQUIRE_ORDER)
- return -1;
- optarg = argv[optind++];
- return 1;
- }
-
- /* We have found another option-ARGV-element.
- Skip the initial punctuation. */
-
- nextchar = (argv[optind] + 1
- + (longopts != NULL && argv[optind][1] == '-'));
- }
-
- /* Decode the current option-ARGV-element. */
-
- /* Check whether the ARGV-element is a long option.
-
- If long_only and the ARGV-element has the form "-f", where f is
- a valid short option, don't consider it an abbreviated form of
- a long option that starts with f. Otherwise there would be no
- way to give the -f short option.
-
- On the other hand, if there's a long option "fubar" and
- the ARGV-element is "-fu", do consider that an abbreviation of
- the long option, just like "--fu", and not "-f" with arg "u".
-
- This distinction seems to be the most useful approach. */
-
- if (longopts != NULL
- && (argv[optind][1] == '-'
- || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
- {
- char *nameend;
- const struct option *p;
- const struct option *pfound = NULL;
- int exact = 0;
- int ambig = 0;
- int indfound = -1;
- int option_index;
-
- for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
- /* Do nothing. */ ;
-
- /* Test all long options for either exact match
- or abbreviated matches. */
- for (p = longopts, option_index = 0; p->name; p++, option_index++)
- if (!strncmp (p->name, nextchar, nameend - nextchar))
- {
- if ((unsigned int) (nameend - nextchar)
- == (unsigned int) strlen (p->name))
- {
- /* Exact match found. */
- pfound = p;
- indfound = option_index;
- exact = 1;
- break;
- }
- else if (pfound == NULL)
- {
- /* First nonexact match found. */
- pfound = p;
- indfound = option_index;
- }
- else
- /* Second or later nonexact match found. */
- ambig = 1;
- }
-
- if (ambig && !exact)
- {
- nextchar += strlen (nextchar);
- optind++;
- optopt = 0;
- return '?';
- }
-
- if (pfound != NULL)
- {
- option_index = indfound;
- optind++;
- if (*nameend)
- {
- /* Don't test has_arg with >, because some C compilers don't
- allow it to be used on enums. */
- if (pfound->has_arg)
- optarg = nameend + 1;
- else
- {
- nextchar += strlen (nextchar);
-
- optopt = pfound->val;
- return '?';
- }
- }
- else if (pfound->has_arg == 1)
- {
- if (optind < argc)
- optarg = argv[optind++];
- else
- {
- nextchar += strlen (nextchar);
- optopt = pfound->val;
- return optstring[0] == ':' ? ':' : '?';
- }
- }
- nextchar += strlen (nextchar);
- if (longind != NULL)
- *longind = option_index;
- if (pfound->flag)
- {
- *(pfound->flag) = pfound->val;
- return 0;
- }
- return pfound->val;
- }
-
- /* Can't find it as a long option. If this is not getopt_long_only,
- or the option starts with '--' or is not a valid short
- option, then it's an error.
- Otherwise interpret it as a short option. */
- if (!long_only || argv[optind][1] == '-'
- || my_index (optstring, *nextchar) == NULL)
- {
- nextchar = (char *) "";
- optind++;
- optopt = 0;
- return '?';
- }
- }
-
- /* Look at and handle the next short option-character. */
-
- {
- char c = *nextchar++;
- char *temp = my_index (optstring, c);
-
- /* Increment `optind' when we start to process its last character. */
- if (*nextchar == '\0')
- ++optind;
-
- if (temp == NULL || c == ':')
- {
- optopt = c;
- return '?';
- }
- /* Convenience. Treat POSIX -W foo same as long option --foo */
- if (temp[0] == 'W' && temp[1] == ';')
- {
- char *nameend;
- const struct option *p;
- const struct option *pfound = NULL;
- int exact = 0;
- int ambig = 0;
- int indfound = 0;
- int option_index;
-
- /* This is an option that requires an argument. */
- if (*nextchar != '\0')
- {
- optarg = nextchar;
- /* If we end this ARGV-element by taking the rest as an arg,
- we must advance to the next element now. */
- optind++;
- }
- else if (optind == argc)
- {
- optopt = c;
- if (optstring[0] == ':')
- c = ':';
- else
- c = '?';
- return c;
- }
- else
- /* We already incremented `optind' once;
- increment it again when taking next ARGV-elt as argument. */
- optarg = argv[optind++];
-
- /* optarg is now the argument, see if it's in the
- table of longopts. */
-
- for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)
- /* Do nothing. */ ;
-
- /* Test all long options for either exact match
- or abbreviated matches. */
- for (p = longopts, option_index = 0; p->name; p++, option_index++)
- if (!strncmp (p->name, nextchar, nameend - nextchar))
- {
- if ((unsigned int) (nameend - nextchar) == strlen (p->name))
- {
- /* Exact match found. */
- pfound = p;
- indfound = option_index;
- exact = 1;
- break;
- }
- else if (pfound == NULL)
- {
- /* First nonexact match found. */
- pfound = p;
- indfound = option_index;
- }
- else
- /* Second or later nonexact match found. */
- ambig = 1;
- }
- if (ambig && !exact)
- {
- nextchar += strlen (nextchar);
- optind++;
- return '?';
- }
- if (pfound != NULL)
- {
- option_index = indfound;
- if (*nameend)
- {
- /* Don't test has_arg with >, because some C compilers don't
- allow it to be used on enums. */
- if (pfound->has_arg)
- optarg = nameend + 1;
- else
- {
- nextchar += strlen (nextchar);
- return '?';
- }
- }
- else if (pfound->has_arg == 1)
- {
- if (optind < argc)
- optarg = argv[optind++];
- else
- {
- nextchar += strlen (nextchar);
- return optstring[0] == ':' ? ':' : '?';
- }
- }
- nextchar += strlen (nextchar);
- if (longind != NULL)
- *longind = option_index;
- if (pfound->flag)
- {
- *(pfound->flag) = pfound->val;
- return 0;
- }
- return pfound->val;
- }
- nextchar = NULL;
- return 'W'; /* Let the application handle it. */
- }
- if (temp[1] == ':')
- {
- if (temp[2] == ':')
- {
- /* This is an option that accepts an argument optionally. */
- if (*nextchar != '\0')
- {
- optarg = nextchar;
- optind++;
- }
- else
- optarg = NULL;
- nextchar = NULL;
- }
- else
- {
- /* This is an option that requires an argument. */
- if (*nextchar != '\0')
- {
- optarg = nextchar;
- /* If we end this ARGV-element by taking the rest as an arg,
- we must advance to the next element now. */
- optind++;
- }
- else if (optind == argc)
- {
- optopt = c;
- if (optstring[0] == ':')
- c = ':';
- else
- c = '?';
- }
- else
- /* We already incremented `optind' once;
- increment it again when taking next ARGV-elt as argument. */
- optarg = argv[optind++];
- nextchar = NULL;
- }
- }
- return c;
- }
-}
-
diff --git a/pjsip/src/pjsua/getopt.h b/pjsip/src/pjsua/getopt.h
deleted file mode 100644
index ea19c718..00000000
--- a/pjsip/src/pjsua/getopt.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/* $Id$ */
-/* This file has now become GPL. */
-/* Declarations for getopt.
- Copyright (C) 1989,90,91,92,93,94,96,97,98 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The GNU C 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-#ifndef _GETOPT_H
-#define _GETOPT_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* For communication from `getopt' to the caller.
- When `getopt' finds an option that takes an argument,
- the argument value is returned here.
- Also, when `ordering' is RETURN_IN_ORDER,
- each non-option ARGV-element is returned here. */
-
-extern char *optarg;
-
-/* Index in ARGV of the next element to be scanned.
- This is used for communication to and from the caller
- and for communication between successive calls to `getopt'.
-
- On entry to `getopt', zero means this is the first call; initialize.
-
- When `getopt' returns -1, this is the index of the first of the
- non-option elements that the caller should itself scan.
-
- Otherwise, `optind' communicates from one call to the next
- how much of ARGV has been scanned so far. */
-
-extern int optind;
-
-/* Callers store zero here to inhibit the error message `getopt' prints
- for unrecognized options. */
-
-extern int opterr;
-
-/* Set to an option character which was unrecognized. */
-
-extern int optopt;
-
-/* Describe the long-named options requested by the application.
- The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
- of `struct option' terminated by an element containing a name which is
- zero.
-
- The field `has_arg' is:
- no_argument (or 0) if the option does not take an argument,
- required_argument (or 1) if the option requires an argument,
- optional_argument (or 2) if the option takes an optional argument.
-
- If the field `flag' is not NULL, it points to a variable that is set
- to the value given in the field `val' when the option is found, but
- left unchanged if the option is not found.
-
- To have a long-named option do something other than set an `int' to
- a compiled-in constant, such as set a value from `optarg', set the
- option's `flag' field to zero and its `val' field to a nonzero
- value (the equivalent single-letter option character, if there is
- one). For long options that have a zero `flag' field, `getopt'
- returns the contents of the `val' field. */
-
-struct option
-{
- const char *name;
- /* has_arg can't be an enum because some compilers complain about
- type mismatches in all the code that assumes it is an int. */
- int has_arg;
- int *flag;
- int val;
-};
-
-/* Names for the values of the `has_arg' field of `struct option'. */
-
-# define no_argument 0
-# define required_argument 1
-# define optional_argument 2
-
-
-/* Get definitions and prototypes for functions to process the
- arguments in ARGV (ARGC of them, minus the program name) for
- options given in OPTS.
-
- Return the option character from OPTS just read. Return -1 when
- there are no more options. For unrecognized options, or options
- missing arguments, `optopt' is set to the option letter, and '?' is
- returned.
-
- The OPTS string is a list of characters which are recognized option
- letters, optionally followed by colons, specifying that that letter
- takes an argument, to be placed in `optarg'.
-
- If a letter in OPTS is followed by two colons, its argument is
- optional. This behavior is specific to the GNU `getopt'.
-
- The argument `--' causes premature termination of argument
- scanning, explicitly telling `getopt' that there are no more
- options.
-
- If OPTS begins with `--', then non-option arguments are treated as
- arguments to the option '\0'. This behavior is specific to the GNU
- `getopt'. */
-
-int getopt (int argc, char *const *argv, const char *shortopts);
-
-int getopt_long (int argc, char *const *argv, const char *options,
- const struct option *longopts, int *longind);
-int getopt_long_only (int argc, char *const *argv,
- const char *shortopts,
- const struct option *longopts, int *longind);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* getopt.h */
-
diff --git a/pjsip/src/pjsua/main.c b/pjsip/src/pjsua/main.c
index 25ce6dcf..ce317078 100644
--- a/pjsip/src/pjsua/main.c
+++ b/pjsip/src/pjsua/main.c
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "pjsua.h"
+#include <pjsua-lib/pjsua.h>
#include <stdlib.h>
diff --git a/pjsip/src/pjsua/pjsua.h b/pjsip/src/pjsua/pjsua.h
deleted file mode 100644
index 09874160..00000000
--- a/pjsip/src/pjsua/pjsua.h
+++ /dev/null
@@ -1,468 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.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 __PJSUA_H__
-#define __PJSUA_H__
-
-/* Include all PJSIP core headers. */
-#include <pjsip.h>
-
-/* Include all PJMEDIA headers. */
-#include <pjmedia.h>
-
-/* Include all PJMEDIA-CODEC headers. */
-#include <pjmedia-codec.h>
-
-/* Include all PJSIP-UA headers */
-#include <pjsip_ua.h>
-
-/* Include all PJSIP-SIMPLE headers */
-#include <pjsip_simple.h>
-
-/* Include all PJLIB-UTIL headers. */
-#include <pjlib-util.h>
-
-/* Include all PJLIB headers. */
-#include <pjlib.h>
-
-
-PJ_BEGIN_DECL
-
-
-/**
- * Max buddies in buddy list.
- */
-#ifndef PJSUA_MAX_BUDDIES
-# define PJSUA_MAX_BUDDIES 32
-#endif
-
-
-/**
- * Max simultaneous calls.
- */
-#ifndef PJSUA_MAX_CALLS
-# define PJSUA_MAX_CALLS 256
-#endif
-
-
-/**
- * Aditional ports to be allocated in the conference ports for non-call
- * streams.
- */
-#define PJSUA_CONF_MORE_PORTS 2
-
-
-/**
- * Maximum accounts.
- */
-#ifndef PJSUA_MAX_ACC
-# define PJSUA_MAX_ACC 8
-#endif
-
-
-/**
- * Maximum credentials.
- */
-#ifndef PJSUA_MAX_CRED
-# define PJSUA_MAX_CRED PJSUA_MAX_ACC
-#endif
-
-
-/**
- * Structure to be attached to invite dialog.
- * Given a dialog "dlg", application can retrieve this structure
- * by accessing dlg->mod_data[pjsua.mod.id].
- */
-struct pjsua_call
-{
- unsigned index; /**< Index in pjsua array. */
- pjsip_inv_session *inv; /**< The invite session. */
- int acc_index; /**< Account index being used. */
- pjmedia_session *session; /**< The media session. */
- unsigned conf_slot; /**< Slot # in conference bridge. */
- pjsip_evsub *xfer_sub; /**< Xfer server subscription, if this
- call was triggered by xfer. */
- pjmedia_sock_info skinfo; /**< Preallocated media sockets. */
-
- void *app_data; /**< Application data. */
-};
-
-typedef struct pjsua_call pjsua_call;
-
-
-/**
- * Buddy data.
- */
-struct pjsua_buddy
-{
- pj_str_t uri; /**< Buddy URI */
- int acc_index; /**< Which account to use. */
- pj_bool_t monitor; /**< Should we monitor? */
- pjsip_evsub *sub; /**< Buddy presence subscription */
- pjsip_pres_status status; /**< Buddy presence status. */
-};
-
-typedef struct pjsua_buddy pjsua_buddy;
-
-
-/**
- * Server presence subscription list head.
- */
-struct pjsua_srv_pres
-{
- PJ_DECL_LIST_MEMBER(struct pjsua_srv_pres);
- pjsip_evsub *sub;
- char *remote;
-};
-
-typedef struct pjsua_srv_pres pjsua_srv_pres;
-
-
-/**
- * Account
- */
-struct pjsua_acc
-{
- int index; /**< Index in accounts array. */
- pj_str_t local_uri; /**< Uri in From: header. */
- pj_str_t user_part; /**< User part of local URI. */
- pj_str_t host_part; /**< Host part of local URI. */
- pj_str_t contact_uri; /**< Uri in Contact: header. */
-
- pj_str_t reg_uri; /**< Registrar URI. */
- pjsip_regc *regc; /**< Client registration session. */
- pj_int32_t reg_timeout; /**< Default timeout. */
- pj_timer_entry reg_timer; /**< Registration timer. */
- pj_status_t reg_last_err; /**< Last registration error. */
- int reg_last_code; /**< Last status last register. */
-
- pj_str_t proxy; /**< Proxy URL. */
- pjsip_route_hdr route_set; /**< Route set. */
-
- pj_bool_t online_status; /**< Our online status. */
- pjsua_srv_pres pres_srv_list; /**< Server subscription list. */
-
- void *app_data; /**< Application data. */
-};
-
-
-typedef struct pjsua_acc pjsua_acc;
-
-
-/* PJSUA application variables. */
-struct pjsua
-{
- /* Control: */
- pj_caching_pool cp; /**< Global pool factory. */
- pjsip_endpoint *endpt; /**< Global endpoint. */
- pj_pool_t *pool; /**< pjsua's private pool. */
- pjsip_module mod; /**< pjsua's PJSIP module. */
-
-
- /* Media: */
- pjmedia_endpt *med_endpt; /**< Media endpoint. */
- pjmedia_conf *mconf; /**< Media conference. */
- pj_bool_t null_audio; /**< Null audio flag. */
- char *wav_file; /**< WAV file name to play. */
- unsigned wav_slot; /**< WAV player slot in bridge */
- pj_bool_t auto_play; /**< Auto play file for calls? */
- pj_bool_t auto_loop; /**< Auto loop RTP stream? */
- pj_bool_t auto_conf; /**< Auto put to conference? */
-
-
- /* User Agent behaviour: */
- int auto_answer; /**< Automatically answer in calls. */
-
- /* Account: */
- int acc_cnt; /**< Number of client registrations */
- pjsua_acc acc[PJSUA_MAX_ACC]; /** Client regs array. */
-
-
- /* Authentication credentials: */
-
- int cred_count; /**< Number of credentials. */
- pjsip_cred_info cred_info[10]; /**< Array of credentials. */
-
-
- /* Threading (optional): */
- int thread_cnt; /**< Thread count. */
- pj_thread_t *threads[8]; /**< Thread instances. */
- pj_bool_t quit_flag; /**< To signal thread to quit. */
-
- /* Transport (UDP): */
- pj_uint16_t sip_port; /**< SIP signaling port. */
- pj_sock_t sip_sock; /**< SIP UDP socket. */
- pj_sockaddr_in sip_sock_name; /**< Public/STUN UDP socket addr. */
-
- pj_str_t outbound_proxy;/**< Outbound proxy. */
-
-
- /* STUN: */
- pj_str_t stun_srv1;
- int stun_port1;
- pj_str_t stun_srv2;
- int stun_port2;
-
-
- /* Logging: */
- int log_level; /**< Logging verbosity. */
- int app_log_level; /**< stdout log verbosity. */
- unsigned log_decor; /**< Log decoration. */
- char *log_filename; /**< Log filename. */
-
-
- /* PJSUA Calls: */
- int max_calls; /**< Max nb of calls. */
- int call_cnt; /**< Number of calls. */
- pjsua_call calls[PJSUA_MAX_CALLS]; /** Calls array. */
-
-
- /* SIMPLE and buddy status: */
- int buddy_cnt;
- pjsua_buddy buddies[PJSUA_MAX_BUDDIES];
-};
-
-
-/** PJSUA instance. */
-extern struct pjsua pjsua;
-
-
-
-/*****************************************************************************
- * PJSUA API (defined in pjsua_core.c).
- */
-
-/**
- * Initialize pjsua settings with default parameters.
- */
-void pjsua_default(void);
-
-
-/**
- * Display error message for the specified error code.
- */
-void pjsua_perror(const char *sender, const char *title,
- pj_status_t status);
-
-
-/**
- * Initialize pjsua application. Application can call this before parsing
- * application settings.
- *
- * This will initialize all libraries, create endpoint instance, and register
- * pjsip modules. Transport will NOT be created however.
- *
- * Application may register module after calling this function.
- */
-pj_status_t pjsua_init(void);
-
-
-/**
- * Start pjsua stack. Application calls this after pjsua settings has been
- * configured.
- *
- * This will start the transport, worker threads (if any), and registration
- * process, if registration is configured.
- */
-pj_status_t pjsua_start(void);
-
-
-/**
- * Destroy pjsua.
- */
-pj_status_t pjsua_destroy(void);
-
-
-/**
- * Find account for incoming request.
- */
-int pjsua_find_account_for_incoming(pjsip_rx_data *rdata);
-
-
-/**
- * Find account for outgoing request.
- */
-int pjsua_find_account_for_outgoing(const pj_str_t *url);
-
-
-/*****************************************************************************
- * PJSUA Call API (defined in pjsua_call.c).
- */
-
-/**
- * Init pjsua call module.
- */
-pj_status_t pjsua_call_init(void);
-
-/**
- * Make outgoing call.
- */
-pj_status_t pjsua_make_call(int acc_index,
- const char *cstr_dest_uri,
- int *p_call_index);
-
-
-/**
- * Handle incoming invite request.
- */
-pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata);
-
-
-/**
- * Answer call.
- */
-void pjsua_call_answer(int call_index, int code);
-
-/**
- * Hangup call.
- */
-void pjsua_call_hangup(int call_index, int code);
-
-
-/**
- * Put call on-hold.
- */
-void pjsua_call_set_hold(int call_index);
-
-
-/**
- * Send re-INVITE (to release hold).
- */
-void pjsua_call_reinvite(int call_index);
-
-
-/**
- * Transfer call.
- */
-void pjsua_call_xfer(int call_index, const char *dest);
-
-
-/**
- * Terminate all calls.
- */
-void pjsua_inv_shutdown(void);
-
-
-/*****************************************************************************
- * PJSUA Client Registration API (defined in pjsua_reg.c).
- */
-
-/**
- * Initialize client registration session.
- *
- * @param app_callback Optional callback
- */
-pj_status_t pjsua_regc_init(int acc_index);
-
-/**
- * Update registration or perform unregistration. If renew argument is zero,
- * this will start unregistration process.
- */
-void pjsua_regc_update(int acc_index, pj_bool_t renew);
-
-
-
-
-/*****************************************************************************
- * PJSUA Presence (pjsua_pres.c)
- */
-
-/**
- * Init presence.
- */
-pj_status_t pjsua_pres_init();
-
-/**
- * Refresh both presence client and server subscriptions.
- */
-void pjsua_pres_refresh(int acc_index);
-
-/**
- * Terminate all subscriptions
- */
-void pjsua_pres_shutdown(void);
-
-/**
- * Dump presence subscriptions.
- */
-void pjsua_pres_dump(void);
-
-
-/*****************************************************************************
- * User Interface API.
- *
- * The UI API specifies functions that will be called by pjsua upon
- * occurence of various events.
- */
-
-/**
- * Notify UI when invite state has changed.
- */
-void pjsua_ui_inv_on_state_changed(int call_index, pjsip_event *e);
-
-/**
- * Notify UI when registration status has changed.
- */
-void pjsua_ui_regc_on_state_changed(int acc_index);
-
-
-/*****************************************************************************
- * Utilities.
- *
- */
-
-/** String to describe invite session states */
-extern const char *pjsua_inv_state_names[];
-
-/**
- * Parse arguments (pjsua_opt.c).
- */
-pj_status_t pjsua_parse_args(int argc, char *argv[]);
-
-/**
- * Load settings from a file.
- */
-pj_status_t pjsua_load_settings(const char *filename);
-
-/**
- * Dump settings.
- */
-int pjsua_dump_settings(char *buf, pj_size_t max);
-
-/**
- * Save settings to a file.
- */
-pj_status_t pjsua_save_settings(const char *filename);
-
-
-/*
- * Verify that valid SIP url is given.
- * @return PJ_SUCCESS if valid.
- */
-pj_status_t pjsua_verify_sip_url(const char *c_url);
-
-/*
- * Dump application states.
- */
-void pjsua_dump(void);
-
-
-PJ_END_DECL
-
-
-#endif /* __PJSUA_H__ */
diff --git a/pjsip/src/pjsua/pjsua_call.c b/pjsip/src/pjsua/pjsua_call.c
deleted file mode 100644
index e0a9a0af..00000000
--- a/pjsip/src/pjsua/pjsua_call.c
+++ /dev/null
@@ -1,1090 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.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 "pjsua.h"
-#include <pj/log.h>
-
-
-/*
- * pjsua_inv.c
- *
- * Invite session specific functionalities.
- */
-
-#define THIS_FILE "pjsua_inv.c"
-
-
-/**
- * Make outgoing call.
- */
-pj_status_t pjsua_make_call(int acc_index,
- const char *cstr_dest_uri,
- int *p_call_index)
-{
- pj_str_t dest_uri;
- pjsip_dialog *dlg;
- pjmedia_sdp_session *offer;
- pjsip_inv_session *inv;
- int call_index = -1;
- pjsip_tx_data *tdata;
- pj_status_t status;
-
- /* Convert cstr_dest_uri to dest_uri */
-
- dest_uri = pj_str((char*)cstr_dest_uri);
-
- /* Find free call slot. */
- for (call_index=0; call_index<pjsua.max_calls; ++call_index) {
- if (pjsua.calls[call_index].inv == NULL)
- break;
- }
-
- if (call_index == pjsua.max_calls) {
- PJ_LOG(3,(THIS_FILE, "Error: too many calls!"));
- return PJ_ETOOMANY;
- }
-
- /* Create outgoing dialog: */
-
- status = pjsip_dlg_create_uac( pjsip_ua_instance(),
- &pjsua.acc[acc_index].local_uri,
- &pjsua.acc[acc_index].contact_uri,
- &dest_uri, &dest_uri,
- &dlg);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Dialog creation failed", status);
- return status;
- }
-
- /* Get media capability from media endpoint: */
-
- status = pjmedia_endpt_create_sdp( pjsua.med_endpt, dlg->pool, 1,
- &pjsua.calls[call_index].skinfo,
- &offer);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "pjmedia unable to create SDP", status);
- goto on_error;
- }
-
- /* Create the INVITE session: */
-
- status = pjsip_inv_create_uac( dlg, offer, 0, &inv);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Invite session creation failed", status);
- goto on_error;
- }
-
-
- /* Create and associate our data in the session. */
-
- pjsua.calls[call_index].inv = inv;
-
- dlg->mod_data[pjsua.mod.id] = &pjsua.calls[call_index];
- inv->mod_data[pjsua.mod.id] = &pjsua.calls[call_index];
-
-
- /* Set dialog Route-Set: */
-
- if (!pj_list_empty(&pjsua.acc[acc_index].route_set))
- pjsip_dlg_set_route_set(dlg, &pjsua.acc[acc_index].route_set);
-
-
- /* Set credentials: */
-
- pjsip_auth_clt_set_credentials( &dlg->auth_sess, pjsua.cred_count,
- pjsua.cred_info);
-
-
- /* Create initial INVITE: */
-
- status = pjsip_inv_invite(inv, &tdata);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to create initial INVITE request",
- status);
- goto on_error;
- }
-
-
- /* Send initial INVITE: */
-
- status = pjsip_inv_send_msg(inv, tdata, NULL);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to send initial INVITE request",
- status);
- goto on_error;
- }
-
-
- /* Done. */
-
- ++pjsua.call_cnt;
-
- if (p_call_index)
- *p_call_index = call_index;
-
- return PJ_SUCCESS;
-
-
-on_error:
- PJ_TODO(DESTROY_DIALOG_ON_FAIL);
- if (call_index != -1) {
- pjsua.calls[call_index].inv = NULL;
- }
- return status;
-}
-
-
-/**
- * Handle incoming INVITE request.
- */
-pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
-{
- pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
- pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
- pjsip_msg *msg = rdata->msg_info.msg;
- pjsip_tx_data *response = NULL;
- unsigned options = 0;
- pjsip_inv_session *inv;
- int acc_index;
- int call_index = -1;
- pjmedia_sdp_session *answer;
- pj_status_t status;
-
- /* Don't want to handle anything but INVITE */
- if (msg->line.req.method.id != PJSIP_INVITE_METHOD)
- return PJ_FALSE;
-
- /* Don't want to handle anything that's already associated with
- * existing dialog or transaction.
- */
- if (dlg || tsx)
- return PJ_FALSE;
-
-
- /* Verify that we can handle the request. */
- status = pjsip_inv_verify_request(rdata, &options, NULL, NULL,
- pjsua.endpt, &response);
- if (status != PJ_SUCCESS) {
-
- /*
- * No we can't handle the incoming INVITE request.
- */
-
- if (response) {
- pjsip_response_addr res_addr;
-
- pjsip_get_response_addr(response->pool, rdata, &res_addr);
- pjsip_endpt_send_response(pjsua.endpt, &res_addr, response,
- NULL, NULL);
-
- } else {
-
- /* Respond with 500 (Internal Server Error) */
- pjsip_endpt_respond_stateless(pjsua.endpt, rdata, 500, NULL,
- NULL, NULL);
- }
-
- return PJ_TRUE;
- }
-
-
- /*
- * Yes we can handle the incoming INVITE request.
- */
-
- /* Find free call slot. */
- for (call_index=0; call_index < pjsua.max_calls; ++call_index) {
- if (pjsua.calls[call_index].inv == NULL)
- break;
- }
-
- if (call_index == PJSUA_MAX_CALLS) {
- pjsip_endpt_respond_stateless(pjsua.endpt, rdata,
- PJSIP_SC_BUSY_HERE, NULL,
- NULL, NULL);
- return PJ_TRUE;
- }
-
-
- /* Get media capability from media endpoint: */
-
- status = pjmedia_endpt_create_sdp( pjsua.med_endpt, rdata->tp_info.pool, 1,
- &pjsua.calls[call_index].skinfo,
- &answer );
- if (status != PJ_SUCCESS) {
- pjsip_endpt_respond_stateless(pjsua.endpt, rdata, 500, NULL,
- NULL, NULL);
-
- return PJ_TRUE;
- }
-
- /* TODO:
- *
- * Get which account is most likely to be associated with this incoming
- * call. We need the account to find which contact URI to put for
- * the call.
- */
- acc_index = 0;
-
- /* Create dialog: */
-
- status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata,
- &pjsua.acc[acc_index].contact_uri,
- &dlg);
- if (status != PJ_SUCCESS) {
- pjsip_endpt_respond_stateless(pjsua.endpt, rdata, 500, NULL,
- NULL, NULL);
-
- return PJ_TRUE;
- }
-
-
- /* Create invite session: */
-
- status = pjsip_inv_create_uas( dlg, rdata, answer, 0, &inv);
- if (status != PJ_SUCCESS) {
-
- pjsip_dlg_respond(dlg, rdata, 500, NULL);
-
- // TODO: Need to delete dialog
- return PJ_TRUE;
- }
-
-
- /* Create and attach pjsua data to the dialog: */
-
- pjsua.calls[call_index].inv = inv;
-
- dlg->mod_data[pjsua.mod.id] = &pjsua.calls[call_index];
- inv->mod_data[pjsua.mod.id] = &pjsua.calls[call_index];
-
-
- /* Must answer with some response to initial INVITE.
- * If auto-answer flag is set, send 200 straight away, otherwise send 100.
- */
-
- status = pjsip_inv_initial_answer(inv, rdata,
- (pjsua.auto_answer ? 200 : 100),
- NULL, NULL, &response);
- if (status != PJ_SUCCESS) {
-
- pjsua_perror(THIS_FILE, "Unable to create 100 response", status);
-
- pjsip_dlg_respond(dlg, rdata, 500, NULL);
-
- // TODO: Need to delete dialog
-
- } else {
- status = pjsip_inv_send_msg(inv, response, NULL);
- if (status != PJ_SUCCESS)
- pjsua_perror(THIS_FILE, "Unable to send 100 response", status);
- }
-
- if (pjsua.auto_answer < 200) {
- PJ_LOG(3,(THIS_FILE,
- "\nIncoming call!!\n"
- "From: %.*s\n"
- "To: %.*s\n"
- "(press 'a' to answer, 'h' to decline)",
- (int)dlg->remote.info_str.slen,
- dlg->remote.info_str.ptr,
- (int)dlg->local.info_str.slen,
- dlg->local.info_str.ptr));
- } else {
- PJ_LOG(3,(THIS_FILE,
- "Call From:%.*s To:%.*s was answered with %d (%s)",
- (int)dlg->remote.info_str.slen,
- dlg->remote.info_str.ptr,
- (int)dlg->local.info_str.slen,
- dlg->local.info_str.ptr,
- pjsua.auto_answer,
- pjsip_get_status_text(pjsua.auto_answer)->ptr ));
- }
-
- ++pjsua.call_cnt;
-
- /* This INVITE request has been handled. */
- return PJ_TRUE;
-}
-
-
-/*
- * This callback receives notification from invite session when the
- * session state has changed.
- */
-static void pjsua_call_on_state_changed(pjsip_inv_session *inv,
- pjsip_event *e)
-{
- pjsua_call *call = inv->dlg->mod_data[pjsua.mod.id];
-
- /* If this is an outgoing INVITE that was created because of
- * REFER/transfer, send NOTIFY to transferer.
- */
- if (call && call->xfer_sub && e->type==PJSIP_EVENT_TSX_STATE) {
- int st_code = -1;
- pjsip_evsub_state ev_state = PJSIP_EVSUB_STATE_ACTIVE;
-
-
- switch (call->inv->state) {
- case PJSIP_INV_STATE_NULL:
- case PJSIP_INV_STATE_CALLING:
- /* Do nothing */
- break;
-
- case PJSIP_INV_STATE_EARLY:
- case PJSIP_INV_STATE_CONNECTING:
- st_code = e->body.tsx_state.tsx->status_code;
- ev_state = PJSIP_EVSUB_STATE_ACTIVE;
- break;
-
- case PJSIP_INV_STATE_CONFIRMED:
- /* When state is confirmed, send the final 200/OK and terminate
- * subscription.
- */
- st_code = e->body.tsx_state.tsx->status_code;
- ev_state = PJSIP_EVSUB_STATE_TERMINATED;
- break;
-
- case PJSIP_INV_STATE_DISCONNECTED:
- st_code = e->body.tsx_state.tsx->status_code;
- ev_state = PJSIP_EVSUB_STATE_TERMINATED;
- break;
- }
-
- if (st_code != -1) {
- pjsip_tx_data *tdata;
- pj_status_t status;
-
- status = pjsip_xfer_notify( call->xfer_sub,
- ev_state, st_code,
- NULL, &tdata);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to create NOTIFY", status);
- } else {
- status = pjsip_xfer_send_request(call->xfer_sub, tdata);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to send NOTIFY", status);
- }
- }
- }
- }
-
-
- pjsua_ui_inv_on_state_changed(call->index, e);
-
- /* call->inv may be NULL now */
-
- /* Destroy media session when invite session is disconnected. */
- if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
-
- pj_assert(call != NULL);
-
- if (call && call->session) {
- pjmedia_conf_remove_port(pjsua.mconf, call->conf_slot);
- pjmedia_session_destroy(call->session);
- call->session = NULL;
-
- PJ_LOG(3,(THIS_FILE,"Media session is destroyed"));
- }
-
- call->inv = NULL;
- --pjsua.call_cnt;
- }
-}
-
-
-/*
- * Callback called by event framework when the xfer subscription state
- * has changed.
- */
-static void xfer_on_evsub_state( pjsip_evsub *sub, pjsip_event *event)
-{
-
- PJ_UNUSED_ARG(event);
-
- /*
- * We're only interested when subscription is terminated, to
- * clear the xfer_sub member of the inv_data.
- */
- if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) {
- pjsua_call *call;
-
- call = pjsip_evsub_get_mod_data(sub, pjsua.mod.id);
- if (!call)
- return;
-
- pjsip_evsub_set_mod_data(sub, pjsua.mod.id, NULL);
- call->xfer_sub = NULL;
-
- PJ_LOG(3,(THIS_FILE, "Xfer subscription terminated"));
- }
-}
-
-
-/*
- * Follow transfer (REFER) request.
- */
-static void on_call_transfered( pjsip_inv_session *inv,
- pjsip_rx_data *rdata )
-{
- pj_status_t status;
- pjsip_tx_data *tdata;
- pjsua_call *existing_call;
- int new_call;
- const pj_str_t str_refer_to = { "Refer-To", 8};
- pjsip_generic_string_hdr *refer_to;
- char *uri;
- struct pjsip_evsub_user xfer_cb;
- pjsip_evsub *sub;
-
- existing_call = inv->dlg->mod_data[pjsua.mod.id];
-
- /* Find the Refer-To header */
- refer_to = (pjsip_generic_string_hdr*)
- pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_refer_to, NULL);
-
- if (refer_to == NULL) {
- /* Invalid Request.
- * No Refer-To header!
- */
- PJ_LOG(4,(THIS_FILE, "Received REFER without Refer-To header!"));
- pjsip_dlg_respond( inv->dlg, rdata, 400, NULL);
- return;
- }
-
- PJ_LOG(3,(THIS_FILE, "Call to %.*s is being transfered to %.*s",
- (int)inv->dlg->remote.info_str.slen,
- inv->dlg->remote.info_str.ptr,
- (int)refer_to->hvalue.slen,
- refer_to->hvalue.ptr));
-
- /* Init callback */
- pj_memset(&xfer_cb, 0, sizeof(xfer_cb));
- xfer_cb.on_evsub_state = &xfer_on_evsub_state;
-
- /* Create transferee event subscription */
- status = pjsip_xfer_create_uas( inv->dlg, &xfer_cb, rdata, &sub);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to create xfer uas", status);
- pjsip_dlg_respond( inv->dlg, rdata, 500, NULL);
- return;
- }
-
- /* Accept the REFER request, send 200 (OK). */
- pjsip_xfer_accept(sub, rdata, 200, NULL);
-
- /* Create initial NOTIFY request */
- status = pjsip_xfer_notify( sub, PJSIP_EVSUB_STATE_ACTIVE,
- 100, NULL, &tdata);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to create NOTIFY to REFER", status);
- return;
- }
-
- /* Send initial NOTIFY request */
- status = pjsip_xfer_send_request( sub, tdata);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to send NOTIFY to REFER", status);
- return;
- }
-
- /* We're cheating here.
- * We need to get a null terminated string from a pj_str_t.
- * So grab the pointer from the hvalue and NULL terminate it, knowing
- * that the NULL position will be occupied by a newline.
- */
- uri = refer_to->hvalue.ptr;
- uri[refer_to->hvalue.slen] = '\0';
-
- /* Now make the outgoing call. */
- status = pjsua_make_call(existing_call->acc_index, uri, &new_call);
- if (status != PJ_SUCCESS) {
-
- /* Notify xferer about the error */
- status = pjsip_xfer_notify(sub, PJSIP_EVSUB_STATE_TERMINATED,
- 500, NULL, &tdata);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to create NOTIFY to REFER",
- status);
- return;
- }
- status = pjsip_xfer_send_request(sub, tdata);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to send NOTIFY to REFER",
- status);
- return;
- }
- return;
- }
-
- /* Put the server subscription in inv_data.
- * Subsequent state changed in pjsua_inv_on_state_changed() will be
- * reported back to the server subscription.
- */
- pjsua.calls[new_call].xfer_sub = sub;
-
- /* Put the invite_data in the subscription. */
- pjsip_evsub_set_mod_data(sub, pjsua.mod.id, &pjsua.calls[new_call]);
-}
-
-
-/*
- * This callback is called when transaction state has changed in INVITE
- * session. We use this to trap incoming REFER request.
- */
-static void pjsua_call_on_tsx_state_changed(pjsip_inv_session *inv,
- pjsip_transaction *tsx,
- pjsip_event *e)
-{
- pjsua_call *call = inv->dlg->mod_data[pjsua.mod.id];
-
- if (tsx->role==PJSIP_ROLE_UAS &&
- tsx->state==PJSIP_TSX_STATE_TRYING &&
- pjsip_method_cmp(&tsx->method, &pjsip_refer_method)==0)
- {
- /*
- * Incoming REFER request.
- */
- on_call_transfered(call->inv, e->body.tsx_state.src.rdata);
- }
-}
-
-
-/*
- * This callback is called by invite session framework when UAC session
- * has forked.
- */
-static void pjsua_call_on_forked( pjsip_inv_session *inv,
- pjsip_event *e)
-{
- PJ_UNUSED_ARG(inv);
- PJ_UNUSED_ARG(e);
-
- PJ_TODO(HANDLE_FORKED_DIALOG);
-}
-
-
-/*
- * Create inactive SDP for call hold.
- */
-static pj_status_t create_inactive_sdp(pjsua_call *call,
- pjmedia_sdp_session **p_answer)
-{
- pj_status_t status;
- pjmedia_sdp_conn *conn;
- pjmedia_sdp_attr *attr;
- pjmedia_sdp_session *sdp;
-
- /* Create new offer */
- status = pjmedia_endpt_create_sdp(pjsua.med_endpt, pjsua.pool, 1,
- &call->skinfo, &sdp);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to create local SDP", status);
- return status;
- }
-
- /* Get SDP media connection line */
- conn = sdp->media[0]->conn;
- if (!conn)
- conn = sdp->conn;
-
- /* Modify address */
- conn->addr = pj_str("0.0.0.0");
-
- /* Remove existing directions attributes */
- pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendrecv");
- pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendonly");
- pjmedia_sdp_media_remove_all_attr(sdp->media[0], "recvonly");
- pjmedia_sdp_media_remove_all_attr(sdp->media[0], "inactive");
-
- /* Add inactive attribute */
- attr = pjmedia_sdp_attr_create(pjsua.pool, "inactive", NULL);
- pjmedia_sdp_media_add_attr(sdp->media[0], attr);
-
- *p_answer = sdp;
-
- return status;
-}
-
-/*
- * Called when session received new offer.
- */
-static void pjsua_call_on_rx_offer(pjsip_inv_session *inv,
- const pjmedia_sdp_session *offer)
-{
- pjsua_call *call;
- pjmedia_sdp_conn *conn;
- pjmedia_sdp_session *answer;
- pj_bool_t is_remote_active;
- pj_status_t status;
-
- call = inv->dlg->mod_data[pjsua.mod.id];
-
- /*
- * See if remote is offering active media (i.e. not on-hold)
- */
- is_remote_active = PJ_TRUE;
-
- conn = offer->media[0]->conn;
- if (!conn)
- conn = offer->conn;
-
- if (pj_strcmp2(&conn->addr, "0.0.0.0")==0 ||
- pj_strcmp2(&conn->addr, "0")==0)
- {
- is_remote_active = PJ_FALSE;
-
- }
- else if (pjmedia_sdp_media_find_attr2(offer->media[0], "inactive", NULL))
- {
- is_remote_active = PJ_FALSE;
- }
-
- PJ_LOG(4,(THIS_FILE, "Received SDP offer, remote media is %s",
- (is_remote_active ? "active" : "inactive")));
-
- /* Supply candidate answer */
- if (is_remote_active) {
- status = pjmedia_endpt_create_sdp( pjsua.med_endpt, call->inv->pool, 1,
- &call->skinfo, &answer);
- } else {
- status = create_inactive_sdp( call, &answer );
- }
-
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to create local SDP", status);
- return;
- }
-
- status = pjsip_inv_set_sdp_answer(call->inv, answer);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to set answer", status);
- return;
- }
-
-}
-
-
-/*
- * Callback to be called when SDP offer/answer negotiation has just completed
- * in the session. This function will start/update media if negotiation
- * has succeeded.
- */
-static void pjsua_call_on_media_update(pjsip_inv_session *inv,
- pj_status_t status)
-{
- pjsua_call *call;
- const pjmedia_sdp_session *local_sdp;
- const pjmedia_sdp_session *remote_sdp;
- pjmedia_port *media_port;
- pj_str_t port_name;
- char tmp[PJSIP_MAX_URL_SIZE];
-
- call = inv->dlg->mod_data[pjsua.mod.id];
-
- if (status != PJ_SUCCESS) {
-
- pjsua_perror(THIS_FILE, "SDP negotiation has failed", status);
- return;
-
- }
-
- /* Destroy existing media session, if any. */
-
- if (call && call->session) {
- pjmedia_conf_remove_port(pjsua.mconf, call->conf_slot);
- pjmedia_session_destroy(call->session);
- call->session = NULL;
- }
-
- /* Get local and remote SDP */
-
- status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &local_sdp);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE,
- "Unable to retrieve currently active local SDP",
- status);
- return;
- }
-
-
- status = pjmedia_sdp_neg_get_active_remote(call->inv->neg, &remote_sdp);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE,
- "Unable to retrieve currently active remote SDP",
- status);
- return;
- }
-
- /* Create new media session.
- * The media session is active immediately.
- */
- if (pjsua.null_audio)
- return;
-
- status = pjmedia_session_create( pjsua.med_endpt, 1,
- &call->skinfo,
- local_sdp, remote_sdp,
- call,
- &call->session );
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to create media session",
- status);
- return;
- }
-
-
- /* Get the port interface of the first stream in the session.
- * We need the port interface to add to the conference bridge.
- */
- pjmedia_session_get_port(call->session, 0, &media_port);
-
-
- /*
- * Add the call to conference bridge.
- */
- port_name.ptr = tmp;
- port_name.slen = pjsip_uri_print(PJSIP_URI_IN_REQ_URI,
- call->inv->dlg->remote.info->uri,
- tmp, sizeof(tmp));
- if (port_name.slen < 1) {
- port_name = pj_str("call");
- }
- status = pjmedia_conf_add_port( pjsua.mconf, call->inv->pool,
- media_port,
- &port_name,
- &call->conf_slot);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to create conference slot",
- status);
- pjmedia_session_destroy(call->session);
- call->session = NULL;
- return;
- }
-
- /* If auto-play is configured, connect the call to the file player
- * port
- */
- if (pjsua.auto_play && pjsua.wav_file &&
- call->inv->role == PJSIP_ROLE_UAS)
- {
-
- pjmedia_conf_connect_port( pjsua.mconf, pjsua.wav_slot,
- call->conf_slot);
-
- } else if (pjsua.auto_loop && call->inv->role == PJSIP_ROLE_UAS) {
-
- pjmedia_conf_connect_port( pjsua.mconf, call->conf_slot,
- call->conf_slot);
-
- } else if (pjsua.auto_conf) {
-
- int i;
-
- pjmedia_conf_connect_port( pjsua.mconf, 0, call->conf_slot);
- pjmedia_conf_connect_port( pjsua.mconf, call->conf_slot, 0);
-
- for (i=0; i < pjsua.max_calls; ++i) {
-
- if (!pjsua.calls[i].session)
- continue;
-
- pjmedia_conf_connect_port( pjsua.mconf, call->conf_slot,
- pjsua.calls[i].conf_slot);
- pjmedia_conf_connect_port( pjsua.mconf, pjsua.calls[i].conf_slot,
- call->conf_slot);
- }
-
- } else {
-
- /* Connect new call to the sound device port (port zero) in the
- * main conference bridge.
- */
- pjmedia_conf_connect_port( pjsua.mconf, 0, call->conf_slot);
- pjmedia_conf_connect_port( pjsua.mconf, call->conf_slot, 0);
- }
-
-
- /* Done. */
- {
- struct pjmedia_session_info sess_info;
- char info[80];
- int info_len = 0;
- unsigned i;
-
- pjmedia_session_get_info(call->session, &sess_info);
- for (i=0; i<sess_info.stream_cnt; ++i) {
- int len;
- const char *dir;
- pjmedia_stream_info *strm_info = &sess_info.stream_info[i];
-
- switch (strm_info->dir) {
- case PJMEDIA_DIR_NONE:
- dir = "inactive";
- break;
- case PJMEDIA_DIR_ENCODING:
- dir = "sendonly";
- break;
- case PJMEDIA_DIR_DECODING:
- dir = "recvonly";
- break;
- case PJMEDIA_DIR_ENCODING_DECODING:
- dir = "sendrecv";
- break;
- default:
- dir = "unknown";
- break;
- }
- len = pj_ansi_sprintf( info+info_len,
- ", stream #%d: %.*s (%s)", i,
- (int)strm_info->fmt.encoding_name.slen,
- (int)strm_info->fmt.encoding_name.ptr,
- dir);
- if (len > 0)
- info_len += len;
- }
- PJ_LOG(3,(THIS_FILE,"Media started%s", info));
- }
-}
-
-
-/*
- * Hangup call.
- */
-void pjsua_call_hangup(int call_index, int code)
-{
- pjsua_call *call;
- pj_status_t status;
- pjsip_tx_data *tdata;
-
-
- call = &pjsua.calls[call_index];
-
- if (!call->inv) {
- PJ_LOG(3,(THIS_FILE,"Call has been disconnected"));
- return;
- }
-
- status = pjsip_inv_end_session(call->inv, code, NULL, &tdata);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE,
- "Failed to create end session message",
- status);
- return;
- }
-
- /* pjsip_inv_end_session may return PJ_SUCCESS with NULL
- * as p_tdata when INVITE transaction has not been answered
- * with any provisional responses.
- */
- if (tdata == NULL)
- return;
-
- status = pjsip_inv_send_msg(call->inv, tdata, NULL);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE,
- "Failed to send end session message",
- status);
- return;
- }
-}
-
-
-/*
- * Put call on-Hold.
- */
-void pjsua_call_set_hold(int call_index)
-{
- pjmedia_sdp_session *sdp;
- pjsua_call *call;
- pjsip_tx_data *tdata;
- pj_status_t status;
-
- call = &pjsua.calls[call_index];
-
- if (!call->inv) {
- PJ_LOG(3,(THIS_FILE,"Call has been disconnected"));
- return;
- }
-
- if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) {
- PJ_LOG(3,(THIS_FILE, "Can not hold call that is not confirmed"));
- return;
- }
-
- status = create_inactive_sdp(call, &sdp);
- if (status != PJ_SUCCESS)
- return;
-
- /* Send re-INVITE with new offer */
- status = pjsip_inv_reinvite( call->inv, NULL, sdp, &tdata);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to create re-INVITE", status);
- return;
- }
-
- status = pjsip_inv_send_msg( call->inv, tdata, NULL);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to send re-INVITE", status);
- return;
- }
-}
-
-
-/*
- * re-INVITE.
- */
-void pjsua_call_reinvite(int call_index)
-{
- pjmedia_sdp_session *sdp;
- pjsip_tx_data *tdata;
- pjsua_call *call;
- pj_status_t status;
-
- call = &pjsua.calls[call_index];
-
- if (!call->inv) {
- PJ_LOG(3,(THIS_FILE,"Call has been disconnected"));
- return;
- }
-
-
- if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) {
- PJ_LOG(3,(THIS_FILE, "Can not re-INVITE call that is not confirmed"));
- return;
- }
-
- /* Create SDP */
- status = pjmedia_endpt_create_sdp( pjsua.med_endpt, call->inv->pool, 1,
- &call->skinfo, &sdp);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to get SDP from media endpoint",
- status);
- return;
- }
-
- /* Send re-INVITE with new offer */
- status = pjsip_inv_reinvite( call->inv, NULL, sdp, &tdata);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to create re-INVITE", status);
- return;
- }
-
- status = pjsip_inv_send_msg( call->inv, tdata, NULL);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to send re-INVITE", status);
- return;
- }
-}
-
-
-/*
- * Transfer call.
- */
-void pjsua_call_xfer(int call_index, const char *dest)
-{
- pjsip_evsub *sub;
- pjsip_tx_data *tdata;
- pjsua_call *call;
- pj_str_t tmp;
- pj_status_t status;
-
-
- call = &pjsua.calls[call_index];
-
- if (!call->inv) {
- PJ_LOG(3,(THIS_FILE,"Call has been disconnected"));
- return;
- }
-
- /* Create xfer client subscription.
- * We're not interested in knowing the transfer result, so we
- * put NULL as the callback.
- */
- status = pjsip_xfer_create_uac(call->inv->dlg, NULL, &sub);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to create xfer", status);
- return;
- }
-
- /*
- * Create REFER request.
- */
- status = pjsip_xfer_initiate(sub, pj_cstr(&tmp, dest), &tdata);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to create REFER request", status);
- return;
- }
-
- /* Send. */
- status = pjsip_xfer_send_request(sub, tdata);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to send REFER request", status);
- return;
- }
-
- /* For simplicity (that's what this program is intended to be!),
- * leave the original invite session as it is. More advanced application
- * may want to hold the INVITE, or terminate the invite, or whatever.
- */
-}
-
-
-/*
- * Terminate all calls.
- */
-void pjsua_inv_shutdown()
-{
- int i;
-
- for (i=0; i<pjsua.max_calls; ++i) {
- pjsip_tx_data *tdata;
- pjsua_call *call;
-
- if (pjsua.calls[i].inv == NULL)
- continue;
-
- call = &pjsua.calls[i];
-
- if (pjsip_inv_end_session(call->inv, 410, NULL, &tdata)==0) {
- if (tdata)
- pjsip_inv_send_msg(call->inv, tdata, NULL);
- }
- }
-}
-
-
-pj_status_t pjsua_call_init(void)
-{
- /* Initialize invite session callback. */
- pjsip_inv_callback inv_cb;
- pj_status_t status;
-
- pj_memset(&inv_cb, 0, sizeof(inv_cb));
- inv_cb.on_state_changed = &pjsua_call_on_state_changed;
- inv_cb.on_new_session = &pjsua_call_on_forked;
- inv_cb.on_media_update = &pjsua_call_on_media_update;
- inv_cb.on_rx_offer = &pjsua_call_on_rx_offer;
- inv_cb.on_tsx_state_changed = &pjsua_call_on_tsx_state_changed;
-
-
- /* Initialize invite session module: */
- status = pjsip_inv_usage_init(pjsua.endpt, &pjsua.mod, &inv_cb);
-
- return status;
-}
diff --git a/pjsip/src/pjsua/pjsua_core.c b/pjsip/src/pjsua/pjsua_core.c
deleted file mode 100644
index 974c6d53..00000000
--- a/pjsip/src/pjsua/pjsua_core.c
+++ /dev/null
@@ -1,910 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.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 "pjsua.h"
-
-/*
- * pjsua_core.c
- *
- * Core application functionalities.
- */
-
-#define THIS_FILE "pjsua_core.c"
-
-
-/*
- * Global variable.
- */
-struct pjsua pjsua;
-
-
-/*
- * Default local URI, if none is specified in cmd-line
- */
-#define PJSUA_LOCAL_URI "<sip:user@127.0.0.1>"
-
-
-
-/*
- * Init default application parameters.
- */
-void pjsua_default(void)
-{
- unsigned i;
-
-
- /* Normally need another thread for console application, because main
- * thread will be blocked in fgets().
- */
- pjsua.thread_cnt = 1;
-
-
- /* Default transport settings: */
- pjsua.sip_port = 5060;
-
-
- /* Default logging settings: */
- pjsua.log_level = 5;
- pjsua.app_log_level = 4;
- pjsua.log_decor = PJ_LOG_HAS_SENDER | PJ_LOG_HAS_TIME |
- PJ_LOG_HAS_MICRO_SEC | PJ_LOG_HAS_NEWLINE;
-
-
- /* Default: do not use STUN: */
- pjsua.stun_port1 = pjsua.stun_port2 = 0;
-
- /* Init accounts: */
- pjsua.acc_cnt = 1;
- for (i=0; i<PJ_ARRAY_SIZE(pjsua.acc); ++i) {
- pjsua.acc[i].index = i;
- pjsua.acc[i].local_uri = pj_str(PJSUA_LOCAL_URI);
- pjsua.acc[i].reg_timeout = 55;
- pj_list_init(&pjsua.acc[i].route_set);
- pj_list_init(&pjsua.acc[i].pres_srv_list);
- }
-
- /* Init call array: */
- for (i=0; i<PJ_ARRAY_SIZE(pjsua.calls); ++i)
- pjsua.calls[i].index = i;
-
- /* Default max nb of calls. */
- pjsua.max_calls = 4;
-
- /* Init server presence subscription list: */
-
-
-}
-
-
-
-/*
- * Handler for receiving incoming requests.
- *
- * This handler serves multiple purposes:
- * - it receives requests outside dialogs.
- * - it receives requests inside dialogs, when the requests are
- * unhandled by other dialog usages. Example of these
- * requests are: MESSAGE.
- */
-static pj_bool_t mod_pjsua_on_rx_request(pjsip_rx_data *rdata)
-{
-
- if (rdata->msg_info.msg->line.req.method.id == PJSIP_INVITE_METHOD) {
-
- return pjsua_call_on_incoming(rdata);
- }
-
- return PJ_FALSE;
-}
-
-
-/*
- * Handler for receiving incoming responses.
- *
- * This handler serves multiple purposes:
- * - it receives strayed responses (i.e. outside any dialog and
- * outside any transactions).
- * - it receives responses coming to a transaction, when pjsua
- * module is set as transaction user for the transaction.
- * - it receives responses inside a dialog, when these responses
- * are unhandled by other dialog usages.
- */
-static pj_bool_t mod_pjsua_on_rx_response(pjsip_rx_data *rdata)
-{
- PJ_UNUSED_ARG(rdata);
- return PJ_FALSE;
-}
-
-
-/*
- * Initialize sockets and optionally get the public address via STUN.
- */
-static pj_status_t init_sockets(pj_bool_t sip,
- pjmedia_sock_info *skinfo)
-{
- enum {
- RTP_START_PORT = 4000,
- RTP_RANDOM_START = 2,
- RTP_RETRY = 100
- };
- enum {
- SIP_SOCK,
- RTP_SOCK,
- RTCP_SOCK,
- };
- int i;
- static pj_uint16_t rtp_port = RTP_START_PORT;
- pj_sock_t sock[3];
- pj_sockaddr_in mapped_addr[3];
- pj_status_t status = PJ_SUCCESS;
-
- for (i=0; i<3; ++i)
- sock[i] = PJ_INVALID_SOCKET;
-
- /* Create and bind SIP UDP socket. */
- status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock[SIP_SOCK]);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "socket() error", status);
- goto on_error;
- }
-
- if (sip) {
- status = pj_sock_bind_in(sock[SIP_SOCK], 0, pjsua.sip_port);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "bind() error", status);
- goto on_error;
- }
- } else {
- status = pj_sock_bind_in(sock[SIP_SOCK], 0, 0);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "bind() error", status);
- goto on_error;
- }
- }
-
-
- /* Loop retry to bind RTP and RTCP sockets. */
- for (i=0; i<RTP_RETRY; ++i, rtp_port += 2) {
-
- /* Create and bind RTP socket. */
- status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock[RTP_SOCK]);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "socket() error", status);
- goto on_error;
- }
-
- status = pj_sock_bind_in(sock[RTP_SOCK], 0, rtp_port);
- if (status != PJ_SUCCESS) {
- pj_sock_close(sock[RTP_SOCK]);
- sock[RTP_SOCK] = PJ_INVALID_SOCKET;
- continue;
- }
-
- /* Create and bind RTCP socket. */
- status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock[RTCP_SOCK]);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "socket() error", status);
- goto on_error;
- }
-
- status = pj_sock_bind_in(sock[RTCP_SOCK], 0, (pj_uint16_t)(rtp_port+1));
- if (status != PJ_SUCCESS) {
- pj_sock_close(sock[RTP_SOCK]);
- sock[RTP_SOCK] = PJ_INVALID_SOCKET;
-
- pj_sock_close(sock[RTCP_SOCK]);
- sock[RTCP_SOCK] = PJ_INVALID_SOCKET;
- continue;
- }
-
- /*
- * If we're configured to use STUN, then find out the mapped address,
- * and make sure that the mapped RTCP port is adjacent with the RTP.
- */
- if (pjsua.stun_port1 == 0) {
- const pj_str_t *hostname;
- pj_sockaddr_in addr;
-
- /* Get local IP address. */
- hostname = pj_gethostname();
-
- pj_memset( &addr, 0, sizeof(addr));
- addr.sin_family = PJ_AF_INET;
- status = pj_sockaddr_in_set_str_addr( &addr, hostname);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unresolvable local hostname",
- status);
- goto on_error;
- }
-
- for (i=0; i<3; ++i)
- pj_memcpy(&mapped_addr[i], &addr, sizeof(addr));
-
- if (sip) {
- mapped_addr[SIP_SOCK].sin_port =
- pj_htons((pj_uint16_t)pjsua.sip_port);
- }
- mapped_addr[RTP_SOCK].sin_port=pj_htons((pj_uint16_t)rtp_port);
- mapped_addr[RTCP_SOCK].sin_port=pj_htons((pj_uint16_t)(rtp_port+1));
- break;
-
- } else {
- status=pj_stun_get_mapped_addr(&pjsua.cp.factory, 3, sock,
- &pjsua.stun_srv1, pjsua.stun_port1,
- &pjsua.stun_srv2, pjsua.stun_port2,
- mapped_addr);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "STUN error", status);
- goto on_error;
- }
-
- if (pj_ntohs(mapped_addr[2].sin_port) ==
- pj_ntohs(mapped_addr[1].sin_port)+1)
- {
- break;
- }
-
- pj_sock_close(sock[RTP_SOCK]);
- sock[RTP_SOCK] = PJ_INVALID_SOCKET;
-
- pj_sock_close(sock[RTCP_SOCK]);
- sock[RTCP_SOCK] = PJ_INVALID_SOCKET;
- }
- }
-
- if (sock[RTP_SOCK] == PJ_INVALID_SOCKET) {
- PJ_LOG(1,(THIS_FILE,
- "Unable to find appropriate RTP/RTCP ports combination"));
- goto on_error;
- }
-
- if (sip) {
- pjsua.sip_sock = sock[SIP_SOCK];
- pj_memcpy(&pjsua.sip_sock_name,
- &mapped_addr[SIP_SOCK],
- sizeof(pj_sockaddr_in));
- } else {
- pj_sock_close(sock[0]);
- }
-
- skinfo->rtp_sock = sock[RTP_SOCK];
- pj_memcpy(&skinfo->rtp_addr_name,
- &mapped_addr[RTP_SOCK], sizeof(pj_sockaddr_in));
-
- skinfo->rtcp_sock = sock[RTCP_SOCK];
- pj_memcpy(&skinfo->rtcp_addr_name,
- &mapped_addr[RTCP_SOCK], sizeof(pj_sockaddr_in));
-
- if (sip) {
- PJ_LOG(4,(THIS_FILE, "SIP UDP socket reachable at %s:%d",
- pj_inet_ntoa(pjsua.sip_sock_name.sin_addr),
- pj_ntohs(pjsua.sip_sock_name.sin_port)));
- }
- PJ_LOG(4,(THIS_FILE, "RTP socket reachable at %s:%d",
- pj_inet_ntoa(skinfo->rtp_addr_name.sin_addr),
- pj_ntohs(skinfo->rtp_addr_name.sin_port)));
- PJ_LOG(4,(THIS_FILE, "RTCP UDP socket reachable at %s:%d",
- pj_inet_ntoa(skinfo->rtcp_addr_name.sin_addr),
- pj_ntohs(skinfo->rtcp_addr_name.sin_port)));
-
- rtp_port += 2;
- return PJ_SUCCESS;
-
-on_error:
- for (i=0; i<3; ++i) {
- if (sip && i==0)
- continue;
- if (sock[i] != PJ_INVALID_SOCKET)
- pj_sock_close(sock[i]);
- }
- return status;
-}
-
-
-
-/*
- * Initialize stack.
- */
-static pj_status_t init_stack(void)
-{
- pj_status_t status;
-
- /* Create global endpoint: */
-
- {
- const pj_str_t *hostname;
- const char *endpt_name;
-
- /* Endpoint MUST be assigned a globally unique name.
- * The name will be used as the hostname in Warning header.
- */
-
- /* For this implementation, we'll use hostname for simplicity */
- hostname = pj_gethostname();
- endpt_name = hostname->ptr;
-
- /* Create the endpoint: */
-
- status = pjsip_endpt_create(&pjsua.cp.factory, endpt_name,
- &pjsua.endpt);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to create SIP endpoint", status);
- return status;
- }
- }
-
-
- /* Initialize transaction layer: */
-
- status = pjsip_tsx_layer_init_module(pjsua.endpt);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Transaction layer initialization error",
- status);
- goto on_error;
- }
-
- /* Initialize UA layer module: */
-
- status = pjsip_ua_init_module( pjsua.endpt, NULL );
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "UA layer initialization error", status);
- goto on_error;
- }
-
- /* Initialize and register pjsua's application module: */
-
- {
- pjsip_module my_mod =
- {
- NULL, NULL, /* prev, next. */
- { "mod-pjsua", 9 }, /* Name. */
- -1, /* Id */
- PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
- NULL, /* load() */
- NULL, /* start() */
- NULL, /* stop() */
- NULL, /* unload() */
- &mod_pjsua_on_rx_request, /* on_rx_request() */
- &mod_pjsua_on_rx_response, /* on_rx_response() */
- NULL, /* on_tx_request. */
- NULL, /* on_tx_response() */
- NULL, /* on_tsx_state() */
- };
-
- pjsua.mod = my_mod;
-
- status = pjsip_endpt_register_module(pjsua.endpt, &pjsua.mod);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to register pjsua module",
- status);
- goto on_error;
- }
- }
-
- /* Initialize invite session module: */
-
- status = pjsua_call_init();
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Invite usage initialization error",
- status);
- goto on_error;
- }
-
- /* Done */
-
- return PJ_SUCCESS;
-
-
-on_error:
- pjsip_endpt_destroy(pjsua.endpt);
- pjsua.endpt = NULL;
- return status;
-}
-
-
-static int PJ_THREAD_FUNC pjsua_poll(void *arg)
-{
- PJ_UNUSED_ARG(arg);
-
- do {
- pj_time_val timeout = { 0, 10 };
- pjsip_endpt_handle_events (pjsua.endpt, &timeout);
- } while (!pjsua.quit_flag);
-
- return 0;
-}
-
-/*
- * Initialize pjsua application.
- * This will initialize all libraries, create endpoint instance, and register
- * pjsip modules.
- */
-pj_status_t pjsua_init(void)
-{
- pj_status_t status;
-
- /* Init PJLIB logging: */
-
- pj_log_set_level(pjsua.log_level);
- pj_log_set_decor(pjsua.log_decor);
-
-
- /* Init PJLIB: */
-
- status = pj_init();
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "pj_init() error", status);
- return status;
- }
-
- /* Init PJLIB-UTIL: */
-
- status = pjlib_util_init();
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "pjlib_util_init() error", status);
- return status;
- }
-
- /* Init memory pool: */
-
- /* Init caching pool. */
- pj_caching_pool_init(&pjsua.cp, &pj_pool_factory_default_policy, 0);
-
- /* Create memory pool for application. */
- pjsua.pool = pj_pool_create(&pjsua.cp.factory, "pjsua", 4000, 4000, NULL);
-
-
- /* Init PJSIP : */
-
- status = init_stack();
- if (status != PJ_SUCCESS) {
- pj_caching_pool_destroy(&pjsua.cp);
- pjsua_perror(THIS_FILE, "Stack initialization has returned error",
- status);
- return status;
- }
-
-
- /* Init core SIMPLE module : */
-
- pjsip_evsub_init_module(pjsua.endpt);
-
- /* Init presence module: */
-
- pjsip_pres_init_module( pjsua.endpt, pjsip_evsub_instance());
-
- /* Init xfer/REFER module */
-
- pjsip_xfer_init_module( pjsua.endpt );
-
- /* Init pjsua presence handler: */
-
- pjsua_pres_init();
-
-
- /* Init media endpoint: */
-
- status = pjmedia_endpt_create(&pjsua.cp.factory, &pjsua.med_endpt);
- if (status != PJ_SUCCESS) {
- pj_caching_pool_destroy(&pjsua.cp);
- pjsua_perror(THIS_FILE,
- "Media stack initialization has returned error",
- status);
- return status;
- }
-
- /* Init conference bridge. */
-
- status = pjmedia_conf_create(pjsua.pool,
- pjsua.max_calls+PJSUA_CONF_MORE_PORTS,
- 8000, 160, 16, &pjsua.mconf);
- if (status != PJ_SUCCESS) {
- pj_caching_pool_destroy(&pjsua.cp);
- pjsua_perror(THIS_FILE,
- "Media stack initialization has returned error",
- status);
- return status;
- }
-
- /* Init pjmedia-codecs: */
-
- status = pjmedia_codec_init(pjsua.med_endpt);
- if (status != PJ_SUCCESS) {
- pj_caching_pool_destroy(&pjsua.cp);
- pjsua_perror(THIS_FILE,
- "Media codec initialization has returned error",
- status);
- return status;
- }
-
-
- /* Done. */
- return PJ_SUCCESS;
-}
-
-
-/*
- * Find account for incoming request.
- */
-int pjsua_find_account_for_incoming(pjsip_rx_data *rdata)
-{
- pjsip_uri *uri;
- pjsip_sip_uri *sip_uri;
- int acc_index;
-
- uri = rdata->msg_info.to->uri;
-
- /* Just return account #0 if To URI is not SIP: */
- if (!PJSIP_URI_SCHEME_IS_SIP(uri) &&
- !PJSIP_URI_SCHEME_IS_SIPS(uri))
- {
- return 0;
- }
-
-
- sip_uri = (pjsip_sip_uri*)pjsip_uri_get_uri(uri);
-
- /* Find account which has matching username and domain. */
- for (acc_index=0; acc_index < pjsua.acc_cnt; ++acc_index) {
-
- pjsua_acc *acc = &pjsua.acc[acc_index];
-
- if (pj_stricmp(&acc->user_part, &sip_uri->user)==0 &&
- pj_stricmp(&acc->host_part, &sip_uri->host)==0)
- {
- /* Match ! */
- return acc_index;
- }
- }
-
- /* No matching, try match domain part only. */
- for (acc_index=0; acc_index < pjsua.acc_cnt; ++acc_index) {
-
- pjsua_acc *acc = &pjsua.acc[acc_index];
-
- if (pj_stricmp(&acc->host_part, &sip_uri->host)==0) {
- /* Match ! */
- return acc_index;
- }
- }
-
- /* Still no match, just return account #0 */
- return 0;
-}
-
-
-/*
- * Find account for outgoing request.
- */
-int pjsua_find_account_for_outgoing(const pj_str_t *url)
-{
- PJ_UNUSED_ARG(url);
-
- /* Just use account #0 */
- return 0;
-}
-
-
-/*
- * Start pjsua stack.
- * This will start the registration process, if registration is configured.
- */
-pj_status_t pjsua_start(void)
-{
- int i; /* Must be signed */
- pjsip_transport *udp_transport;
- pj_status_t status = PJ_SUCCESS;
-
- /* Create WAV file player if required: */
-
- if (pjsua.wav_file) {
- pjmedia_port *port;
- pj_str_t port_name;
-
- /* Create the file player port. */
- status = pjmedia_file_player_port_create( pjsua.pool, pjsua.wav_file,
- 0, -1, NULL, &port);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE,
- "Error playing media file",
- status);
- return status;
- }
-
- /* Add port to conference bridge: */
- status = pjmedia_conf_add_port(pjsua.mconf, pjsua.pool, port,
- pj_cstr(&port_name, pjsua.wav_file),
- &pjsua.wav_slot);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE,
- "Unable to add file player to conference bridge",
- status);
- return status;
- }
- }
-
-
- /* Init sockets (STUN etc): */
- for (i=0; i<(int)pjsua.max_calls; ++i) {
- status = init_sockets(i==0, &pjsua.calls[i].skinfo);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "init_sockets() has returned error",
- status);
- --i;
- if (i >= 0)
- pj_sock_close(pjsua.sip_sock);
- while (i >= 0) {
- pj_sock_close(pjsua.calls[i].skinfo.rtp_sock);
- pj_sock_close(pjsua.calls[i].skinfo.rtcp_sock);
- }
- return status;
- }
- }
-
- /* Add UDP transport: */
-
- {
- /* Init the published name for the transport.
- * Depending whether STUN is used, this may be the STUN mapped
- * address, or socket's bound address.
- */
- pjsip_host_port addr_name;
-
- addr_name.host.ptr = pj_inet_ntoa(pjsua.sip_sock_name.sin_addr);
- addr_name.host.slen = pj_ansi_strlen(addr_name.host.ptr);
- addr_name.port = pj_ntohs(pjsua.sip_sock_name.sin_port);
-
- /* Create UDP transport from previously created UDP socket: */
-
- status = pjsip_udp_transport_attach( pjsua.endpt, pjsua.sip_sock,
- &addr_name, 1,
- &udp_transport);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to start UDP transport",
- status);
- return status;
- }
- }
-
- /* Initialize Contact URI, if one is not specified: */
- for (i=0; i<pjsua.acc_cnt; ++i) {
-
- pjsip_uri *uri;
- pjsip_sip_uri *sip_uri;
-
- /* Need to parse local_uri to get the elements: */
-
- uri = pjsip_parse_uri(pjsua.pool, pjsua.acc[i].local_uri.ptr,
- pjsua.acc[i].local_uri.slen, 0);
- if (uri == NULL) {
- pjsua_perror(THIS_FILE, "Invalid local URI",
- PJSIP_EINVALIDURI);
- return PJSIP_EINVALIDURI;
- }
-
- /* Local URI MUST be a SIP or SIPS: */
-
- if (!PJSIP_URI_SCHEME_IS_SIP(uri) &&
- !PJSIP_URI_SCHEME_IS_SIPS(uri))
- {
- pjsua_perror(THIS_FILE, "Invalid local URI",
- PJSIP_EINVALIDSCHEME);
- return PJSIP_EINVALIDSCHEME;
- }
-
-
- /* Get the SIP URI object: */
-
- sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(uri);
-
- pjsua.acc[i].user_part = sip_uri->user;
- pjsua.acc[i].host_part = sip_uri->host;
-
- if (pjsua.acc[i].contact_uri.slen == 0 &&
- pjsua.acc[i].local_uri.slen)
- {
- char contact[128];
- int len;
-
- /* The local Contact is the username@ip-addr, where
- * - username is taken from the local URI,
- * - ip-addr in UDP transport's address name (which may have been
- * resolved from STUN.
- */
-
- /* Build temporary contact string. */
-
- if (sip_uri->user.slen) {
-
- /* With the user part. */
- len = pj_snprintf(contact, sizeof(contact),
- "<sip:%.*s@%.*s:%d>",
- (int)sip_uri->user.slen,
- sip_uri->user.ptr,
- (int)udp_transport->local_name.host.slen,
- udp_transport->local_name.host.ptr,
- udp_transport->local_name.port);
- } else {
-
- /* Without user part */
-
- len = pj_snprintf(contact, sizeof(contact),
- "<sip:%.*s:%d>",
- (int)udp_transport->local_name.host.slen,
- udp_transport->local_name.host.ptr,
- udp_transport->local_name.port);
- }
-
- if (len < 1 || len >= sizeof(contact)) {
- pjsua_perror(THIS_FILE, "Invalid Contact", PJSIP_EURITOOLONG);
- return PJSIP_EURITOOLONG;
- }
-
- /* Duplicate Contact uri. */
-
- pj_strdup2(pjsua.pool, &pjsua.acc[i].contact_uri, contact);
-
- }
- }
-
- /* If outbound_proxy is specified, put it in the route_set: */
-
- if (pjsua.outbound_proxy.slen) {
-
- pjsip_route_hdr *route;
- const pj_str_t hname = { "Route", 5 };
- int parsed_len;
-
- route = pjsip_parse_hdr( pjsua.pool, &hname,
- pjsua.outbound_proxy.ptr,
- pjsua.outbound_proxy.slen,
- &parsed_len);
- if (route == NULL) {
- pjsua_perror(THIS_FILE, "Invalid outbound proxy URL",
- PJSIP_EINVALIDURI);
- return PJSIP_EINVALIDURI;
- }
-
- for (i=0; i<pjsua.acc_cnt; ++i) {
- pj_list_push_front(&pjsua.acc[i].route_set, route);
- }
- }
-
-
- /* Create worker thread(s), if required: */
-
- for (i=0; i<pjsua.thread_cnt; ++i) {
- status = pj_thread_create( pjsua.pool, "pjsua", &pjsua_poll,
- NULL, 0, 0, &pjsua.threads[i]);
- if (status != PJ_SUCCESS) {
- pjsua.quit_flag = 1;
- for (--i; i>=0; --i) {
- pj_thread_join(pjsua.threads[i]);
- pj_thread_destroy(pjsua.threads[i]);
- }
- return status;
- }
- }
-
- /* Start registration: */
-
- /* Create client registration session: */
- for (i=0; i<pjsua.acc_cnt; ++i) {
- status = pjsua_regc_init(i);
- if (status != PJ_SUCCESS)
- return status;
-
- /* Perform registration, if required. */
- if (pjsua.acc[i].regc) {
- pjsua_regc_update(i, 1);
- }
- }
-
-
- /* Find account for outgoing preence subscription */
- for (i=0; i<pjsua.buddy_cnt; ++i) {
- pjsua.buddies[i].acc_index =
- pjsua_find_account_for_outgoing(&pjsua.buddies[i].uri);
- }
-
-
- PJ_LOG(3,(THIS_FILE, "PJSUA version %s started", PJ_VERSION));
- return PJ_SUCCESS;
-}
-
-
-/* Sleep with polling */
-static void busy_sleep(unsigned msec)
-{
- pj_time_val timeout, now;
-
- pj_gettimeofday(&timeout);
- timeout.msec += msec;
- pj_time_val_normalize(&timeout);
-
- do {
- pjsua_poll(NULL);
- pj_gettimeofday(&now);
- } while (PJ_TIME_VAL_LT(now, timeout));
-}
-
-/*
- * Destroy pjsua.
- */
-pj_status_t pjsua_destroy(void)
-{
- int i;
-
- /* Signal threads to quit: */
- pjsua.quit_flag = 1;
-
- /* Terminate all calls. */
- pjsua_inv_shutdown();
-
- /* Terminate all presence subscriptions. */
- pjsua_pres_shutdown();
-
- /* Unregister, if required: */
- for (i=0; i<pjsua.acc_cnt; ++i) {
- if (pjsua.acc[i].regc) {
- pjsua_regc_update(i, 0);
- }
- }
-
- /* Wait worker threads to quit: */
- for (i=0; i<pjsua.thread_cnt; ++i) {
-
- if (pjsua.threads[i]) {
- pj_thread_join(pjsua.threads[i]);
- pj_thread_destroy(pjsua.threads[i]);
- pjsua.threads[i] = NULL;
- }
- }
-
-
- /* Wait for some time to allow unregistration to complete: */
- PJ_LOG(4,(THIS_FILE, "Shutting down..."));
- busy_sleep(1000);
-
- /* Destroy conference bridge. */
- if (pjsua.mconf)
- pjmedia_conf_destroy(pjsua.mconf);
-
- /* Shutdown pjmedia-codec: */
- pjmedia_codec_deinit();
-
- /* Destroy sound framework:
- * (this should be done in pjmedia_shutdown())
- */
- pj_snd_deinit();
-
- /* Destroy endpoint. */
-
- pjsip_endpt_destroy(pjsua.endpt);
- pjsua.endpt = NULL;
-
- /* Destroy caching pool. */
-
- pj_caching_pool_destroy(&pjsua.cp);
-
-
- /* Done. */
-
- return PJ_SUCCESS;
-}
-
diff --git a/pjsip/src/pjsua/pjsua_opt.c b/pjsip/src/pjsua/pjsua_opt.c
deleted file mode 100644
index 5ec37980..00000000
--- a/pjsip/src/pjsua/pjsua_opt.c
+++ /dev/null
@@ -1,860 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.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 "pjsua.h"
-#include "getopt.h"
-#include <stdlib.h>
-
-#define THIS_FILE "pjsua_opt.c"
-
-
-const char *pjsua_inv_state_names[] =
-{
- "NULL ",
- "CALLING ",
- "INCOMING ",
- "EARLY ",
- "CONNECTING",
- "CONFIRMED ",
- "DISCONNCTD",
- "TERMINATED",
-};
-
-
-
-/* Show usage */
-static void usage(void)
-{
- puts("Usage:");
- puts(" pjsua [options]");
- puts("");
- puts("General options:");
- puts(" --help Display this help screen");
- puts(" --version Display version info");
- puts("");
- puts("Logging options:");
- puts(" --config-file=file Read the config/arguments from file.");
- puts(" --log-file=fname Log to filename (default stderr)");
- puts(" --log-level=N Set log max level to N (0(none) to 6(trace))");
- puts(" --app-log-level=N Set log max level for stdout display to N");
- puts("");
- puts("SIP Account options:");
- puts(" --id=url Set the URL of local ID (used in From header)");
- puts(" --contact=url Override the Contact information");
- puts(" --proxy=url Set the URL of proxy server");
- puts("");
- puts("SIP Account Registration Options:");
- puts(" --registrar=url Set the URL of registrar server");
- puts(" --reg-timeout=secs Set registration interval to secs (default 3600)");
- puts("");
- puts("SIP Account Control:");
- puts(" --next-account Add more account");
- puts("");
- puts("Authentication options:");
- puts(" --realm=string Set realm");
- puts(" --username=string Set authentication username");
- puts(" --password=string Set authentication password");
- puts(" --next-cred Add more credential");
- puts("");
- puts("Transport Options:");
- puts(" --local-port=port Set TCP/UDP port");
- puts(" --outbound=url Set the URL of outbound proxy server");
- puts(" --use-stun1=host[:port]");
- puts(" --use-stun2=host[:port] Resolve local IP with the specified STUN servers");
- puts("");
- puts("Media Options:");
- puts(" --null-audio Use NULL audio device");
- puts(" --play-file=file Play WAV file in conference bridge");
- puts(" --auto-play Automatically play the file (to incoming calls only)");
- puts(" --auto-loop Automatically loop incoming RTP to outgoing RTP");
- puts(" --auto-conf Automatically put incoming calls to conference");
- puts("");
- puts("Buddy List (can be more than one):");
- puts(" --add-buddy url Add the specified URL to the buddy list.");
- puts("");
- puts("User Agent options:");
- puts(" --auto-answer=code Automatically answer incoming calls with code (e.g. 200)");
- puts(" --max-calls=N Maximum number of concurrent calls (default:4, max:255)");
- puts("");
- fflush(stdout);
-}
-
-
-
-/*
- * Verify that valid SIP url is given.
- */
-pj_status_t pjsua_verify_sip_url(const char *c_url)
-{
- pjsip_uri *p;
- pj_pool_t *pool;
- char *url;
- int len = (c_url ? pj_ansi_strlen(c_url) : 0);
-
- if (!len) return -1;
-
- pool = pj_pool_create(&pjsua.cp.factory, "check%p", 1024, 0, NULL);
- if (!pool) return -1;
-
- url = pj_pool_alloc(pool, len+1);
- pj_ansi_strcpy(url, c_url);
-
- p = pjsip_parse_uri(pool, url, len, 0);
- if (!p || pj_stricmp2(pjsip_uri_get_scheme(p), "sip") != 0)
- p = NULL;
-
- pj_pool_release(pool);
- return p ? 0 : -1;
-}
-
-
-/*
- * Read command arguments from config file.
- */
-static int read_config_file(pj_pool_t *pool, const char *filename,
- int *app_argc, char ***app_argv)
-{
- int i;
- FILE *fhnd;
- char line[200];
- int argc = 0;
- char **argv;
- enum { MAX_ARGS = 64 };
-
- /* Allocate MAX_ARGS+1 (argv needs to be terminated with NULL argument) */
- argv = pj_pool_calloc(pool, MAX_ARGS+1, sizeof(char*));
- argv[argc++] = *app_argv[0];
-
- /* Open config file. */
- fhnd = fopen(filename, "rt");
- if (!fhnd) {
- printf("Unable to open config file %s\n", filename);
- fflush(stdout);
- return -1;
- }
-
- /* Scan tokens in the file. */
- while (argc < MAX_ARGS && !feof(fhnd)) {
- char *token, *p = line;
-
- if (fgets(line, sizeof(line), fhnd) == NULL) break;
-
- for (token = strtok(p, " \t\r\n"); argc < MAX_ARGS;
- token = strtok(NULL, " \t\r\n"))
- {
- int token_len;
-
- if (!token) break;
- if (*token == '#') break;
-
- token_len = strlen(token);
- if (!token_len)
- continue;
- argv[argc] = pj_pool_alloc(pool, token_len+1);
- pj_memcpy(argv[argc], token, token_len+1);
- ++argc;
- }
- }
-
- /* Copy arguments from command line */
- for (i=1; i<*app_argc && argc < MAX_ARGS; ++i)
- argv[argc++] = (*app_argv)[i];
-
- if (argc == MAX_ARGS && (i!=*app_argc || !feof(fhnd))) {
- printf("Too many arguments specified in cmd line/config file\n");
- fflush(stdout);
- fclose(fhnd);
- return -1;
- }
-
- fclose(fhnd);
-
- /* Assign the new command line back to the original command line. */
- *app_argc = argc;
- *app_argv = argv;
- return 0;
-
-}
-
-
-/* Parse arguments. */
-pj_status_t pjsua_parse_args(int argc, char *argv[])
-{
- int c;
- int option_index;
- enum { OPT_CONFIG_FILE, OPT_LOG_FILE, OPT_LOG_LEVEL, OPT_APP_LOG_LEVEL,
- OPT_HELP, OPT_VERSION, OPT_NULL_AUDIO,
- OPT_LOCAL_PORT, OPT_PROXY, OPT_OUTBOUND_PROXY, OPT_REGISTRAR,
- OPT_REG_TIMEOUT, OPT_ID, OPT_CONTACT,
- OPT_REALM, OPT_USERNAME, OPT_PASSWORD,
- OPT_USE_STUN1, OPT_USE_STUN2,
- OPT_ADD_BUDDY, OPT_OFFER_X_MS_MSG, OPT_NO_PRESENCE,
- OPT_AUTO_ANSWER, OPT_AUTO_HANGUP, OPT_AUTO_PLAY, OPT_AUTO_LOOP,
- OPT_AUTO_CONF,
- OPT_PLAY_FILE,
- OPT_NEXT_ACCOUNT, OPT_NEXT_CRED, OPT_MAX_CALLS,
- };
- struct option long_options[] = {
- { "config-file",1, 0, OPT_CONFIG_FILE},
- { "log-file", 1, 0, OPT_LOG_FILE},
- { "log-level", 1, 0, OPT_LOG_LEVEL},
- { "app-log-level",1,0,OPT_APP_LOG_LEVEL},
- { "help", 0, 0, OPT_HELP},
- { "version", 0, 0, OPT_VERSION},
- { "null-audio", 0, 0, OPT_NULL_AUDIO},
- { "local-port", 1, 0, OPT_LOCAL_PORT},
- { "proxy", 1, 0, OPT_PROXY},
- { "outbound", 1, 0, OPT_OUTBOUND_PROXY},
- { "registrar", 1, 0, OPT_REGISTRAR},
- { "reg-timeout",1, 0, OPT_REG_TIMEOUT},
- { "id", 1, 0, OPT_ID},
- { "contact", 1, 0, OPT_CONTACT},
- { "realm", 1, 0, OPT_REALM},
- { "username", 1, 0, OPT_USERNAME},
- { "password", 1, 0, OPT_PASSWORD},
- { "use-stun1", 1, 0, OPT_USE_STUN1},
- { "use-stun2", 1, 0, OPT_USE_STUN2},
- { "add-buddy", 1, 0, OPT_ADD_BUDDY},
- { "offer-x-ms-msg",0,0,OPT_OFFER_X_MS_MSG},
- { "no-presence", 0, 0, OPT_NO_PRESENCE},
- { "auto-answer",1, 0, OPT_AUTO_ANSWER},
- { "auto-hangup",1, 0, OPT_AUTO_HANGUP},
- { "auto-play", 0, 0, OPT_AUTO_PLAY},
- { "auto-loop", 0, 0, OPT_AUTO_LOOP},
- { "auto-conf", 0, 0, OPT_AUTO_CONF},
- { "play-file", 1, 0, OPT_PLAY_FILE},
- { "next-account",0,0, OPT_NEXT_ACCOUNT},
- { "next-cred", 0, 0, OPT_NEXT_CRED},
- { "max-calls", 1, 0, OPT_MAX_CALLS},
- { NULL, 0, 0, 0}
- };
- pj_status_t status;
- pjsua_acc *cur_acc;
- pjsip_cred_info *cur_cred;
- char *config_file = NULL;
-
- /* Run getopt once to see if user specifies config file to read. */
- while ((c=getopt_long(argc, argv, "", long_options, &option_index)) != -1) {
- switch (c) {
- case OPT_CONFIG_FILE:
- config_file = optarg;
- break;
- }
- if (config_file)
- break;
- }
-
- if (config_file) {
- status = read_config_file(pjsua.pool, config_file, &argc, &argv);
- if (status != 0)
- return status;
- }
-
-
- cur_acc = &pjsua.acc[0];
- cur_cred = &pjsua.cred_info[0];
-
-
- /* Reinitialize and re-run getopt again, possibly with new arguments
- * read from config file.
- */
- optind = 0;
- while ((c=getopt_long(argc, argv, "", long_options, &option_index)) != -1) {
- char *p;
- pj_str_t tmp;
- long lval;
-
- switch (c) {
-
- case OPT_LOG_FILE:
- pjsua.log_filename = optarg;
- break;
-
- case OPT_LOG_LEVEL:
- c = pj_strtoul(pj_cstr(&tmp, optarg));
- if (c < 0 || c > 6) {
- printf("Error: expecting integer value 0-6 for --log-level\n");
- return PJ_EINVAL;
- }
- pj_log_set_level( c );
- break;
-
- case OPT_APP_LOG_LEVEL:
- pjsua.app_log_level = pj_strtoul(pj_cstr(&tmp, optarg));
- if (pjsua.app_log_level < 0 || pjsua.app_log_level > 6) {
- printf("Error: expecting integer value 0-6 for --app-log-level\n");
- return PJ_EINVAL;
- }
- break;
-
- case OPT_HELP:
- usage();
- return PJ_EINVAL;
-
- case OPT_VERSION: /* version */
- pj_dump_config();
- return PJ_EINVAL;
-
- case OPT_NULL_AUDIO:
- pjsua.null_audio = 1;
- break;
-
- case OPT_LOCAL_PORT: /* local-port */
- lval = pj_strtoul(pj_cstr(&tmp, optarg));
- if (lval < 1 || lval > 65535) {
- printf("Error: expecting integer value for --local-port\n");
- return PJ_EINVAL;
- }
- pjsua.sip_port = (pj_uint16_t)lval;
- break;
-
- case OPT_PROXY: /* proxy */
- if (pjsua_verify_sip_url(optarg) != 0) {
- printf("Error: invalid SIP URL '%s' in proxy argument\n", optarg);
- return PJ_EINVAL;
- }
- cur_acc->proxy = pj_str(optarg);
- break;
-
- case OPT_OUTBOUND_PROXY: /* outbound proxy */
- if (pjsua_verify_sip_url(optarg) != 0) {
- printf("Error: invalid SIP URL '%s' in outbound proxy argument\n", optarg);
- return PJ_EINVAL;
- }
- pjsua.outbound_proxy = pj_str(optarg);
- break;
-
- case OPT_REGISTRAR: /* registrar */
- if (pjsua_verify_sip_url(optarg) != 0) {
- printf("Error: invalid SIP URL '%s' in registrar argument\n", optarg);
- return PJ_EINVAL;
- }
- cur_acc->reg_uri = pj_str(optarg);
- break;
-
- case OPT_REG_TIMEOUT: /* reg-timeout */
- cur_acc->reg_timeout = pj_strtoul(pj_cstr(&tmp,optarg));
- if (cur_acc->reg_timeout < 1 || cur_acc->reg_timeout > 3600) {
- printf("Error: invalid value for --reg-timeout (expecting 1-3600)\n");
- return PJ_EINVAL;
- }
- break;
-
- case OPT_ID: /* id */
- if (pjsua_verify_sip_url(optarg) != 0) {
- printf("Error: invalid SIP URL '%s' in local id argument\n", optarg);
- return PJ_EINVAL;
- }
- cur_acc->local_uri = pj_str(optarg);
- break;
-
- case OPT_CONTACT: /* contact */
- if (pjsua_verify_sip_url(optarg) != 0) {
- printf("Error: invalid SIP URL '%s' in contact argument\n", optarg);
- return PJ_EINVAL;
- }
- cur_acc->contact_uri = pj_str(optarg);
- break;
-
- case OPT_NEXT_ACCOUNT: /* Add more account. */
- pjsua.acc_cnt++;
- cur_acc = &pjsua.acc[pjsua.acc_cnt - 1];
- break;
-
- case OPT_USERNAME: /* Default authentication user */
- if (pjsua.cred_count==0) pjsua.cred_count=1;
- cur_cred->username = pj_str(optarg);
- break;
-
- case OPT_REALM: /* Default authentication realm. */
- if (pjsua.cred_count==0) pjsua.cred_count=1;
- cur_cred->realm = pj_str(optarg);
- break;
-
- case OPT_PASSWORD: /* authentication password */
- if (pjsua.cred_count==0) pjsua.cred_count=1;
- cur_cred->data_type = 0;
- cur_cred->data = pj_str(optarg);
- break;
-
- case OPT_NEXT_CRED: /* Next credential */
- pjsua.cred_count++;
- cur_cred = &pjsua.cred_info[pjsua.cred_count - 1];
- break;
-
- case OPT_USE_STUN1: /* STUN server 1 */
- p = pj_ansi_strchr(optarg, ':');
- if (p) {
- *p = '\0';
- pjsua.stun_srv1 = pj_str(optarg);
- pjsua.stun_port1 = pj_strtoul(pj_cstr(&tmp, p+1));
- if (pjsua.stun_port1 < 1 || pjsua.stun_port1 > 65535) {
- printf("Error: expecting port number with option --use-stun1\n");
- return PJ_EINVAL;
- }
- } else {
- pjsua.stun_port1 = 3478;
- pjsua.stun_srv1 = pj_str(optarg);
- }
- break;
-
- case OPT_USE_STUN2: /* STUN server 2 */
- p = pj_ansi_strchr(optarg, ':');
- if (p) {
- *p = '\0';
- pjsua.stun_srv2 = pj_str(optarg);
- pjsua.stun_port2 = pj_strtoul(pj_cstr(&tmp,p+1));
- if (pjsua.stun_port2 < 1 || pjsua.stun_port2 > 65535) {
- printf("Error: expecting port number with option --use-stun2\n");
- return PJ_EINVAL;
- }
- } else {
- pjsua.stun_port2 = 3478;
- pjsua.stun_srv2 = pj_str(optarg);
- }
- break;
-
- case OPT_ADD_BUDDY: /* Add to buddy list. */
- if (pjsua_verify_sip_url(optarg) != 0) {
- printf("Error: invalid URL '%s' in --add-buddy option\n", optarg);
- return -1;
- }
- if (pjsua.buddy_cnt == PJSUA_MAX_BUDDIES) {
- printf("Error: too many buddies in buddy list.\n");
- return -1;
- }
- pjsua.buddies[pjsua.buddy_cnt++].uri = pj_str(optarg);
- break;
-
- case OPT_AUTO_PLAY:
- pjsua.auto_play = 1;
- break;
-
- case OPT_AUTO_LOOP:
- pjsua.auto_loop = 1;
- break;
-
- case OPT_AUTO_CONF:
- pjsua.auto_conf = 1;
- break;
-
- case OPT_PLAY_FILE:
- pjsua.wav_file = optarg;
- break;
-
- case OPT_AUTO_ANSWER:
- pjsua.auto_answer = atoi(optarg);
- if (pjsua.auto_answer < 100 || pjsua.auto_answer > 699) {
- puts("Error: invalid code in --auto-answer (expecting 100-699");
- return -1;
- }
- break;
-
- case OPT_MAX_CALLS:
- pjsua.max_calls = atoi(optarg);
- if (pjsua.max_calls < 1 || pjsua.max_calls > 255) {
- puts("Too many calls for max-calls (1-255)");
- return -1;
- }
- break;
- }
- }
-
- if (optind != argc) {
- printf("Error: unknown options %s\n", argv[optind]);
- return PJ_EINVAL;
- }
-
- return PJ_SUCCESS;
-}
-
-
-
-static void print_call(const char *title,
- int call_index,
- char *buf, pj_size_t size)
-{
- int len;
- pjsip_inv_session *inv = pjsua.calls[call_index].inv;
- pjsip_dialog *dlg = inv->dlg;
- char userinfo[128];
-
- /* Dump invite sesion info. */
-
- len = pjsip_hdr_print_on(dlg->remote.info, userinfo, sizeof(userinfo));
- if (len < 1)
- pj_ansi_strcpy(userinfo, "<--uri too long-->");
- else
- userinfo[len] = '\0';
-
- len = pj_snprintf(buf, size, "%s[%s] %s",
- title,
- pjsua_inv_state_names[inv->state],
- userinfo);
- if (len < 1 || len >= (int)size) {
- pj_ansi_strcpy(buf, "<--uri too long-->");
- len = 18;
- } else
- buf[len] = '\0';
-}
-
-static void dump_media_session(pjmedia_session *session)
-{
- unsigned i;
- pjmedia_session_info info;
-
- pjmedia_session_get_info(session, &info);
-
- for (i=0; i<info.stream_cnt; ++i) {
- pjmedia_stream_stat strm_stat;
- const char *rem_addr;
- int rem_port;
- const char *dir;
-
- pjmedia_session_get_stream_stat(session, i, &strm_stat);
- rem_addr = pj_inet_ntoa(info.stream_info[i].rem_addr.sin_addr);
- rem_port = pj_ntohs(info.stream_info[i].rem_addr.sin_port);
-
- if (info.stream_info[i].dir == PJMEDIA_DIR_ENCODING)
- dir = "sendonly";
- else if (info.stream_info[i].dir == PJMEDIA_DIR_DECODING)
- dir = "recvonly";
- else if (info.stream_info[i].dir == PJMEDIA_DIR_ENCODING_DECODING)
- dir = "sendrecv";
- else
- dir = "inactive";
-
-
- PJ_LOG(3,(THIS_FILE,
- "%s[Media strm#%d] %.*s, %s, peer=%s:%d",
- " ",
- i,
- info.stream_info[i].fmt.encoding_name.slen,
- info.stream_info[i].fmt.encoding_name.ptr,
- dir,
- rem_addr, rem_port));
- PJ_LOG(3,(THIS_FILE,
- "%s tx {pkt=%u, bytes=%u} rx {pkt=%u, bytes=%u}",
- " ",
- strm_stat.enc.pkt, strm_stat.enc.bytes,
- strm_stat.dec.pkt, strm_stat.dec.bytes));
-
- }
-}
-
-/*
- * Dump application states.
- */
-void pjsua_dump(void)
-{
- char buf[128];
- unsigned old_decor;
-
- PJ_LOG(3,(THIS_FILE, "Start dumping application states:"));
-
- old_decor = pj_log_get_decor();
- pj_log_set_decor(old_decor & (PJ_LOG_HAS_NEWLINE | PJ_LOG_HAS_CR));
-
- pjsip_endpt_dump(pjsua.endpt, 1);
- pjmedia_endpt_dump(pjsua.med_endpt);
- pjsip_tsx_layer_dump();
- pjsip_ua_dump();
-
-
- /* Dump all invite sessions: */
- PJ_LOG(3,(THIS_FILE, "Dumping invite sessions:"));
-
- if (pjsua.call_cnt == 0) {
-
- PJ_LOG(3,(THIS_FILE, " - no sessions -"));
-
- } else {
- int i;
-
- for (i=0; i<pjsua.max_calls; ++i) {
-
- if (pjsua.calls[i].inv == NULL)
- continue;
-
- print_call(" ", i, buf, sizeof(buf));
- PJ_LOG(3,(THIS_FILE, "%s", buf));
-
- if (pjsua.calls[i].session)
- dump_media_session(pjsua.calls[i].session);
- }
- }
-
- /* Dump presence status */
- pjsua_pres_dump();
-
- pj_log_set_decor(old_decor);
- PJ_LOG(3,(THIS_FILE, "Dump complete"));
-}
-
-
-/*
- * Load settings.
- */
-pj_status_t pjsua_load_settings(const char *filename)
-{
- int argc = 3;
- char *argv[4] = { "pjsua", "--config-file", NULL, NULL};
-
- argv[3] = (char*)filename;
- return pjsua_parse_args(argc, argv);
-}
-
-
-/*
- * Save account settings
- */
-static void save_account_settings(int acc_index, pj_str_t *result)
-{
- char line[128];
- pjsua_acc *acc = &pjsua.acc[acc_index];
-
-
- pj_ansi_sprintf(line, "#\n# Account %d:\n#\n", acc_index);
- pj_strcat2(result, line);
-
-
- /* Identity */
- if (acc->local_uri.slen) {
- pj_ansi_sprintf(line, "--id %.*s\n",
- (int)acc->local_uri.slen,
- acc->local_uri.ptr);
- pj_strcat2(result, line);
- }
-
- /* Registrar server */
- if (acc->reg_uri.slen) {
- pj_ansi_sprintf(line, "--registrar %.*s\n",
- (int)acc->reg_uri.slen,
- acc->reg_uri.ptr);
- pj_strcat2(result, line);
-
- pj_ansi_sprintf(line, "--reg-timeout %u\n",
- acc->reg_timeout);
- pj_strcat2(result, line);
- }
-
-
- /* Proxy */
- if (acc->proxy.slen) {
- pj_ansi_sprintf(line, "--proxy %.*s\n",
- (int)acc->proxy.slen,
- acc->proxy.ptr);
- pj_strcat2(result, line);
- }
-}
-
-
-
-/*
- * Dump settings.
- */
-int pjsua_dump_settings(char *buf, pj_size_t max)
-{
- int acc_index;
- int i;
- pj_str_t cfg;
- char line[128];
-
- cfg.ptr = buf;
- cfg.slen = 0;
-
-
- /* Logging. */
- pj_strcat2(&cfg, "#\n# Logging options:\n#\n");
- pj_ansi_sprintf(line, "--log-level %d\n",
- pjsua.log_level);
- pj_strcat2(&cfg, line);
-
- pj_ansi_sprintf(line, "--app-log-level %d\n",
- pjsua.app_log_level);
- pj_strcat2(&cfg, line);
-
- if (pjsua.log_filename) {
- pj_ansi_sprintf(line, "--log-file %s\n",
- pjsua.log_filename);
- pj_strcat2(&cfg, line);
- }
-
-
- /* Save account settings. */
- for (acc_index=0; acc_index < pjsua.acc_cnt; ++acc_index) {
-
- save_account_settings(acc_index, &cfg);
-
- if (acc_index < pjsua.acc_cnt-1)
- pj_strcat2(&cfg, "--next-account\n");
- }
-
- /* Credentials. */
- for (i=0; i<pjsua.cred_count; ++i) {
-
- pj_ansi_sprintf(line, "#\n# Credential %d:\n#\n", i);
- pj_strcat2(&cfg, line);
-
- if (pjsua.cred_info[i].realm.slen) {
- pj_ansi_sprintf(line, "--realm %.*s\n",
- (int)pjsua.cred_info[i].realm.slen,
- pjsua.cred_info[i].realm.ptr);
- pj_strcat2(&cfg, line);
- }
-
- pj_ansi_sprintf(line, "--username %.*s\n",
- (int)pjsua.cred_info[i].username.slen,
- pjsua.cred_info[i].username.ptr);
- pj_strcat2(&cfg, line);
-
- pj_ansi_sprintf(line, "--password %.*s\n",
- (int)pjsua.cred_info[i].data.slen,
- pjsua.cred_info[i].data.ptr);
- pj_strcat2(&cfg, line);
-
- if (i < pjsua.cred_count-1)
- pj_strcat2(&cfg, "--next-cred\n");
- }
-
-
- pj_strcat2(&cfg, "#\n# Network settings:\n#\n");
-
- /* Outbound proxy */
- if (pjsua.outbound_proxy.slen) {
- pj_ansi_sprintf(line, "--outbound %.*s\n",
- (int)pjsua.outbound_proxy.slen,
- pjsua.outbound_proxy.ptr);
- pj_strcat2(&cfg, line);
- }
-
-
- /* Transport. */
- pj_ansi_sprintf(line, "--local-port %d\n", pjsua.sip_port);
- pj_strcat2(&cfg, line);
-
-
- /* STUN */
- if (pjsua.stun_port1) {
- pj_ansi_sprintf(line, "--use-stun1 %.*s:%d\n",
- (int)pjsua.stun_srv1.slen,
- pjsua.stun_srv1.ptr,
- pjsua.stun_port1);
- pj_strcat2(&cfg, line);
- }
-
- if (pjsua.stun_port2) {
- pj_ansi_sprintf(line, "--use-stun2 %.*s:%d\n",
- (int)pjsua.stun_srv2.slen,
- pjsua.stun_srv2.ptr,
- pjsua.stun_port2);
- pj_strcat2(&cfg, line);
- }
-
-
- pj_strcat2(&cfg, "#\n# Media settings:\n#\n");
-
-
- /* Media */
- if (pjsua.null_audio)
- pj_strcat2(&cfg, "--null-audio\n");
- if (pjsua.auto_play)
- pj_strcat2(&cfg, "--auto-play\n");
- if (pjsua.auto_loop)
- pj_strcat2(&cfg, "--auto-loop\n");
- if (pjsua.auto_conf)
- pj_strcat2(&cfg, "--auto-conf\n");
- if (pjsua.wav_file) {
- pj_ansi_sprintf(line, "--play-file %s\n",
- pjsua.wav_file);
- pj_strcat2(&cfg, line);
- }
-
-
- pj_strcat2(&cfg, "#\n# User agent:\n#\n");
-
- /* Auto-answer. */
- if (pjsua.auto_answer != 0) {
- pj_ansi_sprintf(line, "--auto-answer %d\n",
- pjsua.auto_answer);
- pj_strcat2(&cfg, line);
- }
-
- /* Max calls. */
- pj_ansi_sprintf(line, "--max-calls %d\n",
- pjsua.max_calls);
- pj_strcat2(&cfg, line);
-
-
- pj_strcat2(&cfg, "#\n# Buddies:\n#\n");
-
- /* Add buddies. */
- for (i=0; i<pjsua.buddy_cnt; ++i) {
- pj_ansi_sprintf(line, "--add-buddy %.*s\n",
- (int)pjsua.buddies[i].uri.slen,
- pjsua.buddies[i].uri.ptr);
- pj_strcat2(&cfg, line);
- }
-
-
- *(cfg.ptr + cfg.slen) = '\0';
- return cfg.slen;
-}
-
-/*
- * Save settings.
- */
-pj_status_t pjsua_save_settings(const char *filename)
-{
- pj_str_t cfg;
- pj_pool_t *pool;
- FILE *fhnd;
-
- /* Create pool for temporary buffer. */
- pool = pj_pool_create(&pjsua.cp.factory, "settings", 4000, 0, NULL);
- if (!pool)
- return PJ_ENOMEM;
-
-
- cfg.ptr = pj_pool_alloc(pool, 3800);
- if (!cfg.ptr) {
- pj_pool_release(pool);
- return PJ_EBUG;
- }
-
-
- cfg.slen = pjsua_dump_settings(cfg.ptr, 3800);
- if (cfg.slen < 1) {
- pj_pool_release(pool);
- return PJ_ENOMEM;
- }
-
-
- /* Write to file. */
- fhnd = fopen(filename, "wt");
- if (!fhnd) {
- pj_pool_release(pool);
- return pj_get_os_error();
- }
-
- fwrite(cfg.ptr, cfg.slen, 1, fhnd);
- fclose(fhnd);
-
- pj_pool_release(pool);
- return PJ_SUCCESS;
-}
diff --git a/pjsip/src/pjsua/pjsua_pres.c b/pjsip/src/pjsua/pjsua_pres.c
deleted file mode 100644
index b203a2ca..00000000
--- a/pjsip/src/pjsua/pjsua_pres.c
+++ /dev/null
@@ -1,504 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.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 "pjsua.h"
-
-/*
- * pjsua_pres.c
- *
- * Presence related stuffs.
- */
-
-#define THIS_FILE "pjsua_pres.c"
-
-
-
-/* **************************************************************************
- * THE FOLLOWING PART HANDLES SERVER SUBSCRIPTION
- * **************************************************************************
- */
-
-/* Proto */
-static pj_bool_t pres_on_rx_request(pjsip_rx_data *rdata);
-
-/* The module instance. */
-static pjsip_module mod_pjsua_pres =
-{
- NULL, NULL, /* prev, next. */
- { "mod-pjsua-pres", 14 }, /* Name. */
- -1, /* Id */
- PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
- NULL, /* load() */
- NULL, /* start() */
- NULL, /* stop() */
- NULL, /* unload() */
- &pres_on_rx_request, /* on_rx_request() */
- NULL, /* on_rx_response() */
- NULL, /* on_tx_request. */
- NULL, /* on_tx_response() */
- NULL, /* on_tsx_state() */
-
-};
-
-
-/* Callback called when *server* subscription state has changed. */
-static void pres_evsub_on_srv_state( pjsip_evsub *sub, pjsip_event *event)
-{
- pjsua_srv_pres *uapres = pjsip_evsub_get_mod_data(sub, pjsua.mod.id);
-
- PJ_UNUSED_ARG(event);
-
- if (uapres) {
- PJ_LOG(3,(THIS_FILE, "Server subscription to %s is %s",
- uapres->remote, pjsip_evsub_get_state_name(sub)));
-
- if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) {
- pjsip_evsub_set_mod_data(sub, pjsua.mod.id, NULL);
- pj_list_erase(uapres);
- }
- }
-}
-
-/* This is called when request is received.
- * We need to check for incoming SUBSCRIBE request.
- */
-static pj_bool_t pres_on_rx_request(pjsip_rx_data *rdata)
-{
- int acc_index;
- pjsip_method *req_method = &rdata->msg_info.msg->line.req.method;
- pjsua_srv_pres *uapres;
- pjsip_evsub *sub;
- pjsip_evsub_user pres_cb;
- pjsip_tx_data *tdata;
- pjsip_pres_status pres_status;
- pjsip_dialog *dlg;
- pj_status_t status;
-
- if (pjsip_method_cmp(req_method, &pjsip_subscribe_method) != 0)
- return PJ_FALSE;
-
- /* Incoming SUBSCRIBE: */
-
- /* Find which account for the incoming request. */
- acc_index = pjsua_find_account_for_incoming(rdata);
-
- /* Create UAS dialog: */
- status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata,
- &pjsua.acc[acc_index].contact_uri,
- &dlg);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE,
- "Unable to create UAS dialog for subscription",
- status);
- return PJ_FALSE;
- }
-
- /* Init callback: */
- pj_memset(&pres_cb, 0, sizeof(pres_cb));
- pres_cb.on_evsub_state = &pres_evsub_on_srv_state;
-
- /* Create server presence subscription: */
- status = pjsip_pres_create_uas( dlg, &pres_cb, rdata, &sub);
- if (status != PJ_SUCCESS) {
- PJ_TODO(DESTROY_DIALOG);
- pjsua_perror(THIS_FILE, "Unable to create server subscription",
- status);
- return PJ_FALSE;
- }
-
- /* Attach our data to the subscription: */
- uapres = pj_pool_alloc(dlg->pool, sizeof(pjsua_srv_pres));
- uapres->sub = sub;
- uapres->remote = pj_pool_alloc(dlg->pool, PJSIP_MAX_URL_SIZE);
- status = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, dlg->remote.info->uri,
- uapres->remote, PJSIP_MAX_URL_SIZE);
- if (status < 1)
- pj_ansi_strcpy(uapres->remote, "<-- url is too long-->");
- else
- uapres->remote[status] = '\0';
-
- pjsip_evsub_set_mod_data(sub, pjsua.mod.id, uapres);
-
- /* Add server subscription to the list: */
- pj_list_push_back(&pjsua.acc[acc_index].pres_srv_list, uapres);
-
-
- /* Create and send 200 (OK) to the SUBSCRIBE request: */
- status = pjsip_pres_accept(sub, rdata, 200, NULL);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to accept presence subscription",
- status);
- pj_list_erase(uapres);
- return PJ_FALSE;
- }
-
-
- /* Set our online status: */
- pj_memset(&pres_status, 0, sizeof(pres_status));
- pres_status.info_cnt = 1;
- pres_status.info[0].basic_open = pjsua.acc[acc_index].online_status;
- //Both pjsua.local_uri and pjsua.contact_uri are enclosed in "<" and ">"
- //causing XML parsing to fail.
- //pres_status.info[0].contact = pjsua.local_uri;
-
- pjsip_pres_set_status(sub, &pres_status);
-
- /* Create and send the first NOTIFY to active subscription: */
- status = pjsip_pres_notify( sub, PJSIP_EVSUB_STATE_ACTIVE, NULL,
- NULL, &tdata);
- if (status == PJ_SUCCESS)
- status = pjsip_pres_send_request( sub, tdata);
-
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to create/send NOTIFY",
- status);
- pj_list_erase(uapres);
- return PJ_FALSE;
- }
-
-
- /* Done: */
-
- return PJ_TRUE;
-}
-
-
-/* Refresh subscription (e.g. when our online status has changed) */
-static void refresh_server_subscription(int acc_index)
-{
- pjsua_srv_pres *uapres;
-
- uapres = pjsua.acc[acc_index].pres_srv_list.next;
-
- while (uapres != &pjsua.acc[acc_index].pres_srv_list) {
-
- pjsip_pres_status pres_status;
- pjsip_tx_data *tdata;
-
- pjsip_pres_get_status(uapres->sub, &pres_status);
- if (pres_status.info[0].basic_open != pjsua.acc[acc_index].online_status) {
- pres_status.info[0].basic_open = pjsua.acc[acc_index].online_status;
- pjsip_pres_set_status(uapres->sub, &pres_status);
-
- if (pjsua.quit_flag) {
- pj_str_t reason = { "noresource", 10 };
- if (pjsip_pres_notify(uapres->sub,
- PJSIP_EVSUB_STATE_TERMINATED, NULL,
- &reason, &tdata)==PJ_SUCCESS)
- {
- pjsip_pres_send_request(uapres->sub, tdata);
- }
- } else {
- if (pjsip_pres_current_notify(uapres->sub, &tdata)==PJ_SUCCESS)
- pjsip_pres_send_request(uapres->sub, tdata);
- }
- }
-
- uapres = uapres->next;
- }
-}
-
-
-
-/* **************************************************************************
- * THE FOLLOWING PART HANDLES CLIENT SUBSCRIPTION
- * **************************************************************************
- */
-
-/* Callback called when *client* subscription state has changed. */
-static void pjsua_evsub_on_state( pjsip_evsub *sub, pjsip_event *event)
-{
- pjsua_buddy *buddy;
-
- PJ_UNUSED_ARG(event);
-
- buddy = pjsip_evsub_get_mod_data(sub, pjsua.mod.id);
- if (buddy) {
- PJ_LOG(3,(THIS_FILE,
- "Presence subscription to %s is %s",
- buddy->uri.ptr,
- pjsip_evsub_get_state_name(sub)));
-
- if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) {
- buddy->sub = NULL;
- buddy->status.info_cnt = 0;
- pjsip_evsub_set_mod_data(sub, pjsua.mod.id, NULL);
- }
- }
-}
-
-/* Callback called when we receive NOTIFY */
-static void pjsua_evsub_on_rx_notify(pjsip_evsub *sub,
- pjsip_rx_data *rdata,
- int *p_st_code,
- pj_str_t **p_st_text,
- pjsip_hdr *res_hdr,
- pjsip_msg_body **p_body)
-{
- pjsua_buddy *buddy;
-
- buddy = pjsip_evsub_get_mod_data(sub, pjsua.mod.id);
- if (buddy) {
- /* Update our info. */
- pjsip_pres_get_status(sub, &buddy->status);
-
- if (buddy->status.info_cnt) {
- PJ_LOG(3,(THIS_FILE, "%s is %s",
- buddy->uri.ptr,
- (buddy->status.info[0].basic_open?"online":"offline")));
- } else {
- PJ_LOG(3,(THIS_FILE, "No presence info for %s",
- buddy->uri.ptr));
- }
- }
-
- /* The default is to send 200 response to NOTIFY.
- * Just leave it there..
- */
- PJ_UNUSED_ARG(rdata);
- PJ_UNUSED_ARG(p_st_code);
- PJ_UNUSED_ARG(p_st_text);
- PJ_UNUSED_ARG(res_hdr);
- PJ_UNUSED_ARG(p_body);
-}
-
-
-/* Event subscription callback. */
-static pjsip_evsub_user pres_callback =
-{
- &pjsua_evsub_on_state,
-
- NULL, /* on_tsx_state: don't care about transaction state. */
-
- NULL, /* on_rx_refresh: don't care about SUBSCRIBE refresh, unless
- * we want to authenticate
- */
-
- &pjsua_evsub_on_rx_notify,
-
- NULL, /* on_client_refresh: Use default behaviour, which is to
- * refresh client subscription. */
-
- NULL, /* on_server_timeout: Use default behaviour, which is to send
- * NOTIFY to terminate.
- */
-};
-
-
-/* It does what it says.. */
-static void subscribe_buddy_presence(unsigned index)
-{
- int acc_index;
- pjsip_dialog *dlg;
- pjsip_tx_data *tdata;
- pj_status_t status;
-
- acc_index = pjsua.buddies[index].acc_index;
-
- status = pjsip_dlg_create_uac( pjsip_ua_instance(),
- &pjsua.acc[acc_index].local_uri,
- &pjsua.acc[acc_index].contact_uri,
- &pjsua.buddies[index].uri,
- NULL, &dlg);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to create dialog",
- status);
- return;
- }
-
- status = pjsip_pres_create_uac( dlg, &pres_callback,
- &pjsua.buddies[index].sub);
- if (status != PJ_SUCCESS) {
- pjsua.buddies[index].sub = NULL;
- pjsua_perror(THIS_FILE, "Unable to create presence client",
- status);
- return;
- }
-
- pjsip_evsub_set_mod_data(pjsua.buddies[index].sub, pjsua.mod.id,
- &pjsua.buddies[index]);
-
- status = pjsip_pres_initiate(pjsua.buddies[index].sub, -1, &tdata);
- if (status != PJ_SUCCESS) {
- pjsua.buddies[index].sub = NULL;
- pjsua_perror(THIS_FILE, "Unable to create initial SUBSCRIBE",
- status);
- return;
- }
-
- status = pjsip_pres_send_request(pjsua.buddies[index].sub, tdata);
- if (status != PJ_SUCCESS) {
- pjsua.buddies[index].sub = NULL;
- pjsua_perror(THIS_FILE, "Unable to send initial SUBSCRIBE",
- status);
- return;
- }
-
- PJ_TODO(DESTROY_DIALOG_ON_ERROR);
-}
-
-
-/* It does what it says... */
-static void unsubscribe_buddy_presence(unsigned index)
-{
- pjsip_tx_data *tdata;
- pj_status_t status;
-
- if (pjsua.buddies[index].sub == NULL)
- return;
-
- if (pjsip_evsub_get_state(pjsua.buddies[index].sub) ==
- PJSIP_EVSUB_STATE_TERMINATED)
- {
- pjsua.buddies[index].sub = NULL;
- return;
- }
-
- status = pjsip_pres_initiate( pjsua.buddies[index].sub, 0, &tdata);
- if (status == PJ_SUCCESS)
- status = pjsip_pres_send_request( pjsua.buddies[index].sub, tdata );
-
- if (status == PJ_SUCCESS) {
-
- //pjsip_evsub_set_mod_data(pjsua.buddies[index].sub, pjsua.mod.id,
- // NULL);
- //pjsua.buddies[index].sub = NULL;
-
- } else {
- pjsua_perror(THIS_FILE, "Unable to unsubscribe presence",
- status);
- }
-}
-
-
-/* It does what it says.. */
-static void refresh_client_subscription(void)
-{
- int i;
-
- for (i=0; i<pjsua.buddy_cnt; ++i) {
-
- if (pjsua.buddies[i].monitor && !pjsua.buddies[i].sub) {
- subscribe_buddy_presence(i);
-
- } else if (!pjsua.buddies[i].monitor && pjsua.buddies[i].sub) {
- unsubscribe_buddy_presence(i);
-
- }
- }
-}
-
-
-/*
- * Init presence
- */
-pj_status_t pjsua_pres_init()
-{
- pj_status_t status;
-
- status = pjsip_endpt_register_module( pjsua.endpt, &mod_pjsua_pres);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to register pjsua presence module",
- status);
- }
-
- return status;
-}
-
-/*
- * Refresh presence
- */
-void pjsua_pres_refresh(int acc_index)
-{
- refresh_client_subscription();
- refresh_server_subscription(acc_index);
-}
-
-
-/*
- * Shutdown presence.
- */
-void pjsua_pres_shutdown(void)
-{
- int acc_index;
- int i;
-
- for (acc_index=0; acc_index<pjsua.acc_cnt; ++acc_index) {
- pjsua.acc[acc_index].online_status = 0;
- }
-
- for (i=0; i<pjsua.buddy_cnt; ++i) {
- pjsua.buddies[i].monitor = 0;
- }
-
- for (acc_index=0; acc_index<pjsua.acc_cnt; ++acc_index) {
- pjsua_pres_refresh(acc_index);
- }
-}
-
-/*
- * Dump presence status.
- */
-void pjsua_pres_dump(void)
-{
- int acc_index;
- int i;
-
- PJ_LOG(3,(THIS_FILE, "Dumping pjsua server subscriptions:"));
- for (acc_index=0; acc_index < pjsua.acc_cnt; ++acc_index) {
-
- PJ_LOG(3,(THIS_FILE, " %.*s",
- (int)pjsua.acc[acc_index].local_uri.slen,
- pjsua.acc[acc_index].local_uri.ptr));
-
- if (pj_list_empty(&pjsua.acc[acc_index].pres_srv_list)) {
- PJ_LOG(3,(THIS_FILE, " - none - "));
- } else {
- struct pjsua_srv_pres *uapres;
-
- uapres = pjsua.acc[acc_index].pres_srv_list.next;
- while (uapres != &pjsua.acc[acc_index].pres_srv_list) {
-
- PJ_LOG(3,(THIS_FILE, " %10s %s",
- pjsip_evsub_get_state_name(uapres->sub),
- uapres->remote));
-
- uapres = uapres->next;
- }
- }
- }
-
- PJ_LOG(3,(THIS_FILE, "Dumping pjsua client subscriptions:"));
- if (pjsua.buddy_cnt == 0) {
- PJ_LOG(3,(THIS_FILE, " - no buddy list - "));
- } else {
- for (i=0; i<pjsua.buddy_cnt; ++i) {
-
- if (pjsua.buddies[i].sub) {
- PJ_LOG(3,(THIS_FILE, " %10s %s",
- pjsip_evsub_get_state_name(pjsua.buddies[i].sub),
- pjsua.buddies[i].uri.ptr));
- } else {
- PJ_LOG(3,(THIS_FILE, " %10s %s",
- "(null)",
- pjsua.buddies[i].uri.ptr));
- }
- }
- }
-}
-
diff --git a/pjsip/src/pjsua/pjsua_reg.c b/pjsip/src/pjsua/pjsua_reg.c
deleted file mode 100644
index 006bc732..00000000
--- a/pjsip/src/pjsua/pjsua_reg.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.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 "pjsua.h"
-
-
-/*
- * pjsua_reg.c
- *
- * Client registration handler.
- */
-
-#define THIS_FILE "pjsua_reg.c"
-
-
-/*
- * This callback is called by pjsip_regc when outgoing register
- * request has completed.
- */
-static void regc_cb(struct pjsip_regc_cbparam *param)
-{
-
- pjsua_acc *acc = param->token;
-
- /*
- * Print registration status.
- */
- if (param->status!=PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "SIP registration error",
- param->status);
- pjsip_regc_destroy(acc->regc);
- acc->regc = NULL;
-
- } else if (param->code < 0 || param->code >= 300) {
- PJ_LOG(2, (THIS_FILE, "SIP registration failed, status=%d (%s)",
- param->code,
- pjsip_get_status_text(param->code)->ptr));
- pjsip_regc_destroy(acc->regc);
- acc->regc = NULL;
-
- } else if (PJSIP_IS_STATUS_IN_CLASS(param->code, 200)) {
-
- if (param->expiration < 1) {
- pjsip_regc_destroy(acc->regc);
- acc->regc = NULL;
- PJ_LOG(3,(THIS_FILE, "%s: unregistration success",
- acc->local_uri.ptr));
- } else {
- PJ_LOG(3, (THIS_FILE,
- "%s: registration success, status=%d (%s), "
- "will re-register in %d seconds",
- acc->local_uri.ptr,
- param->code,
- pjsip_get_status_text(param->code)->ptr,
- param->expiration));
- }
-
- } else {
- PJ_LOG(4, (THIS_FILE, "SIP registration updated status=%d", param->code));
- }
-
- acc->reg_last_err = param->status;
- acc->reg_last_code = param->code;
-
- pjsua_ui_regc_on_state_changed(acc->index);
-}
-
-
-/*
- * Update registration. If renew is false, then unregistration will be performed.
- */
-void pjsua_regc_update(int acc_index, pj_bool_t renew)
-{
- pj_status_t status;
- pjsip_tx_data *tdata;
-
- if (renew) {
- if (pjsua.acc[acc_index].regc == NULL) {
- status = pjsua_regc_init(acc_index);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to create registration",
- status);
- return;
- }
- }
- status = pjsip_regc_register(pjsua.acc[acc_index].regc, 1, &tdata);
- } else {
- if (pjsua.acc[acc_index].regc == NULL) {
- PJ_LOG(3,(THIS_FILE, "Currently not registered"));
- return;
- }
- status = pjsip_regc_unregister(pjsua.acc[acc_index].regc, &tdata);
- }
-
- if (status == PJ_SUCCESS)
- status = pjsip_regc_send( pjsua.acc[acc_index].regc, tdata );
-
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to create/send REGISTER",
- status);
- } else {
- PJ_LOG(3,(THIS_FILE, "%s sent",
- (renew? "Registration" : "Unregistration")));
- }
-}
-
-/*
- * Initialize client registration.
- */
-pj_status_t pjsua_regc_init(int acc_index)
-{
- pj_status_t status;
-
- /* initialize SIP registration if registrar is configured */
- if (pjsua.acc[acc_index].reg_uri.slen) {
-
- status = pjsip_regc_create( pjsua.endpt,
- &pjsua.acc[acc_index],
- &regc_cb,
- &pjsua.acc[acc_index].regc);
-
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE, "Unable to create client registration",
- status);
- return status;
- }
-
-
- status = pjsip_regc_init( pjsua.acc[acc_index].regc,
- &pjsua.acc[acc_index].reg_uri,
- &pjsua.acc[acc_index].local_uri,
- &pjsua.acc[acc_index].local_uri,
- 1, &pjsua.acc[acc_index].contact_uri,
- pjsua.acc[acc_index].reg_timeout);
- if (status != PJ_SUCCESS) {
- pjsua_perror(THIS_FILE,
- "Client registration initialization error",
- status);
- return status;
- }
-
- pjsip_regc_set_credentials( pjsua.acc[acc_index].regc,
- pjsua.cred_count,
- pjsua.cred_info );
-
- pjsip_regc_set_route_set( pjsua.acc[acc_index].regc,
- &pjsua.acc[acc_index].route_set );
- }
-
- return PJ_SUCCESS;
-}
-