Changeset 503


Ignore:
Timestamp:
Jun 13, 2006 10:57:13 PM (19 years ago)
Author:
bennylp
Message:

-- REWRITE OF PJSUA API --

Location:
pjproject/trunk
Files:
4 added
5 deleted
12 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib/src/pj/config.c

    r468 r503  
    2222 
    2323static const char *id = "config.c"; 
    24 const char *PJ_VERSION = "0.5.5.6"; 
     24const char *PJ_VERSION = "0.5.6.0"; 
    2525 
    2626PJ_DEF(void) pj_dump_config(void) 
  • pjproject/trunk/pjsip-apps/build

    • Property svn:ignore
      •  

        old new  
        88*.suo 
        99*.pdb 
         10activex-pjsua_p.c 
         11dlldata.c 
  • pjproject/trunk/pjsip-apps/build/activex-pjsua.dsp

    r487 r503  
    324324# Begin Source File 
    325325 
    326 SOURCE="..\src\activex-pjsua\pjsua.h" 
     326SOURCE="..\src\activex-pjsua\pjsua-structs.h" 
    327327# End Source File 
    328328# Begin Source File 
  • pjproject/trunk/pjsip-apps/build/pjsua.dsp

    r458 r503  
    9393SOURCE=..\src\pjsua\main.c 
    9494# End Source File 
     95# Begin Source File 
     96 
     97SOURCE=..\src\pjsua\pjsua.c 
     98# End Source File 
    9599# End Group 
    96100# Begin Group "Header Files" 
  • pjproject/trunk/pjsip-apps/src/activex-pjsua

    • Property svn:ignore set to
      old*
      backup*
      *.tlb
      *.aps
      activex-pjsua.h
      activex-pjsua_i.c
      pjsua-structs.h
      resource.h
  • pjproject/trunk/pjsip-apps/src/pjsua/main.c

    r492 r503  
    1818 */ 
    1919#include <pjsua-lib/pjsua.h> 
    20 #include <pjsua-lib/pjsua_console_app.h> 
    21  
    2220 
    2321#define THIS_FILE       "main.c" 
    2422 
    25 /***************************************************************************** 
    26  * main(): 
     23 
     24/* 
     25 * These are defined in pjsua.c. 
    2726 */ 
     27pj_status_t app_init(int argc, char *argv[]); 
     28pj_status_t app_main(void); 
     29pj_status_t app_destroy(void); 
     30 
    2831int main(int argc, char *argv[]) 
    2932{ 
    30     pjsua_config cfg; 
    31     pj_str_t uri_to_call = { NULL, 0 }; 
    32  
    33     /* Init default settings. */ 
    34     pjsua_default_config(&cfg); 
    35  
    36  
    37     /* Create PJLIB and memory pool */ 
    38     pjsua_create(); 
    39  
    40  
    41     /* Parse command line arguments: */ 
    42     if (pjsua_parse_args(argc, argv, &cfg, &uri_to_call) != PJ_SUCCESS) 
     33    if (app_init(argc, argv) != PJ_SUCCESS) 
    4334        return 1; 
    4435 
    45  
    46     /* Init pjsua */ 
    47     if (pjsua_init(&cfg, &console_callback) != PJ_SUCCESS) 
    48         return 1; 
    49  
    50  
    51     /* Start pjsua! */ 
    52     if (pjsua_start() != PJ_SUCCESS) { 
    53         pjsua_destroy(); 
    54         return 1; 
    55     } 
    56  
    57  
    58     /* Sleep for a while, let any messages get printed to console: */ 
    59     pj_thread_sleep(500); 
    60  
    61  
    62     /* Start UI console main loop: */ 
    63     pjsua_console_app_main(&uri_to_call); 
    64  
    65  
    66     /* Destroy pjsua: */ 
    67     pjsua_destroy(); 
    68  
    69     /* This is for internal testing, to make sure that pjsua_destroy() 
    70      * can be called multiple times.  
    71      */ 
    72     pjsua_destroy(); 
    73  
    74  
    75     /* Exit... */ 
     36    app_main(); 
     37    app_destroy(); 
    7638 
    7739    return 0; 
  • pjproject/trunk/pjsip/build/pjsua_lib.dsp

    r476 r503  
    8888# Begin Source File 
    8989 
    90 SOURCE="..\src\pjsua-lib\pjsua_call.c" 
     90SOURCE="..\src\pjsua-lib\pjsua_acc.c" 
    9191# End Source File 
    9292# Begin Source File 
    9393 
    94 SOURCE="..\src\pjsua-lib\pjsua_console_app.c" 
     94SOURCE="..\src\pjsua-lib\pjsua_call.c" 
    9595# End Source File 
    9696# Begin Source File 
     
    104104# Begin Source File 
    105105 
    106 SOURCE="..\src\pjsua-lib\pjsua_imp.h" 
     106SOURCE="..\src\pjsua-lib\pjsua_media.c" 
    107107# End Source File 
    108108# Begin Source File 
    109109 
    110110SOURCE="..\src\pjsua-lib\pjsua_pres.c" 
    111 # End Source File 
    112 # Begin Source File 
    113  
    114 SOURCE="..\src\pjsua-lib\pjsua_reg.c" 
    115 # End Source File 
    116 # Begin Source File 
    117  
    118 SOURCE="..\src\pjsua-lib\pjsua_settings.c" 
    119111# End Source File 
    120112# End Group 
     
    128120# Begin Source File 
    129121 
    130 SOURCE="..\include\pjsua-lib\pjsua_console_app.h" 
     122SOURCE="..\include\pjsua-lib\pjsua_internal.h" 
    131123# End Source File 
    132124# End Group 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r492 r503  
    5757 */ 
    5858#ifndef PJSUA_MAX_CALLS 
    59 #   define PJSUA_MAX_CALLS          256 
     59#   define PJSUA_MAX_CALLS          32 
    6060#endif 
    6161 
    6262 
    6363/** 
     64 * Max ports in the conference bridge. 
     65 */ 
     66#ifndef PJSUA_MAX_CONF_PORTS 
     67#   define PJSUA_MAX_CONF_PORTS     254 
     68#endif 
     69 
     70 
     71/** 
    6472 * Maximum accounts. 
    6573 */ 
    6674#ifndef PJSUA_MAX_ACC 
    67 #   define PJSUA_MAX_ACC            32 
     75#   define PJSUA_MAX_ACC            8 
    6876#endif 
    6977 
    7078 
     79/** 
     80 * Maximum proxies in account. 
     81 */ 
     82#ifndef PJSUA_ACC_MAX_PROXIES 
     83#   define PJSUA_ACC_MAX_PROXIES    8 
     84#endif 
     85 
     86/** 
     87 * Default registration interval. 
     88 */ 
     89#ifndef PJSUA_REG_INTERVAL 
     90#   define PJSUA_REG_INTERVAL       55 
     91#endif 
     92 
     93 
     94/** Account identification */ 
    7195typedef int pjsua_acc_id; 
     96 
     97/** Call identification */ 
     98typedef int pjsua_call_id; 
     99 
     100/** SIP transport identification */ 
     101typedef int pjsua_transport_id; 
     102 
     103/** Buddy identification */ 
    72104typedef int pjsua_buddy_id; 
     105 
     106/** File player identification */ 
    73107typedef int pjsua_player_id; 
     108 
     109/** File recorder identification */ 
    74110typedef int pjsua_recorder_id; 
     111 
     112/** Conference port identification */ 
    75113typedef int pjsua_conf_port_id; 
    76114 
    77115 
     116/** Constant to identify invalid ID for all sorts of IDs. */ 
     117#define PJSUA_INVALID_ID            (-1) 
     118 
     119 
     120 
    78121/** 
    79122 * Account configuration. 
    80123 */ 
    81 struct pjsua_acc_config 
    82 { 
    83     /** SIP URL for account ID (mandatory) */ 
     124typedef struct pjsua_acc_config 
     125{ 
     126    /**  
     127     * The full SIP URL for the account. The value can take name address or  
     128     * URL format, and will look something like "sip:account@serviceprovider". 
     129     * 
     130     * This field is mandatory. 
     131     */ 
    84132    pj_str_t        id; 
    85133 
    86     /** Registrar URI (mandatory) */ 
     134    /**  
     135     * This is the URL to be put in the request URI for the registration, 
     136     * and will look something like "sip:serviceprovider". 
     137     * 
     138     * This field should be specified if registration is desired. If the 
     139     * value is empty, no account registration will be performed. 
     140     */ 
    87141    pj_str_t        reg_uri; 
    88142 
    89     /** Optional contact URI */ 
     143    /**  
     144     * Optional URI to be put as Contact for this account. It is recommended 
     145     * that this field is left empty, so that the value will be calculated 
     146     * automatically based on the transport address. 
     147     */ 
    90148    pj_str_t        contact; 
    91149 
    92     /** Service proxy (default: none) */ 
    93     pj_str_t        proxy; 
    94  
    95     /** Default timeout (mandatory) */ 
    96     pj_int32_t      reg_timeout; 
    97  
    98     /** Number of credentials. */ 
     150    /** 
     151     * Number of proxies in the proxy array below. 
     152     */ 
     153    unsigned        proxy_cnt; 
     154 
     155    /**  
     156     * Optional URI of the proxies to be visited for all outgoing requests  
     157     * that are using this account (REGISTER, INVITE, etc). Application need  
     158     * to specify these proxies if the service provider requires that requests 
     159     * destined towards its network should go through certain proxies first 
     160     * (for example, border controllers). 
     161     * 
     162     * These proxies will be put in the route set for this account, with  
     163     * maintaining the orders (the first proxy in the array will be visited 
     164     * first). 
     165     */ 
     166    pj_str_t        proxy[PJSUA_ACC_MAX_PROXIES]; 
     167 
     168    /**  
     169     * Optional interval for registration, in seconds. If the value is zero,  
     170     * default interval will be used (PJSUA_REG_INTERVAL, 55 seconds). 
     171     */ 
     172    unsigned        reg_timeout; 
     173 
     174    /**  
     175     * Number of credentials in the credential array. 
     176     */ 
    99177    unsigned        cred_count; 
    100178 
    101     /** Array of credentials. */ 
    102     pjsip_cred_info cred_info[4]; 
    103  
    104 }; 
    105  
    106  
    107 /** 
    108  * @see pjsua_acc_config 
    109  */ 
    110 typedef struct pjsua_acc_config pjsua_acc_config; 
    111  
    112  
    113 /** 
    114  * PJSUA settings. 
    115  */ 
    116 struct pjsua_config 
    117 { 
    118     /** SIP UDP signaling port. Set to zero to disable UDP signaling, 
    119      * which in this case application must manually add a transport 
    120      * to SIP endpoint. 
    121      * (default: 5060)  
    122      */ 
    123     unsigned    udp_port; 
    124  
    125     /** Optional hostname or IP address to publish as the host part of 
    126      *  Contact header. This must be specified if UDP transport is 
    127      *  disabled. 
    128      *  (default: NULL) 
    129      */ 
    130     pj_str_t    sip_host; 
    131  
    132     /** Optional port number to publish in the port part of Contact header. 
    133      *  This must be specified if UDP transport is disabled. 
    134      *  (default: 0) 
    135      */ 
    136     unsigned    sip_port; 
    137  
    138     /** Start of RTP port. Set to zero to prevent pjsua from creating 
    139      *  media transports, which in this case application must manually 
    140      *  create media transport for each calls. 
    141      *  (default: 4000)  
    142      */ 
    143     unsigned    start_rtp_port; 
    144  
    145     /** 
    146      * Enable incoming and outgoing message logging (default: 1). 
     179    /**  
     180     * Array of credentials. If registration is desired, normally there should 
     181     * be at least one credential specified, to successfully authenticate 
     182     * against the service provider. More credentials can be specified, for 
     183     * example when the requests are expected to be challenged by the 
     184     * proxies in the route set. 
     185     */ 
     186    pjsip_cred_info cred_info[PJSUA_ACC_MAX_PROXIES]; 
     187 
     188} pjsua_acc_config; 
     189 
     190 
     191/** 
     192 * Call this function to initialize account config with default values. 
     193 * 
     194 * @param cfg       The account config to be initialized. 
     195 */ 
     196PJ_INLINE(void) pjsua_acc_config_default(pjsua_acc_config *cfg) 
     197{ 
     198    pj_memset(cfg, 0, sizeof(*cfg)); 
     199 
     200    cfg->reg_timeout = PJSUA_REG_INTERVAL; 
     201} 
     202 
     203 
     204 
     205/** 
     206 * Account info. Application can query account info by calling  
     207 * #pjsua_acc_get_info(). 
     208 */ 
     209typedef struct pjsua_acc_info 
     210{ 
     211    /**  
     212     * The account ID.  
     213     */ 
     214    pjsua_acc_id        id; 
     215 
     216    /** 
     217     * Flag to indicate whether this is the default account. 
     218     */ 
     219    pj_bool_t           is_default; 
     220 
     221    /**  
     222     * Account URI  
     223     */ 
     224    pj_str_t            acc_uri; 
     225 
     226    /**  
     227     * Flag to tell whether this account has registration setting 
     228     * (reg_uri is not empty). 
     229     */ 
     230    pj_bool_t           has_registration; 
     231 
     232    /** 
     233     * An up to date expiration interval for account registration session. 
     234     */ 
     235    int                 expires; 
     236 
     237    /** 
     238     * Last registration status code. If status code is zero, the account 
     239     * is currently not registered. Any other value indicates the SIP 
     240     * status code of the registration. 
     241     */ 
     242    pjsip_status_code   status; 
     243 
     244    /** 
     245     * String describing the registration status. 
     246     */ 
     247    pj_str_t            status_text; 
     248 
     249    /** 
     250     * Presence online status for this account. 
     251     */ 
     252    pj_bool_t           online_status; 
     253 
     254    /** 
     255     * Buffer that is used internally to store the status text. 
     256     */ 
     257    char                buf_[PJ_ERR_MSG_SIZE]; 
     258 
     259} pjsua_acc_info; 
     260 
     261 
     262 
     263/** 
     264 * STUN configuration. 
     265 */ 
     266typedef struct pjsua_stun_config 
     267{ 
     268    /** 
     269     * The first STUN server IP address or hostname. 
     270     */ 
     271    pj_str_t    stun_srv1; 
     272 
     273    /** 
     274     * Port number of the first STUN server. 
     275     * If zero, default STUN port will be used. 
     276     */ 
     277    unsigned    stun_port1; 
     278     
     279    /** 
     280     * Optional second STUN server IP address or hostname, for which the 
     281     * result of the mapping request will be compared to. If the value 
     282     * is empty, only one STUN server will be used. 
     283     */ 
     284    pj_str_t    stun_srv2; 
     285 
     286    /** 
     287     * Port number of the second STUN server. 
     288     * If zero, default STUN port will be used. 
     289     */ 
     290    unsigned    stun_port2; 
     291 
     292} pjsua_stun_config; 
     293 
     294 
     295 
     296/** 
     297 * Call this function to initialize STUN config with default values. 
     298 * 
     299 * @param cfg       The STUN config to be initialized. 
     300 */ 
     301PJ_INLINE(void) pjsua_stun_config_default(pjsua_stun_config *cfg) 
     302{ 
     303    pj_memset(cfg, 0, sizeof(*cfg)); 
     304} 
     305 
     306 
     307/** 
     308 * Transport configuration for creating UDP transports for both SIP 
     309 * and media. 
     310 */ 
     311typedef struct pjsua_transport_config 
     312{ 
     313    /** 
     314     * UDP port number to bind locally. This setting MUST be specified 
     315     * even when default port is desired. If the value is zero, the 
     316     * transport will be bound to any available port, and application 
     317     * can query the port by querying the transport info. 
     318     */ 
     319    unsigned            port; 
     320 
     321    /** 
     322     * Optional address where the socket should be bound. 
     323     */ 
     324    pj_in_addr          ip_addr; 
     325 
     326    /** 
     327     * Flag to indicate whether STUN should be used. 
     328     */ 
     329    pj_bool_t           use_stun; 
     330 
     331    /** 
     332     * STUN configuration, must be specified when STUN is used. 
     333     */ 
     334    pjsua_stun_config   stun_config; 
     335 
     336} pjsua_transport_config; 
     337 
     338 
     339/** 
     340 * Call this function to initialize UDP config with default values. 
     341 * 
     342 * @param cfg       The UDP config to be initialized. 
     343 */ 
     344PJ_INLINE(void) pjsua_transport_config_default(pjsua_transport_config *cfg) 
     345{ 
     346    pj_memset(cfg, 0, sizeof(*cfg)); 
     347} 
     348 
     349 
     350/** 
     351 * Normalize STUN config. 
     352 */ 
     353PJ_INLINE(void) pjsua_normalize_stun_config( pjsua_stun_config *cfg ) 
     354{ 
     355    if (cfg->stun_srv1.slen) { 
     356 
     357        if (cfg->stun_port1 == 0) 
     358            cfg->stun_port1 = 3478; 
     359 
     360        if (cfg->stun_srv2.slen == 0) { 
     361            cfg->stun_srv2 = cfg->stun_srv1; 
     362            cfg->stun_port2 = cfg->stun_port1; 
     363        } else { 
     364            if (cfg->stun_port2 == 0) 
     365                cfg->stun_port2 = 3478; 
     366        } 
     367 
     368    } else { 
     369        cfg->stun_port1 = 0; 
     370        cfg->stun_srv2.slen = 0; 
     371        cfg->stun_port2 = 0; 
     372    } 
     373} 
     374 
     375 
     376/** 
     377 * Duplicate transport config. 
     378 */ 
     379PJ_INLINE(void) pjsua_transport_config_dup(pj_pool_t *pool, 
     380                                           pjsua_transport_config *dst, 
     381                                           const pjsua_transport_config *src) 
     382{ 
     383    pj_memcpy(dst, src, sizeof(*src)); 
     384 
     385    if (src->stun_config.stun_srv1.slen) { 
     386        pj_strdup_with_null(pool, &dst->stun_config.stun_srv1, 
     387                            &src->stun_config.stun_srv1); 
     388    } 
     389 
     390    if (src->stun_config.stun_srv2.slen) { 
     391        pj_strdup_with_null(pool, &dst->stun_config.stun_srv2, 
     392                            &src->stun_config.stun_srv2); 
     393    } 
     394 
     395    pjsua_normalize_stun_config(&dst->stun_config); 
     396} 
     397 
     398 
     399 
     400/** 
     401 * Transport info. 
     402 */ 
     403typedef struct pjsua_transport_info 
     404{ 
     405    /** 
     406     * PJSUA transport identification. 
     407     */ 
     408    pjsua_transport_id      id; 
     409 
     410    /** 
     411     * Transport type. 
     412     */ 
     413    pjsip_transport_type_e  type; 
     414 
     415    /** 
     416     * Transport type name. 
     417     */ 
     418    pj_str_t                type_name; 
     419 
     420    /** 
     421     * Transport string info/description. 
     422     */ 
     423    pj_str_t                info; 
     424 
     425    /** 
     426     * Transport flag (see ##pjsip_transport_flags_e). 
     427     */ 
     428    unsigned                flag; 
     429 
     430    /** 
     431     * Local address length. 
     432     */ 
     433    unsigned                addr_len; 
     434 
     435    /** 
     436     * Local/bound address. 
     437     */ 
     438    pj_sockaddr             local_addr; 
     439 
     440    /** 
     441     * Published address (or transport address name). 
     442     */ 
     443    pjsip_host_port         local_name; 
     444 
     445    /** 
     446     * Current number of objects currently referencing this transport. 
     447     */ 
     448    unsigned                usage_count; 
     449 
     450 
     451} pjsua_transport_info; 
     452 
     453 
     454/** 
     455 * Media configuration. 
     456 */ 
     457typedef struct pjsua_media_config 
     458{ 
     459    /** 
     460     * Clock rate to be applied to the conference bridge. 
     461     * If value is zero, default clock rate will be used (16KHz). 
     462     */ 
     463    unsigned            clock_rate; 
     464 
     465    /** 
     466     * Specify maximum number of media ports to be created in the 
     467     * conference bridge. Since all media terminate in the bridge 
     468     * (calls, file player, file recorder, etc), the value must be 
     469     * large enough to support all of them. However, the larger 
     470     * the value, the more computations are performed. 
     471     */ 
     472    unsigned            max_media_ports; 
     473 
     474    /** 
     475     * Specify whether the media manager should manage its own 
     476     * ioqueue for the RTP/RTCP sockets. If yes, ioqueue will be created 
     477     * and at least one worker thread will be created too. If no, 
     478     * the RTP/RTCP sockets will share the same ioqueue as SIP sockets, 
     479     * and no worker thread is needed. 
     480     * 
     481     * Normally application would say yes here, unless it wants to 
     482     * run everything from a single thread. 
     483     */ 
     484    pj_bool_t           has_ioqueue; 
     485 
     486    /** 
     487     * Specify the number of worker threads to handle incoming RTP 
     488     * packets. A value of one is recommended for most applications. 
     489     */ 
     490    unsigned            thread_cnt; 
     491 
     492 
     493} pjsua_media_config; 
     494 
     495 
     496/** 
     497 * Use this function to initialize media config. 
     498 * 
     499 * @param cfg   The media config to be initialized. 
     500 */ 
     501PJ_INLINE(void) pjsua_media_config_default(pjsua_media_config *cfg) 
     502{ 
     503    pj_memset(cfg, 0, sizeof(*cfg)); 
     504 
     505    cfg->clock_rate = 16000; 
     506    cfg->max_media_ports = 32; 
     507    cfg->has_ioqueue = PJ_TRUE; 
     508    cfg->thread_cnt = 1; 
     509} 
     510 
     511 
     512 
     513/** 
     514 * Logging configuration. 
     515 */ 
     516typedef struct pjsua_logging_config 
     517{ 
     518    /** 
     519     * Log incoming and outgoing SIP message? Yes! 
    147520     */ 
    148521    pj_bool_t   msg_logging; 
    149522 
    150     /** Maximum calls to support (default: 4) */ 
    151     unsigned    max_calls; 
    152  
    153     /** Maximum slots in the conference bridge (default: 0/calculated 
    154      *  as max_calls*2 
    155      */ 
    156     unsigned    conf_ports; 
    157  
    158     /** Number of worker threads (value >=0, default: 1) */ 
    159     unsigned    thread_cnt; 
    160  
    161     /** Separate ioqueue for media? (default: yes) */ 
    162     pj_bool_t   media_has_ioqueue; 
    163  
    164     /** Number of worker thread for media (value >=0, default: 1) */ 
    165     unsigned    media_thread_cnt; 
    166  
    167     /** First STUN server IP address. When STUN is configured, then the 
    168      *  two STUN server settings must be fully set. 
    169      *  (default: none)  
    170      */ 
    171     pj_str_t    stun_srv1; 
    172  
    173     /** First STUN port number */ 
    174     unsigned    stun_port1; 
    175  
    176     /** Second STUN server IP address */ 
    177     pj_str_t    stun_srv2; 
    178  
    179     /** Second STUN server port number */ 
    180     unsigned    stun_port2; 
    181  
    182     /** Sound player device ID (default: 0) */ 
    183     unsigned    snd_player_id; 
    184  
    185     /** Sound capture device ID (default: 0) */ 
    186     unsigned    snd_capture_id; 
    187  
    188     /** Internal clock rate (to be applied to sound devices and conference 
    189      *  bridge, default is 0/follows the codec, or 44100 for MacOS). 
    190      */ 
    191     unsigned    clock_rate; 
    192  
    193     /** Do not use sound device (default: 0). */ 
    194     pj_bool_t   null_audio; 
    195  
    196     /** WAV file to load for auto_play (default: NULL) */ 
    197     pj_str_t    wav_file; 
    198  
    199     /** Auto play WAV file for calls? (default: no) */ 
    200     pj_bool_t   auto_play; 
    201  
    202     /** Auto loopback calls? (default: no) */ 
    203     pj_bool_t   auto_loop; 
    204  
    205     /** Automatically put calls to conference? (default: no) */ 
    206     pj_bool_t   auto_conf; 
    207  
    208     /** Speex codec complexity? (default: 10) */ 
    209     unsigned    complexity; 
    210  
    211     /** Speex codec quality? (default: 10) */ 
    212     unsigned    quality; 
    213  
    214     /** Codec ptime? (default: 0 (follows the codec)) */ 
    215     unsigned    ptime; 
    216  
    217     /** Number of additional codecs/"--add-codec" with pjsua (default: 0) */ 
    218     unsigned    codec_cnt; 
    219  
    220     /** Additional codecs/"--add-codec" options */ 
    221     pj_str_t    codec_arg[32]; 
    222  
    223     /** SIP status code to be automatically sent to incoming calls 
    224      *  (default: 100). 
    225      */ 
    226     unsigned    auto_answer; 
    227  
    228     /** Periodic time to refresh call with re-INVITE (default: 0) 
    229      */ 
    230     unsigned    uas_refresh; 
    231  
    232     /** Maximum incoming call duration (default: 3600) */ 
    233     unsigned    uas_duration; 
    234  
    235     /** Outbound proxy (default: none) */ 
    236     pj_str_t    outbound_proxy; 
    237  
    238     /** Number of SIP accounts */ 
    239     unsigned    acc_cnt; 
    240  
    241     /** SIP accounts configuration */ 
    242     pjsua_acc_config    acc_config[32]; 
    243  
    244     /** Logging verbosity (default: 5). */ 
    245     unsigned    log_level; 
    246  
    247     /** Logging to be displayed to stdout (default: 4) */ 
    248     unsigned    app_log_level; 
    249  
    250     /** Log decoration */ 
    251     unsigned    log_decor; 
    252  
    253     /** Optional log filename (default: NULL) */ 
     523    /** 
     524     * Input verbosity level. Value 5 is reasonable. 
     525     */ 
     526    unsigned    level; 
     527 
     528    /** 
     529     * Verbosity level for console. Value 4 is reasonable. 
     530     */ 
     531    unsigned    console_level; 
     532 
     533    /** 
     534     * Log decoration. 
     535     */ 
     536    unsigned    decor; 
     537 
     538    /** 
     539     * Optional log filename. 
     540     */ 
    254541    pj_str_t    log_filename; 
    255542 
    256     /** Number of buddies in address book (default: 0) */ 
    257     unsigned    buddy_cnt; 
    258  
    259     /** Buddies URI */ 
    260     pj_str_t    buddy_uri[256]; 
    261 }; 
    262  
    263  
    264 /** 
    265  * @see pjsua_config 
    266  */ 
    267 typedef struct pjsua_config pjsua_config; 
    268  
     543    /** 
     544     * Optional callback function to be called to write log to  
     545     * application specific device. This function will be called for 
     546     * log messages on input verbosity level. 
     547     */ 
     548    void       (*cb)(int level, const char *data, pj_size_t len); 
     549 
     550 
     551} pjsua_logging_config; 
     552 
     553 
     554/** 
     555 * Use this function to initialize logging config. 
     556 * 
     557 * @param cfg   The logging config to be initialized. 
     558 */ 
     559PJ_INLINE(void) pjsua_logging_config_default(pjsua_logging_config *cfg) 
     560{ 
     561    pj_memset(cfg, 0, sizeof(*cfg)); 
     562 
     563    cfg->msg_logging = PJ_TRUE; 
     564    cfg->level = 5; 
     565    cfg->console_level = 4; 
     566    cfg->decor = PJ_LOG_HAS_SENDER | PJ_LOG_HAS_TIME |  
     567                 PJ_LOG_HAS_MICRO_SEC | PJ_LOG_HAS_NEWLINE; 
     568} 
     569 
     570/** 
     571 * Use this function to duplicate logging config. 
     572 * 
     573 * @param pool      Pool to use. 
     574 * @param dst       Destination config. 
     575 * @param src       Source config. 
     576 */ 
     577PJ_INLINE(void) pjsua_logging_config_dup(pj_pool_t *pool, 
     578                                         pjsua_logging_config *dst, 
     579                                         const pjsua_logging_config *src) 
     580{ 
     581    pj_memcpy(dst, src, sizeof(*src)); 
     582    pj_strdup_with_null(pool, &dst->log_filename, &src->log_filename); 
     583} 
     584 
     585 
     586/** 
     587 * Buddy configuration. 
     588 */ 
     589typedef struct pjsua_buddy_config 
     590{ 
     591    /** 
     592     * Buddy URL or name address. 
     593     */ 
     594    pj_str_t    uri; 
     595 
     596    /** 
     597     * Specify whether presence subscription should start immediately. 
     598     */ 
     599    pj_bool_t   subscribe; 
     600 
     601} pjsua_buddy_config; 
     602 
     603 
     604/** 
     605 * Buddy's online status. 
     606 */ 
     607typedef enum pjsua_buddy_status 
     608{ 
     609    /** 
     610     * Online status is unknown (possibly because no presence subscription 
     611     * has been established). 
     612     */ 
     613    PJSUA_BUDDY_STATUS_UNKNOWN, 
     614 
     615    /** 
     616     * Buddy is known to be offline. 
     617     */ 
     618    PJSUA_BUDDY_STATUS_ONLINE, 
     619 
     620    /** 
     621     * Buddy is offline. 
     622     */ 
     623    PJSUA_BUDDY_STATUS_OFFLINE, 
     624 
     625} pjsua_buddy_status; 
     626 
     627 
     628 
     629/** 
     630 * Buddy info. 
     631 */ 
     632typedef struct pjsua_buddy_info 
     633{ 
     634    /** 
     635     * The buddy ID. 
     636     */ 
     637    pjsua_buddy_id      id; 
     638 
     639    /** 
     640     * The full URI of the buddy, as specified in the configuration. 
     641     */ 
     642    pj_str_t            uri; 
     643 
     644    /** 
     645     * Buddy's Contact, only available when presence subscription has 
     646     * been established to the buddy. 
     647     */ 
     648    pj_str_t            contact; 
     649 
     650    /** 
     651     * Buddy's online status. 
     652     */ 
     653    pjsua_buddy_status  status; 
     654 
     655    /** 
     656     * Text to describe buddy's online status. 
     657     */ 
     658    pj_str_t            status_text; 
     659 
     660    /** 
     661     * Flag to indicate that we should monitor the presence information for 
     662     * this buddy (normally yes, unless explicitly disabled). 
     663     */ 
     664    pj_bool_t           monitor_pres; 
     665 
     666    /** 
     667     * Internal buffer. 
     668     */ 
     669    char                buf_[256]; 
     670 
     671} pjsua_buddy_info; 
     672 
     673 
     674/** 
     675 * Codec config. 
     676 */ 
     677typedef struct pjsua_codec_info 
     678{ 
     679    /** 
     680     * Codec unique identification. 
     681     */ 
     682    pj_str_t            codec_id; 
     683 
     684    /** 
     685     * Codec priority (integer 0-255). 
     686     */ 
     687    pj_uint8_t          priority; 
     688 
     689    /** 
     690     * Internal buffer. 
     691     */ 
     692    char                buf_[32]; 
     693 
     694} pjsua_codec_info; 
    269695 
    270696 
     
    272698 * Application callbacks. 
    273699 */ 
    274 struct pjsua_callback 
     700typedef struct pjsua_callback 
    275701{ 
    276702    /** 
     
    279705     * detail call states. 
    280706     */ 
    281     void (*on_call_state)(int call_index, pjsip_event *e); 
     707    void (*on_call_state)(pjsua_call_id call_id, pjsip_event *e); 
    282708 
    283709    /** 
    284710     * Notify application on incoming call. 
    285711     */ 
    286     void (*on_incoming_call)(pjsua_acc_id acc_id, int call_index, 
     712    void (*on_incoming_call)(pjsua_acc_id acc_id, pjsua_call_id call_id, 
    287713                             pjsip_rx_data *rdata); 
     714 
     715    /** 
     716     * Notify application when media state in the call has changed. 
     717     * Normal application would need to implement this callback, e.g. 
     718     * to connect the call's media to sound device. 
     719     */ 
     720    void (*on_call_media_state)(pjsua_call_id call_id); 
    288721 
    289722    /** 
     
    294727     * transfer. 
    295728     */ 
    296     void (*on_call_transfered)(int call_index, 
     729    void (*on_call_transfered)(pjsua_call_id call_id, 
    297730                               const pj_str_t *dst, 
    298731                               pjsip_status_code *code); 
     
    313746    /** 
    314747     * Notify application on incoming pager (i.e. MESSAGE request). 
    315      * Argument call_index will be -1 if MESSAGE request is not related to an  
     748     * Argument call_id will be -1 if MESSAGE request is not related to an 
    316749     * existing call. 
    317750     */ 
    318     void (*on_pager)(int call_index, const pj_str_t *from, 
    319                      const pj_str_t *to, const pj_str_t *txt); 
     751    void (*on_pager)(pjsua_call_id call_id, const pj_str_t *from, 
     752                     const pj_str_t *to, const pj_str_t *contact, 
     753                     const pj_str_t *mime_type, const pj_str_t *body); 
     754 
     755    /** 
     756     * Notify application about the delivery status of outgoing pager 
     757     * request. 
     758     * 
     759     * @param call_id       Containts the ID of the call where the IM was 
     760     *                      sent, or PJSUA_INVALID_ID if the IM was sent 
     761     *                      outside call context. 
     762     * @param to            Destination URI. 
     763     * @param body          Message body. 
     764     * @param user_data     Arbitrary data that was specified when sending 
     765     *                      IM message. 
     766     * @param status        Delivery status. 
     767     * @param reason        Delivery status reason. 
     768     */ 
     769    void (*on_pager_status)(pjsua_call_id call_id, 
     770                            const pj_str_t *to, 
     771                            const pj_str_t *body, 
     772                            void *user_data, 
     773                            pjsip_status_code status, 
     774                            const pj_str_t *reason); 
    320775 
    321776    /** 
    322777     * Notify application about typing indication. 
    323778     */ 
    324     void (*on_typing)(int call_index, const pj_str_t *from, 
    325                       const pj_str_t *to, pj_bool_t is_typing); 
    326  
    327 }; 
    328  
    329 /** 
    330  * @see pjsua_callback 
    331  */ 
    332 typedef struct pjsua_callback pjsua_callback; 
     779    void (*on_typing)(pjsua_call_id call_id, const pj_str_t *from, 
     780                      const pj_str_t *to, const pj_str_t *contact, 
     781                      pj_bool_t is_typing); 
     782 
     783} pjsua_callback; 
     784 
     785 
     786 
     787 
     788/** 
     789 * PJSUA settings. 
     790 */ 
     791typedef struct pjsua_config 
     792{ 
     793 
     794    /**  
     795     * Maximum calls to support (default: 4)  
     796     */ 
     797    unsigned        max_calls; 
     798 
     799    /**  
     800     * Number of worker threads. Normally application will want to have at 
     801     * least one worker thread, unless when it wants to poll the library 
     802     * periodically, which in this case the worker thread can be set to 
     803     * zero. 
     804     */ 
     805    unsigned        thread_cnt; 
     806 
     807    /** 
     808     * Number of outbound proxies in the array. 
     809     */ 
     810    unsigned        outbound_proxy_cnt; 
     811 
     812    /**  
     813     * Specify the URL of outbound proxies to visit for all outgoing requests. 
     814     * The outbound proxies will be used for all accounts, and it will 
     815     * be used to build the route set for outgoing requests. The final 
     816     * route set for outgoing requests will consists of the outbound proxies 
     817     * and the proxy configured in the account. 
     818     */ 
     819    pj_str_t        outbound_proxy[4]; 
     820 
     821    /**  
     822     * Number of credentials in the credential array. 
     823     */ 
     824    unsigned        cred_count; 
     825 
     826    /**  
     827     * Array of credentials. These credentials will be used by all accounts, 
     828     * and can be used to authenticate against outbound proxies. 
     829     */ 
     830    pjsip_cred_info cred_info[PJSUA_ACC_MAX_PROXIES]; 
     831 
     832    /** 
     833     * Application callback. 
     834     */ 
     835    pjsua_callback  cb; 
     836 
     837} pjsua_config; 
     838 
     839 
     840/** 
     841 * Use this function to initialize pjsua config. 
     842 * 
     843 * @param cfg   pjsua config to be initialized. 
     844 */ 
     845PJ_INLINE(void) pjsua_config_default(pjsua_config *cfg) 
     846{ 
     847    pj_memset(cfg, 0, sizeof(*cfg)); 
     848 
     849    cfg->max_calls = 4; 
     850    cfg->thread_cnt = 1; 
     851} 
     852 
     853 
     854/** 
     855 * Duplicate credential. 
     856 */ 
     857PJ_INLINE(void) pjsip_cred_dup( pj_pool_t *pool, 
     858                                pjsip_cred_info *dst, 
     859                                const pjsip_cred_info *src) 
     860{ 
     861    pj_strdup_with_null(pool, &dst->realm, &src->realm); 
     862    pj_strdup_with_null(pool, &dst->scheme, &src->scheme); 
     863    pj_strdup_with_null(pool, &dst->username, &src->username); 
     864    pj_strdup_with_null(pool, &dst->data, &src->data); 
     865 
     866} 
     867 
     868 
     869/** 
     870 * Duplicate pjsua_config. 
     871 */ 
     872PJ_INLINE(void) pjsua_config_dup(pj_pool_t *pool, 
     873                                 pjsua_config *dst, 
     874                                 const pjsua_config *src) 
     875{ 
     876    unsigned i; 
     877 
     878    pj_memcpy(dst, src, sizeof(*src)); 
     879 
     880    for (i=0; i<src->outbound_proxy_cnt; ++i) { 
     881        pj_strdup_with_null(pool, &dst->outbound_proxy[i], 
     882                            &src->outbound_proxy[i]); 
     883    } 
     884 
     885    for (i=0; i<src->cred_count; ++i) { 
     886        pjsip_cred_dup(pool, &dst->cred_info[i], &src->cred_info[i]); 
     887    } 
     888} 
     889 
     890 
     891/** 
     892 * Call media status. 
     893 */ 
     894typedef enum pjsua_call_media_status 
     895{ 
     896    PJSUA_CALL_MEDIA_NONE, 
     897    PJSUA_CALL_MEDIA_ACTIVE, 
     898    PJSUA_CALL_MEDIA_LOCAL_HOLD, 
     899    PJSUA_CALL_MEDIA_REMOTE_HOLD, 
     900} pjsua_call_media_status; 
    333901 
    334902 
     
    336904 * Call info. 
    337905 */ 
    338 struct pjsua_call_info 
    339 { 
    340     unsigned            index; 
    341     pj_bool_t           active; 
     906typedef struct pjsua_call_info 
     907{ 
     908    /** Call identification. */ 
     909    pjsua_call_id       id; 
     910 
     911    /** Initial call role (UAC == caller) */ 
    342912    pjsip_role_e        role; 
     913 
     914    /** Local URI */ 
    343915    pj_str_t            local_info; 
     916 
     917    /** Local Contact */ 
     918    pj_str_t            local_contact; 
     919 
     920    /** Remote URI */ 
    344921    pj_str_t            remote_info; 
     922 
     923    /** Remote contact */ 
     924    pj_str_t            remote_contact; 
     925 
     926    /** Dialog Call-ID string. */ 
     927    pj_str_t            call_id; 
     928 
     929    /** Call state */ 
    345930    pjsip_inv_state     state; 
     931 
     932    /** Text describing the state */ 
    346933    pj_str_t            state_text; 
     934 
     935    /** Last status code heard, which can be used as cause code */ 
    347936    pjsip_status_code   last_status; 
     937 
     938    /** The reason phrase describing the status. */ 
    348939    pj_str_t            last_status_text; 
     940 
     941    /** Call media status. */ 
     942    pjsua_call_media_status media_status; 
     943 
     944    /** Media direction */ 
     945    pjmedia_dir         media_dir; 
     946 
     947    /** The conference port number for the call */ 
     948    pjsua_conf_port_id  conf_slot; 
     949 
     950    /** Up-to-date call connected duration (zero when call is not  
     951     *  established) 
     952     */ 
    349953    pj_time_val         connect_duration; 
     954 
     955    /** Total call duration, including set-up time */ 
    350956    pj_time_val         total_duration; 
    351     pj_bool_t           has_media; 
    352     pjsua_conf_port_id  conf_slot; 
    353 }; 
    354  
    355 typedef struct pjsua_call_info pjsua_call_info; 
    356  
    357  
    358 enum pjsua_buddy_status 
    359 { 
    360     PJSUA_BUDDY_STATUS_UNKNOWN, 
    361     PJSUA_BUDDY_STATUS_ONLINE, 
    362     PJSUA_BUDDY_STATUS_OFFLINE, 
    363 }; 
    364  
    365 typedef enum pjsua_buddy_status pjsua_buddy_status; 
    366  
    367  
    368 /** 
    369  * Buddy info. 
    370  */ 
    371 struct pjsua_buddy_info 
    372 { 
    373     pjsua_buddy_id      index; 
    374     pj_bool_t           is_valid; 
     957 
     958    /** Internal */ 
     959    struct { 
     960        char    local_info[128]; 
     961        char    local_contact[128]; 
     962        char    remote_info[128]; 
     963        char    remote_contact[128]; 
     964        char    call_id[128]; 
     965        char    last_status_text[128]; 
     966    } buf_; 
     967 
     968} pjsua_call_info; 
     969 
     970 
     971 
     972 
     973/** 
     974 * Conference port info. 
     975 */ 
     976typedef struct pjsua_conf_port_info 
     977{ 
     978    /** Conference port number. */ 
     979    pjsua_conf_port_id  slot_id; 
     980 
     981    /** Port name. */ 
    375982    pj_str_t            name; 
    376     pj_str_t            display_name; 
    377     pj_str_t            host; 
    378     unsigned            port; 
    379     pj_str_t            uri; 
    380     pjsua_buddy_status  status; 
    381     pj_str_t            status_text; 
    382     pj_bool_t           monitor; 
    383 }; 
    384  
    385 typedef struct pjsua_buddy_info pjsua_buddy_info; 
    386  
    387  
    388 /** 
    389  * Account info. 
    390  */ 
    391 struct pjsua_acc_info 
    392 { 
    393     pjsua_acc_id        index; 
    394     pj_str_t            acc_id; 
    395     pj_bool_t           has_registration; 
    396     int                 expires; 
    397     pjsip_status_code   status; 
    398     pj_str_t            status_text; 
    399     pj_bool_t           online_status; 
    400     char                buf[PJ_ERR_MSG_SIZE]; 
    401 }; 
    402  
    403 typedef struct pjsua_acc_info pjsua_acc_info; 
    404  
    405  
    406 /** 
    407  * Conference port info. 
    408  */ 
    409 struct pjsua_conf_port_info 
    410 { 
    411     pjsua_conf_port_id  slot_id; 
    412     pj_str_t            name; 
     983 
     984    /** Clock rate. */ 
    413985    unsigned            clock_rate; 
     986 
     987    /** Number of channels. */ 
    414988    unsigned            channel_count; 
     989 
     990    /** Samples per frame */ 
    415991    unsigned            samples_per_frame; 
     992 
     993    /** Bits per sample */ 
    416994    unsigned            bits_per_sample; 
     995 
     996    /** Number of listeners in the array. */ 
    417997    unsigned            listener_cnt; 
    418     pjsua_conf_port_id  listeners[256]; 
    419 }; 
    420  
    421  
    422 typedef struct pjsua_conf_port_info pjsua_conf_port_info; 
     998 
     999    /** Array of listeners (in other words, ports where this port is  
     1000     *  transmitting to. 
     1001     */ 
     1002    pjsua_conf_port_id  listeners[PJSUA_MAX_CONF_PORTS]; 
     1003 
     1004} pjsua_conf_port_info; 
     1005 
     1006 
     1007/** 
     1008 * This structure holds information about custom media transport to 
     1009 * be registered to pjsua. 
     1010 */ 
     1011typedef struct pjsua_media_transport 
     1012{ 
     1013    /** 
     1014     * Media socket information containing the address information 
     1015     * of the RTP and RTCP socket. 
     1016     */ 
     1017    pjmedia_sock_info    skinfo; 
     1018 
     1019    /** 
     1020     * The media transport instance. 
     1021     */ 
     1022    pjmedia_transport   *transport; 
     1023 
     1024} pjsua_media_transport; 
     1025 
     1026 
     1027/** 
     1028 * This structure describes additional information to be sent with 
     1029 * outgoing SIP message. 
     1030 */ 
     1031typedef struct pjsua_msg_data 
     1032{ 
     1033    /** 
     1034     * Additional message headers as linked list. 
     1035     */ 
     1036    pjsip_hdr   hdr_list; 
     1037 
     1038    /** 
     1039     * MIME type of optional message body.  
     1040     */ 
     1041    pj_str_t    content_type; 
     1042 
     1043    /** 
     1044     * Optional message body. 
     1045     */ 
     1046    pj_str_t    msg_body; 
     1047 
     1048} pjsua_msg_data; 
     1049 
     1050 
     1051/** 
     1052 * Initialize message data. 
     1053 * 
     1054 * @param msg_data  Message data to be initialized. 
     1055 */ 
     1056PJ_INLINE(void) pjsua_msg_data_init(pjsua_msg_data *msg_data) 
     1057{ 
     1058    pj_memset(msg_data, 0, sizeof(*msg_data)); 
     1059    pj_list_init(&msg_data->hdr_list); 
     1060} 
    4231061 
    4241062 
    4251063/***************************************************************************** 
    426  * PJSUA API (defined in pjsua_core.c). 
    427  */ 
    428  
    429 /** 
    430  * Initialize pjsua settings with default parameters. 
    431  */ 
    432 PJ_DECL(void) pjsua_default_config(pjsua_config *cfg); 
    433  
    434  
    435 /** 
    436  * Validate configuration. 
    437  */ 
    438 PJ_DECL(pj_status_t) pjsua_test_config(const pjsua_config *cfg, 
    439                                        char *errmsg, 
    440                                        int len); 
    441  
    442  
    443 /** 
    444  * Instantiate pjsua application. This initializes pjlib/pjlib-util, and  
    445  * creates memory pool factory to be used by application. 
     1064 * PJSUA Core API 
     1065 */ 
     1066 
     1067 
     1068/** 
     1069 * Instantiate pjsua application. Application must call this function before 
     1070 * calling any other functions, to make sure that the underlying libraries 
     1071 * are properly initialized. Once this function has returned success, 
     1072 * application must call pjsua_destroy() before quitting. 
     1073 * 
     1074 * @return              PJ_SUCCESS on success, or the appropriate error code. 
    4461075 */ 
    4471076PJ_DECL(pj_status_t) pjsua_create(void); 
     
    4491078 
    4501079/** 
    451  * Initialize pjsua application with the specified settings. 
    452  * 
    453  * This will initialize all libraries, create endpoint instance, and register 
    454  * pjsip modules.  
    455  * 
    456  * Application may register module after calling this function. 
    457  */ 
    458 PJ_DECL(pj_status_t) pjsua_init(const pjsua_config *cfg, 
    459                                 const pjsua_callback *cb); 
    460  
    461  
    462 /** 
    463  * Start pjsua stack. Application calls this after pjsua settings has been 
    464  * configured. 
    465  * 
    466  * This will start the transport, worker threads (if any), and registration  
    467  * process, if registration is configured. 
     1080 * Initialize pjsua with the specified settings. All the settings are  
     1081 * optional, and the default values will be used when the config is not 
     1082 * specified. 
     1083 * 
     1084 * @param ua_cfg        User agent configuration. 
     1085 * @param log_cfg       Optional logging configuration. 
     1086 * @param media_cfg     Optional media configuration. 
     1087 * 
     1088 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1089 */ 
     1090PJ_DECL(pj_status_t) pjsua_init(const pjsua_config *ua_cfg, 
     1091                                const pjsua_logging_config *log_cfg, 
     1092                                const pjsua_media_config *media_cfg); 
     1093 
     1094 
     1095/** 
     1096 * Application is recommended to call this function after all initialization 
     1097 * is done, so that the library can do additional checking set up 
     1098 * additional  
     1099 * 
     1100 * @return              PJ_SUCCESS on success, or the appropriate error code. 
    4681101 */ 
    4691102PJ_DECL(pj_status_t) pjsua_start(void); 
    4701103 
    471 /** 
    472  * Destroy pjsua. 
     1104 
     1105/** 
     1106 * Destroy pjsua. This function must be called once PJSUA is created. To 
     1107 * make it easier for application, application may call this function 
     1108 * several times with no danger. 
     1109 * 
     1110 * @return              PJ_SUCCESS on success, or the appropriate error code. 
    4731111 */ 
    4741112PJ_DECL(pj_status_t) pjsua_destroy(void); 
    4751113 
    476 /** 
    477  * Poll pjsua. 
     1114 
     1115/** 
     1116 * Poll pjsua for events, and if necessary block the caller thread for 
     1117 * the specified maximum interval (in miliseconds). 
     1118 * 
     1119 * @param msec_timeout  Maximum time to wait, in miliseconds. 
     1120 * 
     1121 * @return  The number of events that have been handled during the 
     1122 *          poll. Negative value indicates error, and application 
     1123 *          can retrieve the error as (err = -return_value). 
    4781124 */ 
    4791125PJ_DECL(int) pjsua_handle_events(unsigned msec_timeout); 
     
    4811127 
    4821128/** 
    483  * Get SIP endpoint instance. 
    484  * Only valid after pjsua_init(). 
     1129 * Create memory pool. 
     1130 * 
     1131 * @param name          Optional pool name. 
     1132 * @param size          Initial size of the pool. 
     1133 * @param increment     Increment size. 
     1134 * 
     1135 * @return              The pool, or NULL when there's no memory. 
     1136 */ 
     1137PJ_DECL(pj_pool_t*) pjsua_pool_create(const char *name, pj_size_t init_size, 
     1138                                      pj_size_t increment); 
     1139 
     1140 
     1141/** 
     1142 * Application can call this function at any time (after pjsua_create(), of 
     1143 * course) to change logging settings. 
     1144 * 
     1145 * @param c             Logging configuration. 
     1146 * 
     1147 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1148 */ 
     1149PJ_DECL(pj_status_t) pjsua_reconfigure_logging(const pjsua_logging_config *c); 
     1150 
     1151 
     1152/** 
     1153 * Internal function to get SIP endpoint instance of pjsua, which is 
     1154 * needed for example to register module, create transports, etc. 
     1155 * Probably is only valid after #pjsua_init() is called. 
     1156 *  
     1157 * @return              SIP endpoint instance. 
    4851158 */ 
    4861159PJ_DECL(pjsip_endpoint*) pjsua_get_pjsip_endpt(void); 
    4871160 
    4881161/** 
    489  * Get media endpoint instance. 
    490  * Only valid after pjsua_init(). 
     1162 * Internal function to get media endpoint instance. 
     1163 * Only valid after #pjsua_init() is called. 
     1164 * 
     1165 * @return              Media endpoint instance. 
    4911166 */ 
    4921167PJ_DECL(pjmedia_endpt*) pjsua_get_pjmedia_endpt(void); 
    4931168 
    494 /** 
    495  * Replace media transport. 
    496  */ 
    497 PJ_DECL(pj_status_t) pjsua_set_call_media_transport(unsigned call_index, 
    498                                                     const pjmedia_sock_info *i, 
    499                                                     pjmedia_transport *tp); 
    500  
    5011169 
    5021170/***************************************************************************** 
    503  * PJSUA Call API (defined in pjsua_call.c). 
     1171 * PJSUA SIP Transport API. 
     1172 */ 
     1173 
     1174/** 
     1175 * Create SIP transport. 
     1176 * 
     1177 * @param type          Transport type. 
     1178 * @param cfg           Transport configuration. 
     1179 * @param p_id          Optional pointer to receive transport ID. 
     1180 * 
     1181 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1182 */ 
     1183PJ_DECL(pj_status_t) pjsua_transport_create(pjsip_transport_type_e type, 
     1184                                            const pjsua_transport_config *cfg, 
     1185                                            pjsua_transport_id *p_id); 
     1186 
     1187/** 
     1188 * Register transport that has been created by application. 
     1189 * 
     1190 * @param tp            Transport instance. 
     1191 * @param p_id          Optional pointer to receive transport ID. 
     1192 * 
     1193 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1194 */ 
     1195PJ_DECL(pj_status_t) pjsua_transport_register(pjsip_transport *tp, 
     1196                                              pjsua_transport_id *p_id); 
     1197 
     1198 
     1199/** 
     1200 * Enumerate all transports currently created in the system. 
     1201 * 
     1202 * @param id            Array to receive transport ids. 
     1203 * @param count         In input, specifies the maximum number of elements. 
     1204 *                      On return, it contains the actual number of elements. 
     1205 * 
     1206 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1207 */ 
     1208PJ_DECL(pj_status_t) pjsua_enum_transports( pjsua_transport_id id[], 
     1209                                            unsigned *count ); 
     1210 
     1211 
     1212/** 
     1213 * Get information about transports. 
     1214 * 
     1215 * @param id            Transport ID. 
     1216 * @param info          Pointer to receive transport info. 
     1217 * 
     1218 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1219 */ 
     1220PJ_DECL(pj_status_t) pjsua_transport_get_info(pjsua_transport_id id, 
     1221                                              pjsua_transport_info *info); 
     1222 
     1223 
     1224/** 
     1225 * Disable a transport or re-enable it. By default transport is always  
     1226 * enabled after it is created. Disabling a transport does not necessarily 
     1227 * close the socket, it will only discard incoming messages and prevent 
     1228 * the transport from being used to send outgoing messages. 
     1229 * 
     1230 * @param id            Transport ID. 
     1231 * @param enabled       Non-zero to enable, zero to disable. 
     1232 * 
     1233 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1234 */ 
     1235PJ_DECL(pj_status_t) pjsua_transport_set_enable(pjsua_transport_id id, 
     1236                                                pj_bool_t enabled); 
     1237 
     1238 
     1239/** 
     1240 * Close the transport. If transport is forcefully closed, it will be 
     1241 * immediately closed, and any pending transactions that are using the 
     1242 * transport may not terminate properly. Otherwise, the system will wait 
     1243 * until all transactions are closed while preventing new users from 
     1244 * using the transport, and will close the transport when it is safe to 
     1245 * do so. 
     1246 * 
     1247 * @param id            Transport ID. 
     1248 * @param force         Non-zero to immediately close the transport. This 
     1249 *                      is not recommended! 
     1250 * 
     1251 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1252 */ 
     1253PJ_DECL(pj_status_t) pjsua_transport_close( pjsua_transport_id id, 
     1254                                            pj_bool_t force ); 
     1255 
     1256 
     1257/***************************************************************************** 
     1258 * PJSUA Media Transport. 
     1259 */ 
     1260 
     1261/** 
     1262 * Create UDP media transports for all the calls. This function creates 
     1263 * one UDP media transport for each call. 
     1264 * 
     1265 * @param cfg           Media transport configuration. The "port" field in the 
     1266 *                      configuration is used as the start port to bind the 
     1267 *                      sockets. 
     1268 * 
     1269 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1270 */ 
     1271PJ_DECL(pj_status_t)  
     1272pjsua_media_transports_create(const pjsua_transport_config *cfg); 
     1273 
     1274 
     1275/** 
     1276 * Register custom media transports to be used by calls. There must 
     1277 * enough media transports for all calls. 
     1278 * 
     1279 * @param tp            The media transport array. 
     1280 * @param count         Number of elements in the array. This number MUST 
     1281 *                      match the number of maximum calls configured when 
     1282 *                      pjsua is created. 
     1283 * @param auto_delete   Flag to indicate whether the transports should be 
     1284 *                      destroyed when pjsua is shutdown. 
     1285 * 
     1286 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1287 */ 
     1288PJ_DECL(pj_status_t)  
     1289pjsua_media_transports_attach( pjsua_media_transport tp[], 
     1290                               unsigned count, 
     1291                               pj_bool_t auto_delete); 
     1292 
     1293 
     1294 
     1295/***************************************************************************** 
     1296 * PJSUA Call API. 
    5041297 */ 
    5051298 
    5061299/** 
    5071300 * Get maximum number of calls configured in pjsua. 
     1301 * 
     1302 * @return              Maximum number of calls configured. 
    5081303 */ 
    5091304PJ_DECL(unsigned) pjsua_call_get_max_count(void); 
    5101305 
    5111306/** 
    512  * Get current number of active calls. 
     1307 * Get number of currently active calls. 
     1308 * 
     1309 * @return              Number of currently active calls. 
    5131310 */ 
    5141311PJ_DECL(unsigned) pjsua_call_get_count(void); 
     1312 
     1313/** 
     1314 * Enumerate all active calls. 
     1315 * 
     1316 * @param ids           Array of account IDs to be initialized. 
     1317 * @param count         In input, specifies the maximum number of elements. 
     1318 *                      On return, it contains the actual number of elements. 
     1319 * 
     1320 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1321 */ 
     1322PJ_DECL(pj_status_t) pjsua_enum_calls(pjsua_call_id ids[], 
     1323                                      unsigned *count); 
     1324 
     1325 
     1326/** 
     1327 * Make outgoing call to the specified URI using the specified account. 
     1328 * 
     1329 * @param acc_id        The account to be used. 
     1330 * @param target        URI to be put in the request URI. 
     1331 * @param dst_uri       URI to be put in the To header (normally is the same 
     1332 *                      as the target URI). 
     1333 * @param options       Options (must be zero at the moment). 
     1334 * @param user_data     Arbitrary user data to be attached to the call, and 
     1335 *                      can be retrieved later. 
     1336 * @param msg_data      Optional headers etc to be added to outgoing INVITE 
     1337 *                      request, or NULL if no custom header is desired. 
     1338 * @param p_call_id     Pointer to receive call identification. 
     1339 * 
     1340 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1341 */ 
     1342PJ_DECL(pj_status_t) pjsua_call_make_call(pjsua_acc_id acc_id, 
     1343                                          const pj_str_t *dst_uri, 
     1344                                          unsigned options, 
     1345                                          void *user_data, 
     1346                                          const pjsua_msg_data *msg_data, 
     1347                                          pjsua_call_id *p_call_id); 
     1348 
    5151349 
    5161350/** 
    5171351 * Check if the specified call has active INVITE session and the INVITE 
    5181352 * session has not been disconnected. 
    519  */ 
    520 PJ_DECL(pj_bool_t) pjsua_call_is_active(unsigned call_index); 
    521  
    522  
    523 /** 
    524  * Check if call has a media session. 
    525  */ 
    526 PJ_DECL(pj_bool_t) pjsua_call_has_media(unsigned call_index); 
    527  
    528  
    529 /** 
    530  * Get call info. 
    531  */ 
    532 PJ_DECL(pj_status_t) pjsua_call_get_info(unsigned call_index, 
     1353 * 
     1354 * @param call_id       Call identification. 
     1355 * 
     1356 * @return              Non-zero if call is active. 
     1357 */ 
     1358PJ_DECL(pj_bool_t) pjsua_call_is_active(pjsua_call_id call_id); 
     1359 
     1360 
     1361/** 
     1362 * Check if call has an active media session. 
     1363 * 
     1364 * @param call_id       Call identification. 
     1365 * 
     1366 * @return              Non-zero if yes. 
     1367 */ 
     1368PJ_DECL(pj_bool_t) pjsua_call_has_media(pjsua_call_id call_id); 
     1369 
     1370 
     1371/** 
     1372 * Get the conference port identification associated with the call. 
     1373 * 
     1374 * @param call_id       Call identification. 
     1375 * 
     1376 * @return              Conference port ID, or PJSUA_INVALID_ID when the  
     1377 *                      media has not been established or is not active. 
     1378 */ 
     1379PJ_DECL(pjsua_conf_port_id) pjsua_call_get_conf_port(pjsua_call_id call_id); 
     1380 
     1381/** 
     1382 * Obtain detail information about the specified call. 
     1383 * 
     1384 * @param call_id       Call identification. 
     1385 * @param info          Call info to be initialized. 
     1386 * 
     1387 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1388 */ 
     1389PJ_DECL(pj_status_t) pjsua_call_get_info(pjsua_call_id call_id, 
    5331390                                         pjsua_call_info *info); 
    5341391 
    5351392 
    5361393/** 
    537  * Duplicate call info. 
    538  */ 
    539 PJ_DECL(void) pjsua_call_info_dup(pj_pool_t *pool, 
    540                                   pjsua_call_info *dst_info, 
    541                                   const pjsua_call_info *src_info); 
    542  
    543  
    544 /** 
    545  * Make outgoing call. 
    546  */ 
    547 PJ_DECL(pj_status_t) pjsua_call_make_call(unsigned acc_id, 
    548                                           const pj_str_t *dst_uri, 
    549                                           int *p_call_index); 
    550  
    551  
    552 /** 
    553  * Answer call. 
    554  */ 
    555 PJ_DECL(pj_status_t) pjsua_call_answer(int call_index, int code); 
    556  
    557 /** 
    558  * Hangup call. 
    559  */ 
    560 PJ_DECL(void) pjsua_call_hangup(int call_index); 
    561  
    562  
    563 /** 
    564  * Put call on-hold. 
    565  */ 
    566 PJ_DECL(pj_status_t) pjsua_call_set_hold(int call_index); 
     1394 * Attach application specific data to the call. 
     1395 * 
     1396 * @param call_id       Call identification. 
     1397 * @param user_data     Arbitrary data to be attached to the call. 
     1398 * 
     1399 * @return              The user data. 
     1400 */ 
     1401PJ_DECL(pj_status_t) pjsua_call_set_user_data(pjsua_call_id call_id, 
     1402                                              void *user_data); 
     1403 
     1404 
     1405/** 
     1406 * Get user data attached to the call. 
     1407 * 
     1408 * @param call_id       Call identification. 
     1409 * 
     1410 * @return              The user data. 
     1411 */ 
     1412PJ_DECL(void*) pjsua_call_get_user_data(pjsua_call_id call_id); 
     1413 
     1414 
     1415/** 
     1416 * Send response to incoming INVITE request. 
     1417 * 
     1418 * @param call_id       Incoming call identification. 
     1419 * @param code          Status code, (100-699). 
     1420 * @param reason        Optional reason phrase. If NULL, default text 
     1421 *                      will be used. 
     1422 * @param msg_data      Optional list of headers etc to be added to outgoing 
     1423 *                      response message. 
     1424 * 
     1425 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1426 */ 
     1427PJ_DECL(pj_status_t) pjsua_call_answer(pjsua_call_id call_id,  
     1428                                       unsigned code, 
     1429                                       const pj_str_t *reason, 
     1430                                       const pjsua_msg_data *msg_data); 
     1431 
     1432/** 
     1433 * Hangup call by using method that is appropriate according to the 
     1434 * call state. 
     1435 * 
     1436 * @param call_id       Call identification. 
     1437 * @param code          Optional status code to be sent when we're rejecting 
     1438 *                      incoming call. If the value is zero, "603/Decline" 
     1439 *                      will be sent. 
     1440 * @param reason        Optional reason phrase to be sent when we're rejecting 
     1441 *                      incoming call.  If NULL, default text will be used. 
     1442 * @param msg_data      Optional list of headers etc to be added to outgoing 
     1443 *                      request/response message. 
     1444 * 
     1445 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1446 */ 
     1447PJ_DECL(pj_status_t) pjsua_call_hangup(pjsua_call_id call_id, 
     1448                                       unsigned code, 
     1449                                       const pj_str_t *reason, 
     1450                                       const pjsua_msg_data *msg_data); 
     1451 
     1452 
     1453/** 
     1454 * Put the specified call on hold. 
     1455 * 
     1456 * @param call_id       Call identification. 
     1457 * @param msg_data      Optional message components to be sent with 
     1458 *                      the request. 
     1459 * 
     1460 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1461 */ 
     1462PJ_DECL(pj_status_t) pjsua_call_set_hold(pjsua_call_id call_id, 
     1463                                         const pjsua_msg_data *msg_data); 
    5671464 
    5681465 
    5691466/** 
    5701467 * Send re-INVITE (to release hold). 
    571  */ 
    572 PJ_DECL(pj_status_t) pjsua_call_reinvite(int call_index); 
    573  
    574  
    575 /** 
    576  * Transfer call. 
    577  */ 
    578 PJ_DECL(pj_status_t) pjsua_call_xfer(unsigned call_index, const pj_str_t *dest); 
    579  
    580 /** 
    581  * Dial DTMF. 
    582  */ 
    583 PJ_DECL(pj_status_t) pjsua_call_dial_dtmf(unsigned call_index,  
     1468 * 
     1469 * @param call_id       Call identification. 
     1470 * @param unhold        If this argument is non-zero and the call is locally 
     1471 *                      held, this will release the local hold. 
     1472 * @param msg_data      Optional message components to be sent with 
     1473 *                      the request. 
     1474 * 
     1475 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1476 */ 
     1477PJ_DECL(pj_status_t) pjsua_call_reinvite(pjsua_call_id call_id, 
     1478                                         pj_bool_t unhold, 
     1479                                         const pjsua_msg_data *msg_data); 
     1480 
     1481 
     1482/** 
     1483 * Initiate call transfer to the specified address. 
     1484 * 
     1485 * @param call_id       Call identification. 
     1486 * @param dest          Address of new target to be contacted. 
     1487 * @param msg_data      Optional message components to be sent with 
     1488 *                      the request. 
     1489 * 
     1490 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1491 */ 
     1492PJ_DECL(pj_status_t) pjsua_call_xfer(pjsua_call_id call_id,  
     1493                                     const pj_str_t *dest, 
     1494                                     const pjsua_msg_data *msg_data); 
     1495 
     1496/** 
     1497 * Send DTMF digits to remote using RFC 2833 payload formats. 
     1498 * 
     1499 * @param call_id       Call identification. 
     1500 * @param digits        DTMF digits to be sent. 
     1501 * 
     1502 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1503 */ 
     1504PJ_DECL(pj_status_t) pjsua_call_dial_dtmf(pjsua_call_id call_id,  
    5841505                                          const pj_str_t *digits); 
    5851506 
    586  
    5871507/** 
    5881508 * Send instant messaging inside INVITE session. 
    589  */ 
    590 PJ_DECL(pj_status_t) pjsua_call_send_im(int call_index, const pj_str_t *text); 
     1509 * 
     1510 * @param call_id       Call identification. 
     1511 * @param mime_type     Optional MIME type. If NULL, then "text/plain" is  
     1512 *                      assumed. 
     1513 * @param content       The message content. 
     1514 * @param msg_data      Optional list of headers etc to be included in outgoing 
     1515 *                      request. The body descriptor in the msg_data is  
     1516 *                      ignored. 
     1517 * @param user_data     Optional user data, which will be given back when 
     1518 *                      the IM callback is called. 
     1519 * 
     1520 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1521 */ 
     1522PJ_DECL(pj_status_t) pjsua_call_send_im( pjsua_call_id call_id,  
     1523                                         const pj_str_t *mime_type, 
     1524                                         const pj_str_t *content, 
     1525                                         const pjsua_msg_data *msg_data, 
     1526                                         void *user_data); 
    5911527 
    5921528 
    5931529/** 
    5941530 * Send IM typing indication inside INVITE session. 
    595  */ 
    596 PJ_DECL(pj_status_t) pjsua_call_send_typing_ind(int call_index,  
    597                                                 pj_bool_t is_typing); 
     1531 * 
     1532 * @param call_id       Call identification. 
     1533 * @param is_typing     Non-zero to indicate to remote that local person is 
     1534 *                      currently typing an IM. 
     1535 * @param msg_data      Optional list of headers etc to be included in outgoing 
     1536 *                      request. 
     1537 * 
     1538 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1539 */ 
     1540PJ_DECL(pj_status_t) pjsua_call_send_typing_ind(pjsua_call_id call_id,  
     1541                                                pj_bool_t is_typing, 
     1542                                                const pjsua_msg_data*msg_data); 
    5981543 
    5991544/** 
     
    6051550/** 
    6061551 * Dump call and media statistics to string. 
    607  */ 
    608 PJ_DECL(void) pjsua_call_dump(int call_index, int with_media,  
    609                               char *buffer, unsigned maxlen, 
    610                               const char *indent); 
     1552 * 
     1553 * @param call_id       Call identification. 
     1554 * @param with_media    Non-zero to include media information too. 
     1555 * @param buffer        Buffer where the statistics are to be written to. 
     1556 * @param maxlen        Maximum length of buffer. 
     1557 * @param indent        Spaces for left indentation. 
     1558 * 
     1559 * @return              PJ_SUCCESS on success. 
     1560 */ 
     1561PJ_DECL(pj_status_t) pjsua_call_dump(pjsua_call_id call_id,  
     1562                                     pj_bool_t with_media,  
     1563                                     char *buffer,  
     1564                                     unsigned maxlen, 
     1565                                     const char *indent); 
    6111566 
    6121567 
    6131568/***************************************************************************** 
    614  * PJSUA Account and Client Registration API (defined in pjsua_reg.c). 
    615  */ 
    616  
    617  
    618 /** 
    619  * Get number of accounts. 
    620  */ 
    621 PJ_DECL(unsigned) pjsua_get_acc_count(void); 
    622  
    623 /** 
    624  * Get account info. 
     1569 * PJSUA Account and Client Registration API. 
     1570 */ 
     1571 
     1572 
     1573/** 
     1574 * Get number of current accounts. 
     1575 * 
     1576 * @return              Current number of accounts. 
     1577 */ 
     1578PJ_DECL(unsigned) pjsua_acc_get_count(void); 
     1579 
     1580 
     1581/** 
     1582 * Check if the specified account ID is valid. 
     1583 * 
     1584 * @param acc_id        Account ID to check. 
     1585 * 
     1586 * @return              Non-zero if account ID is valid. 
     1587 */ 
     1588PJ_DECL(pj_bool_t) pjsua_acc_is_valid(pjsua_acc_id acc_id); 
     1589 
     1590 
     1591/** 
     1592 * Add a new account to pjsua. PJSUA must have been initialized (with 
     1593 * #pjsua_init()) before calling this function. 
     1594 * 
     1595 * @param cfg           Account configuration. 
     1596 * @param is_default    If non-zero, this account will be set as the default 
     1597 *                      account. The default account will be used when sending 
     1598 *                      outgoing requests (e.g. making call) when no account is 
     1599 *                      specified, and when receiving incoming requests when the 
     1600 *                      request does not match any accounts. It is recommended 
     1601 *                      that default account is set to local/LAN account. 
     1602 * @param p_acc_id      Pointer to receive account ID of the new account. 
     1603 * 
     1604 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1605 */ 
     1606PJ_DECL(pj_status_t) pjsua_acc_add(const pjsua_acc_config *cfg, 
     1607                                   pj_bool_t is_default, 
     1608                                   pjsua_acc_id *p_acc_id); 
     1609 
     1610 
     1611/** 
     1612 * Add a local account. A local account is used to identify local endpoint 
     1613 * instead of a specific user, and for this reason, a transport ID is needed 
     1614 * to obtain the local address information. 
     1615 * 
     1616 * @param tid           Transport ID to generate account address. 
     1617 * @param is_default    If non-zero, this account will be set as the default 
     1618 *                      account. The default account will be used when sending 
     1619 *                      outgoing requests (e.g. making call) when no account is 
     1620 *                      specified, and when receiving incoming requests when the 
     1621 *                      request does not match any accounts. It is recommended 
     1622 *                      that default account is set to local/LAN account. 
     1623 * @param p_acc_id      Pointer to receive account ID of the new account. 
     1624 * 
     1625 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1626 */ 
     1627PJ_DECL(pj_status_t) pjsua_acc_add_local(pjsua_transport_id tid, 
     1628                                         pj_bool_t is_default, 
     1629                                         pjsua_acc_id *p_acc_id); 
     1630 
     1631/** 
     1632 * Delete account. 
     1633 * 
     1634 * @param acc_id        Id of the account to be deleted. 
     1635 * 
     1636 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1637 */ 
     1638PJ_DECL(pj_status_t) pjsua_acc_del(pjsua_acc_id acc_id); 
     1639 
     1640 
     1641/** 
     1642 * Modify account information. 
     1643 * 
     1644 * @param acc_id        Id of the account to be modified. 
     1645 * @param cfg           New account configuration. 
     1646 * 
     1647 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1648 */ 
     1649PJ_DECL(pj_status_t) pjsua_acc_modify(pjsua_acc_id acc_id, 
     1650                                      const pjsua_acc_config *cfg); 
     1651 
     1652 
     1653/** 
     1654 * Modify account's presence status to be advertised to remote/presence 
     1655 * subscribers. 
     1656 * 
     1657 * @param acc_id        The account ID. 
     1658 * @param is_online     True of false. 
     1659 * 
     1660 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1661 */ 
     1662PJ_DECL(pj_status_t) pjsua_acc_set_online_status(pjsua_acc_id acc_id, 
     1663                                                 pj_bool_t is_online); 
     1664 
     1665 
     1666/** 
     1667 * Update registration or perform unregistration.  
     1668 * 
     1669 * @param acc_id        The account ID. 
     1670 * @param renew         If renew argument is zero, this will start  
     1671 *                      unregistration process. 
     1672 * 
     1673 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1674 */ 
     1675PJ_DECL(pj_status_t) pjsua_acc_set_registration(pjsua_acc_id acc_id,  
     1676                                                pj_bool_t renew); 
     1677 
     1678 
     1679/** 
     1680 * Get account information. 
     1681 * 
     1682 * @param acc_id        Account identification. 
     1683 * @param info          Pointer to receive account information. 
     1684 * 
     1685 * @return              PJ_SUCCESS on success, or the appropriate error code. 
    6251686 */ 
    6261687PJ_DECL(pj_status_t) pjsua_acc_get_info(pjsua_acc_id acc_id, 
     
    6291690 
    6301691/** 
    631  * Enum accounts id. 
    632  */ 
    633 PJ_DECL(pj_status_t) pjsua_acc_enum_id( pjsua_acc_id ids[], 
    634                                         unsigned *count ); 
     1692 * Enum accounts all account ids. 
     1693 * 
     1694 * @param ids           Array of account IDs to be initialized. 
     1695 * @param count         In input, specifies the maximum number of elements. 
     1696 *                      On return, it contains the actual number of elements. 
     1697 * 
     1698 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1699 */ 
     1700PJ_DECL(pj_status_t) pjsua_enum_accs(pjsua_acc_id ids[], 
     1701                                     unsigned *count ); 
    6351702 
    6361703 
    6371704/** 
    6381705 * Enum accounts info. 
     1706 * 
     1707 * @param info          Array of account infos to be initialized. 
     1708 * @param count         In input, specifies the maximum number of elements. 
     1709 *                      On return, it contains the actual number of elements. 
     1710 * 
     1711 * @return              PJ_SUCCESS on success, or the appropriate error code. 
    6391712 */ 
    6401713PJ_DECL(pj_status_t) pjsua_acc_enum_info( pjsua_acc_info info[], 
     
    6431716 
    6441717/** 
    645  * Find account for outgoing request. 
     1718 * This is an internal function to find the most appropriate account to 
     1719 * used to reach to the specified URL. 
     1720 * 
     1721 * @param url           The remote URL to reach. 
     1722 * 
     1723 * @return              Account id. 
    6461724 */ 
    6471725PJ_DECL(pjsua_acc_id) pjsua_acc_find_for_outgoing(const pj_str_t *url); 
    6481726 
    649 /** 
    650  * Find account for incoming request. 
     1727 
     1728/** 
     1729 * This is an internal function to find the most appropriate account to be 
     1730 * used to handle incoming calls. 
     1731 * 
     1732 * @param rdata         The incoming request message. 
     1733 * 
     1734 * @return              Account id. 
    6511735 */ 
    6521736PJ_DECL(pjsua_acc_id) pjsua_acc_find_for_incoming(pjsip_rx_data *rdata); 
    653  
    654 /** 
    655  * Add a new account. 
    656  * This function should be called after pjsua_init(). 
    657  * Application should call pjsua_acc_set_registration() to start  
    658  * registration for this account. 
    659  */ 
    660 PJ_DECL(pj_status_t) pjsua_acc_add(const pjsua_acc_config *cfg, 
    661                                    pjsua_acc_id *acc_id); 
    662  
    663 /** 
    664  * Delete account. 
    665  */ 
    666 PJ_DECL(pj_status_t) pjsua_acc_del(pjsua_acc_id acc_id); 
    667  
    668  
    669 /** 
    670  * Set account's presence status. 
    671  */ 
    672 PJ_DECL(pj_status_t) pjsua_acc_set_online_status(pjsua_acc_id acc_id, 
    673                                                  pj_bool_t is_online); 
    674  
    675  
    676 /** 
    677  * Update registration or perform unregistration. If renew argument is zero, 
    678  * this will start unregistration process. 
    679  */ 
    680 PJ_DECL(pj_status_t) pjsua_acc_set_registration(pjsua_acc_id acc_id,  
    681                                                 pj_bool_t renew); 
    682  
    6831737 
    6841738 
     
    6891743 
    6901744/** 
    691  * Get buddy count. 
     1745 * Get total number of buddies. 
     1746 * 
     1747 * @return              Number of buddies. 
    6921748 */ 
    6931749PJ_DECL(unsigned) pjsua_get_buddy_count(void); 
     
    6951751 
    6961752/** 
    697  * Get buddy info. 
    698  */ 
    699 PJ_DECL(pj_status_t) pjsua_buddy_get_info(pjsua_buddy_id buddy_index, 
     1753 * Check if buddy ID is valid. 
     1754 * 
     1755 * @param buddy_id      Buddy ID to check. 
     1756 * 
     1757 * @return              Non-zero if buddy ID is valid. 
     1758 */ 
     1759PJ_DECL(pj_bool_t) pjsua_buddy_is_valid(pjsua_buddy_id buddy_id); 
     1760 
     1761 
     1762/** 
     1763 * Enum buddy IDs. 
     1764 * 
     1765 * @param ids           Array of ids to be initialized. 
     1766 * @param count         On input, specifies max elements in the array. 
     1767 *                      On return, it contains actual number of elements 
     1768 *                      that have been initialized. 
     1769 * 
     1770 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1771 */ 
     1772PJ_DECL(pj_status_t) pjsua_enum_buddies(pjsua_buddy_id ids[], 
     1773                                        unsigned *count); 
     1774 
     1775/** 
     1776 * Get detailed buddy info. 
     1777 * 
     1778 * @param buddy_id      The buddy identification. 
     1779 * @param info          Pointer to receive information about buddy. 
     1780 * 
     1781 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1782 */ 
     1783PJ_DECL(pj_status_t) pjsua_buddy_get_info(pjsua_buddy_id buddy_id, 
    7001784                                          pjsua_buddy_info *info); 
    7011785 
    7021786/** 
    7031787 * Add new buddy. 
    704  */ 
    705 PJ_DECL(pj_status_t) pjsua_buddy_add(const pj_str_t *uri, 
    706                                      pjsua_buddy_id *buddy_index); 
     1788 * 
     1789 * @param cfg           Buddy configuration. 
     1790 * @param p_buddy_id    Pointer to receive buddy ID. 
     1791 * 
     1792 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1793 */ 
     1794PJ_DECL(pj_status_t) pjsua_buddy_add(const pjsua_buddy_config *cfg, 
     1795                                     pjsua_buddy_id *p_buddy_id); 
    7071796 
    7081797 
    7091798/** 
    7101799 * Delete buddy. 
    711  */ 
    712 PJ_DECL(pj_status_t) pjsua_buddy_del(pjsua_buddy_id buddy_index); 
     1800 * 
     1801 * @param buddy_id      Buddy identification. 
     1802 * 
     1803 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1804 */ 
     1805PJ_DECL(pj_status_t) pjsua_buddy_del(pjsua_buddy_id buddy_id); 
    7131806 
    7141807 
    7151808/** 
    7161809 * Enable/disable buddy's presence monitoring. 
    717  */ 
    718 PJ_DECL(pj_status_t) pjsua_buddy_subscribe_pres(pjsua_buddy_id buddy_index, 
    719                                                 pj_bool_t monitor); 
    720  
    721  
    722 /** 
    723  * Dump presence subscriptions. 
    724  */ 
    725 PJ_DECL(void) pjsua_pres_dump(pj_bool_t detail); 
     1810 * 
     1811 * @param buddy_id      Buddy identification. 
     1812 * @param subscribe     Specify non-zero to activate presence subscription to 
     1813 *                      the specified buddy. 
     1814 * 
     1815 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1816 */ 
     1817PJ_DECL(pj_status_t) pjsua_buddy_subscribe_pres(pjsua_buddy_id buddy_id, 
     1818                                                pj_bool_t subscribe); 
     1819 
     1820 
     1821/** 
     1822 * Dump presence subscriptions to log file. 
     1823 * 
     1824 * @param verbose       Yes or no. 
     1825 */ 
     1826PJ_DECL(void) pjsua_pres_dump(pj_bool_t verbose); 
    7261827 
    7271828 
     
    7381839 
    7391840/** 
    740  * Send IM outside dialog. 
    741  */ 
    742 PJ_DECL(pj_status_t) pjsua_im_send(int acc_id, const pj_str_t *dst_uri,  
    743                                    const pj_str_t *text); 
     1841 * Send instant messaging outside dialog, using the specified account for 
     1842 * route set and authentication. 
     1843 * 
     1844 * @param acc_id        Account ID to be used to send the request. 
     1845 * @param to            Remote URI. 
     1846 * @param mime_type     Optional MIME type. If NULL, then "text/plain" is  
     1847 *                      assumed. 
     1848 * @param content       The message content. 
     1849 * @param msg_data      Optional list of headers etc to be included in outgoing 
     1850 *                      request. The body descriptor in the msg_data is  
     1851 *                      ignored. 
     1852 * @param user_data     Optional user data, which will be given back when 
     1853 *                      the IM callback is called. 
     1854 * 
     1855 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1856 */ 
     1857PJ_DECL(pj_status_t) pjsua_im_send(pjsua_acc_id acc_id,  
     1858                                   const pj_str_t *to, 
     1859                                   const pj_str_t *mime_type, 
     1860                                   const pj_str_t *content, 
     1861                                   const pjsua_msg_data *msg_data, 
     1862                                   void *user_data); 
    7441863 
    7451864 
    7461865/** 
    7471866 * Send typing indication outside dialog. 
    748  */ 
    749 PJ_DECL(pj_status_t) pjsua_im_typing(int acc_id, const pj_str_t *dst_uri,  
    750                                      pj_bool_t is_typing); 
     1867 * 
     1868 * @param acc_id        Account ID to be used to send the request. 
     1869 * @param to            Remote URI. 
     1870 * @param is_typing     If non-zero, it tells remote person that local person 
     1871 *                      is currently composing an IM. 
     1872 * @param msg_data      Optional list of headers etc to be added to outgoing 
     1873 *                      request. 
     1874 * 
     1875 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1876 */ 
     1877PJ_DECL(pj_status_t) pjsua_im_typing(pjsua_acc_id acc_id,  
     1878                                     const pj_str_t *to,  
     1879                                     pj_bool_t is_typing, 
     1880                                     const pjsua_msg_data *msg_data); 
    7511881 
    7521882 
    7531883 
    7541884/***************************************************************************** 
    755  * Media. 
     1885 * Conference bridge manipulation. 
    7561886 */ 
    7571887 
    7581888/** 
    7591889 * Get maxinum number of conference ports. 
    760  */ 
    761 PJ_DECL(unsigned) pjsua_conf_max_ports(void); 
    762  
    763  
    764 /** 
    765  * Enum all conference ports. 
    766  */ 
    767 PJ_DECL(pj_status_t) pjsua_conf_enum_port_ids(pjsua_conf_port_id id[], 
    768                                               unsigned *count); 
     1890 * 
     1891 * @return              Maximum number of ports in the conference bridge. 
     1892 */ 
     1893PJ_DECL(unsigned) pjsua_conf_get_max_ports(void); 
     1894 
     1895 
     1896/** 
     1897 * Get current number of active ports in the bridge. 
     1898 * 
     1899 * @return              The number. 
     1900 */ 
     1901PJ_DECL(unsigned) pjsua_conf_get_active_ports(void); 
     1902 
     1903 
     1904/** 
     1905 * Enumerate all conference ports. 
     1906 * 
     1907 * @param id            Array of conference port ID to be initialized. 
     1908 * @param count         On input, specifies max elements in the array. 
     1909 *                      On return, it contains actual number of elements 
     1910 *                      that have been initialized. 
     1911 * 
     1912 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1913 */ 
     1914PJ_DECL(pj_status_t) pjsua_enum_conf_ports(pjsua_conf_port_id id[], 
     1915                                           unsigned *count); 
    7691916 
    7701917 
    7711918/** 
    7721919 * Get information about the specified conference port 
     1920 * 
     1921 * @param id            Port identification. 
     1922 * @param info          Pointer to store the port info. 
     1923 * 
     1924 * @return              PJ_SUCCESS on success, or the appropriate error code. 
    7731925 */ 
    7741926PJ_DECL(pj_status_t) pjsua_conf_get_port_info( pjsua_conf_port_id id, 
     
    7771929 
    7781930/** 
    779  * Connect conference port. 
    780  */ 
    781 PJ_DECL(pj_status_t) pjsua_conf_connect(pjsua_conf_port_id src_port, 
    782                                         pjsua_conf_port_id dst_port); 
    783  
    784  
    785 /** 
    786  * Connect conference port connection. 
    787  */ 
    788 PJ_DECL(pj_status_t) pjsua_conf_disconnect(pjsua_conf_port_id src_port, 
    789                                            pjsua_conf_port_id dst_port); 
    790  
    791  
    792 /** 
    793  * Create a file player. 
     1931 * Establish unidirectional media flow from souce to sink. One source 
     1932 * may transmit to multiple destinations/sink. And if multiple 
     1933 * sources are transmitting to the same sink, the media will be mixed 
     1934 * together. Source and sink may refer to the same ID, effectively 
     1935 * looping the media. 
     1936 * 
     1937 * If bidirectional media flow is desired, application needs to call 
     1938 * this function twice, with the second one having the arguments 
     1939 * reversed. 
     1940 * 
     1941 * @param source        Port ID of the source media/transmitter. 
     1942 * @param sink          Port ID of the destination media/received. 
     1943 * 
     1944 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1945 */ 
     1946PJ_DECL(pj_status_t) pjsua_conf_connect(pjsua_conf_port_id source, 
     1947                                        pjsua_conf_port_id sink); 
     1948 
     1949 
     1950/** 
     1951 * Disconnect media flow from the source to destination port. 
     1952 * 
     1953 * @param source        Port ID of the source media/transmitter. 
     1954 * @param sink          Port ID of the destination media/received. 
     1955 * 
     1956 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     1957 */ 
     1958PJ_DECL(pj_status_t) pjsua_conf_disconnect(pjsua_conf_port_id source, 
     1959                                           pjsua_conf_port_id sink); 
     1960 
     1961 
     1962/***************************************************************************** 
     1963 * File player. 
     1964 */ 
     1965 
     1966/** 
     1967 * Create a file player, and automatically connect this player to 
     1968 * the conference bridge. 
     1969 * 
     1970 * @param filename      The filename to be played. Currently only 
     1971 *                      WAV files are supported. 
     1972 * @param options       Options (currently zero). 
     1973 * @param user_data     Arbitrary user data to be associated with the player. 
     1974 * @param p_id          Pointer to receive player ID. 
     1975 * 
     1976 * @return              PJ_SUCCESS on success, or the appropriate error code. 
    7941977 */ 
    7951978PJ_DECL(pj_status_t) pjsua_player_create(const pj_str_t *filename, 
    796                                          pjsua_player_id *id); 
    797  
    798  
    799 /** 
    800  * Get conference port associated with player. 
     1979                                         unsigned options, 
     1980                                         void *user_data, 
     1981                                         pjsua_player_id *p_id); 
     1982 
     1983 
     1984/** 
     1985 * Get conference port ID associated with player. 
     1986 * 
     1987 * @param id            The file player ID. 
     1988 * 
     1989 * @return              Conference port ID associated with this player. 
    8011990 */ 
    8021991PJ_DECL(pjsua_conf_port_id) pjsua_player_get_conf_port(pjsua_player_id id); 
     
    8051994/** 
    8061995 * Set playback position. 
     1996 * 
     1997 * @param id            The file player ID. 
     1998 * @param samples       The playback position, in samples. Application can 
     1999 *                      specify zero to re-start the playback. 
     2000 * 
     2001 * @return              PJ_SUCCESS on success, or the appropriate error code. 
    8072002 */ 
    8082003PJ_DECL(pj_status_t) pjsua_player_set_pos(pjsua_player_id id, 
     
    8112006 
    8122007/** 
    813  * Destroy player. 
     2008 * Close the file, remove the player from the bridge, and free 
     2009 * resources associated with the file player. 
     2010 * 
     2011 * @param id            The file player ID. 
     2012 * 
     2013 * @return              PJ_SUCCESS on success, or the appropriate error code. 
    8142014 */ 
    8152015PJ_DECL(pj_status_t) pjsua_player_destroy(pjsua_player_id id); 
    8162016 
    8172017 
    818  
    819 /** 
    820  * Create a file recorder. 
     2018/***************************************************************************** 
     2019 * File recorder. 
     2020 */ 
     2021 
     2022/** 
     2023 * Create a file recorder, and automatically connect this recorder to 
     2024 * the conference bridge. 
     2025 * 
     2026 * @param filename      Output file name. 
     2027 * @param file_format   Specify the file format (currently only WAV is 
     2028 *                      supported, so the value MUST be zero). 
     2029 * @param encoding      Specify the encoding to be applied to the file. 
     2030 *                      Currently only 16bit raw PCM is supported, so 
     2031 *                      the value must be NULL. 
     2032 * @param max_size      Maximum file size. Specify -1 to remove size 
     2033 *                      limitation. 
     2034 * @param options       Optional options. 
     2035 * @param user_data     Arbitrary user data which will be given in the  
     2036 *                      callback once the recording complete. 
     2037 * @param p_id          Pointer to receive the recorder instance. 
     2038 * 
     2039 * @return              PJ_SUCCESS on success, or the appropriate error code. 
    8212040 */ 
    8222041PJ_DECL(pj_status_t) pjsua_recorder_create(const pj_str_t *filename, 
    823                                            pjsua_recorder_id *id); 
     2042                                           unsigned file_format, 
     2043                                           const pj_str_t *encoding, 
     2044                                           pj_ssize_t max_size, 
     2045                                           unsigned options, 
     2046                                           void *user_data, 
     2047                                           pjsua_recorder_id *p_id); 
    8242048 
    8252049 
    8262050/** 
    8272051 * Get conference port associated with recorder. 
     2052 * 
     2053 * @param id            The recorder ID. 
     2054 * 
     2055 * @return              Conference port ID associated with this recorder. 
    8282056 */ 
    8292057PJ_DECL(pjsua_conf_port_id) pjsua_recorder_get_conf_port(pjsua_recorder_id id); 
     
    8312059 
    8322060/** 
    833  * Destroy recorder (will complete recording). 
     2061 * Destroy recorder (this will complete recording). 
     2062 * 
     2063 * @param id            The recorder ID. 
     2064 * 
     2065 * @return              PJ_SUCCESS on success, or the appropriate error code. 
    8342066 */ 
    8352067PJ_DECL(pj_status_t) pjsua_recorder_destroy(pjsua_recorder_id id); 
    8362068 
    8372069 
     2070/***************************************************************************** 
     2071 * Sound devices. 
     2072 */ 
     2073 
    8382074/** 
    8392075 * Enum sound devices. 
    840  */ 
    841 PJ_DECL(pj_status_t) pjsua_enum_snd_devices(unsigned *count, 
    842                                             pjmedia_snd_dev_info info[]); 
    843  
    844  
    845 /** 
    846  * Select or change sound device. 
    847  * This will only change the device ID in configuration (not changing 
    848  * the current device). 
    849  */ 
    850 PJ_DECL(pj_status_t) pjsua_set_snd_dev(int snd_capture_id, 
    851                                        int snd_player_id); 
     2076 * 
     2077 * @param info          Array of info to be initialized. 
     2078 * @param count         On input, specifies max elements in the array. 
     2079 *                      On return, it contains actual number of elements 
     2080 *                      that have been initialized. 
     2081 * 
     2082 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     2083 */ 
     2084PJ_DECL(pj_status_t) pjsua_enum_snd_devs(pjmedia_snd_dev_info info[], 
     2085                                         unsigned *count); 
     2086 
     2087 
     2088/** 
     2089 * Select or change sound device. Application may call this function at 
     2090 * any time to replace current sound device. 
     2091 * 
     2092 * @param capture_dev   Device ID of the capture device. 
     2093 * @param playback_dev  Device ID of the playback device. 
     2094 * 
     2095 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     2096 */ 
     2097PJ_DECL(pj_status_t) pjsua_set_snd_dev(int capture_dev, 
     2098                                       int playback_dev); 
     2099 
     2100 
     2101/** 
     2102 * Set pjsua to use null sound device. The null sound device only provides 
     2103 * the timing needed by the conference bridge, and will not interract with 
     2104 * any hardware. 
     2105 * 
     2106 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     2107 */ 
     2108PJ_DECL(pj_status_t) pjsua_set_null_snd_dev(void); 
     2109 
     2110 
     2111/***************************************************************************** 
     2112 * Codecs. 
     2113 */ 
     2114 
     2115/** 
     2116 * Enum all supported codecs in the system. 
     2117 * 
     2118 * @param id            Array of ID to be initialized. 
     2119 * @param count         On input, specifies max elements in the array. 
     2120 *                      On return, it contains actual number of elements 
     2121 *                      that have been initialized. 
     2122 * 
     2123 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     2124 */ 
     2125PJ_DECL(pj_status_t) pjsua_enum_codecs( pjsua_codec_info id[], 
     2126                                        unsigned *count ); 
     2127 
     2128 
     2129/** 
     2130 * Change codec priority. 
     2131 * 
     2132 * @param id            Codec ID. 
     2133 * @param priority      Codec priority, 0-255, where zero means to disable 
     2134 *                      the codec. 
     2135 * 
     2136 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     2137 */ 
     2138PJ_DECL(pj_status_t) pjsua_codec_set_priority( const pj_str_t *id, 
     2139                                               pj_uint8_t priority ); 
     2140 
     2141 
     2142/** 
     2143 * Get codec parameters. 
     2144 * 
     2145 * @param id            Codec ID. 
     2146 * @param param         Structure to receive codec parameters. 
     2147 * 
     2148 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     2149 */ 
     2150PJ_DECL(pj_status_t) pjsua_codec_get_param( const pj_str_t *id, 
     2151                                            pjmedia_codec_param *param ); 
     2152 
     2153 
     2154/** 
     2155 * Set codec parameters. 
     2156 * 
     2157 * @param id            Codec ID. 
     2158 * @param param         Codec parameter to set. 
     2159 * 
     2160 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     2161 */ 
     2162PJ_DECL(pj_status_t) pjsua_codec_set_param( const pj_str_t *id, 
     2163                                            const pjmedia_codec_param *param); 
     2164 
     2165 
     2166 
    8522167 
    8532168 
     
    8572172 */ 
    8582173 
    859 /** String to describe invite session states */ 
    860 extern const char *pjsua_inv_state_names[]; 
    861  
    862 /** 
    863  * Parse arguments (pjsua_opt.c). 
    864  */ 
    865 PJ_DECL(pj_status_t) pjsua_parse_args(int argc, char *argv[], 
    866                                       pjsua_config *cfg, 
    867                                       pj_str_t *uri_to_call); 
    868  
    869 /** 
    870  * Load settings from a file. 
    871  */ 
    872 PJ_DECL(pj_status_t) pjsua_load_settings(const char *filename, 
    873                                          pjsua_config *cfg, 
    874                                          pj_str_t *uri_to_call); 
    875  
    876 /** 
    877  * Get pjsua running config. 
    878  */ 
    879 PJ_DECL(void) pjsua_get_config(pj_pool_t *pool, 
    880                                pjsua_config *config); 
    881  
    882  
    883 /** 
    884  * Dump settings. 
    885  * If cfg is NULL, it will dump current settings. 
    886  */ 
    887 PJ_DECL(int) pjsua_dump_settings(const pjsua_config *cfg, 
    888                                  char *buf, pj_size_t max); 
    889  
    890 /** 
    891  * Save settings to a file. 
    892  */ 
    893 PJ_DECL(pj_status_t) pjsua_save_settings(const char *filename, 
    894                                          const pjsua_config *cfg); 
    895  
    896  
    8972174/* 
    8982175 * Verify that valid SIP url is given. 
    899  * @return  PJ_SUCCESS if valid. 
     2176 * 
     2177 * @param c_url         The URL, as NULL terminated string. 
     2178 * 
     2179 * @return              PJ_SUCCESS on success, or the appropriate error code. 
    9002180 */ 
    9012181PJ_DECL(pj_status_t) pjsua_verify_sip_url(const char *c_url); 
    9022182 
    903 /* 
    904  * Dump application states. 
    905  */ 
    906 PJ_DECL(void) pjsua_dump(pj_bool_t detail); 
    9072183 
    9082184/** 
    9092185 * Display error message for the specified error code. 
     2186 * 
     2187 * @param sender        The log sender field. 
     2188 * @param title         Message title for the error. 
     2189 * @param status        Status code. 
    9102190 */ 
    9112191PJ_DECL(void) pjsua_perror(const char *sender, const char *title,  
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c

    r492 r503  
    1818 */ 
    1919#include <pjsua-lib/pjsua.h> 
    20 #include <pj/log.h> 
    21 #include "pjsua_imp.h" 
    22  
    23 /* 
    24  * pjsua_call.c 
    25  * 
    26  * Call (INVITE) related stuffs. 
    27  */ 
    28  
    29 #define THIS_FILE   "pjsua_call.c" 
    30  
    31  
    32 #define REFRESH_CALL_TIMER      0x63 
    33 #define HANGUP_CALL_TIMER       0x64 
    34  
    35 /* Proto */ 
    36 static void schedule_call_timer( pjsua_call *call, pj_timer_entry *e, 
    37                                  int timer_type, int duration ); 
    38  
    39 /* 
    40  * Timer callback when UAS needs to send re-INVITE to see if remote 
    41  * is still there. 
    42  */ 
    43 static void call_on_timer(pj_timer_heap_t *ht, pj_timer_entry *e) 
    44 { 
    45     pjsua_call *call = e->user_data; 
    46  
    47     PJ_UNUSED_ARG(ht); 
    48  
    49     if (e->id == REFRESH_CALL_TIMER) { 
    50  
    51         /* If call is still not connected, hangup. */ 
    52         if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) { 
    53             PJ_LOG(3,(THIS_FILE, "Refresh call timer is called when " 
    54                       "invite is still not confirmed. Call %d will " 
    55                       "disconnect.", call->index)); 
    56             pjsua_call_hangup(call->index); 
    57         } else { 
    58             PJ_LOG(3,(THIS_FILE, "Refreshing call %d", call->index)); 
    59             schedule_call_timer(call,e,REFRESH_CALL_TIMER, 
    60                                 pjsua.config.uas_refresh); 
    61             pjsua_call_reinvite(call->index); 
    62         } 
    63  
    64     } else if (e->id == HANGUP_CALL_TIMER) { 
    65         PJ_LOG(3,(THIS_FILE, "Call %d duration exceeded, disconnecting call", 
    66                              call->index)); 
    67         pjsua_call_hangup(call->index); 
    68  
    69     } 
    70 } 
    71  
    72 /* 
    73  * Schedule call timer. 
    74  */ 
    75 static void schedule_call_timer( pjsua_call *call, pj_timer_entry *e, 
    76                                  int timer_type, int duration ) 
    77 { 
    78     pj_time_val timeout; 
    79  
    80     if (duration == 0) { 
    81         /* Cancel timer. */ 
    82         if (e->id != 0) { 
    83             pjsip_endpt_cancel_timer(pjsua.endpt, e); 
    84             e->id = 0; 
    85         } 
    86  
    87     } else { 
    88         /* Schedule timer. */ 
    89         timeout.sec = duration; 
    90         timeout.msec = 0; 
    91  
    92         e->cb = &call_on_timer; 
    93         e->id = timer_type; 
    94         e->user_data = call; 
    95  
    96         pjsip_endpt_schedule_timer( pjsua.endpt, e, &timeout); 
    97     } 
    98 } 
    99  
    100  
    101 /* 
    102  * Destroy the call's media 
    103  */ 
    104 static pj_status_t call_destroy_media(int call_index) 
    105 { 
    106     pjsua_call *call = &pjsua.calls[call_index]; 
    107  
    108     if (call->conf_slot > 0) { 
    109         pjmedia_conf_remove_port(pjsua.mconf, call->conf_slot); 
    110         call->conf_slot = 0; 
    111     } 
    112  
    113     if (call->session) { 
    114         /* Destroy session (this will also close RTP/RTCP sockets). */ 
    115         pjmedia_session_destroy(call->session); 
    116         call->session = NULL; 
    117  
    118         PJ_LOG(3,(THIS_FILE, "Media session for call %d is destroyed",  
    119                              call_index)); 
    120  
    121     } 
    122  
     20#include <pjsua-lib/pjsua_internal.h> 
     21 
     22 
     23#define THIS_FILE               "pjsua_call.c" 
     24 
     25 
     26/* This callback receives notification from invite session when the 
     27 * session state has changed. 
     28 */ 
     29static void pjsua_call_on_state_changed(pjsip_inv_session *inv,  
     30                                        pjsip_event *e); 
     31 
     32/* This callback is called by invite session framework when UAC session 
     33 * has forked. 
     34 */ 
     35static void pjsua_call_on_forked( pjsip_inv_session *inv,  
     36                                  pjsip_event *e); 
     37 
     38/* 
     39 * Callback to be called when SDP offer/answer negotiation has just completed 
     40 * in the session. This function will start/update media if negotiation 
     41 * has succeeded. 
     42 */ 
     43static void pjsua_call_on_media_update(pjsip_inv_session *inv, 
     44                                       pj_status_t status); 
     45 
     46/* 
     47 * Called when session received new offer. 
     48 */ 
     49static void pjsua_call_on_rx_offer(pjsip_inv_session *inv, 
     50                                   const pjmedia_sdp_session *offer); 
     51 
     52/* 
     53 * This callback is called when transaction state has changed in INVITE 
     54 * session. We use this to trap: 
     55 *  - incoming REFER request. 
     56 *  - incoming MESSAGE request. 
     57 */ 
     58static void pjsua_call_on_tsx_state_changed(pjsip_inv_session *inv, 
     59                                            pjsip_transaction *tsx, 
     60                                            pjsip_event *e); 
     61 
     62 
     63/* Destroy the call's media */ 
     64static pj_status_t call_destroy_media(int call_id); 
     65 
     66/* Create inactive SDP for call hold. */ 
     67static pj_status_t create_inactive_sdp(pjsua_call *call, 
     68                                       pjmedia_sdp_session **p_answer); 
     69 
     70 
     71/* 
     72 * Reset call descriptor. 
     73 */ 
     74static void reset_call(pjsua_call_id id) 
     75{ 
     76    pjsua_call *call = &pjsua_var.calls[id]; 
     77 
     78    call->index = id; 
     79    call->inv = NULL; 
     80    call->user_data = NULL; 
     81    call->session = NULL; 
     82    call->xfer_sub = NULL; 
     83    call->last_code = 0; 
     84    call->conf_slot = PJSUA_INVALID_ID; 
     85    call->last_text.ptr = call->last_text_buf_; 
     86    call->last_text.slen = 0; 
     87} 
     88 
     89 
     90/* 
     91 * Init call subsystem. 
     92 */ 
     93pj_status_t pjsua_call_subsys_init(const pjsua_config *cfg) 
     94{ 
     95    pjsip_inv_callback inv_cb; 
     96    unsigned i; 
     97    pj_status_t status; 
     98 
     99    /* Init calls array. */ 
     100    for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.calls); ++i) 
     101        reset_call(i); 
     102 
     103    /* Copy config */ 
     104    pjsua_config_dup(pjsua_var.pool, &pjsua_var.ua_cfg, cfg); 
     105 
     106    /* Initialize invite session callback. */ 
     107    pj_memset(&inv_cb, 0, sizeof(inv_cb)); 
     108    inv_cb.on_state_changed = &pjsua_call_on_state_changed; 
     109    inv_cb.on_new_session = &pjsua_call_on_forked; 
     110    inv_cb.on_media_update = &pjsua_call_on_media_update; 
     111    inv_cb.on_rx_offer = &pjsua_call_on_rx_offer; 
     112    inv_cb.on_tsx_state_changed = &pjsua_call_on_tsx_state_changed; 
     113 
     114 
     115    /* Initialize invite session module: */ 
     116    status = pjsip_inv_usage_init(pjsua_var.endpt, &inv_cb); 
     117    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 
     118 
     119    return status; 
     120} 
     121 
     122 
     123/* 
     124 * Start call subsystem. 
     125 */ 
     126pj_status_t pjsua_call_subsys_start(void) 
     127{ 
     128    /* Nothing to do */ 
    123129    return PJ_SUCCESS; 
    124130} 
    125131 
    126132 
    127 /** 
     133/* 
    128134 * Get maximum number of calls configured in pjsua. 
    129135 */ 
    130136PJ_DEF(unsigned) pjsua_call_get_max_count(void) 
    131137{ 
    132     return pjsua.config.max_calls; 
    133 } 
    134  
    135  
    136 /** 
    137  * Get current number of active calls. 
     138    return pjsua_var.ua_cfg.max_calls; 
     139} 
     140 
     141 
     142/* 
     143 * Get number of currently active calls. 
    138144 */ 
    139145PJ_DEF(unsigned) pjsua_call_get_count(void) 
    140146{ 
    141     return pjsua.call_cnt; 
    142 } 
    143  
    144  
    145 /** 
    146  * Check if the specified call is active. 
    147  */ 
    148 PJ_DEF(pj_bool_t) pjsua_call_is_active(unsigned call_index) 
    149 { 
    150     PJ_ASSERT_RETURN(call_index < pjsua.config.max_calls, 
    151                      PJ_EINVAL); 
    152     return pjsua.calls[call_index].inv != NULL && 
    153            pjsua.calls[call_index].inv->state != PJSIP_INV_STATE_DISCONNECTED; 
    154 } 
    155  
    156 /** 
    157  * Check if call has a media session. 
    158  */ 
    159 PJ_DEF(pj_bool_t) pjsua_call_has_media(unsigned call_index) 
    160 { 
    161     PJ_ASSERT_RETURN(call_index < pjsua.config.max_calls, PJ_EINVAL); 
    162     return pjsua.calls[call_index].session != NULL; 
    163 } 
    164  
    165  
    166 /** 
    167  * Get call info. 
    168  */ 
    169 PJ_DEF(pj_status_t) pjsua_call_get_info( unsigned call_index, 
    170                                          pjsua_call_info *info) 
    171 { 
    172     pjsua_call *call; 
    173  
    174     PJ_ASSERT_RETURN(call_index < pjsua.config.max_calls, 
    175                      PJ_EINVAL); 
    176  
    177     pj_memset(info, 0, sizeof(pjsua_call_info)); 
    178  
    179     call = &pjsua.calls[call_index]; 
    180     info->active = pjsua_call_is_active(call_index); 
    181  
    182     if (call->inv == NULL) 
    183         return PJ_SUCCESS; 
    184  
    185     info->index = call_index; 
    186     info->role = call->inv->role; 
    187     info->local_info = call->inv->dlg->local.info_str; 
    188     info->remote_info = call->inv->dlg->remote.info_str; 
    189     info->state = call->inv->state; 
    190     info->state_text = pj_str((char*)pjsip_inv_state_name(info->state)); 
    191      
    192     if (info->state >= PJSIP_INV_STATE_DISCONNECTED) { 
    193  
    194         info->total_duration = call->dis_time; 
    195         PJ_TIME_VAL_SUB(info->total_duration, call->start_time); 
    196  
    197         if (call->conn_time.sec) { 
    198             info->connect_duration = call->dis_time; 
    199             PJ_TIME_VAL_SUB(info->total_duration, call->conn_time); 
    200         } 
    201  
    202     } else if (info->state == PJSIP_INV_STATE_CONFIRMED) { 
    203  
    204         pj_gettimeofday(&info->total_duration); 
    205         PJ_TIME_VAL_SUB(info->total_duration, call->start_time); 
    206  
    207         pj_gettimeofday(&info->connect_duration); 
    208         PJ_TIME_VAL_SUB(info->connect_duration, call->conn_time); 
    209  
    210     } else { 
    211         pj_gettimeofday(&info->total_duration); 
    212         PJ_TIME_VAL_SUB(info->total_duration, call->start_time); 
    213     } 
    214  
    215     info->last_status = call->last_code; 
    216     info->last_status_text = *pjsip_get_status_text(info->last_status); 
    217  
    218     info->has_media = (call->session != NULL); 
    219     info->conf_slot = call->conf_slot; 
     147    return pjsua_var.call_cnt; 
     148} 
     149 
     150 
     151/* 
     152 * Enum calls. 
     153 */ 
     154PJ_DEF(pj_status_t) pjsua_enum_calls( pjsua_call_id ids[], 
     155                                      unsigned *count) 
     156{ 
     157    unsigned i, c; 
     158 
     159    PJ_ASSERT_RETURN(ids && *count, PJ_EINVAL); 
     160 
     161    PJSUA_LOCK(); 
     162 
     163    for (i=0, c=0; c<*count && i<pjsua_var.ua_cfg.max_calls; ++i) { 
     164        if (!pjsua_var.calls[i].inv) 
     165            continue; 
     166        ids[c] = i; 
     167        ++c; 
     168    } 
     169 
     170    *count = c; 
     171 
     172    PJSUA_UNLOCK(); 
    220173 
    221174    return PJ_SUCCESS; 
     
    223176 
    224177 
    225 /** 
    226  * Duplicate call info. 
    227  */ 
    228 PJ_DEF(void) pjsua_call_info_dup( pj_pool_t *pool, 
    229                                   pjsua_call_info *dst_info, 
    230                                   const pjsua_call_info *src_info) 
    231 { 
    232     PJ_ASSERT_ON_FAIL(pool && dst_info && src_info, return); 
    233  
    234     pj_memcpy(dst_info, src_info, sizeof(pjsua_call_info)); 
    235  
    236     pj_strdup(pool, &dst_info->local_info, &src_info->local_info); 
    237     pj_strdup(pool, &dst_info->remote_info, &src_info->remote_info); 
    238      
    239     /* state_text and cause_text belong to pjsip, so don't need to be 
    240      * duplicated because they'll always be available. 
    241      */ 
    242 } 
    243  
    244  
    245 /** 
    246  * Make outgoing call. 
    247  */ 
    248 PJ_DEF(pj_status_t) pjsua_call_make_call(unsigned acc_index, 
    249                                          const pj_str_t *dest_uri, 
    250                                          int *p_call_index) 
     178/* 
     179 * Make outgoing call to the specified URI using the specified account. 
     180 */ 
     181PJ_DEF(pj_status_t) pjsua_call_make_call( pjsua_acc_id acc_id, 
     182                                          const pj_str_t *dest_uri, 
     183                                          unsigned options, 
     184                                          void *user_data, 
     185                                          const pjsua_msg_data *msg_data, 
     186                                          pjsua_call_id *p_call_id) 
    251187{ 
    252188    pjsip_dialog *dlg = NULL; 
    253189    pjmedia_sdp_session *offer; 
    254190    pjsip_inv_session *inv = NULL; 
    255     unsigned call_index; 
     191    pjsua_acc *acc; 
     192    pjsua_call *call; 
     193    unsigned call_id; 
    256194    pjsip_tx_data *tdata; 
    257195    pj_status_t status; 
    258196 
    259197 
    260     PJ_ASSERT_RETURN(acc_index==0 || acc_index < pjsua.config.acc_cnt,  
     198    /* Check that account is valid */ 
     199    PJ_ASSERT_RETURN(acc_id>=0 || acc_id<PJ_ARRAY_SIZE(pjsua_var.acc),  
    261200                     PJ_EINVAL); 
    262201 
     202    /* Options must be zero for now */ 
     203    PJ_ASSERT_RETURN(options == 0, PJ_EINVAL); 
     204 
     205    PJSUA_LOCK(); 
     206 
     207    acc = &pjsua_var.acc[acc_id]; 
     208    if (!acc->valid) { 
     209        pjsua_perror(THIS_FILE, "Unable to make call because account " 
     210                     "is not valid", PJ_EINVALIDOP); 
     211        PJSUA_UNLOCK(); 
     212        return PJ_EINVALIDOP; 
     213    } 
    263214 
    264215    /* Find free call slot. */ 
    265     for (call_index=0; call_index<pjsua.config.max_calls; ++call_index) { 
    266         if (pjsua.calls[call_index].inv == NULL) 
     216    for (call_id=0; call_id<pjsua_var.ua_cfg.max_calls; ++call_id) { 
     217        if (pjsua_var.calls[call_id].inv == NULL) 
    267218            break; 
    268219    } 
    269220 
    270     if (call_index == pjsua.config.max_calls) { 
    271         PJ_LOG(3,(THIS_FILE, "Error: too many calls!")); 
     221    if (call_id == pjsua_var.ua_cfg.max_calls) { 
     222        pjsua_perror(THIS_FILE, "Error making file", PJ_ETOOMANY); 
     223        PJSUA_UNLOCK(); 
    272224        return PJ_ETOOMANY; 
    273225    } 
    274226 
     227    call = &pjsua_var.calls[call_id]; 
     228 
    275229    /* Mark call start time. */ 
    276     pj_gettimeofday(&pjsua.calls[call_index].start_time); 
     230    pj_gettimeofday(&call->start_time); 
    277231 
    278232    /* Reset first response time */ 
    279     pjsua.calls[call_index].res_time.sec = 0; 
     233    call->res_time.sec = 0; 
    280234 
    281235    /* Create outgoing dialog: */ 
    282236    status = pjsip_dlg_create_uac( pjsip_ua_instance(),  
    283                                    &pjsua.config.acc_config[acc_index].id, 
    284                                    &pjsua.config.acc_config[acc_index].contact, 
    285                                    dest_uri, dest_uri, 
    286                                    &dlg); 
     237                                   &acc->cfg.id, &acc->cfg.contact, 
     238                                   dest_uri, dest_uri, &dlg); 
    287239    if (status != PJ_SUCCESS) { 
    288240        pjsua_perror(THIS_FILE, "Dialog creation failed", status); 
     241        PJSUA_UNLOCK(); 
    289242        return status; 
    290243    } 
     
    292245    /* Get media capability from media endpoint: */ 
    293246 
    294     status = pjmedia_endpt_create_sdp( pjsua.med_endpt, dlg->pool, 1,  
    295                                        &pjsua.calls[call_index].skinfo,  
    296                                        &offer); 
     247    status = pjmedia_endpt_create_sdp( pjsua_var.med_endpt, dlg->pool, 1,  
     248                                       &call->skinfo, &offer); 
    297249    if (status != PJ_SUCCESS) { 
    298250        pjsua_perror(THIS_FILE, "pjmedia unable to create SDP", status); 
     
    311263    /* Create and associate our data in the session. */ 
    312264 
    313     pjsua.calls[call_index].inv = inv; 
    314  
    315     dlg->mod_data[pjsua.mod.id] = &pjsua.calls[call_index]; 
    316     inv->mod_data[pjsua.mod.id] = &pjsua.calls[call_index]; 
    317  
     265    call->inv = inv; 
     266 
     267    dlg->mod_data[pjsua_var.mod.id] = call; 
     268    inv->mod_data[pjsua_var.mod.id] = call; 
     269 
     270    /* Attach user data */ 
     271    call->user_data = user_data; 
    318272 
    319273    /* Set dialog Route-Set: */ 
    320  
    321     if (!pj_list_empty(&pjsua.acc[acc_index].route_set)) 
    322         pjsip_dlg_set_route_set(dlg, &pjsua.acc[acc_index].route_set); 
     274    if (!pj_list_empty(&acc->route_set)) 
     275        pjsip_dlg_set_route_set(dlg, &acc->route_set); 
    323276 
    324277 
    325278    /* Set credentials: */ 
    326     if (pjsua.config.acc_config[acc_index].cred_count) { 
    327         pjsua_acc_config *acc_cfg = &pjsua.config.acc_config[acc_index]; 
     279    if (acc->cred_cnt) { 
    328280        pjsip_auth_clt_set_credentials( &dlg->auth_sess,  
    329                                         acc_cfg->cred_count, 
    330                                         acc_cfg->cred_info); 
     281                                        acc->cred_cnt, acc->cred); 
    331282    } 
    332283 
     
    341292    } 
    342293 
     294 
     295    /* Add additional headers etc */ 
     296 
     297    pjsua_process_msg_data( tdata, msg_data); 
    343298 
    344299    /* Send initial INVITE: */ 
     
    357312    } 
    358313 
    359  
    360314    /* Done. */ 
    361315 
    362     ++pjsua.call_cnt; 
    363  
    364     if (p_call_index) 
    365         *p_call_index = call_index; 
     316    ++pjsua_var.call_cnt; 
     317 
     318    if (p_call_id) 
     319        *p_call_id = call_id; 
     320 
     321    PJSUA_UNLOCK(); 
    366322 
    367323    return PJ_SUCCESS; 
     
    375331    } 
    376332 
    377     if (call_index != -1) { 
    378         pjsua.calls[call_index].inv = NULL; 
    379     } 
    380     return status; 
    381 } 
    382  
    383  
    384 /** 
    385  * Answer call. 
    386  */ 
    387 PJ_DEF(pj_status_t) pjsua_call_answer(int call_index, int code) 
    388 { 
    389     pjsip_tx_data *tdata; 
    390     pj_status_t status; 
    391  
    392     PJ_ASSERT_RETURN( call_index >= 0 &&  
    393                       call_index < (int)pjsua.config.max_calls, 
    394                       PJ_EINVAL); 
    395  
    396     if (pjsua.calls[call_index].inv == NULL) { 
    397         PJ_LOG(3,(THIS_FILE, "Call %d already disconnected")); 
    398         return PJSIP_ESESSIONTERMINATED; 
    399     } 
    400  
    401     status = pjsip_inv_answer(pjsua.calls[call_index].inv, 
    402                               code, NULL, NULL, &tdata); 
    403     if (status == PJ_SUCCESS) 
    404         status = pjsip_inv_send_msg(pjsua.calls[call_index].inv, 
    405                                     tdata); 
    406  
    407     if (status != PJ_SUCCESS) 
    408         pjsua_perror(THIS_FILE, "Unable to create/send response",  
    409                      status); 
    410  
     333    if (call_id != -1) { 
     334        reset_call(call_id); 
     335    } 
     336 
     337    PJSUA_UNLOCK(); 
    411338    return status; 
    412339} 
     
    415342/** 
    416343 * Handle incoming INVITE request. 
     344 * Called by pjsua_core.c 
    417345 */ 
    418346pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata) 
     
    424352    unsigned options = 0; 
    425353    pjsip_inv_session *inv = NULL; 
    426     int acc_index; 
    427     unsigned call_index; 
     354    int acc_id; 
     355    pjsua_call *call; 
     356    int call_id = -1; 
    428357    pjmedia_sdp_session *answer; 
    429358    pj_status_t status; 
     
    442371    /* Verify that we can handle the request. */ 
    443372    status = pjsip_inv_verify_request(rdata, &options, NULL, NULL, 
    444                                       pjsua.endpt, &response); 
     373                                      pjsua_var.endpt, &response); 
    445374    if (status != PJ_SUCCESS) { 
    446375 
     
    453382 
    454383            pjsip_get_response_addr(response->pool, rdata, &res_addr); 
    455             pjsip_endpt_send_response(pjsua.endpt, &res_addr, response,  
     384            pjsip_endpt_send_response(pjsua_var.endpt, &res_addr, response,  
    456385                                      NULL, NULL); 
    457386 
     
    459388 
    460389            /* Respond with 500 (Internal Server Error) */ 
    461             pjsip_endpt_respond_stateless(pjsua.endpt, rdata, 500, NULL, 
     390            pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL, 
    462391                                          NULL, NULL); 
    463392        } 
     
    472401 
    473402    /* Find free call slot. */ 
    474     for (call_index=0; call_index < pjsua.config.max_calls; ++call_index) { 
    475         if (pjsua.calls[call_index].inv == NULL) 
     403    for (call_id=0; call_id<(int)pjsua_var.ua_cfg.max_calls; ++call_id) { 
     404        if (pjsua_var.calls[call_id].inv == NULL) 
    476405            break; 
    477406    } 
    478407 
    479     if (call_index == PJSUA_MAX_CALLS) { 
    480         pjsip_endpt_respond_stateless(pjsua.endpt, rdata,  
     408    if (call_id == (int)pjsua_var.ua_cfg.max_calls) { 
     409        pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata,  
    481410                                      PJSIP_SC_BUSY_HERE, NULL, 
    482411                                      NULL, NULL); 
     
    484413    } 
    485414 
     415    /* Clear call descriptor */ 
     416    reset_call(call_id); 
     417 
     418    call = &pjsua_var.calls[call_id]; 
     419 
    486420    /* Mark call start time. */ 
    487     pj_gettimeofday(&pjsua.calls[call_index].start_time); 
    488  
    489     /* Reset first response time */ 
    490     pjsua.calls[call_index].res_time.sec = 0; 
     421    pj_gettimeofday(&call->start_time); 
    491422 
    492423    /* Get media capability from media endpoint: */ 
    493  
    494     status = pjmedia_endpt_create_sdp( pjsua.med_endpt, rdata->tp_info.pool, 1, 
    495                                        &pjsua.calls[call_index].skinfo,  
    496                                        &answer ); 
    497     if (status != PJ_SUCCESS) { 
    498         pjsip_endpt_respond_stateless(pjsua.endpt, rdata, 500, NULL, 
     424    status = pjmedia_endpt_create_sdp( pjsua_var.med_endpt,  
     425                                       rdata->tp_info.pool, 1, 
     426                                       &call->skinfo, &answer ); 
     427    if (status != PJ_SUCCESS) { 
     428        pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL, 
    499429                                      NULL, NULL); 
    500  
    501430        return PJ_TRUE; 
    502431    } 
    503432 
    504     /* TODO:  
    505      * 
     433    /*  
    506434     * Get which account is most likely to be associated with this incoming 
    507435     * call. We need the account to find which contact URI to put for 
    508436     * the call. 
    509437     */ 
    510     acc_index = 0; 
     438    acc_id = pjsua_acc_find_for_incoming(rdata); 
    511439 
    512440    /* Create dialog: */ 
    513  
    514441    status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata, 
    515                                    &pjsua.config.acc_config[acc_index].contact, 
     442                                   &pjsua_var.acc[acc_id].cfg.contact,  
    516443                                   &dlg); 
    517444    if (status != PJ_SUCCESS) { 
    518         pjsip_endpt_respond_stateless(pjsua.endpt, rdata, 500, NULL, 
     445        pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL, 
    519446                                      NULL, NULL); 
    520447 
     
    522449    } 
    523450 
     451    /* Set credentials */ 
     452    if (pjsua_var.acc[acc_id].cred_cnt) { 
     453        pjsip_auth_clt_set_credentials(&dlg->auth_sess,  
     454                                       pjsua_var.acc[acc_id].cred_cnt, 
     455                                       pjsua_var.acc[acc_id].cred); 
     456    } 
    524457 
    525458    /* Create invite session: */ 
    526  
    527459    status = pjsip_inv_create_uas( dlg, rdata, answer, 0, &inv); 
    528460    if (status != PJ_SUCCESS) { 
    529  
    530461        pjsip_dlg_respond(dlg, rdata, 500, NULL, NULL, NULL); 
    531462        pjsip_dlg_terminate(dlg); 
     
    534465 
    535466 
    536     /* Create and attach pjsua data to the dialog: */ 
    537  
    538     pjsua.calls[call_index].inv = inv; 
    539  
    540     dlg->mod_data[pjsua.mod.id] = &pjsua.calls[call_index]; 
    541     inv->mod_data[pjsua.mod.id] = &pjsua.calls[call_index]; 
     467    /* Create and attach pjsua_var data to the dialog: */ 
     468    call->inv = inv; 
     469 
     470    dlg->mod_data[pjsua_var.mod.id] = call; 
     471    inv->mod_data[pjsua_var.mod.id] = call; 
    542472 
    543473 
     
    545475     * If auto-answer flag is set, send 200 straight away, otherwise send 100. 
    546476     */ 
    547      
    548477    status = pjsip_inv_initial_answer(inv, rdata,  
    549                                       (pjsua.config.auto_answer ?  
    550                                       pjsua.config.auto_answer : 100),  
    551                                       NULL, NULL, &response); 
    552     if (status != PJ_SUCCESS) { 
    553          
    554         int st_code; 
    555  
     478                                      100, NULL, NULL, &response); 
     479    if (status != PJ_SUCCESS) { 
    556480        pjsua_perror(THIS_FILE, "Unable to send answer to incoming INVITE",  
    557481                     status); 
    558482 
    559         /* If failed to send 2xx response, there's a good chance that it is 
    560          * because SDP negotiation has failed. 
    561          */ 
    562         if (pjsua.config.auto_answer/100 == 2) 
    563             st_code = PJSIP_SC_UNSUPPORTED_MEDIA_TYPE; 
    564         else 
    565             st_code = 500; 
    566  
    567         pjsip_dlg_respond(dlg, rdata, st_code, NULL, NULL, NULL); 
    568         pjsip_inv_terminate(inv, st_code, PJ_FALSE); 
     483        pjsip_dlg_respond(dlg, rdata, 500, NULL, NULL, NULL); 
     484        pjsip_inv_terminate(inv, 500, PJ_FALSE); 
    569485        return PJ_TRUE; 
    570486 
     
    575491    } 
    576492 
    577     if (pjsua.config.auto_answer < 200) { 
    578         PJ_LOG(3,(THIS_FILE, 
    579                   "\nIncoming call!!\n" 
    580                   "From: %.*s\n" 
    581                   "To:   %.*s\n" 
    582                   "(press 'a' to answer, 'h' to decline)", 
    583                   (int)dlg->remote.info_str.slen, 
    584                   dlg->remote.info_str.ptr, 
    585                   (int)dlg->local.info_str.slen, 
    586                   dlg->local.info_str.ptr)); 
    587     } else { 
    588         PJ_LOG(3,(THIS_FILE, 
    589                   "Call From:%.*s To:%.*s was answered with %d (%s)", 
    590                   (int)dlg->remote.info_str.slen, 
    591                   dlg->remote.info_str.ptr, 
    592                   (int)dlg->local.info_str.slen, 
    593                   dlg->local.info_str.ptr, 
    594                   pjsua.config.auto_answer, 
    595                   pjsip_get_status_text(pjsua.config.auto_answer)->ptr )); 
    596     } 
    597  
    598     ++pjsua.call_cnt; 
    599  
    600     /* Schedule timer to refresh. */ 
    601     if (pjsua.config.uas_refresh > 0) { 
    602         schedule_call_timer( &pjsua.calls[call_index],  
    603                              &pjsua.calls[call_index].refresh_tm, 
    604                              REFRESH_CALL_TIMER, 
    605                              pjsua.config.uas_refresh); 
    606     } 
    607  
    608     /* Schedule timer to hangup call. */ 
    609     if (pjsua.config.uas_duration > 0) { 
    610         schedule_call_timer( &pjsua.calls[call_index],  
    611                              &pjsua.calls[call_index].hangup_tm, 
    612                              HANGUP_CALL_TIMER, 
    613                              pjsua.config.uas_duration); 
    614     } 
     493    ++pjsua_var.call_cnt; 
     494 
    615495 
    616496    /* Notify application */ 
    617     if (pjsua.cb.on_incoming_call) 
    618         pjsua.cb.on_incoming_call(acc_index, call_index, rdata); 
    619  
     497    if (pjsua_var.ua_cfg.cb.on_incoming_call) 
     498        pjsua_var.ua_cfg.cb.on_incoming_call(acc_id, call_id, rdata); 
    620499 
    621500    /* This INVITE request has been handled. */ 
     
    624503 
    625504 
     505 
     506/* 
     507 * Check if the specified call has active INVITE session and the INVITE 
     508 * session has not been disconnected. 
     509 */ 
     510PJ_DEF(pj_bool_t) pjsua_call_is_active(pjsua_call_id call_id) 
     511{ 
     512    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     513                     PJ_EINVAL); 
     514    return pjsua_var.calls[call_id].inv != NULL && 
     515           pjsua_var.calls[call_id].inv->state != PJSIP_INV_STATE_DISCONNECTED; 
     516} 
     517 
     518 
     519/* 
     520 * Check if call has an active media session. 
     521 */ 
     522PJ_DEF(pj_bool_t) pjsua_call_has_media(pjsua_call_id call_id) 
     523{ 
     524    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,  
     525                     PJ_EINVAL); 
     526    return pjsua_var.calls[call_id].session != NULL; 
     527} 
     528 
     529 
     530/* 
     531 * Get the conference port identification associated with the call. 
     532 */ 
     533PJ_DEF(pjsua_conf_port_id) pjsua_call_get_conf_port(pjsua_call_id call_id) 
     534{ 
     535    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,  
     536                     PJ_EINVAL); 
     537    return pjsua_var.calls[call_id].conf_slot; 
     538} 
     539 
     540 
     541/* 
     542 * Obtain detail information about the specified call. 
     543 */ 
     544PJ_DEF(pj_status_t) pjsua_call_get_info( pjsua_call_id call_id, 
     545                                         pjsua_call_info *info) 
     546{ 
     547    pjsua_call *call; 
     548 
     549    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     550                     PJ_EINVAL); 
     551 
     552    pj_memset(info, 0, sizeof(*info)); 
     553 
     554    PJSUA_LOCK(); 
     555 
     556    call = &pjsua_var.calls[call_id]; 
     557 
     558    if (call->inv == NULL) { 
     559        PJSUA_UNLOCK(); 
     560        return PJ_SUCCESS; 
     561    } 
     562 
     563    pjsip_dlg_inc_lock(call->inv->dlg); 
     564 
     565 
     566    /* id and role */ 
     567    info->id = call_id; 
     568    info->role = call->inv->role; 
     569 
     570    /* local info */ 
     571    info->local_info.ptr = info->buf_.local_info; 
     572    pj_strncpy(&info->local_info, &call->inv->dlg->local.info_str, 
     573               sizeof(info->buf_.local_info)); 
     574 
     575    /* local contact */ 
     576    info->local_contact.ptr = info->buf_.local_contact; 
     577    info->local_contact.slen = pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, 
     578                                               call->inv->dlg->local.contact->uri, 
     579                                               info->local_contact.ptr, 
     580                                               sizeof(info->buf_.local_contact)); 
     581 
     582    /* remote info */ 
     583    info->remote_info.ptr = info->buf_.remote_info; 
     584    pj_strncpy(&info->remote_info, &call->inv->dlg->remote.info_str, 
     585               sizeof(info->buf_.remote_info)); 
     586 
     587    /* remote contact */ 
     588    if (call->inv->dlg->remote.contact) { 
     589        int len; 
     590        info->remote_contact.ptr = info->buf_.remote_contact; 
     591        len = pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, 
     592                              call->inv->dlg->remote.contact->uri, 
     593                              info->remote_contact.ptr, 
     594                              sizeof(info->buf_.remote_contact)); 
     595        if (len < 0) len = 0; 
     596        info->remote_contact.slen = len; 
     597    } else { 
     598        info->remote_contact.slen = 0; 
     599    } 
     600 
     601    /* call id */ 
     602    info->call_id.ptr = info->buf_.call_id; 
     603    pj_strncpy(&info->call_id, &call->inv->dlg->call_id->id, 
     604               sizeof(info->buf_.call_id)); 
     605 
     606    /* state, state_text */ 
     607    info->state = call->inv->state; 
     608    info->state_text = pj_str((char*)pjsip_inv_state_name(info->state)); 
     609 
     610    /* If call is disconnected, set the last_status from the cause code */ 
     611    if (call->inv->state >= PJSIP_INV_STATE_DISCONNECTED) { 
     612        /* last_status, last_status_text */ 
     613        info->last_status = call->inv->cause; 
     614 
     615        info->last_status_text.ptr = info->buf_.last_status_text; 
     616        pj_strncpy(&info->last_status_text, &call->inv->cause_text, 
     617                   sizeof(info->buf_.last_status_text)); 
     618    } else { 
     619        /* last_status, last_status_text */ 
     620        info->last_status = call->last_code; 
     621 
     622        info->last_status_text.ptr = info->buf_.last_status_text; 
     623        pj_strncpy(&info->last_status_text, &call->last_text, 
     624                   sizeof(info->buf_.last_status_text)); 
     625    } 
     626     
     627    /* media status and dir */ 
     628    info->media_status = call->media_st; 
     629    info->media_dir = call->media_dir; 
     630 
     631 
     632    /* conference slot number */ 
     633    info->conf_slot = call->conf_slot; 
     634 
     635    /* calculate duration */ 
     636    if (info->state >= PJSIP_INV_STATE_DISCONNECTED) { 
     637 
     638        info->total_duration = call->dis_time; 
     639        PJ_TIME_VAL_SUB(info->total_duration, call->start_time); 
     640 
     641        if (call->conn_time.sec) { 
     642            info->connect_duration = call->dis_time; 
     643            PJ_TIME_VAL_SUB(info->connect_duration, call->conn_time); 
     644        } 
     645 
     646    } else if (info->state == PJSIP_INV_STATE_CONFIRMED) { 
     647 
     648        pj_gettimeofday(&info->total_duration); 
     649        PJ_TIME_VAL_SUB(info->total_duration, call->start_time); 
     650 
     651        pj_gettimeofday(&info->connect_duration); 
     652        PJ_TIME_VAL_SUB(info->connect_duration, call->conn_time); 
     653 
     654    } else { 
     655        pj_gettimeofday(&info->total_duration); 
     656        PJ_TIME_VAL_SUB(info->total_duration, call->start_time); 
     657    } 
     658 
     659    pjsip_dlg_dec_lock(call->inv->dlg); 
     660    PJSUA_UNLOCK(); 
     661 
     662    return PJ_SUCCESS; 
     663} 
     664 
     665 
     666/* 
     667 * Attach application specific data to the call. 
     668 */ 
     669PJ_DEF(pj_status_t) pjsua_call_set_user_data( pjsua_call_id call_id, 
     670                                              void *user_data) 
     671{ 
     672    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     673                     PJ_EINVAL); 
     674    pjsua_var.calls[call_id].user_data = user_data; 
     675 
     676    return PJ_SUCCESS; 
     677} 
     678 
     679 
     680/* 
     681 * Get user data attached to the call. 
     682 */ 
     683PJ_DEF(void*) pjsua_call_get_user_data(pjsua_call_id call_id) 
     684{ 
     685    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     686                     NULL); 
     687    return pjsua_var.calls[call_id].user_data; 
     688} 
     689 
     690 
     691/* 
     692 * Send response to incoming INVITE request. 
     693 */ 
     694PJ_DEF(pj_status_t) pjsua_call_answer( pjsua_call_id call_id,  
     695                                       unsigned code, 
     696                                       const pj_str_t *reason, 
     697                                       const pjsua_msg_data *msg_data) 
     698{ 
     699    pjsua_call *call; 
     700    pjsip_tx_data *tdata; 
     701    pj_status_t status; 
     702 
     703    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     704                     PJ_EINVAL); 
     705 
     706    PJSUA_LOCK(); 
     707 
     708    call = &pjsua_var.calls[call_id]; 
     709 
     710    if (call->inv == NULL) { 
     711        PJ_LOG(3,(THIS_FILE, "Call %d already disconnected", call_id)); 
     712        PJSUA_UNLOCK(); 
     713        return PJSIP_ESESSIONTERMINATED; 
     714    } 
     715 
     716    /* Create response message */ 
     717    status = pjsip_inv_answer(call->inv, code, reason, NULL, &tdata); 
     718    if (status != PJ_SUCCESS) { 
     719        pjsua_perror(THIS_FILE, "Error creating response",  
     720                     status); 
     721        PJSUA_UNLOCK(); 
     722        return status; 
     723    } 
     724 
     725    /* Add additional headers etc */ 
     726    pjsua_process_msg_data( tdata, msg_data); 
     727 
     728    /* Send the message */ 
     729    status = pjsip_inv_send_msg(call->inv, tdata); 
     730    if (status != PJ_SUCCESS) 
     731        pjsua_perror(THIS_FILE, "Error sending response",  
     732                     status); 
     733 
     734    PJSUA_UNLOCK(); 
     735 
     736    return status; 
     737} 
     738 
     739 
     740/* 
     741 * Hangup call by using method that is appropriate according to the 
     742 * call state. 
     743 */ 
     744PJ_DEF(pj_status_t) pjsua_call_hangup(pjsua_call_id call_id, 
     745                                      unsigned code, 
     746                                      const pj_str_t *reason, 
     747                                      const pjsua_msg_data *msg_data) 
     748{ 
     749    pjsua_call *call; 
     750    pj_status_t status; 
     751    pjsip_tx_data *tdata; 
     752 
     753 
     754    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     755                     PJ_EINVAL); 
     756 
     757    PJSUA_LOCK(); 
     758 
     759    call = &pjsua_var.calls[call_id]; 
     760 
     761    if (!call->inv) { 
     762        PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
     763        PJSUA_UNLOCK(); 
     764        return PJ_EINVAL; 
     765    } 
     766 
     767    if (code==0) { 
     768        if (call->inv->state == PJSIP_INV_STATE_CONFIRMED) 
     769            code = PJSIP_SC_OK; 
     770        else if (call->inv->role == PJSIP_ROLE_UAS) 
     771            code = PJSIP_SC_DECLINE; 
     772        else 
     773            code = PJSIP_SC_REQUEST_TERMINATED; 
     774    } 
     775 
     776    status = pjsip_inv_end_session(call->inv, code, reason, &tdata); 
     777    if (status != PJ_SUCCESS) { 
     778        pjsua_perror(THIS_FILE,  
     779                     "Failed to create end session message",  
     780                     status); 
     781        PJSUA_UNLOCK(); 
     782        return status; 
     783    } 
     784 
     785    /* pjsip_inv_end_session may return PJ_SUCCESS with NULL  
     786     * as p_tdata when INVITE transaction has not been answered 
     787     * with any provisional responses. 
     788     */ 
     789    if (tdata == NULL) { 
     790        PJSUA_UNLOCK(); 
     791        return PJ_SUCCESS; 
     792    } 
     793 
     794    /* Add additional headers etc */ 
     795    pjsua_process_msg_data( tdata, msg_data); 
     796 
     797    /* Send the message */ 
     798    status = pjsip_inv_send_msg(call->inv, tdata); 
     799    if (status != PJ_SUCCESS) { 
     800        pjsua_perror(THIS_FILE,  
     801                     "Failed to send end session message",  
     802                     status); 
     803        PJSUA_UNLOCK(); 
     804        return status; 
     805    } 
     806 
     807    PJSUA_UNLOCK(); 
     808 
     809    return PJ_SUCCESS; 
     810} 
     811 
     812 
     813/* 
     814 * Put the specified call on hold. 
     815 */ 
     816PJ_DEF(pj_status_t) pjsua_call_set_hold(pjsua_call_id call_id, 
     817                                        const pjsua_msg_data *msg_data) 
     818{ 
     819    pjmedia_sdp_session *sdp; 
     820    pjsua_call *call; 
     821    pjsip_tx_data *tdata; 
     822    pj_status_t status; 
     823 
     824    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     825                     PJ_EINVAL); 
     826 
     827    PJSUA_LOCK(); 
     828 
     829    call = &pjsua_var.calls[call_id]; 
     830     
     831    if (!call->inv) { 
     832        PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
     833        PJSUA_UNLOCK(); 
     834        return PJSIP_ESESSIONTERMINATED; 
     835    } 
     836 
     837    if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) { 
     838        PJ_LOG(3,(THIS_FILE, "Can not hold call that is not confirmed")); 
     839        PJSUA_UNLOCK(); 
     840        return PJSIP_ESESSIONSTATE; 
     841    } 
     842 
     843    status = create_inactive_sdp(call, &sdp); 
     844    if (status != PJ_SUCCESS) { 
     845        PJSUA_UNLOCK(); 
     846        return status; 
     847    } 
     848 
     849    /* Create re-INVITE with new offer */ 
     850    status = pjsip_inv_reinvite( call->inv, NULL, sdp, &tdata); 
     851    if (status != PJ_SUCCESS) { 
     852        pjsua_perror(THIS_FILE, "Unable to create re-INVITE", status); 
     853        PJSUA_UNLOCK(); 
     854        return status; 
     855    } 
     856 
     857    /* Add additional headers etc */ 
     858    pjsua_process_msg_data( tdata, msg_data); 
     859 
     860    /* Send the request */ 
     861    status = pjsip_inv_send_msg( call->inv, tdata); 
     862    if (status != PJ_SUCCESS) { 
     863        pjsua_perror(THIS_FILE, "Unable to send re-INVITE", status); 
     864        PJSUA_UNLOCK(); 
     865        return status; 
     866    } 
     867 
     868    PJSUA_UNLOCK(); 
     869 
     870    return PJ_SUCCESS; 
     871} 
     872 
     873 
     874/* 
     875 * Send re-INVITE (to release hold). 
     876 */ 
     877PJ_DEF(pj_status_t) pjsua_call_reinvite( pjsua_call_id call_id, 
     878                                         pj_bool_t unhold, 
     879                                         const pjsua_msg_data *msg_data) 
     880{ 
     881    pjmedia_sdp_session *sdp; 
     882    pjsip_tx_data *tdata; 
     883    pjsua_call *call; 
     884    pj_status_t status; 
     885 
     886 
     887    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     888                     PJ_EINVAL); 
     889 
     890    PJSUA_LOCK(); 
     891 
     892    call = &pjsua_var.calls[call_id]; 
     893 
     894    if (!call->inv) { 
     895        PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
     896        PJSUA_UNLOCK(); 
     897        return PJSIP_ESESSIONTERMINATED; 
     898    } 
     899 
     900 
     901    if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) { 
     902        PJ_LOG(3,(THIS_FILE, "Can not re-INVITE call that is not confirmed")); 
     903        PJSUA_UNLOCK(); 
     904        return PJSIP_ESESSIONSTATE; 
     905    } 
     906 
     907    /* Create SDP */ 
     908    status = pjmedia_endpt_create_sdp( pjsua_var.med_endpt, call->inv->pool,  
     909                                       1, &call->skinfo, &sdp); 
     910    if (status != PJ_SUCCESS) { 
     911        pjsua_perror(THIS_FILE, "Unable to get SDP from media endpoint",  
     912                     status); 
     913        PJSUA_UNLOCK(); 
     914        return status; 
     915    } 
     916 
     917    /* Create re-INVITE with new offer */ 
     918    status = pjsip_inv_reinvite( call->inv, NULL, sdp, &tdata); 
     919    if (status != PJ_SUCCESS) { 
     920        pjsua_perror(THIS_FILE, "Unable to create re-INVITE", status); 
     921        PJSUA_UNLOCK(); 
     922        return status; 
     923    } 
     924 
     925    /* Add additional headers etc */ 
     926    pjsua_process_msg_data( tdata, msg_data); 
     927 
     928    /* Send the request */ 
     929    status = pjsip_inv_send_msg( call->inv, tdata); 
     930    if (status != PJ_SUCCESS) { 
     931        pjsua_perror(THIS_FILE, "Unable to send re-INVITE", status); 
     932        PJSUA_UNLOCK(); 
     933        return status; 
     934    } 
     935 
     936    PJSUA_UNLOCK(); 
     937 
     938    return PJ_SUCCESS; 
     939} 
     940 
     941 
     942/* 
     943 * Initiate call transfer to the specified address. 
     944 */ 
     945PJ_DEF(pj_status_t) pjsua_call_xfer( pjsua_call_id call_id,  
     946                                     const pj_str_t *dest, 
     947                                     const pjsua_msg_data *msg_data) 
     948{ 
     949    pjsip_evsub *sub; 
     950    pjsip_tx_data *tdata; 
     951    pjsua_call *call; 
     952    pj_status_t status; 
     953 
     954 
     955    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     956                     PJ_EINVAL); 
     957     
     958    PJSUA_LOCK(); 
     959 
     960    call = &pjsua_var.calls[call_id]; 
     961 
     962    if (!call->inv) { 
     963        PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
     964        PJSUA_UNLOCK(); 
     965        return PJSIP_ESESSIONTERMINATED; 
     966    } 
     967    
     968    /* Create xfer client subscription. 
     969     * We're not interested in knowing the transfer result, so we 
     970     * put NULL as the callback. 
     971     */ 
     972    status = pjsip_xfer_create_uac(call->inv->dlg, NULL, &sub); 
     973    if (status != PJ_SUCCESS) { 
     974        pjsua_perror(THIS_FILE, "Unable to create xfer", status); 
     975        PJSUA_UNLOCK(); 
     976        return status; 
     977    } 
     978 
     979    /* 
     980     * Create REFER request. 
     981     */ 
     982    status = pjsip_xfer_initiate(sub, dest, &tdata); 
     983    if (status != PJ_SUCCESS) { 
     984        pjsua_perror(THIS_FILE, "Unable to create REFER request", status); 
     985        PJSUA_UNLOCK(); 
     986        return status; 
     987    } 
     988 
     989    /* Add additional headers etc */ 
     990    pjsua_process_msg_data( tdata, msg_data); 
     991 
     992    /* Send. */ 
     993    status = pjsip_xfer_send_request(sub, tdata); 
     994    if (status != PJ_SUCCESS) { 
     995        pjsua_perror(THIS_FILE, "Unable to send REFER request", status); 
     996        PJSUA_UNLOCK(); 
     997        return status; 
     998    } 
     999 
     1000    /* For simplicity (that's what this program is intended to be!),  
     1001     * leave the original invite session as it is. More advanced application 
     1002     * may want to hold the INVITE, or terminate the invite, or whatever. 
     1003     */ 
     1004 
     1005    PJSUA_UNLOCK(); 
     1006 
     1007    return PJ_SUCCESS; 
     1008 
     1009} 
     1010 
     1011 
     1012/* 
     1013 * Send DTMF digits to remote using RFC 2833 payload formats. 
     1014 */ 
     1015PJ_DEF(pj_status_t) pjsua_call_dial_dtmf( pjsua_call_id call_id,  
     1016                                          const pj_str_t *digits) 
     1017{ 
     1018    pjsua_call *call; 
     1019    pj_status_t status; 
     1020 
     1021    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     1022                     PJ_EINVAL); 
     1023     
     1024    PJSUA_LOCK(); 
     1025 
     1026    call = &pjsua_var.calls[call_id]; 
     1027 
     1028    if (!call->session) { 
     1029        PJ_LOG(3,(THIS_FILE, "Media is not established yet!")); 
     1030        PJSUA_UNLOCK(); 
     1031        return PJ_EINVALIDOP; 
     1032    } 
     1033 
     1034    status = pjmedia_session_dial_dtmf( call->session, 0, digits); 
     1035 
     1036    PJSUA_UNLOCK(); 
     1037 
     1038    return status; 
     1039} 
     1040 
     1041 
     1042/** 
     1043 * Send instant messaging inside INVITE session. 
     1044 */ 
     1045PJ_DEF(pj_status_t) pjsua_call_send_im( pjsua_call_id call_id,  
     1046                                        const pj_str_t *mime_type, 
     1047                                        const pj_str_t *content, 
     1048                                        const pjsua_msg_data *msg_data, 
     1049                                        void *user_data) 
     1050{ 
     1051    pjsua_call *call; 
     1052    const pj_str_t mime_text_plain = pj_str("text/plain"); 
     1053    pjsip_media_type ctype; 
     1054    pjsua_im_data *im_data; 
     1055    pjsip_tx_data *tdata; 
     1056    pj_status_t status; 
     1057 
     1058 
     1059    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     1060                     PJ_EINVAL); 
     1061 
     1062    PJSUA_LOCK(); 
     1063 
     1064    call = &pjsua_var.calls[call_id]; 
     1065 
     1066    if (!call->inv) { 
     1067        PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
     1068        PJSUA_UNLOCK(); 
     1069        return PJSIP_ESESSIONTERMINATED; 
     1070    } 
     1071 
     1072    /* Lock dialog. */ 
     1073    pjsip_dlg_inc_lock(call->inv->dlg); 
     1074 
     1075    /* Set default media type if none is specified */ 
     1076    if (mime_type == NULL) { 
     1077        mime_type = &mime_text_plain; 
     1078    } 
     1079 
     1080    /* Create request message. */ 
     1081    status = pjsip_dlg_create_request( call->inv->dlg, &pjsip_message_method, 
     1082                                       -1, &tdata); 
     1083    if (status != PJ_SUCCESS) { 
     1084        pjsua_perror(THIS_FILE, "Unable to create MESSAGE request", status); 
     1085        goto on_return; 
     1086    } 
     1087 
     1088    /* Add accept header. */ 
     1089    pjsip_msg_add_hdr( tdata->msg,  
     1090                       (pjsip_hdr*)pjsua_im_create_accept(tdata->pool)); 
     1091 
     1092    /* Parse MIME type */ 
     1093    pjsua_parse_media_type(tdata->pool, mime_type, &ctype); 
     1094 
     1095    /* Create "text/plain" message body. */ 
     1096    tdata->msg->body = pjsip_msg_body_create( tdata->pool, &ctype.type, 
     1097                                              &ctype.subtype, content); 
     1098    if (tdata->msg->body == NULL) { 
     1099        pjsua_perror(THIS_FILE, "Unable to create msg body", PJ_ENOMEM); 
     1100        pjsip_tx_data_dec_ref(tdata); 
     1101        goto on_return; 
     1102    } 
     1103 
     1104    /* Add additional headers etc */ 
     1105    pjsua_process_msg_data( tdata, msg_data); 
     1106 
     1107    /* Create IM data and attach to the request. */ 
     1108    im_data = pj_pool_zalloc(tdata->pool, sizeof(*im_data)); 
     1109    im_data->acc_id = call->acc_id; 
     1110    im_data->call_id = call_id; 
     1111    im_data->to = call->inv->dlg->remote.info_str; 
     1112    pj_strdup_with_null(tdata->pool, &im_data->body, content); 
     1113    im_data->user_data = user_data; 
     1114 
     1115 
     1116    /* Send the request. */ 
     1117    status = pjsip_dlg_send_request( call->inv->dlg, tdata,  
     1118                                     pjsua_var.mod.id, im_data); 
     1119    if (status != PJ_SUCCESS) { 
     1120        pjsua_perror(THIS_FILE, "Unable to send MESSAGE request", status); 
     1121        goto on_return; 
     1122    } 
     1123 
     1124on_return: 
     1125    pjsip_dlg_dec_lock(call->inv->dlg); 
     1126    PJSUA_UNLOCK(); 
     1127    return status; 
     1128} 
     1129 
     1130 
     1131/* 
     1132 * Send IM typing indication inside INVITE session. 
     1133 */ 
     1134PJ_DEF(pj_status_t) pjsua_call_send_typing_ind( pjsua_call_id call_id,  
     1135                                                pj_bool_t is_typing, 
     1136                                                const pjsua_msg_data*msg_data) 
     1137{ 
     1138    pjsua_call *call; 
     1139    pjsip_tx_data *tdata; 
     1140    pj_status_t status; 
     1141 
     1142 
     1143    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     1144                     PJ_EINVAL); 
     1145 
     1146    PJSUA_LOCK(); 
     1147 
     1148    call = &pjsua_var.calls[call_id]; 
     1149 
     1150    if (!call->inv) { 
     1151        PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
     1152        PJSUA_UNLOCK(); 
     1153        return PJSIP_ESESSIONTERMINATED; 
     1154    } 
     1155 
     1156    /* Lock dialog. */ 
     1157    pjsip_dlg_inc_lock(call->inv->dlg); 
     1158     
     1159    /* Create request message. */ 
     1160    status = pjsip_dlg_create_request( call->inv->dlg, &pjsip_message_method, 
     1161                                       -1, &tdata); 
     1162    if (status != PJ_SUCCESS) { 
     1163        pjsua_perror(THIS_FILE, "Unable to create MESSAGE request", status); 
     1164        goto on_return; 
     1165    } 
     1166 
     1167    /* Create "application/im-iscomposing+xml" msg body. */ 
     1168    tdata->msg->body = pjsip_iscomposing_create_body(tdata->pool, is_typing, 
     1169                                                     NULL, NULL, -1); 
     1170 
     1171    /* Add additional headers etc */ 
     1172    pjsua_process_msg_data( tdata, msg_data); 
     1173 
     1174    /* Send the request. */ 
     1175    status = pjsip_dlg_send_request( call->inv->dlg, tdata, -1, NULL); 
     1176    if (status != PJ_SUCCESS) { 
     1177        pjsua_perror(THIS_FILE, "Unable to send MESSAGE request", status); 
     1178        goto on_return; 
     1179    } 
     1180 
     1181on_return: 
     1182    pjsip_dlg_dec_lock(call->inv->dlg); 
     1183    PJSUA_UNLOCK(); 
     1184    return status; 
     1185} 
     1186 
     1187 
     1188/* 
     1189 * Terminate all calls. 
     1190 */ 
     1191PJ_DEF(void) pjsua_call_hangup_all(void) 
     1192{ 
     1193    unsigned i; 
     1194 
     1195    PJSUA_LOCK(); 
     1196 
     1197    for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { 
     1198        if (pjsua_var.calls[i].inv) 
     1199            pjsua_call_hangup(i, 0, NULL, NULL); 
     1200    } 
     1201 
     1202    PJSUA_UNLOCK(); 
     1203} 
     1204 
     1205 
     1206static const char *good_number(char *buf, pj_int32_t val) 
     1207{ 
     1208    if (val < 1000) { 
     1209        pj_ansi_sprintf(buf, "%d", val); 
     1210    } else if (val < 1000000) { 
     1211        pj_ansi_sprintf(buf, "%d.%dK",  
     1212                        val / 1000, 
     1213                        (val % 1000) / 100); 
     1214    } else { 
     1215        pj_ansi_sprintf(buf, "%d.%02dM",  
     1216                        val / 1000000, 
     1217                        (val % 1000000) / 10000); 
     1218    } 
     1219 
     1220    return buf; 
     1221} 
     1222 
     1223 
     1224/* Dump media session */ 
     1225static void dump_media_session(const char *indent,  
     1226                               char *buf, unsigned maxlen, 
     1227                               pjmedia_session *session) 
     1228{ 
     1229    unsigned i; 
     1230    char *p = buf, *end = buf+maxlen; 
     1231    int len; 
     1232    pjmedia_session_info info; 
     1233 
     1234    pjmedia_session_get_info(session, &info); 
     1235 
     1236    for (i=0; i<info.stream_cnt; ++i) { 
     1237        pjmedia_rtcp_stat stat; 
     1238        const char *rem_addr; 
     1239        int rem_port; 
     1240        const char *dir; 
     1241        char last_update[40]; 
     1242        char packets[16], bytes[16], ipbytes[16]; 
     1243        pj_time_val now; 
     1244 
     1245        pjmedia_session_get_stream_stat(session, i, &stat); 
     1246        rem_addr = pj_inet_ntoa(info.stream_info[i].rem_addr.sin_addr); 
     1247        rem_port = pj_ntohs(info.stream_info[i].rem_addr.sin_port); 
     1248 
     1249        if (info.stream_info[i].dir == PJMEDIA_DIR_ENCODING) 
     1250            dir = "sendonly"; 
     1251        else if (info.stream_info[i].dir == PJMEDIA_DIR_DECODING) 
     1252            dir = "recvonly"; 
     1253        else if (info.stream_info[i].dir == PJMEDIA_DIR_ENCODING_DECODING) 
     1254            dir = "sendrecv"; 
     1255        else 
     1256            dir = "inactive"; 
     1257 
     1258         
     1259        len = pj_ansi_snprintf(buf, end-p,  
     1260                  "%s  #%d %.*s @%dKHz, %s, peer=%s:%d", 
     1261                  indent, i, 
     1262                  info.stream_info[i].fmt.encoding_name.slen, 
     1263                  info.stream_info[i].fmt.encoding_name.ptr, 
     1264                  info.stream_info[i].fmt.clock_rate / 1000, 
     1265                  dir, 
     1266                  rem_addr, rem_port); 
     1267        if (len < 1 || len > end-p) { 
     1268            *p = '\0'; 
     1269            return; 
     1270        } 
     1271 
     1272        p += len; 
     1273        *p++ = '\n'; 
     1274        *p = '\0'; 
     1275 
     1276        if (stat.rx.update_cnt == 0) 
     1277            strcpy(last_update, "never"); 
     1278        else { 
     1279            pj_gettimeofday(&now); 
     1280            PJ_TIME_VAL_SUB(now, stat.rx.update); 
     1281            sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago", 
     1282                    now.sec / 3600, 
     1283                    (now.sec % 3600) / 60, 
     1284                    now.sec % 60, 
     1285                    now.msec); 
     1286        } 
     1287 
     1288        len = pj_ansi_snprintf(p, end-p, 
     1289               "%s     RX pt=%d, stat last update: %s\n" 
     1290               "%s        total %spkt %sB (%sB +IP hdr)\n" 
     1291               "%s        pkt loss=%d (%3.1f%%), dup=%d (%3.1f%%), reorder=%d (%3.1f%%)\n" 
     1292               "%s              (msec)    min     avg     max     last\n" 
     1293               "%s        loss period: %7.3f %7.3f %7.3f %7.3f\n" 
     1294               "%s        jitter     : %7.3f %7.3f %7.3f %7.3f%s", 
     1295               indent, info.stream_info[i].fmt.pt, 
     1296               last_update, 
     1297               indent, 
     1298               good_number(packets, stat.rx.pkt), 
     1299               good_number(bytes, stat.rx.bytes), 
     1300               good_number(ipbytes, stat.rx.bytes + stat.rx.pkt * 32), 
     1301               indent, 
     1302               stat.rx.loss, 
     1303               stat.rx.loss * 100.0 / stat.rx.pkt, 
     1304               stat.rx.dup,  
     1305               stat.rx.dup * 100.0 / stat.rx.pkt, 
     1306               stat.rx.reorder,  
     1307               stat.rx.reorder * 100.0 / stat.rx.pkt, 
     1308               indent, indent, 
     1309               stat.rx.loss_period.min / 1000.0,  
     1310               stat.rx.loss_period.avg / 1000.0,  
     1311               stat.rx.loss_period.max / 1000.0, 
     1312               stat.rx.loss_period.last / 1000.0, 
     1313               indent, 
     1314               stat.rx.jitter.min / 1000.0, 
     1315               stat.rx.jitter.avg / 1000.0, 
     1316               stat.rx.jitter.max / 1000.0, 
     1317               stat.rx.jitter.last / 1000.0, 
     1318               "" 
     1319               ); 
     1320 
     1321        if (len < 1 || len > end-p) { 
     1322            *p = '\0'; 
     1323            return; 
     1324        } 
     1325 
     1326        p += len; 
     1327        *p++ = '\n'; 
     1328        *p = '\0'; 
     1329         
     1330        if (stat.tx.update_cnt == 0) 
     1331            strcpy(last_update, "never"); 
     1332        else { 
     1333            pj_gettimeofday(&now); 
     1334            PJ_TIME_VAL_SUB(now, stat.tx.update); 
     1335            sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago", 
     1336                    now.sec / 3600, 
     1337                    (now.sec % 3600) / 60, 
     1338                    now.sec % 60, 
     1339                    now.msec); 
     1340        } 
     1341 
     1342        len = pj_ansi_snprintf(p, end-p, 
     1343               "%s     TX pt=%d, ptime=%dms, stat last update: %s\n" 
     1344               "%s        total %spkt %sB (%sB +IP hdr)\n" 
     1345               "%s        pkt loss=%d (%3.1f%%), dup=%d (%3.1f%%), reorder=%d (%3.1f%%)\n" 
     1346               "%s              (msec)    min     avg     max     last\n" 
     1347               "%s        loss period: %7.3f %7.3f %7.3f %7.3f\n" 
     1348               "%s        jitter     : %7.3f %7.3f %7.3f %7.3f%s", 
     1349               indent, 
     1350               info.stream_info[i].tx_pt, 
     1351               info.stream_info[i].param->info.frm_ptime * 
     1352                info.stream_info[i].param->setting.frm_per_pkt, 
     1353               last_update, 
     1354 
     1355               indent, 
     1356               good_number(packets, stat.tx.pkt), 
     1357               good_number(bytes, stat.tx.bytes), 
     1358               good_number(ipbytes, stat.tx.bytes + stat.tx.pkt * 32), 
     1359 
     1360               indent, 
     1361               stat.tx.loss, 
     1362               stat.tx.loss * 100.0 / stat.tx.pkt, 
     1363               stat.tx.dup,  
     1364               stat.tx.dup * 100.0 / stat.tx.pkt, 
     1365               stat.tx.reorder,  
     1366               stat.tx.reorder * 100.0 / stat.tx.pkt, 
     1367 
     1368               indent, indent, 
     1369               stat.tx.loss_period.min / 1000.0,  
     1370               stat.tx.loss_period.avg / 1000.0,  
     1371               stat.tx.loss_period.max / 1000.0, 
     1372               stat.tx.loss_period.last / 1000.0, 
     1373               indent, 
     1374               stat.tx.jitter.min / 1000.0, 
     1375               stat.tx.jitter.avg / 1000.0, 
     1376               stat.tx.jitter.max / 1000.0, 
     1377               stat.tx.jitter.last / 1000.0, 
     1378               "" 
     1379               ); 
     1380 
     1381        if (len < 1 || len > end-p) { 
     1382            *p = '\0'; 
     1383            return; 
     1384        } 
     1385 
     1386        p += len; 
     1387        *p++ = '\n'; 
     1388        *p = '\0'; 
     1389 
     1390        len = pj_ansi_snprintf(p, end-p, 
     1391               "%s    RTT msec       : %7.3f %7.3f %7.3f %7.3f",  
     1392               indent, 
     1393               stat.rtt.min / 1000.0, 
     1394               stat.rtt.avg / 1000.0, 
     1395               stat.rtt.max / 1000.0, 
     1396               stat.rtt.last / 1000.0 
     1397               ); 
     1398        if (len < 1 || len > end-p) { 
     1399            *p = '\0'; 
     1400            return; 
     1401        } 
     1402 
     1403        p += len; 
     1404        *p++ = '\n'; 
     1405        *p = '\0'; 
     1406    } 
     1407} 
     1408 
     1409 
     1410/* Print call info */ 
     1411static void print_call(const char *title, 
     1412                       int call_id,  
     1413                       char *buf, pj_size_t size) 
     1414{ 
     1415    int len; 
     1416    pjsip_inv_session *inv = pjsua_var.calls[call_id].inv; 
     1417    pjsip_dialog *dlg = inv->dlg; 
     1418    char userinfo[128]; 
     1419 
     1420    /* Dump invite sesion info. */ 
     1421 
     1422    len = pjsip_hdr_print_on(dlg->remote.info, userinfo, sizeof(userinfo)); 
     1423    if (len < 1) 
     1424        pj_ansi_strcpy(userinfo, "<--uri too long-->"); 
     1425    else 
     1426        userinfo[len] = '\0'; 
     1427     
     1428    len = pj_ansi_snprintf(buf, size, "%s[%s] %s", 
     1429                           title, 
     1430                           pjsip_inv_state_name(inv->state), 
     1431                           userinfo); 
     1432    if (len < 1 || len >= (int)size) { 
     1433        pj_ansi_strcpy(buf, "<--uri too long-->"); 
     1434        len = 18; 
     1435    } else 
     1436        buf[len] = '\0'; 
     1437} 
     1438 
     1439 
     1440/* 
     1441 * Dump call and media statistics to string. 
     1442 */ 
     1443PJ_DEF(pj_status_t) pjsua_call_dump( pjsua_call_id call_id,  
     1444                                     pj_bool_t with_media,  
     1445                                     char *buffer,  
     1446                                     unsigned maxlen, 
     1447                                     const char *indent) 
     1448{ 
     1449    pjsua_call *call; 
     1450    pj_time_val duration, res_delay, con_delay; 
     1451    char tmp[128]; 
     1452    char *p, *end; 
     1453    int len; 
     1454 
     1455    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     1456                     PJ_EINVAL); 
     1457 
     1458    PJSUA_LOCK(); 
     1459 
     1460    call = &pjsua_var.calls[call_id]; 
     1461 
     1462    *buffer = '\0'; 
     1463    p = buffer; 
     1464    end = buffer + maxlen; 
     1465    len = 0; 
     1466 
     1467    if (call->inv == NULL) { 
     1468        PJSUA_UNLOCK(); 
     1469        return PJ_EINVALIDOP; 
     1470    } 
     1471 
     1472    print_call(indent, call_id, tmp, sizeof(tmp)); 
     1473     
     1474    len = pj_ansi_strlen(tmp); 
     1475    pj_ansi_strcpy(buffer, tmp); 
     1476 
     1477    p += len; 
     1478    *p++ = '\r'; 
     1479    *p++ = '\n'; 
     1480 
     1481    /* Calculate call duration */ 
     1482    if (call->inv->state >= PJSIP_INV_STATE_CONFIRMED) { 
     1483        pj_gettimeofday(&duration); 
     1484        PJ_TIME_VAL_SUB(duration, call->conn_time); 
     1485        con_delay = call->conn_time; 
     1486        PJ_TIME_VAL_SUB(con_delay, call->start_time); 
     1487    } else { 
     1488        duration.sec = duration.msec = 0; 
     1489        con_delay.sec = con_delay.msec = 0; 
     1490    } 
     1491 
     1492    /* Calculate first response delay */ 
     1493    if (call->inv->state >= PJSIP_INV_STATE_EARLY) { 
     1494        res_delay = call->res_time; 
     1495        PJ_TIME_VAL_SUB(res_delay, call->start_time); 
     1496    } else { 
     1497        res_delay.sec = res_delay.msec = 0; 
     1498    } 
     1499 
     1500    /* Print duration */ 
     1501    len = pj_ansi_snprintf(p, end-p,  
     1502                           "%s  Call time: %02dh:%02dm:%02ds, " 
     1503                           "1st res in %d ms, conn in %dms", 
     1504                           indent, 
     1505                           (duration.sec / 3600), 
     1506                           ((duration.sec % 3600)/60), 
     1507                           (duration.sec % 60), 
     1508                           PJ_TIME_VAL_MSEC(res_delay),  
     1509                           PJ_TIME_VAL_MSEC(con_delay)); 
     1510     
     1511    if (len > 0 && len < end-p) { 
     1512        p += len; 
     1513        *p++ = '\n'; 
     1514        *p = '\0'; 
     1515    } 
     1516 
     1517    /* Dump session statistics */ 
     1518    if (with_media && call->session) 
     1519        dump_media_session(indent, p, end-p, call->session); 
     1520 
     1521    PJSUA_UNLOCK(); 
     1522 
     1523    return PJ_SUCCESS; 
     1524} 
     1525 
     1526 
     1527/* 
     1528 * Destroy the call's media 
     1529 */ 
     1530static pj_status_t call_destroy_media(int call_id) 
     1531{ 
     1532    pjsua_call *call = &pjsua_var.calls[call_id]; 
     1533 
     1534    if (call->conf_slot != PJSUA_INVALID_ID) { 
     1535        pjmedia_conf_remove_port(pjsua_var.mconf, call->conf_slot); 
     1536        call->conf_slot = PJSUA_INVALID_ID; 
     1537    } 
     1538 
     1539    if (call->session) { 
     1540        /* Destroy session (this will also close RTP/RTCP sockets). */ 
     1541        pjmedia_session_destroy(call->session); 
     1542        call->session = NULL; 
     1543 
     1544        PJ_LOG(4,(THIS_FILE, "Media session for call %d is destroyed",  
     1545                             call_id)); 
     1546 
     1547    } 
     1548 
     1549    call->media_st = PJSUA_CALL_MEDIA_NONE; 
     1550 
     1551    return PJ_SUCCESS; 
     1552} 
     1553 
     1554 
    6261555/* 
    6271556 * This callback receives notification from invite session when the 
     
    6311560                                        pjsip_event *e) 
    6321561{ 
    633     pjsua_call *call = inv->dlg->mod_data[pjsua.mod.id]; 
    634  
    635     if (!call) 
     1562    pjsua_call *call; 
     1563 
     1564    PJSUA_LOCK(); 
     1565 
     1566    call = inv->dlg->mod_data[pjsua_var.mod.id]; 
     1567 
     1568    if (!call) { 
     1569        PJSUA_UNLOCK(); 
    6361570        return; 
     1571    } 
     1572 
    6371573 
    6381574    /* Get call times */ 
     
    6431579                pj_gettimeofday(&call->res_time); 
    6441580            call->last_code = e->body.tsx_state.tsx->status_code; 
     1581            pj_strncpy(&call->last_text,  
     1582                       &e->body.tsx_state.tsx->status_text, 
     1583                       sizeof(call->last_text_buf_)); 
    6451584            break; 
    6461585        case PJSIP_INV_STATE_CONFIRMED: 
     
    6511590            if (e->body.tsx_state.tsx->status_code > call->last_code) { 
    6521591                call->last_code = e->body.tsx_state.tsx->status_code; 
     1592                pj_strncpy(&call->last_text,  
     1593                           &e->body.tsx_state.tsx->status_text, 
     1594                           sizeof(call->last_text_buf_)); 
    6531595            } 
    6541596            break; 
    6551597        default: 
    6561598            call->last_code = e->body.tsx_state.tsx->status_code; 
     1599            pj_strncpy(&call->last_text,  
     1600                       &e->body.tsx_state.tsx->status_text, 
     1601                       sizeof(call->last_text_buf_)); 
    6571602            break; 
    6581603    } 
     
    7171662 
    7181663 
    719     if (pjsua.cb.on_call_state) 
    720         (*pjsua.cb.on_call_state)(call->index, e); 
     1664    if (pjsua_var.ua_cfg.cb.on_call_state) 
     1665        (*pjsua_var.ua_cfg.cb.on_call_state)(call->index, e); 
    7211666 
    7221667    /* call->inv may be NULL now */ 
     
    7301675            call_destroy_media(call->index); 
    7311676 
    732         /* Remove timers. */ 
    733         schedule_call_timer(call, &call->refresh_tm, REFRESH_CALL_TIMER, 0); 
    734         schedule_call_timer(call, &call->hangup_tm, HANGUP_CALL_TIMER, 0); 
    735  
    7361677        /* Free call */ 
    7371678        call->inv = NULL; 
    738         --pjsua.call_cnt; 
    739     } 
    740 } 
    741  
    742  
    743 /* 
    744  * Callback called by event framework when the xfer subscription state 
    745  * has changed. 
    746  */ 
    747 static void xfer_on_evsub_state( pjsip_evsub *sub, pjsip_event *event) 
    748 { 
    749      
    750     PJ_UNUSED_ARG(event); 
    751  
    752     /* 
    753      * We're only interested when subscription is terminated, to  
    754      * clear the xfer_sub member of the inv_data. 
    755      */ 
    756     if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) { 
    757         pjsua_call *call; 
    758  
    759         call = pjsip_evsub_get_mod_data(sub, pjsua.mod.id); 
    760         if (!call) 
    761             return; 
    762  
    763         pjsip_evsub_set_mod_data(sub, pjsua.mod.id, NULL); 
    764         call->xfer_sub = NULL; 
    765  
    766         PJ_LOG(3,(THIS_FILE, "Xfer subscription terminated")); 
    767     } 
    768 } 
    769  
    770  
    771 /* 
    772  * Follow transfer (REFER) request. 
    773  */ 
    774 static void on_call_transfered( pjsip_inv_session *inv, 
    775                                 pjsip_rx_data *rdata ) 
    776 { 
    777     pj_status_t status; 
    778     pjsip_tx_data *tdata; 
    779     pjsua_call *existing_call; 
    780     int new_call; 
    781     const pj_str_t str_refer_to = { "Refer-To", 8}; 
    782     pjsip_generic_string_hdr *refer_to; 
    783     char *uri; 
    784     pj_str_t tmp; 
    785     struct pjsip_evsub_user xfer_cb; 
    786     pjsip_status_code code; 
    787     pjsip_evsub *sub; 
    788  
    789     existing_call = inv->dlg->mod_data[pjsua.mod.id]; 
    790  
    791     /* Find the Refer-To header */ 
    792     refer_to = (pjsip_generic_string_hdr*) 
    793         pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_refer_to, NULL); 
    794  
    795     if (refer_to == NULL) { 
    796         /* Invalid Request. 
    797          * No Refer-To header! 
    798          */ 
    799         PJ_LOG(4,(THIS_FILE, "Received REFER without Refer-To header!")); 
    800         pjsip_dlg_respond( inv->dlg, rdata, 400, NULL, NULL, NULL); 
    801         return; 
    802     } 
    803  
    804     /* Notify callback */ 
    805     code = PJSIP_SC_OK; 
    806     if (pjsua.cb.on_call_transfered) 
    807         (*pjsua.cb.on_call_transfered)(existing_call->index, 
    808                                        &refer_to->hvalue, &code); 
    809  
    810     if (code < 200) 
    811         code = 200; 
    812     if (code >= 300) { 
    813         /* Application rejects call transfer request */ 
    814         pjsip_dlg_respond( inv->dlg, rdata, code, NULL, NULL, NULL); 
    815         return; 
    816     } 
    817  
    818     PJ_LOG(3,(THIS_FILE, "Call to %.*s is being transfered to %.*s", 
    819               (int)inv->dlg->remote.info_str.slen, 
    820               inv->dlg->remote.info_str.ptr, 
    821               (int)refer_to->hvalue.slen,  
    822               refer_to->hvalue.ptr)); 
    823  
    824     /* Init callback */ 
    825     pj_memset(&xfer_cb, 0, sizeof(xfer_cb)); 
    826     xfer_cb.on_evsub_state = &xfer_on_evsub_state; 
    827  
    828     /* Create transferee event subscription */ 
    829     status = pjsip_xfer_create_uas( inv->dlg, &xfer_cb, rdata, &sub); 
    830     if (status != PJ_SUCCESS) { 
    831         pjsua_perror(THIS_FILE, "Unable to create xfer uas", status); 
    832         pjsip_dlg_respond( inv->dlg, rdata, 500, NULL, NULL, NULL); 
    833         return; 
    834     } 
    835  
    836     /* Accept the REFER request, send 200 (OK). */ 
    837     pjsip_xfer_accept(sub, rdata, code, NULL); 
    838  
    839     /* Create initial NOTIFY request */ 
    840     status = pjsip_xfer_notify( sub, PJSIP_EVSUB_STATE_ACTIVE, 
    841                                 100, NULL, &tdata); 
    842     if (status != PJ_SUCCESS) { 
    843         pjsua_perror(THIS_FILE, "Unable to create NOTIFY to REFER", status); 
    844         return; 
    845     } 
    846  
    847     /* Send initial NOTIFY request */ 
    848     status = pjsip_xfer_send_request( sub, tdata); 
    849     if (status != PJ_SUCCESS) { 
    850         pjsua_perror(THIS_FILE, "Unable to send NOTIFY to REFER", status); 
    851         return; 
    852     } 
    853  
    854     /* We're cheating here. 
    855      * We need to get a null terminated string from a pj_str_t. 
    856      * So grab the pointer from the hvalue and NULL terminate it, knowing 
    857      * that the NULL position will be occupied by a newline.  
    858      */ 
    859     uri = refer_to->hvalue.ptr; 
    860     uri[refer_to->hvalue.slen] = '\0'; 
    861  
    862     /* Now make the outgoing call. */ 
    863     tmp = pj_str(uri); 
    864     status = pjsua_call_make_call(existing_call->acc_index, &tmp, &new_call); 
    865     if (status != PJ_SUCCESS) { 
    866  
    867         /* Notify xferer about the error */ 
    868         status = pjsip_xfer_notify(sub, PJSIP_EVSUB_STATE_TERMINATED, 
    869                                    500, NULL, &tdata); 
    870         if (status != PJ_SUCCESS) { 
    871             pjsua_perror(THIS_FILE, "Unable to create NOTIFY to REFER",  
    872                           status); 
    873             return; 
    874         } 
    875         status = pjsip_xfer_send_request(sub, tdata); 
    876         if (status != PJ_SUCCESS) { 
    877             pjsua_perror(THIS_FILE, "Unable to send NOTIFY to REFER",  
    878                           status); 
    879             return; 
    880         } 
    881         return; 
    882     } 
    883  
    884     /* Put the server subscription in inv_data. 
    885      * Subsequent state changed in pjsua_inv_on_state_changed() will be 
    886      * reported back to the server subscription. 
    887      */ 
    888     pjsua.calls[new_call].xfer_sub = sub; 
    889  
    890     /* Put the invite_data in the subscription. */ 
    891     pjsip_evsub_set_mod_data(sub, pjsua.mod.id, &pjsua.calls[new_call]); 
    892 } 
    893  
    894  
    895 /* 
    896  * This callback is called when transaction state has changed in INVITE 
    897  * session. We use this to trap: 
    898  *  - incoming REFER request. 
    899  *  - incoming MESSAGE request. 
    900  */ 
    901 static void pjsua_call_on_tsx_state_changed(pjsip_inv_session *inv, 
    902                                             pjsip_transaction *tsx, 
    903                                             pjsip_event *e) 
    904 { 
    905     pjsua_call *call = inv->dlg->mod_data[pjsua.mod.id]; 
    906  
    907     if (tsx->role==PJSIP_ROLE_UAS && 
    908         tsx->state==PJSIP_TSX_STATE_TRYING && 
    909         pjsip_method_cmp(&tsx->method, &pjsip_refer_method)==0) 
    910     { 
    911         /* 
    912          * Incoming REFER request. 
    913          */ 
    914         on_call_transfered(call->inv, e->body.tsx_state.src.rdata); 
    915  
    916     } 
    917     else if (tsx->role==PJSIP_ROLE_UAS && 
    918              tsx->state==PJSIP_TSX_STATE_TRYING && 
    919              pjsip_method_cmp(&tsx->method, &pjsip_message_method)==0) 
    920     { 
    921         /* 
    922          * Incoming MESSAGE request! 
    923          */ 
    924         pjsip_rx_data *rdata; 
    925         pjsip_msg *msg; 
    926         pjsip_accept_hdr *accept_hdr; 
    927         pj_status_t status; 
    928  
    929         rdata = e->body.tsx_state.src.rdata; 
    930         msg = rdata->msg_info.msg; 
    931  
    932         /* Request MUST have message body, with Content-Type equal to 
    933          * "text/plain". 
    934          */ 
    935         if (pjsua_im_accept_pager(rdata, &accept_hdr) == PJ_FALSE) { 
    936  
    937             pjsip_hdr hdr_list; 
    938  
    939             pj_list_init(&hdr_list); 
    940             pj_list_push_back(&hdr_list, accept_hdr); 
    941  
    942             pjsip_dlg_respond( inv->dlg, rdata, PJSIP_SC_NOT_ACCEPTABLE_HERE,  
    943                                NULL, &hdr_list, NULL ); 
    944             return; 
    945         } 
    946  
    947         /* Respond with 200 first, so that remote doesn't retransmit in case 
    948          * the UI takes too long to process the message.  
    949          */ 
    950         status = pjsip_dlg_respond( inv->dlg, rdata, 200, NULL, NULL, NULL); 
    951  
    952         /* Process MESSAGE request */ 
    953         pjsua_im_process_pager(call->index, &inv->dlg->remote.info_str, 
    954                                &inv->dlg->local.info_str, rdata); 
    955     } 
    956  
    957 } 
    958  
     1679        --pjsua_var.call_cnt; 
     1680    } 
     1681 
     1682    PJSUA_UNLOCK(); 
     1683} 
    9591684 
    9601685/* 
     
    9711696} 
    9721697 
    973  
    974 /* 
    975  * Create inactive SDP for call hold. 
    976  */ 
    977 static pj_status_t create_inactive_sdp(pjsua_call *call, 
    978                                        pjmedia_sdp_session **p_answer) 
    979 { 
    980     pj_status_t status; 
    981     pjmedia_sdp_conn *conn; 
    982     pjmedia_sdp_attr *attr; 
    983     pjmedia_sdp_session *sdp; 
    984  
    985     /* Create new offer */ 
    986     status = pjmedia_endpt_create_sdp(pjsua.med_endpt, pjsua.pool, 1, 
    987                                       &call->skinfo, &sdp); 
    988     if (status != PJ_SUCCESS) { 
    989         pjsua_perror(THIS_FILE, "Unable to create local SDP", status); 
    990         return status; 
    991     } 
    992  
    993     /* Get SDP media connection line */ 
    994     conn = sdp->media[0]->conn; 
    995     if (!conn) 
    996         conn = sdp->conn; 
    997  
    998     /* Modify address */ 
    999     conn->addr = pj_str("0.0.0.0"); 
    1000  
    1001     /* Remove existing directions attributes */ 
    1002     pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendrecv"); 
    1003     pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendonly"); 
    1004     pjmedia_sdp_media_remove_all_attr(sdp->media[0], "recvonly"); 
    1005     pjmedia_sdp_media_remove_all_attr(sdp->media[0], "inactive"); 
    1006  
    1007     /* Add inactive attribute */ 
    1008     attr = pjmedia_sdp_attr_create(pjsua.pool, "inactive", NULL); 
    1009     pjmedia_sdp_media_add_attr(sdp->media[0], attr); 
    1010  
    1011     *p_answer = sdp; 
    1012  
    1013     return status; 
    1014 } 
    1015  
    1016 /* 
    1017  * Called when session received new offer. 
    1018  */ 
    1019 static void pjsua_call_on_rx_offer(pjsip_inv_session *inv, 
    1020                                    const pjmedia_sdp_session *offer) 
    1021 { 
    1022     pjsua_call *call; 
    1023     pjmedia_sdp_conn *conn; 
    1024     pjmedia_sdp_session *answer; 
    1025     pj_bool_t is_remote_active; 
    1026     pj_status_t status; 
    1027  
    1028     call = inv->dlg->mod_data[pjsua.mod.id]; 
    1029  
    1030     /* 
    1031      * See if remote is offering active media (i.e. not on-hold) 
    1032      */ 
    1033     is_remote_active = PJ_TRUE; 
    1034  
    1035     conn = offer->media[0]->conn; 
    1036     if (!conn) 
    1037         conn = offer->conn; 
    1038  
    1039     if (pj_strcmp2(&conn->addr, "0.0.0.0")==0 || 
    1040         pj_strcmp2(&conn->addr, "0")==0) 
    1041     { 
    1042         is_remote_active = PJ_FALSE; 
    1043  
    1044     }  
    1045     else if (pjmedia_sdp_media_find_attr2(offer->media[0], "inactive", NULL)) 
    1046     { 
    1047         is_remote_active = PJ_FALSE; 
    1048     } 
    1049  
    1050     PJ_LOG(4,(THIS_FILE, "Received SDP offer, remote media is %s", 
    1051               (is_remote_active ? "active" : "inactive"))); 
    1052  
    1053     /* Supply candidate answer */ 
    1054     if (is_remote_active) { 
    1055         status = pjmedia_endpt_create_sdp( pjsua.med_endpt, call->inv->pool, 1, 
    1056                                            &call->skinfo, &answer); 
    1057     } else { 
    1058         status = create_inactive_sdp( call, &answer ); 
    1059     } 
    1060  
    1061     if (status != PJ_SUCCESS) { 
    1062         pjsua_perror(THIS_FILE, "Unable to create local SDP", status); 
    1063         return; 
    1064     } 
    1065  
    1066     status = pjsip_inv_set_sdp_answer(call->inv, answer); 
    1067     if (status != PJ_SUCCESS) { 
    1068         pjsua_perror(THIS_FILE, "Unable to set answer", status); 
    1069         return; 
    1070     } 
    1071  
    1072 } 
    1073  
    1074 #if 0 
    1075 /* Disconnect call */ 
    1076 static void call_disconnect(pjsip_inv_session *inv, 
    1077                             int st_code) 
    1078 { 
    1079     pjsip_tx_data *tdata; 
    1080     pj_status_t status; 
    1081  
    1082     status = pjsip_inv_end_session(inv, st_code, NULL, &tdata); 
    1083     if (status == PJ_SUCCESS) 
    1084         status = pjsip_inv_send_msg(inv, tdata); 
    1085  
    1086     if (status != PJ_SUCCESS) { 
    1087         pjsua_perror(THIS_FILE, "Unable to disconnect call", status); 
    1088     } 
    1089 } 
    1090 #endif 
    10911698 
    10921699/* 
     
    10981705                                       pj_status_t status) 
    10991706{ 
     1707    int prev_media_st = 0; 
    11001708    pjsua_call *call; 
    11011709    pjmedia_session_info sess_info; 
     
    11061714    char tmp[PJSIP_MAX_URL_SIZE]; 
    11071715 
    1108     call = inv->dlg->mod_data[pjsua.mod.id]; 
     1716    PJSUA_LOCK(); 
     1717 
     1718    call = inv->dlg->mod_data[pjsua_var.mod.id]; 
    11091719 
    11101720    if (status != PJ_SUCCESS) { 
     
    11201730            //call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE); 
    11211731        } 
     1732 
     1733        PJSUA_UNLOCK(); 
    11221734        return; 
    1123  
    11241735    } 
    11251736 
    11261737    /* Destroy existing media session, if any. */ 
    11271738 
    1128     if (call) 
     1739    if (call) { 
     1740        prev_media_st = call->media_st; 
    11291741        call_destroy_media(call->index); 
     1742    } 
    11301743 
    11311744    /* Get local and remote SDP */ 
     
    11371750                     status); 
    11381751        //call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE); 
     1752        PJSUA_UNLOCK(); 
    11391753        return; 
    11401754    } 
     
    11471761                     status); 
    11481762        //call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE); 
     1763        PJSUA_UNLOCK(); 
    11491764        return; 
    11501765    } 
    1151  
    1152     if (pjsua.config.null_audio) 
    1153         return; 
    11541766 
    11551767    /* Create media session info based on SDP parameters.  
     
    11571769     */     
    11581770    status = pjmedia_session_info_from_sdp( call->inv->dlg->pool,  
    1159                                             pjsua.med_endpt,  
     1771                                            pjsua_var.med_endpt,  
    11601772                                            1,&sess_info,  
    11611773                                            local_sdp, remote_sdp); 
     
    11641776                     status); 
    11651777        //call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE); 
     1778        PJSUA_UNLOCK(); 
    11661779        return; 
    11671780    } 
    11681781 
    1169     /* Override ptime, if this option is specified. */ 
    1170     if (pjsua.config.ptime) { 
    1171         sess_info.stream_info[0].param->setting.frm_per_pkt = (pj_uint8_t) 
    1172             (pjsua.config.ptime /  
    1173               sess_info.stream_info[0].param->info.frm_ptime); 
    1174         if (sess_info.stream_info[0].param->setting.frm_per_pkt==0) 
    1175             sess_info.stream_info[0].param->setting.frm_per_pkt = 1; 
    1176     } 
    1177  
    1178     /* Optionally, application may modify other stream settings here 
    1179      * (such as jitter buffer parameters, codec ptime, etc.) 
    1180      */ 
    1181  
    1182     /* Create session based on session info. */ 
    1183     status = pjmedia_session_create( pjsua.med_endpt, &sess_info, 
    1184                                      &call->med_tp, 
    1185                                      call, &call->session ); 
    1186     if (status != PJ_SUCCESS) { 
    1187         pjsua_perror(THIS_FILE, "Unable to create media session",  
    1188                      status); 
    1189         //call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE); 
    1190         return; 
    1191     } 
    1192  
    1193  
    1194     /* Get the port interface of the first stream in the session. 
    1195      * We need the port interface to add to the conference bridge. 
    1196      */ 
    1197     pjmedia_session_get_port(call->session, 0, &media_port); 
    1198  
    1199  
    1200     /* 
    1201      * Add the call to conference bridge. 
    1202      */ 
    1203     port_name.ptr = tmp; 
    1204     port_name.slen = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, 
    1205                                      call->inv->dlg->remote.info->uri, 
    1206                                      tmp, sizeof(tmp)); 
    1207     if (port_name.slen < 1) { 
    1208         port_name = pj_str("call"); 
    1209     } 
    1210     status = pjmedia_conf_add_port( pjsua.mconf, call->inv->pool, 
    1211                                     media_port,  
    1212                                     &port_name, 
    1213                                     &call->conf_slot); 
    1214     if (status != PJ_SUCCESS) { 
    1215         pjsua_perror(THIS_FILE, "Unable to create conference slot",  
    1216                      status); 
    1217         call_destroy_media(call->index); 
    1218         //call_disconnect(inv, PJSIP_SC_INTERNAL_SERVER_ERROR); 
    1219         return; 
    1220     } 
    1221  
    1222     /* If auto-play is configured, connect the call to the file player  
    1223      * port  
    1224      */ 
    1225     if (pjsua.config.auto_play && pjsua.config.wav_file.slen &&  
    1226         call->inv->role == PJSIP_ROLE_UAS)  
     1782    /* Check if media is put on-hold */ 
     1783    if (sess_info.stream_cnt == 0 ||  
     1784        sess_info.stream_info[0].dir == PJMEDIA_DIR_NONE) 
    12271785    { 
    12281786 
    1229         pjmedia_conf_connect_port( pjsua.mconf, pjsua.player[0].slot,  
    1230                                    call->conf_slot, 0); 
    1231  
    1232     } 
    1233     if (pjsua.config.auto_loop && call->inv->role == PJSIP_ROLE_UAS) { 
    1234  
    1235         pjmedia_conf_connect_port( pjsua.mconf, call->conf_slot,  
    1236                                    call->conf_slot, 0); 
    1237  
    1238     } 
    1239     if (pjsua.config.auto_conf) { 
    1240         unsigned i; 
    1241  
    1242         pjmedia_conf_connect_port( pjsua.mconf, 0, call->conf_slot, 0); 
    1243         pjmedia_conf_connect_port( pjsua.mconf, call->conf_slot, 0, 0); 
    1244  
    1245         for (i=0; i < pjsua.config.max_calls; ++i) { 
    1246  
    1247             if (!pjsua.calls[i].session) 
    1248                 continue; 
    1249  
    1250             pjmedia_conf_connect_port( pjsua.mconf, call->conf_slot,  
    1251                                        pjsua.calls[i].conf_slot, 0); 
    1252             pjmedia_conf_connect_port( pjsua.mconf, pjsua.calls[i].conf_slot, 
    1253                                        call->conf_slot, 0); 
     1787        /* Determine who puts the call on-hold */ 
     1788        if (prev_media_st == PJSUA_CALL_MEDIA_ACTIVE) { 
     1789            if (pjmedia_sdp_neg_was_answer_remote(call->inv->neg)) { 
     1790                /* It was local who offer hold */ 
     1791                call->media_st = PJSUA_CALL_MEDIA_LOCAL_HOLD; 
     1792            } else { 
     1793                call->media_st = PJSUA_CALL_MEDIA_REMOTE_HOLD; 
     1794            } 
    12541795        } 
    12551796 
    1256     }  
    1257      
    1258     /* Normal operation: if no auto_xx is given, connect new call to  
    1259      * the sound device port (port zero) in the main conference bridge. 
    1260      */ 
    1261     if (pjsua.config.auto_play == 0 && pjsua.config.auto_loop == 0 && 
    1262         pjsua.config.auto_conf == 0) 
     1797        call->media_dir = PJMEDIA_DIR_NONE; 
     1798 
     1799    } else { 
     1800 
     1801        /* Override ptime, if this option is specified. */ 
     1802        PJ_TODO(set_codec_ptime_in_call); 
     1803 
     1804 
     1805        /* Optionally, application may modify other stream settings here 
     1806         * (such as jitter buffer parameters, codec ptime, etc.) 
     1807         */ 
     1808 
     1809        /* Create session based on session info. */ 
     1810        status = pjmedia_session_create( pjsua_var.med_endpt, &sess_info, 
     1811                                         &call->med_tp, 
     1812                                         call, &call->session ); 
     1813        if (status != PJ_SUCCESS) { 
     1814            pjsua_perror(THIS_FILE, "Unable to create media session",  
     1815                         status); 
     1816            //call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE); 
     1817            PJSUA_UNLOCK(); 
     1818            return; 
     1819        } 
     1820 
     1821 
     1822        /* Get the port interface of the first stream in the session. 
     1823         * We need the port interface to add to the conference bridge. 
     1824         */ 
     1825        pjmedia_session_get_port(call->session, 0, &media_port); 
     1826 
     1827 
     1828        /* 
     1829         * Add the call to conference bridge. 
     1830         */ 
     1831        port_name.ptr = tmp; 
     1832        port_name.slen = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, 
     1833                                         call->inv->dlg->remote.info->uri, 
     1834                                         tmp, sizeof(tmp)); 
     1835        if (port_name.slen < 1) { 
     1836            port_name = pj_str("call"); 
     1837        } 
     1838        status = pjmedia_conf_add_port( pjsua_var.mconf, call->inv->pool, 
     1839                                        media_port,  
     1840                                        &port_name, 
     1841                                        (unsigned*)&call->conf_slot); 
     1842        if (status != PJ_SUCCESS) { 
     1843            pjsua_perror(THIS_FILE, "Unable to create conference slot",  
     1844                         status); 
     1845            call_destroy_media(call->index); 
     1846            //call_disconnect(inv, PJSIP_SC_INTERNAL_SERVER_ERROR); 
     1847            PJSUA_UNLOCK(); 
     1848            return; 
     1849        } 
     1850 
     1851        /* Call's media state is active */ 
     1852        call->media_st = PJSUA_CALL_MEDIA_ACTIVE; 
     1853        call->media_dir = sess_info.stream_info[0].dir; 
     1854    } 
     1855 
     1856    /* Print info. */ 
    12631857    { 
    1264         pjmedia_conf_connect_port( pjsua.mconf, 0, call->conf_slot, 0); 
    1265         pjmedia_conf_connect_port( pjsua.mconf, call->conf_slot, 0, 0); 
    1266     } 
    1267  
    1268  
    1269     /* Done. */ 
    1270     { 
    1271         struct pjmedia_session_info sess_info; 
    12721858        char info[80]; 
    12731859        int info_len = 0; 
    12741860        unsigned i; 
    12751861 
    1276         pjmedia_session_get_info(call->session, &sess_info); 
    12771862        for (i=0; i<sess_info.stream_cnt; ++i) { 
    12781863            int len; 
     
    13051890                info_len += len; 
    13061891        } 
    1307         PJ_LOG(3,(THIS_FILE,"Media started%s", info)); 
    1308     } 
    1309 } 
    1310  
    1311  
    1312 /* 
    1313  * Hangup call. 
    1314  */ 
    1315 PJ_DEF(void) pjsua_call_hangup(int call_index) 
    1316 { 
     1892        PJ_LOG(4,(THIS_FILE,"Media updates%s", info)); 
     1893    } 
     1894 
     1895    /* Call application callback, if any */ 
     1896    if (pjsua_var.ua_cfg.cb.on_call_media_state) 
     1897        pjsua_var.ua_cfg.cb.on_call_media_state(call->index); 
     1898 
     1899 
     1900    PJSUA_UNLOCK(); 
     1901} 
     1902 
     1903 
     1904/* 
     1905 * Create inactive SDP for call hold. 
     1906 */ 
     1907static pj_status_t create_inactive_sdp(pjsua_call *call, 
     1908                                       pjmedia_sdp_session **p_answer) 
     1909{ 
     1910    pj_status_t status; 
     1911    pjmedia_sdp_conn *conn; 
     1912    pjmedia_sdp_attr *attr; 
     1913    pjmedia_sdp_session *sdp; 
     1914 
     1915    /* Create new offer */ 
     1916    status = pjmedia_endpt_create_sdp(pjsua_var.med_endpt, pjsua_var.pool, 1, 
     1917                                      &call->skinfo, &sdp); 
     1918    if (status != PJ_SUCCESS) { 
     1919        pjsua_perror(THIS_FILE, "Unable to create local SDP", status); 
     1920        return status; 
     1921    } 
     1922 
     1923    /* Get SDP media connection line */ 
     1924    conn = sdp->media[0]->conn; 
     1925    if (!conn) 
     1926        conn = sdp->conn; 
     1927 
     1928    /* Modify address */ 
     1929    conn->addr = pj_str("0.0.0.0"); 
     1930 
     1931    /* Remove existing directions attributes */ 
     1932    pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendrecv"); 
     1933    pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendonly"); 
     1934    pjmedia_sdp_media_remove_all_attr(sdp->media[0], "recvonly"); 
     1935    pjmedia_sdp_media_remove_all_attr(sdp->media[0], "inactive"); 
     1936 
     1937    /* Add inactive attribute */ 
     1938    attr = pjmedia_sdp_attr_create(pjsua_var.pool, "inactive", NULL); 
     1939    pjmedia_sdp_media_add_attr(sdp->media[0], attr); 
     1940 
     1941    *p_answer = sdp; 
     1942 
     1943    return status; 
     1944} 
     1945 
     1946 
     1947/* 
     1948 * Called when session received new offer. 
     1949 */ 
     1950static void pjsua_call_on_rx_offer(pjsip_inv_session *inv, 
     1951                                   const pjmedia_sdp_session *offer) 
     1952{ 
     1953    const char *remote_state; 
    13171954    pjsua_call *call; 
    1318     int code; 
     1955    pjmedia_sdp_conn *conn; 
     1956    pjmedia_sdp_session *answer; 
     1957    pj_bool_t is_remote_active; 
     1958    pj_status_t status; 
     1959 
     1960    PJSUA_LOCK(); 
     1961 
     1962    call = inv->dlg->mod_data[pjsua_var.mod.id]; 
     1963 
     1964    /* 
     1965     * See if remote is offering active media (i.e. not on-hold) 
     1966     */ 
     1967    is_remote_active = PJ_TRUE; 
     1968 
     1969    conn = offer->media[0]->conn; 
     1970    if (!conn) 
     1971        conn = offer->conn; 
     1972 
     1973    if (pj_strcmp2(&conn->addr, "0.0.0.0")==0 || 
     1974        pj_strcmp2(&conn->addr, "0")==0) 
     1975    { 
     1976        is_remote_active = PJ_FALSE; 
     1977 
     1978    }  
     1979    else if (pjmedia_sdp_media_find_attr2(offer->media[0], "inactive", NULL)) 
     1980    { 
     1981        is_remote_active = PJ_FALSE; 
     1982    } 
     1983 
     1984    remote_state = (is_remote_active ? "active" : "inactive"); 
     1985 
     1986    /* Supply candidate answer */ 
     1987    if (call->media_st == PJSUA_CALL_MEDIA_LOCAL_HOLD || !is_remote_active) { 
     1988        PJ_LOG(4,(THIS_FILE,  
     1989                  "Call %d: RX new media offer, creating inactive SDP " 
     1990                  "(media in offer is %s)", call->index, remote_state)); 
     1991        status = create_inactive_sdp( call, &answer ); 
     1992    } else { 
     1993        PJ_LOG(4,(THIS_FILE, "Call %d: received updated media offer", 
     1994                  call->index)); 
     1995        status = pjmedia_endpt_create_sdp( pjsua_var.med_endpt,  
     1996                                           call->inv->pool, 1, 
     1997                                           &call->skinfo, &answer);      
     1998    } 
     1999 
     2000    if (status != PJ_SUCCESS) { 
     2001        pjsua_perror(THIS_FILE, "Unable to create local SDP", status); 
     2002        PJSUA_UNLOCK(); 
     2003        return; 
     2004    } 
     2005 
     2006    status = pjsip_inv_set_sdp_answer(call->inv, answer); 
     2007    if (status != PJ_SUCCESS) { 
     2008        pjsua_perror(THIS_FILE, "Unable to set answer", status); 
     2009        PJSUA_UNLOCK(); 
     2010        return; 
     2011    } 
     2012 
     2013    PJSUA_UNLOCK(); 
     2014} 
     2015 
     2016 
     2017/* 
     2018 * Callback called by event framework when the xfer subscription state 
     2019 * has changed. 
     2020 */ 
     2021static void xfer_on_evsub_state( pjsip_evsub *sub, pjsip_event *event) 
     2022{ 
     2023     
     2024    PJ_UNUSED_ARG(event); 
     2025 
     2026    /* 
     2027     * We're only interested when subscription is terminated, to  
     2028     * clear the xfer_sub member of the inv_data. 
     2029     */ 
     2030    if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) { 
     2031        pjsua_call *call; 
     2032 
     2033        call = pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id); 
     2034        if (!call) 
     2035            return; 
     2036 
     2037        pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL); 
     2038        call->xfer_sub = NULL; 
     2039 
     2040        PJ_LOG(3,(THIS_FILE, "Xfer subscription terminated")); 
     2041    } 
     2042} 
     2043 
     2044 
     2045/* 
     2046 * Follow transfer (REFER) request. 
     2047 */ 
     2048static void on_call_transfered( pjsip_inv_session *inv, 
     2049                                pjsip_rx_data *rdata ) 
     2050{ 
    13192051    pj_status_t status; 
    13202052    pjsip_tx_data *tdata; 
    1321  
    1322  
    1323     call = &pjsua.calls[call_index]; 
    1324  
    1325     if (!call->inv) { 
    1326         PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
     2053    pjsua_call *existing_call; 
     2054    int new_call; 
     2055    const pj_str_t str_refer_to = { "Refer-To", 8}; 
     2056    pjsip_generic_string_hdr *refer_to; 
     2057    char *uri; 
     2058    pj_str_t tmp; 
     2059    struct pjsip_evsub_user xfer_cb; 
     2060    pjsip_status_code code; 
     2061    pjsip_evsub *sub; 
     2062 
     2063    existing_call = inv->dlg->mod_data[pjsua_var.mod.id]; 
     2064 
     2065    /* Find the Refer-To header */ 
     2066    refer_to = (pjsip_generic_string_hdr*) 
     2067        pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_refer_to, NULL); 
     2068 
     2069    if (refer_to == NULL) { 
     2070        /* Invalid Request. 
     2071         * No Refer-To header! 
     2072         */ 
     2073        PJ_LOG(4,(THIS_FILE, "Received REFER without Refer-To header!")); 
     2074        pjsip_dlg_respond( inv->dlg, rdata, 400, NULL, NULL, NULL); 
    13272075        return; 
    13282076    } 
    13292077 
    1330     if (call->inv->state == PJSIP_INV_STATE_CONFIRMED) 
    1331         code = PJSIP_SC_OK; 
    1332     else if (call->inv->role == PJSIP_ROLE_UAS) 
    1333         code = PJSIP_SC_DECLINE; 
    1334     else 
    1335         code = PJSIP_SC_REQUEST_TERMINATED; 
    1336  
    1337     status = pjsip_inv_end_session(call->inv, code, NULL, &tdata); 
    1338     if (status != PJ_SUCCESS) { 
    1339         pjsua_perror(THIS_FILE,  
    1340                      "Failed to create end session message",  
    1341                      status); 
     2078    /* Notify callback */ 
     2079    code = PJSIP_SC_OK; 
     2080    if (pjsua_var.ua_cfg.cb.on_call_transfered) 
     2081        (*pjsua_var.ua_cfg.cb.on_call_transfered)(existing_call->index, 
     2082                                                  &refer_to->hvalue, &code); 
     2083 
     2084    if (code < 200) 
     2085        code = 200; 
     2086    if (code >= 300) { 
     2087        /* Application rejects call transfer request */ 
     2088        pjsip_dlg_respond( inv->dlg, rdata, code, NULL, NULL, NULL); 
    13422089        return; 
    13432090    } 
    13442091 
    1345     /* pjsip_inv_end_session may return PJ_SUCCESS with NULL  
    1346      * as p_tdata when INVITE transaction has not been answered 
    1347      * with any provisional responses. 
     2092    PJ_LOG(3,(THIS_FILE, "Call to %.*s is being transfered to %.*s", 
     2093              (int)inv->dlg->remote.info_str.slen, 
     2094              inv->dlg->remote.info_str.ptr, 
     2095              (int)refer_to->hvalue.slen,  
     2096              refer_to->hvalue.ptr)); 
     2097 
     2098    /* Init callback */ 
     2099    pj_memset(&xfer_cb, 0, sizeof(xfer_cb)); 
     2100    xfer_cb.on_evsub_state = &xfer_on_evsub_state; 
     2101 
     2102    /* Create transferee event subscription */ 
     2103    status = pjsip_xfer_create_uas( inv->dlg, &xfer_cb, rdata, &sub); 
     2104    if (status != PJ_SUCCESS) { 
     2105        pjsua_perror(THIS_FILE, "Unable to create xfer uas", status); 
     2106        pjsip_dlg_respond( inv->dlg, rdata, 500, NULL, NULL, NULL); 
     2107        return; 
     2108    } 
     2109 
     2110    /* Accept the REFER request, send 200 (OK). */ 
     2111    pjsip_xfer_accept(sub, rdata, code, NULL); 
     2112 
     2113    /* Create initial NOTIFY request */ 
     2114    status = pjsip_xfer_notify( sub, PJSIP_EVSUB_STATE_ACTIVE, 
     2115                                100, NULL, &tdata); 
     2116    if (status != PJ_SUCCESS) { 
     2117        pjsua_perror(THIS_FILE, "Unable to create NOTIFY to REFER", status); 
     2118        return; 
     2119    } 
     2120 
     2121    /* Send initial NOTIFY request */ 
     2122    status = pjsip_xfer_send_request( sub, tdata); 
     2123    if (status != PJ_SUCCESS) { 
     2124        pjsua_perror(THIS_FILE, "Unable to send NOTIFY to REFER", status); 
     2125        return; 
     2126    } 
     2127 
     2128    /* We're cheating here. 
     2129     * We need to get a null terminated string from a pj_str_t. 
     2130     * So grab the pointer from the hvalue and NULL terminate it, knowing 
     2131     * that the NULL position will be occupied by a newline.  
    13482132     */ 
    1349     if (tdata == NULL) 
     2133    uri = refer_to->hvalue.ptr; 
     2134    uri[refer_to->hvalue.slen] = '\0'; 
     2135 
     2136    /* Now make the outgoing call. */ 
     2137    tmp = pj_str(uri); 
     2138    status = pjsua_call_make_call(existing_call->acc_id, &tmp, 0, 
     2139                                  existing_call->user_data, NULL,  
     2140                                  &new_call); 
     2141    if (status != PJ_SUCCESS) { 
     2142 
     2143        /* Notify xferer about the error */ 
     2144        status = pjsip_xfer_notify(sub, PJSIP_EVSUB_STATE_TERMINATED, 
     2145                                   500, NULL, &tdata); 
     2146        if (status != PJ_SUCCESS) { 
     2147            pjsua_perror(THIS_FILE, "Unable to create NOTIFY to REFER",  
     2148                          status); 
     2149            return; 
     2150        } 
     2151        status = pjsip_xfer_send_request(sub, tdata); 
     2152        if (status != PJ_SUCCESS) { 
     2153            pjsua_perror(THIS_FILE, "Unable to send NOTIFY to REFER",  
     2154                          status); 
     2155            return; 
     2156        } 
    13502157        return; 
    1351  
    1352     status = pjsip_inv_send_msg(call->inv, tdata); 
    1353     if (status != PJ_SUCCESS) { 
    1354         pjsua_perror(THIS_FILE,  
    1355                      "Failed to send end session message",  
    1356                      status); 
    1357         return; 
    1358     } 
    1359 } 
    1360  
    1361  
    1362 /* 
    1363  * Put call on-Hold. 
    1364  */ 
    1365 PJ_DEF(pj_status_t) pjsua_call_set_hold(int call_index) 
    1366 { 
    1367     pjmedia_sdp_session *sdp; 
    1368     pjsua_call *call; 
    1369     pjsip_tx_data *tdata; 
    1370     pj_status_t status; 
    1371  
    1372     call = &pjsua.calls[call_index]; 
    1373      
    1374     if (!call->inv) { 
    1375         PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
    1376         return PJSIP_ESESSIONTERMINATED; 
    1377     } 
    1378  
    1379     if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) { 
    1380         PJ_LOG(3,(THIS_FILE, "Can not hold call that is not confirmed")); 
    1381         return PJSIP_ESESSIONSTATE; 
    1382     } 
    1383  
    1384     status = create_inactive_sdp(call, &sdp); 
    1385     if (status != PJ_SUCCESS) 
    1386         return status; 
    1387  
    1388     /* Send re-INVITE with new offer */ 
    1389     status = pjsip_inv_reinvite( call->inv, NULL, sdp, &tdata); 
    1390     if (status != PJ_SUCCESS) { 
    1391         pjsua_perror(THIS_FILE, "Unable to create re-INVITE", status); 
    1392         return status; 
    1393     } 
    1394  
    1395     status = pjsip_inv_send_msg( call->inv, tdata); 
    1396     if (status != PJ_SUCCESS) { 
    1397         pjsua_perror(THIS_FILE, "Unable to send re-INVITE", status); 
    1398         return status; 
    1399     } 
    1400  
    1401     return PJ_SUCCESS; 
    1402 } 
    1403  
    1404  
    1405 /* 
    1406  * re-INVITE. 
    1407  */ 
    1408 PJ_DEF(pj_status_t) pjsua_call_reinvite(int call_index) 
    1409 { 
    1410     pjmedia_sdp_session *sdp; 
    1411     pjsip_tx_data *tdata; 
    1412     pjsua_call *call; 
    1413     pj_status_t status; 
    1414  
    1415     call = &pjsua.calls[call_index]; 
    1416  
    1417     if (!call->inv) { 
    1418         PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
    1419         return PJSIP_ESESSIONTERMINATED; 
    1420     } 
    1421  
    1422  
    1423     if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) { 
    1424         PJ_LOG(3,(THIS_FILE, "Can not re-INVITE call that is not confirmed")); 
    1425         return PJSIP_ESESSIONSTATE; 
    1426     } 
    1427  
    1428     /* Create SDP */ 
    1429     status = pjmedia_endpt_create_sdp( pjsua.med_endpt, call->inv->pool, 1, 
    1430                                        &call->skinfo, &sdp); 
    1431     if (status != PJ_SUCCESS) { 
    1432         pjsua_perror(THIS_FILE, "Unable to get SDP from media endpoint",  
    1433                      status); 
    1434         return status; 
    1435     } 
    1436  
    1437     /* Send re-INVITE with new offer */ 
    1438     status = pjsip_inv_reinvite( call->inv, NULL, sdp, &tdata); 
    1439     if (status != PJ_SUCCESS) { 
    1440         pjsua_perror(THIS_FILE, "Unable to create re-INVITE", status); 
    1441         return status; 
    1442     } 
    1443  
    1444     status = pjsip_inv_send_msg( call->inv, tdata); 
    1445     if (status != PJ_SUCCESS) { 
    1446         pjsua_perror(THIS_FILE, "Unable to send re-INVITE", status); 
    1447         return status; 
    1448     } 
    1449  
    1450     return PJ_SUCCESS; 
    1451 } 
    1452  
    1453  
    1454 /* 
    1455  * Transfer call. 
    1456  */ 
    1457 PJ_DEF(pj_status_t) pjsua_call_xfer(unsigned call_index, const pj_str_t *dest) 
    1458 { 
    1459     pjsip_evsub *sub; 
    1460     pjsip_tx_data *tdata; 
    1461     pjsua_call *call; 
    1462     pj_status_t status; 
    1463  
    1464      
    1465     call = &pjsua.calls[call_index]; 
    1466  
    1467     if (!call->inv) { 
    1468         PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
    1469         return PJSIP_ESESSIONTERMINATED; 
    1470     } 
    1471     
    1472     /* Create xfer client subscription. 
    1473      * We're not interested in knowing the transfer result, so we 
    1474      * put NULL as the callback. 
     2158    } 
     2159 
     2160    /* Put the server subscription in inv_data. 
     2161     * Subsequent state changed in pjsua_inv_on_state_changed() will be 
     2162     * reported back to the server subscription. 
    14752163     */ 
    1476     status = pjsip_xfer_create_uac(call->inv->dlg, NULL, &sub); 
    1477     if (status != PJ_SUCCESS) { 
    1478         pjsua_perror(THIS_FILE, "Unable to create xfer", status); 
    1479         return status; 
    1480     } 
    1481  
    1482     /* 
    1483      * Create REFER request. 
    1484      */ 
    1485     status = pjsip_xfer_initiate(sub, dest, &tdata); 
    1486     if (status != PJ_SUCCESS) { 
    1487         pjsua_perror(THIS_FILE, "Unable to create REFER request", status); 
    1488         return status; 
    1489     } 
    1490  
    1491     /* Send. */ 
    1492     status = pjsip_xfer_send_request(sub, tdata); 
    1493     if (status != PJ_SUCCESS) { 
    1494         pjsua_perror(THIS_FILE, "Unable to send REFER request", status); 
    1495         return status; 
    1496     } 
    1497  
    1498     /* For simplicity (that's what this program is intended to be!),  
    1499      * leave the original invite session as it is. More advanced application 
    1500      * may want to hold the INVITE, or terminate the invite, or whatever. 
    1501      */ 
    1502  
    1503     return PJ_SUCCESS; 
    1504 } 
    1505  
    1506  
    1507 /** 
    1508  * Dial DTMF. 
    1509  */ 
    1510 PJ_DEF(pj_status_t) pjsua_call_dial_dtmf( unsigned call_index,  
    1511                                           const pj_str_t *digits) 
    1512 { 
    1513     pjsua_call *call = &pjsua.calls[call_index]; 
    1514  
    1515     PJ_ASSERT_RETURN(call_index < pjsua.config.max_calls, PJ_EINVAL); 
    1516  
    1517     if (!call->session) { 
    1518         PJ_LOG(3,(THIS_FILE, "Media is not established yet!")); 
    1519         return -1; 
    1520     } 
    1521  
    1522     return pjmedia_session_dial_dtmf( call->session, 0, digits); 
    1523 } 
    1524  
    1525  
    1526 /** 
    1527  * Send instant messaging inside INVITE session. 
    1528  */ 
    1529 PJ_DEF(pj_status_t) pjsua_call_send_im(int call_index, const pj_str_t *str) 
    1530 { 
    1531     pjsua_call *call; 
    1532     const pj_str_t mime_text = pj_str("text"); 
    1533     const pj_str_t mime_plain = pj_str("plain"); 
    1534     pjsip_tx_data *tdata; 
    1535     pj_status_t status; 
    1536  
    1537     call = &pjsua.calls[call_index]; 
    1538  
    1539     if (!call->inv) { 
    1540         PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
    1541         return PJSIP_ESESSIONTERMINATED; 
    1542     } 
    1543  
    1544     /* Lock dialog. */ 
    1545     pjsip_dlg_inc_lock(call->inv->dlg); 
    1546      
    1547     /* Create request message. */ 
    1548     status = pjsip_dlg_create_request( call->inv->dlg, &pjsip_message_method, 
    1549                                        -1, &tdata); 
    1550     if (status != PJ_SUCCESS) { 
    1551         pjsua_perror(THIS_FILE, "Unable to create MESSAGE request", status); 
    1552         goto on_return; 
    1553     } 
    1554  
    1555     /* Add accept header. */ 
    1556     pjsip_msg_add_hdr( tdata->msg,  
    1557                        (pjsip_hdr*)pjsua_im_create_accept(tdata->pool)); 
    1558  
    1559     /* Create "text/plain" message body. */ 
    1560     tdata->msg->body = pjsip_msg_body_create( tdata->pool, &mime_text, 
    1561                                               &mime_plain, str); 
    1562     if (tdata->msg->body == NULL) { 
    1563         pjsua_perror(THIS_FILE, "Unable to create msg body", PJ_ENOMEM); 
    1564         pjsip_tx_data_dec_ref(tdata); 
    1565         goto on_return; 
    1566     } 
    1567  
    1568     /* Send the request. */ 
    1569     status = pjsip_dlg_send_request( call->inv->dlg, tdata, -1, NULL); 
    1570     if (status != PJ_SUCCESS) { 
    1571         pjsua_perror(THIS_FILE, "Unable to send MESSAGE request", status); 
    1572         goto on_return; 
    1573     } 
    1574  
    1575 on_return: 
    1576     pjsip_dlg_dec_lock(call->inv->dlg); 
    1577     return status; 
    1578 } 
    1579  
    1580  
    1581 /** 
    1582  * Send IM typing indication inside INVITE session. 
    1583  */ 
    1584 PJ_DEF(pj_status_t) pjsua_call_send_typing_ind(int call_index,  
    1585                                                pj_bool_t is_typing) 
    1586 { 
    1587     pjsua_call *call; 
    1588     pjsip_tx_data *tdata; 
    1589     pj_status_t status; 
    1590  
    1591     call = &pjsua.calls[call_index]; 
    1592  
    1593     if (!call->inv) { 
    1594         PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
    1595         return PJSIP_ESESSIONTERMINATED; 
    1596     } 
    1597  
    1598     /* Lock dialog. */ 
    1599     pjsip_dlg_inc_lock(call->inv->dlg); 
    1600      
    1601     /* Create request message. */ 
    1602     status = pjsip_dlg_create_request( call->inv->dlg, &pjsip_message_method, 
    1603                                        -1, &tdata); 
    1604     if (status != PJ_SUCCESS) { 
    1605         pjsua_perror(THIS_FILE, "Unable to create MESSAGE request", status); 
    1606         goto on_return; 
    1607     } 
    1608  
    1609     /* Create "application/im-iscomposing+xml" msg body. */ 
    1610     tdata->msg->body = pjsip_iscomposing_create_body(tdata->pool, is_typing, 
    1611                                                      NULL, NULL, -1); 
    1612  
    1613     /* Send the request. */ 
    1614     status = pjsip_dlg_send_request( call->inv->dlg, tdata, -1, NULL); 
    1615     if (status != PJ_SUCCESS) { 
    1616         pjsua_perror(THIS_FILE, "Unable to send MESSAGE request", status); 
    1617         goto on_return; 
    1618     } 
    1619  
    1620 on_return: 
    1621     pjsip_dlg_dec_lock(call->inv->dlg); 
    1622     return status; 
    1623 } 
    1624  
    1625  
    1626 /* 
    1627  * Terminate all calls. 
    1628  */ 
    1629 PJ_DEF(void) pjsua_call_hangup_all(void) 
    1630 { 
    1631     unsigned i; 
    1632  
    1633     for (i=0; i<pjsua.config.max_calls; ++i) { 
    1634         pjsip_tx_data *tdata; 
    1635         int st_code; 
    1636         pjsua_call *call; 
    1637  
    1638         if (pjsua.calls[i].inv == NULL) 
    1639             continue; 
    1640  
    1641         call = &pjsua.calls[i]; 
    1642  
    1643         if (call->inv->state == PJSIP_INV_STATE_CONFIRMED) { 
    1644             st_code = 200; 
    1645         } else { 
    1646             st_code = PJSIP_SC_GONE; 
     2164    pjsua_var.calls[new_call].xfer_sub = sub; 
     2165 
     2166    /* Put the invite_data in the subscription. */ 
     2167    pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id,  
     2168                             &pjsua_var.calls[new_call]); 
     2169} 
     2170 
     2171 
     2172 
     2173/* 
     2174 * This callback is called when transaction state has changed in INVITE 
     2175 * session. We use this to trap: 
     2176 *  - incoming REFER request. 
     2177 *  - incoming MESSAGE request. 
     2178 */ 
     2179static void pjsua_call_on_tsx_state_changed(pjsip_inv_session *inv, 
     2180                                            pjsip_transaction *tsx, 
     2181                                            pjsip_event *e) 
     2182{ 
     2183    pjsua_call *call = inv->dlg->mod_data[pjsua_var.mod.id]; 
     2184 
     2185    PJSUA_LOCK(); 
     2186 
     2187    if (tsx->role==PJSIP_ROLE_UAS && 
     2188        tsx->state==PJSIP_TSX_STATE_TRYING && 
     2189        pjsip_method_cmp(&tsx->method, &pjsip_refer_method)==0) 
     2190    { 
     2191        /* 
     2192         * Incoming REFER request. 
     2193         */ 
     2194        on_call_transfered(call->inv, e->body.tsx_state.src.rdata); 
     2195 
     2196    } 
     2197    else if (tsx->role==PJSIP_ROLE_UAS && 
     2198             tsx->state==PJSIP_TSX_STATE_TRYING && 
     2199             pjsip_method_cmp(&tsx->method, &pjsip_message_method)==0) 
     2200    { 
     2201        /* 
     2202         * Incoming MESSAGE request! 
     2203         */ 
     2204        pjsip_rx_data *rdata; 
     2205        pjsip_msg *msg; 
     2206        pjsip_accept_hdr *accept_hdr; 
     2207        pj_status_t status; 
     2208 
     2209        rdata = e->body.tsx_state.src.rdata; 
     2210        msg = rdata->msg_info.msg; 
     2211 
     2212        /* Request MUST have message body, with Content-Type equal to 
     2213         * "text/plain". 
     2214         */ 
     2215        if (pjsua_im_accept_pager(rdata, &accept_hdr) == PJ_FALSE) { 
     2216 
     2217            pjsip_hdr hdr_list; 
     2218 
     2219            pj_list_init(&hdr_list); 
     2220            pj_list_push_back(&hdr_list, accept_hdr); 
     2221 
     2222            pjsip_dlg_respond( inv->dlg, rdata, PJSIP_SC_NOT_ACCEPTABLE_HERE,  
     2223                               NULL, &hdr_list, NULL ); 
     2224            PJSUA_UNLOCK(); 
     2225            return; 
    16472226        } 
    16482227 
    1649         if (pjsip_inv_end_session(call->inv, st_code, NULL, &tdata)==0) { 
    1650             if (tdata) 
    1651                 pjsip_inv_send_msg(call->inv, tdata); 
     2228        /* Respond with 200 first, so that remote doesn't retransmit in case 
     2229         * the UI takes too long to process the message.  
     2230         */ 
     2231        status = pjsip_dlg_respond( inv->dlg, rdata, 200, NULL, NULL, NULL); 
     2232 
     2233        /* Process MESSAGE request */ 
     2234        pjsua_im_process_pager(call->index, &inv->dlg->remote.info_str, 
     2235                               &inv->dlg->local.info_str, rdata); 
     2236 
     2237    } 
     2238    else if (tsx->role == PJSIP_ROLE_UAC && 
     2239             pjsip_method_cmp(&tsx->method, &pjsip_message_method)==0) 
     2240    { 
     2241        /* Handle outgoing pager status */ 
     2242        if (tsx->status_code >= 200) { 
     2243            pjsua_im_data *im_data; 
     2244 
     2245            im_data = tsx->mod_data[pjsua_var.mod.id]; 
     2246            /* im_data can be NULL if this is typing indication */ 
     2247 
     2248            if (im_data && pjsua_var.ua_cfg.cb.on_pager_status) { 
     2249                pjsua_var.ua_cfg.cb.on_pager_status(im_data->call_id, 
     2250                                                    &im_data->to, 
     2251                                                    &im_data->body, 
     2252                                                    im_data->user_data, 
     2253                                                    tsx->status_code, 
     2254                                                    &tsx->status_text); 
     2255            } 
    16522256        } 
    16532257    } 
    1654 } 
    1655  
    1656  
    1657 pj_status_t pjsua_call_init(void) 
    1658 { 
    1659     /* Initialize invite session callback. */ 
    1660     pjsip_inv_callback inv_cb; 
    1661     pj_status_t status; 
    1662  
    1663     pj_memset(&inv_cb, 0, sizeof(inv_cb)); 
    1664     inv_cb.on_state_changed = &pjsua_call_on_state_changed; 
    1665     inv_cb.on_new_session = &pjsua_call_on_forked; 
    1666     inv_cb.on_media_update = &pjsua_call_on_media_update; 
    1667     inv_cb.on_rx_offer = &pjsua_call_on_rx_offer; 
    1668     inv_cb.on_tsx_state_changed = &pjsua_call_on_tsx_state_changed; 
    1669  
    1670  
    1671     /* Initialize invite session module: */ 
    1672     status = pjsip_inv_usage_init(pjsua.endpt, &inv_cb); 
    1673      
    1674     return status; 
    1675 } 
    1676  
    1677 /** 
    1678  * Replace media transport. 
    1679  */ 
    1680 PJ_DEF(pj_status_t) pjsua_set_call_media_transport( unsigned call_index, 
    1681                                                     const pjmedia_sock_info *i, 
    1682                                                     pjmedia_transport *tp) 
    1683 { 
    1684     pjsua_call *call = &pjsua.calls[call_index]; 
    1685  
    1686     if (i) 
    1687         pj_memcpy(&call->skinfo, i, sizeof(pjmedia_sock_info)); 
    1688      
    1689     if (call->med_tp) 
    1690         (*call->med_tp->op->destroy)(call->med_tp); 
    1691  
    1692     call->med_tp = tp; 
    1693     return PJ_SUCCESS; 
    1694 } 
     2258 
     2259 
     2260    PJSUA_UNLOCK(); 
     2261} 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c

    r492 r503  
    1818 */ 
    1919#include <pjsua-lib/pjsua.h> 
    20 #include "pjsua_imp.h" 
    21  
    22 /* 
    23  * pjsua_core.c 
     20#include <pjsua-lib/pjsua_internal.h> 
     21 
     22 
     23#define THIS_FILE   "pjsua_core.c" 
     24 
     25 
     26/* PJSUA application instance. */ 
     27struct pjsua_data pjsua_var; 
     28 
     29 
     30/* Display error */ 
     31PJ_DEF(void) pjsua_perror( const char *sender, const char *title,  
     32                           pj_status_t status) 
     33{ 
     34    char errmsg[PJ_ERR_MSG_SIZE]; 
     35 
     36    pj_strerror(status, errmsg, sizeof(errmsg)); 
     37    PJ_LOG(3,(sender, "%s: %s [status=%d]", title, errmsg, status)); 
     38} 
     39 
     40 
     41static void init_data() 
     42{ 
     43    unsigned i; 
     44 
     45    for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.acc); ++i) 
     46        pjsua_var.acc[i].index = i; 
     47     
     48    for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.tpdata); ++i) 
     49        pjsua_var.tpdata[i].index = i; 
     50} 
     51 
     52 
     53 
     54/***************************************************************************** 
     55 * This is a very simple PJSIP module, whose sole purpose is to display 
     56 * incoming and outgoing messages to log. This module will have priority 
     57 * higher than transport layer, which means: 
    2458 * 
    25  * Core application functionalities. 
    26  */ 
    27  
    28 #define THIS_FILE   "pjsua_core.c" 
    29  
    30  
    31 /*  
    32  * Global variable. 
    33  */ 
    34 struct pjsua pjsua; 
    35  
    36  
    37 /*  
    38  * Default local URI, if none is specified in cmd-line  
    39  */ 
    40 #define PJSUA_LOCAL_URI     "<sip:user@127.0.0.1>" 
    41  
    42  
    43  
    44 /* 
    45  * Init default application parameters. 
    46  */ 
    47 PJ_DEF(void) pjsua_default_config(pjsua_config *cfg) 
    48 { 
    49     unsigned i; 
    50  
    51     pj_memset(cfg, 0, sizeof(pjsua_config)); 
    52  
    53     cfg->thread_cnt = 1; 
    54     cfg->media_has_ioqueue = 1; 
    55     cfg->media_thread_cnt = 1; 
    56     cfg->udp_port = 5060; 
    57     cfg->start_rtp_port = 4000; 
    58     cfg->msg_logging = PJ_TRUE; 
    59     cfg->max_calls = 4; 
    60     cfg->conf_ports = 0; 
    61  
    62 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 
    63     pjsua.clock_rate = 44100; 
    64 #endif 
    65  
    66     cfg->complexity = 10; 
    67     cfg->quality = 10; 
     59 *  - incoming messages will come to this module first before reaching 
     60 *    transaction layer. 
     61 * 
     62 *  - outgoing messages will come to this module last, after the message 
     63 *    has been 'printed' to contiguous buffer by transport layer and 
     64 *    appropriate transport instance has been decided for this message. 
     65 * 
     66 */ 
     67 
     68/* Notification on incoming messages */ 
     69static pj_bool_t logging_on_rx_msg(pjsip_rx_data *rdata) 
     70{ 
     71    PJ_LOG(4,(THIS_FILE, "RX %d bytes %s from %s:%d:\n" 
     72                         "%s\n" 
     73                         "--end msg--", 
     74                         rdata->msg_info.len, 
     75                         pjsip_rx_data_get_info(rdata), 
     76                         rdata->pkt_info.src_name, 
     77                         rdata->pkt_info.src_port, 
     78                         rdata->msg_info.msg_buf)); 
    6879     
    69     cfg->auto_answer = 100; 
    70     cfg->uas_duration = 3600; 
    71  
    72     /* Default logging settings: */ 
    73     cfg->log_level = 5; 
    74     cfg->app_log_level = 4; 
    75     cfg->log_decor =  PJ_LOG_HAS_SENDER | PJ_LOG_HAS_TIME |  
    76                       PJ_LOG_HAS_MICRO_SEC | PJ_LOG_HAS_NEWLINE; 
    77  
    78  
    79     /* Also init logging settings in pjsua.config, because log 
    80      * may be written before pjsua_init() is called. 
     80    /* Always return false, otherwise messages will not get processed! */ 
     81    return PJ_FALSE; 
     82} 
     83 
     84/* Notification on outgoing messages */ 
     85static pj_status_t logging_on_tx_msg(pjsip_tx_data *tdata) 
     86{ 
     87     
     88    /* Important note: 
     89     *  tp_info field is only valid after outgoing messages has passed 
     90     *  transport layer. So don't try to access tp_info when the module 
     91     *  has lower priority than transport layer. 
    8192     */ 
    82     pjsua.config.log_level = 5; 
    83     pjsua.config.app_log_level = 4; 
    84  
    85  
    86     /* Init accounts: */ 
    87     for (i=0; i<PJ_ARRAY_SIZE(pjsua.acc); ++i) { 
    88         cfg->acc_config[i].reg_timeout = 55; 
    89     } 
    90  
    91 } 
    92  
    93  
    94 #define strncpy_with_null(dst,src,len)  \ 
    95 do { \ 
    96     strncpy(dst, src, len); \ 
    97     dst[len-1] = '\0'; \ 
    98 } while (0) 
    99  
    100  
    101  
    102 PJ_DEF(pj_status_t) pjsua_test_config( const pjsua_config *cfg, 
    103                                        char *errmsg, 
    104                                        int len) 
    105 { 
    106     unsigned i; 
    107  
    108     /* If UDP port is zero, then sip_host and sip_port must be specified */ 
    109     if (cfg->udp_port == 0) { 
    110         if (cfg->sip_host.slen==0 || cfg->sip_port==0) { 
    111             strncpy_with_null(errmsg,  
    112                               "sip_host and sip_port must be specified", 
    113                               len); 
    114             return -1; 
    115         } 
    116     } 
    117  
    118     if (cfg->max_calls < 1) { 
    119         strncpy_with_null(errmsg,  
    120                           "max_calls needs to be at least 1", 
    121                           len); 
    122       &nbs