Changeset 503
- Timestamp:
- Jun 13, 2006 10:57:13 PM (19 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 4 added
- 5 deleted
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib/src/pj/config.c
r468 r503 22 22 23 23 static const char *id = "config.c"; 24 const char *PJ_VERSION = "0.5. 5.6";24 const char *PJ_VERSION = "0.5.6.0"; 25 25 26 26 PJ_DEF(void) pj_dump_config(void) -
pjproject/trunk/pjsip-apps/build
- Property svn:ignore
-
old new 8 8 *.suo 9 9 *.pdb 10 activex-pjsua_p.c 11 dlldata.c
-
- Property svn:ignore
-
pjproject/trunk/pjsip-apps/build/activex-pjsua.dsp
r487 r503 324 324 # Begin Source File 325 325 326 SOURCE="..\src\activex-pjsua\pjsua .h"326 SOURCE="..\src\activex-pjsua\pjsua-structs.h" 327 327 # End Source File 328 328 # Begin Source File -
pjproject/trunk/pjsip-apps/build/pjsua.dsp
r458 r503 93 93 SOURCE=..\src\pjsua\main.c 94 94 # End Source File 95 # Begin Source File 96 97 SOURCE=..\src\pjsua\pjsua.c 98 # End Source File 95 99 # End Group 96 100 # 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
-
Property
svn:ignore
set to
-
pjproject/trunk/pjsip-apps/src/pjsua/main.c
r492 r503 18 18 */ 19 19 #include <pjsua-lib/pjsua.h> 20 #include <pjsua-lib/pjsua_console_app.h>21 22 20 23 21 #define THIS_FILE "main.c" 24 22 25 /***************************************************************************** 26 * main(): 23 24 /* 25 * These are defined in pjsua.c. 27 26 */ 27 pj_status_t app_init(int argc, char *argv[]); 28 pj_status_t app_main(void); 29 pj_status_t app_destroy(void); 30 28 31 int main(int argc, char *argv[]) 29 32 { 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) 43 34 return 1; 44 35 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(); 76 38 77 39 return 0; -
pjproject/trunk/pjsip/build/pjsua_lib.dsp
r476 r503 88 88 # Begin Source File 89 89 90 SOURCE="..\src\pjsua-lib\pjsua_ call.c"90 SOURCE="..\src\pjsua-lib\pjsua_acc.c" 91 91 # End Source File 92 92 # Begin Source File 93 93 94 SOURCE="..\src\pjsua-lib\pjsua_c onsole_app.c"94 SOURCE="..\src\pjsua-lib\pjsua_call.c" 95 95 # End Source File 96 96 # Begin Source File … … 104 104 # Begin Source File 105 105 106 SOURCE="..\src\pjsua-lib\pjsua_ imp.h"106 SOURCE="..\src\pjsua-lib\pjsua_media.c" 107 107 # End Source File 108 108 # Begin Source File 109 109 110 110 SOURCE="..\src\pjsua-lib\pjsua_pres.c" 111 # End Source File112 # Begin Source File113 114 SOURCE="..\src\pjsua-lib\pjsua_reg.c"115 # End Source File116 # Begin Source File117 118 SOURCE="..\src\pjsua-lib\pjsua_settings.c"119 111 # End Source File 120 112 # End Group … … 128 120 # Begin Source File 129 121 130 SOURCE="..\include\pjsua-lib\pjsua_ console_app.h"122 SOURCE="..\include\pjsua-lib\pjsua_internal.h" 131 123 # End Source File 132 124 # End Group -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
r492 r503 57 57 */ 58 58 #ifndef PJSUA_MAX_CALLS 59 # define PJSUA_MAX_CALLS 25659 # define PJSUA_MAX_CALLS 32 60 60 #endif 61 61 62 62 63 63 /** 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 /** 64 72 * Maximum accounts. 65 73 */ 66 74 #ifndef PJSUA_MAX_ACC 67 # define PJSUA_MAX_ACC 3275 # define PJSUA_MAX_ACC 8 68 76 #endif 69 77 70 78 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 */ 71 95 typedef int pjsua_acc_id; 96 97 /** Call identification */ 98 typedef int pjsua_call_id; 99 100 /** SIP transport identification */ 101 typedef int pjsua_transport_id; 102 103 /** Buddy identification */ 72 104 typedef int pjsua_buddy_id; 105 106 /** File player identification */ 73 107 typedef int pjsua_player_id; 108 109 /** File recorder identification */ 74 110 typedef int pjsua_recorder_id; 111 112 /** Conference port identification */ 75 113 typedef int pjsua_conf_port_id; 76 114 77 115 116 /** Constant to identify invalid ID for all sorts of IDs. */ 117 #define PJSUA_INVALID_ID (-1) 118 119 120 78 121 /** 79 122 * Account configuration. 80 123 */ 81 struct pjsua_acc_config 82 { 83 /** SIP URL for account ID (mandatory) */ 124 typedef 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 */ 84 132 pj_str_t id; 85 133 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 */ 87 141 pj_str_t reg_uri; 88 142 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 */ 90 148 pj_str_t contact; 91 149 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 */ 99 177 unsigned cred_count; 100 178 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 */ 196 PJ_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 */ 209 typedef 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 */ 266 typedef 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 */ 301 PJ_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 */ 311 typedef 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 */ 344 PJ_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 */ 353 PJ_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 */ 379 PJ_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 */ 403 typedef 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 */ 457 typedef 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 */ 501 PJ_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 */ 516 typedef struct pjsua_logging_config 517 { 518 /** 519 * Log incoming and outgoing SIP message? Yes! 147 520 */ 148 521 pj_bool_t msg_logging; 149 522 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 */ 254 541 pj_str_t log_filename; 255 542 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 */ 559 PJ_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 */ 577 PJ_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 */ 589 typedef 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 */ 607 typedef 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 */ 632 typedef 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 */ 677 typedef 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; 269 695 270 696 … … 272 698 * Application callbacks. 273 699 */ 274 struct pjsua_callback700 typedef struct pjsua_callback 275 701 { 276 702 /** … … 279 705 * detail call states. 280 706 */ 281 void (*on_call_state)( int call_index, pjsip_event *e);707 void (*on_call_state)(pjsua_call_id call_id, pjsip_event *e); 282 708 283 709 /** 284 710 * Notify application on incoming call. 285 711 */ 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, 287 713 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); 288 721 289 722 /** … … 294 727 * transfer. 295 728 */ 296 void (*on_call_transfered)( int call_index,729 void (*on_call_transfered)(pjsua_call_id call_id, 297 730 const pj_str_t *dst, 298 731 pjsip_status_code *code); … … 313 746 /** 314 747 * Notify application on incoming pager (i.e. MESSAGE request). 315 * Argument call_i ndex will be -1 if MESSAGE request is not related to an748 * Argument call_id will be -1 if MESSAGE request is not related to an 316 749 * existing call. 317 750 */ 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); 320 775 321 776 /** 322 777 * Notify application about typing indication. 323 778 */ 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 */ 791 typedef 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 */ 845 PJ_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 */ 857 PJ_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 */ 872 PJ_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 */ 894 typedef 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; 333 901 334 902 … … 336 904 * Call info. 337 905 */ 338 struct pjsua_call_info 339 { 340 unsigned index; 341 pj_bool_t active; 906 typedef struct pjsua_call_info 907 { 908 /** Call identification. */ 909 pjsua_call_id id; 910 911 /** Initial call role (UAC == caller) */ 342 912 pjsip_role_e role; 913 914 /** Local URI */ 343 915 pj_str_t local_info; 916 917 /** Local Contact */ 918 pj_str_t local_contact; 919 920 /** Remote URI */ 344 921 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 */ 345 930 pjsip_inv_state state; 931 932 /** Text describing the state */ 346 933 pj_str_t state_text; 934 935 /** Last status code heard, which can be used as cause code */ 347 936 pjsip_status_code last_status; 937 938 /** The reason phrase describing the status. */ 348 939 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 */ 349 953 pj_time_val connect_duration; 954 955 /** Total call duration, including set-up time */ 350 956 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 */ 976 typedef struct pjsua_conf_port_info 977 { 978 /** Conference port number. */ 979 pjsua_conf_port_id slot_id; 980 981 /** Port name. */ 375 982 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. */ 413 985 unsigned clock_rate; 986 987 /** Number of channels. */ 414 988 unsigned channel_count; 989 990 /** Samples per frame */ 415 991 unsigned samples_per_frame; 992 993 /** Bits per sample */ 416 994 unsigned bits_per_sample; 995 996 /** Number of listeners in the array. */ 417 997 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 */ 1011 typedef 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 */ 1031 typedef 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 */ 1056 PJ_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 } 423 1061 424 1062 425 1063 /***************************************************************************** 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. 446 1075 */ 447 1076 PJ_DECL(pj_status_t) pjsua_create(void); … … 449 1078 450 1079 /** 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 */ 1090 PJ_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. 468 1101 */ 469 1102 PJ_DECL(pj_status_t) pjsua_start(void); 470 1103 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. 473 1111 */ 474 1112 PJ_DECL(pj_status_t) pjsua_destroy(void); 475 1113 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). 478 1124 */ 479 1125 PJ_DECL(int) pjsua_handle_events(unsigned msec_timeout); … … 481 1127 482 1128 /** 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 */ 1137 PJ_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 */ 1149 PJ_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. 485 1158 */ 486 1159 PJ_DECL(pjsip_endpoint*) pjsua_get_pjsip_endpt(void); 487 1160 488 1161 /** 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. 491 1166 */ 492 1167 PJ_DECL(pjmedia_endpt*) pjsua_get_pjmedia_endpt(void); 493 1168 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 501 1169 502 1170 /***************************************************************************** 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 */ 1183 PJ_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 */ 1195 PJ_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 */ 1208 PJ_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 */ 1220 PJ_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 */ 1235 PJ_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 */ 1253 PJ_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 */ 1271 PJ_DECL(pj_status_t) 1272 pjsua_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 */ 1288 PJ_DECL(pj_status_t) 1289 pjsua_media_transports_attach( pjsua_media_transport tp[], 1290 unsigned count, 1291 pj_bool_t auto_delete); 1292 1293 1294 1295 /***************************************************************************** 1296 * PJSUA Call API. 504 1297 */ 505 1298 506 1299 /** 507 1300 * Get maximum number of calls configured in pjsua. 1301 * 1302 * @return Maximum number of calls configured. 508 1303 */ 509 1304 PJ_DECL(unsigned) pjsua_call_get_max_count(void); 510 1305 511 1306 /** 512 * Get current number of active calls. 1307 * Get number of currently active calls. 1308 * 1309 * @return Number of currently active calls. 513 1310 */ 514 1311 PJ_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 */ 1322 PJ_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 */ 1342 PJ_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 515 1349 516 1350 /** 517 1351 * Check if the specified call has active INVITE session and the INVITE 518 1352 * 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 */ 1358 PJ_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 */ 1368 PJ_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 */ 1379 PJ_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 */ 1389 PJ_DECL(pj_status_t) pjsua_call_get_info(pjsua_call_id call_id, 533 1390 pjsua_call_info *info); 534 1391 535 1392 536 1393 /** 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 */ 1401 PJ_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 */ 1412 PJ_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 */ 1427 PJ_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 */ 1447 PJ_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 */ 1462 PJ_DECL(pj_status_t) pjsua_call_set_hold(pjsua_call_id call_id, 1463 const pjsua_msg_data *msg_data); 567 1464 568 1465 569 1466 /** 570 1467 * 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 */ 1477 PJ_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 */ 1492 PJ_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 */ 1504 PJ_DECL(pj_status_t) pjsua_call_dial_dtmf(pjsua_call_id call_id, 584 1505 const pj_str_t *digits); 585 1506 586 587 1507 /** 588 1508 * 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 */ 1522 PJ_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); 591 1527 592 1528 593 1529 /** 594 1530 * 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 */ 1540 PJ_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); 598 1543 599 1544 /** … … 605 1550 /** 606 1551 * 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 */ 1561 PJ_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); 611 1566 612 1567 613 1568 /***************************************************************************** 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 */ 1578 PJ_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 */ 1588 PJ_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 */ 1606 PJ_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 */ 1627 PJ_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 */ 1638 PJ_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 */ 1649 PJ_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 */ 1662 PJ_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 */ 1675 PJ_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. 625 1686 */ 626 1687 PJ_DECL(pj_status_t) pjsua_acc_get_info(pjsua_acc_id acc_id, … … 629 1690 630 1691 /** 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 */ 1700 PJ_DECL(pj_status_t) pjsua_enum_accs(pjsua_acc_id ids[], 1701 unsigned *count ); 635 1702 636 1703 637 1704 /** 638 1705 * 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. 639 1712 */ 640 1713 PJ_DECL(pj_status_t) pjsua_acc_enum_info( pjsua_acc_info info[], … … 643 1716 644 1717 /** 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. 646 1724 */ 647 1725 PJ_DECL(pjsua_acc_id) pjsua_acc_find_for_outgoing(const pj_str_t *url); 648 1726 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. 651 1735 */ 652 1736 PJ_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 start658 * 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 683 1737 684 1738 … … 689 1743 690 1744 /** 691 * Get buddy count. 1745 * Get total number of buddies. 1746 * 1747 * @return Number of buddies. 692 1748 */ 693 1749 PJ_DECL(unsigned) pjsua_get_buddy_count(void); … … 695 1751 696 1752 /** 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 */ 1759 PJ_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 */ 1772 PJ_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 */ 1783 PJ_DECL(pj_status_t) pjsua_buddy_get_info(pjsua_buddy_id buddy_id, 700 1784 pjsua_buddy_info *info); 701 1785 702 1786 /** 703 1787 * 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 */ 1794 PJ_DECL(pj_status_t) pjsua_buddy_add(const pjsua_buddy_config *cfg, 1795 pjsua_buddy_id *p_buddy_id); 707 1796 708 1797 709 1798 /** 710 1799 * 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 */ 1805 PJ_DECL(pj_status_t) pjsua_buddy_del(pjsua_buddy_id buddy_id); 713 1806 714 1807 715 1808 /** 716 1809 * 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 */ 1817 PJ_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 */ 1826 PJ_DECL(void) pjsua_pres_dump(pj_bool_t verbose); 726 1827 727 1828 … … 738 1839 739 1840 /** 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 */ 1857 PJ_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); 744 1863 745 1864 746 1865 /** 747 1866 * 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 */ 1877 PJ_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); 751 1881 752 1882 753 1883 754 1884 /***************************************************************************** 755 * Media.1885 * Conference bridge manipulation. 756 1886 */ 757 1887 758 1888 /** 759 1889 * 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 */ 1893 PJ_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 */ 1901 PJ_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 */ 1914 PJ_DECL(pj_status_t) pjsua_enum_conf_ports(pjsua_conf_port_id id[], 1915 unsigned *count); 769 1916 770 1917 771 1918 /** 772 1919 * 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. 773 1925 */ 774 1926 PJ_DECL(pj_status_t) pjsua_conf_get_port_info( pjsua_conf_port_id id, … … 777 1929 778 1930 /** 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 */ 1946 PJ_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 */ 1958 PJ_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. 794 1977 */ 795 1978 PJ_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. 801 1990 */ 802 1991 PJ_DECL(pjsua_conf_port_id) pjsua_player_get_conf_port(pjsua_player_id id); … … 805 1994 /** 806 1995 * 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. 807 2002 */ 808 2003 PJ_DECL(pj_status_t) pjsua_player_set_pos(pjsua_player_id id, … … 811 2006 812 2007 /** 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. 814 2014 */ 815 2015 PJ_DECL(pj_status_t) pjsua_player_destroy(pjsua_player_id id); 816 2016 817 2017 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. 821 2040 */ 822 2041 PJ_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); 824 2048 825 2049 826 2050 /** 827 2051 * Get conference port associated with recorder. 2052 * 2053 * @param id The recorder ID. 2054 * 2055 * @return Conference port ID associated with this recorder. 828 2056 */ 829 2057 PJ_DECL(pjsua_conf_port_id) pjsua_recorder_get_conf_port(pjsua_recorder_id id); … … 831 2059 832 2060 /** 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. 834 2066 */ 835 2067 PJ_DECL(pj_status_t) pjsua_recorder_destroy(pjsua_recorder_id id); 836 2068 837 2069 2070 /***************************************************************************** 2071 * Sound devices. 2072 */ 2073 838 2074 /** 839 2075 * 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 */ 2084 PJ_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 */ 2097 PJ_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 */ 2108 PJ_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 */ 2125 PJ_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 */ 2138 PJ_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 */ 2150 PJ_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 */ 2162 PJ_DECL(pj_status_t) pjsua_codec_set_param( const pj_str_t *id, 2163 const pjmedia_codec_param *param); 2164 2165 2166 852 2167 853 2168 … … 857 2172 */ 858 2173 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 897 2174 /* 898 2175 * 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. 900 2180 */ 901 2181 PJ_DECL(pj_status_t) pjsua_verify_sip_url(const char *c_url); 902 2182 903 /*904 * Dump application states.905 */906 PJ_DECL(void) pjsua_dump(pj_bool_t detail);907 2183 908 2184 /** 909 2185 * 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. 910 2190 */ 911 2191 PJ_DECL(void) pjsua_perror(const char *sender, const char *title, -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
r492 r503 18 18 */ 19 19 #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 */ 29 static 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 */ 35 static 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 */ 43 static 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 */ 49 static 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 */ 58 static 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 */ 64 static pj_status_t call_destroy_media(int call_id); 65 66 /* Create inactive SDP for call hold. */ 67 static pj_status_t create_inactive_sdp(pjsua_call *call, 68 pjmedia_sdp_session **p_answer); 69 70 71 /* 72 * Reset call descriptor. 73 */ 74 static 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 */ 93 pj_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 */ 126 pj_status_t pjsua_call_subsys_start(void) 127 { 128 /* Nothing to do */ 123 129 return PJ_SUCCESS; 124 130 } 125 131 126 132 127 /* *133 /* 128 134 * Get maximum number of calls configured in pjsua. 129 135 */ 130 136 PJ_DEF(unsigned) pjsua_call_get_max_count(void) 131 137 { 132 return pjsua .config.max_calls;133 } 134 135 136 /* *137 * Get current number ofactive calls.138 return pjsua_var.ua_cfg.max_calls; 139 } 140 141 142 /* 143 * Get number of currently active calls. 138 144 */ 139 145 PJ_DEF(unsigned) pjsua_call_get_count(void) 140 146 { 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 */ 154 PJ_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(); 220 173 221 174 return PJ_SUCCESS; … … 223 176 224 177 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 */ 181 PJ_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) 251 187 { 252 188 pjsip_dialog *dlg = NULL; 253 189 pjmedia_sdp_session *offer; 254 190 pjsip_inv_session *inv = NULL; 255 unsigned call_index; 191 pjsua_acc *acc; 192 pjsua_call *call; 193 unsigned call_id; 256 194 pjsip_tx_data *tdata; 257 195 pj_status_t status; 258 196 259 197 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), 261 200 PJ_EINVAL); 262 201 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 } 263 214 264 215 /* Find free call slot. */ 265 for (call_i ndex=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) 267 218 break; 268 219 } 269 220 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(); 272 224 return PJ_ETOOMANY; 273 225 } 274 226 227 call = &pjsua_var.calls[call_id]; 228 275 229 /* Mark call start time. */ 276 pj_gettimeofday(& pjsua.calls[call_index].start_time);230 pj_gettimeofday(&call->start_time); 277 231 278 232 /* Reset first response time */ 279 pjsua.calls[call_index].res_time.sec = 0;233 call->res_time.sec = 0; 280 234 281 235 /* Create outgoing dialog: */ 282 236 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); 287 239 if (status != PJ_SUCCESS) { 288 240 pjsua_perror(THIS_FILE, "Dialog creation failed", status); 241 PJSUA_UNLOCK(); 289 242 return status; 290 243 } … … 292 245 /* Get media capability from media endpoint: */ 293 246 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); 297 249 if (status != PJ_SUCCESS) { 298 250 pjsua_perror(THIS_FILE, "pjmedia unable to create SDP", status); … … 311 263 /* Create and associate our data in the session. */ 312 264 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; 318 272 319 273 /* 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); 323 276 324 277 325 278 /* 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) { 328 280 pjsip_auth_clt_set_credentials( &dlg->auth_sess, 329 acc_cfg->cred_count, 330 acc_cfg->cred_info); 281 acc->cred_cnt, acc->cred); 331 282 } 332 283 … … 341 292 } 342 293 294 295 /* Add additional headers etc */ 296 297 pjsua_process_msg_data( tdata, msg_data); 343 298 344 299 /* Send initial INVITE: */ … … 357 312 } 358 313 359 360 314 /* Done. */ 361 315 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(); 366 322 367 323 return PJ_SUCCESS; … … 375 331 } 376 332 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(); 411 338 return status; 412 339 } … … 415 342 /** 416 343 * Handle incoming INVITE request. 344 * Called by pjsua_core.c 417 345 */ 418 346 pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata) … … 424 352 unsigned options = 0; 425 353 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; 428 357 pjmedia_sdp_session *answer; 429 358 pj_status_t status; … … 442 371 /* Verify that we can handle the request. */ 443 372 status = pjsip_inv_verify_request(rdata, &options, NULL, NULL, 444 pjsua .endpt, &response);373 pjsua_var.endpt, &response); 445 374 if (status != PJ_SUCCESS) { 446 375 … … 453 382 454 383 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, 456 385 NULL, NULL); 457 386 … … 459 388 460 389 /* 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, 462 391 NULL, NULL); 463 392 } … … 472 401 473 402 /* Find free call slot. */ 474 for (call_i ndex=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) 476 405 break; 477 406 } 478 407 479 if (call_i ndex == 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, 481 410 PJSIP_SC_BUSY_HERE, NULL, 482 411 NULL, NULL); … … 484 413 } 485 414 415 /* Clear call descriptor */ 416 reset_call(call_id); 417 418 call = &pjsua_var.calls[call_id]; 419 486 420 /* 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); 491 422 492 423 /* 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, 499 429 NULL, NULL); 500 501 430 return PJ_TRUE; 502 431 } 503 432 504 /* TODO: 505 * 433 /* 506 434 * Get which account is most likely to be associated with this incoming 507 435 * call. We need the account to find which contact URI to put for 508 436 * the call. 509 437 */ 510 acc_i ndex = 0;438 acc_id = pjsua_acc_find_for_incoming(rdata); 511 439 512 440 /* Create dialog: */ 513 514 441 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, 516 443 &dlg); 517 444 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, 519 446 NULL, NULL); 520 447 … … 522 449 } 523 450 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 } 524 457 525 458 /* Create invite session: */ 526 527 459 status = pjsip_inv_create_uas( dlg, rdata, answer, 0, &inv); 528 460 if (status != PJ_SUCCESS) { 529 530 461 pjsip_dlg_respond(dlg, rdata, 500, NULL, NULL, NULL); 531 462 pjsip_dlg_terminate(dlg); … … 534 465 535 466 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; 542 472 543 473 … … 545 475 * If auto-answer flag is set, send 200 straight away, otherwise send 100. 546 476 */ 547 548 477 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) { 556 480 pjsua_perror(THIS_FILE, "Unable to send answer to incoming INVITE", 557 481 status); 558 482 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); 569 485 return PJ_TRUE; 570 486 … … 575 491 } 576 492 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 615 495 616 496 /* 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); 620 499 621 500 /* This INVITE request has been handled. */ … … 624 503 625 504 505 506 /* 507 * Check if the specified call has active INVITE session and the INVITE 508 * session has not been disconnected. 509 */ 510 PJ_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 */ 522 PJ_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 */ 533 PJ_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 */ 544 PJ_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 */ 669 PJ_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 */ 683 PJ_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 */ 694 PJ_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 */ 744 PJ_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 */ 816 PJ_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 */ 877 PJ_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 */ 945 PJ_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 */ 1015 PJ_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 */ 1045 PJ_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 1124 on_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 */ 1134 PJ_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 1181 on_return: 1182 pjsip_dlg_dec_lock(call->inv->dlg); 1183 PJSUA_UNLOCK(); 1184 return status; 1185 } 1186 1187 1188 /* 1189 * Terminate all calls. 1190 */ 1191 PJ_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 1206 static 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 */ 1225 static 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 */ 1411 static 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 */ 1443 PJ_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 */ 1530 static 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 626 1555 /* 627 1556 * This callback receives notification from invite session when the … … 631 1560 pjsip_event *e) 632 1561 { 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(); 636 1570 return; 1571 } 1572 637 1573 638 1574 /* Get call times */ … … 643 1579 pj_gettimeofday(&call->res_time); 644 1580 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_)); 645 1584 break; 646 1585 case PJSIP_INV_STATE_CONFIRMED: … … 651 1590 if (e->body.tsx_state.tsx->status_code > call->last_code) { 652 1591 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_)); 653 1595 } 654 1596 break; 655 1597 default: 656 1598 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_)); 657 1602 break; 658 1603 } … … 717 1662 718 1663 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); 721 1666 722 1667 /* call->inv may be NULL now */ … … 730 1675 call_destroy_media(call->index); 731 1676 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 736 1677 /* Free call */ 737 1678 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 } 959 1684 960 1685 /* … … 971 1696 } 972 1697 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 01075 /* 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 #endif1091 1698 1092 1699 /* … … 1098 1705 pj_status_t status) 1099 1706 { 1707 int prev_media_st = 0; 1100 1708 pjsua_call *call; 1101 1709 pjmedia_session_info sess_info; … … 1106 1714 char tmp[PJSIP_MAX_URL_SIZE]; 1107 1715 1108 call = inv->dlg->mod_data[pjsua.mod.id]; 1716 PJSUA_LOCK(); 1717 1718 call = inv->dlg->mod_data[pjsua_var.mod.id]; 1109 1719 1110 1720 if (status != PJ_SUCCESS) { … … 1120 1730 //call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE); 1121 1731 } 1732 1733 PJSUA_UNLOCK(); 1122 1734 return; 1123 1124 1735 } 1125 1736 1126 1737 /* Destroy existing media session, if any. */ 1127 1738 1128 if (call) 1739 if (call) { 1740 prev_media_st = call->media_st; 1129 1741 call_destroy_media(call->index); 1742 } 1130 1743 1131 1744 /* Get local and remote SDP */ … … 1137 1750 status); 1138 1751 //call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE); 1752 PJSUA_UNLOCK(); 1139 1753 return; 1140 1754 } … … 1147 1761 status); 1148 1762 //call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE); 1763 PJSUA_UNLOCK(); 1149 1764 return; 1150 1765 } 1151 1152 if (pjsua.config.null_audio)1153 return;1154 1766 1155 1767 /* Create media session info based on SDP parameters. … … 1157 1769 */ 1158 1770 status = pjmedia_session_info_from_sdp( call->inv->dlg->pool, 1159 pjsua .med_endpt,1771 pjsua_var.med_endpt, 1160 1772 1,&sess_info, 1161 1773 local_sdp, remote_sdp); … … 1164 1776 status); 1165 1777 //call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE); 1778 PJSUA_UNLOCK(); 1166 1779 return; 1167 1780 } 1168 1781 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) 1227 1785 { 1228 1786 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 } 1254 1795 } 1255 1796 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. */ 1263 1857 { 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;1272 1858 char info[80]; 1273 1859 int info_len = 0; 1274 1860 unsigned i; 1275 1861 1276 pjmedia_session_get_info(call->session, &sess_info);1277 1862 for (i=0; i<sess_info.stream_cnt; ++i) { 1278 1863 int len; … … 1305 1890 info_len += len; 1306 1891 } 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 */ 1907 static 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 */ 1950 static void pjsua_call_on_rx_offer(pjsip_inv_session *inv, 1951 const pjmedia_sdp_session *offer) 1952 { 1953 const char *remote_state; 1317 1954 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 */ 2021 static 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 */ 2048 static void on_call_transfered( pjsip_inv_session *inv, 2049 pjsip_rx_data *rdata ) 2050 { 1319 2051 pj_status_t status; 1320 2052 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); 1327 2075 return; 1328 2076 } 1329 2077 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); 1342 2089 return; 1343 2090 } 1344 2091 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. 1348 2132 */ 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 } 1350 2157 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. 1475 2163 */ 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 */ 2179 static 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; 1647 2226 } 1648 2227 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 } 1652 2256 } 1653 2257 } 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 18 18 */ 19 19 #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. */ 27 struct pjsua_data pjsua_var; 28 29 30 /* Display error */ 31 PJ_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 41 static 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: 24 58 * 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 */ 69 static 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)); 68 79 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 log80 * 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 */ 85 static 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. 81 92 */ 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