Compare commits

...

225 Commits
master ... 1.x

Author SHA1 Message Date
Perry Ismangil ef4f1a7962 Tidying branches for git migration
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/archives/1.x@5236 74dad513-b988-da41-8d7b-12977e46ad98
2016-01-23 04:27:33 +00:00
Nanang Izzuddin e1a49e9707 Changed version to 1.16-svn
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4431 74dad513-b988-da41-8d7b-12977e46ad98
2013-03-07 10:56:54 +00:00
Nanang Izzuddin 484ef33f2a Changed version to 1.16
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4429 74dad513-b988-da41-8d7b-12977e46ad98
2013-03-07 09:35:20 +00:00
Sauw Ming 180571ca9b Fixed #1635: Fixed the backport of ticket #1568 (smarter media update) to version 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4428 74dad513-b988-da41-8d7b-12977e46ad98
2013-03-07 08:25:35 +00:00
Nanang Izzuddin 75d644cb9c Misc (re #1634): fixed compile warnings on Symbian platform.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4427 74dad513-b988-da41-8d7b-12977e46ad98
2013-03-07 06:04:43 +00:00
Riza Sulistyo 1b28148b58 Misc (re #1634): fixed compile errors/warnings on MSVC
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4426 74dad513-b988-da41-8d7b-12977e46ad98
2013-03-07 05:08:10 +00:00
Nanang Izzuddin 6d74e9bf8d Re 1394 and re #1531: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4410 74dad513-b988-da41-8d7b-12977e46ad98
2013-03-01 03:46:45 +00:00
Riza Sulistyo 14c9f87ff0 Re #1604: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4409 74dad513-b988-da41-8d7b-12977e46ad98
2013-03-01 03:04:16 +00:00
Riza Sulistyo 61d29933fb Re #1627: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4408 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 15:05:29 +00:00
Riza Sulistyo 82e6c63042 Re #1620: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4407 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 15:02:03 +00:00
Riza Sulistyo b9e110ac0f Re #1619: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4406 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 14:55:02 +00:00
Riza Sulistyo 7e15a033b3 Re #1618: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4405 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 14:51:34 +00:00
Riza Sulistyo feb5c59039 Re #1615: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4404 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 14:47:37 +00:00
Riza Sulistyo 59c958dcda Re #1613: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4403 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 14:43:38 +00:00
Sauw Ming 9024184b74 Re #1599: Backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4402 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 14:41:32 +00:00
Riza Sulistyo f6eb3e66ff Re #1611: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4401 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 14:38:36 +00:00
Riza Sulistyo 23f62f41fc Re #1610: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4400 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 14:31:05 +00:00
Riza Sulistyo c9a2760650 Re #1609: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4399 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 14:26:03 +00:00
Riza Sulistyo 9d43c9c538 Re #1607: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4398 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 14:18:20 +00:00
Riza Sulistyo fdfbdf0455 Re #1603: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4397 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 13:44:48 +00:00
Sauw Ming 591a5caf79 Re #1596: Backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4396 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 12:12:59 +00:00
Sauw Ming d6372ce634 Re #1593: Backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4395 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 12:07:30 +00:00
Sauw Ming c7e64ef672 Re #1592: Backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4394 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 12:02:42 +00:00
Sauw Ming a2dbe98b0b Re #1583: Backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4393 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 11:57:43 +00:00
Sauw Ming 06cb5fc792 Re #1573: Backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4392 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 11:42:24 +00:00
Sauw Ming b91c3f689a Re #1566: Backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4391 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 11:39:03 +00:00
Sauw Ming 864e7129e3 Re #1565: Backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4390 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 11:37:02 +00:00
Sauw Ming 86b1195389 Re #1563: Backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4389 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 10:44:04 +00:00
Sauw Ming b3362da1d9 Re #1560: Backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4388 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 10:41:22 +00:00
Sauw Ming 2b53792c09 Re #1559: Backported to 1.x, except r4312,r4330
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4387 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 10:16:08 +00:00
Nanang Izzuddin fa6ed22257 Re #1557: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4386 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 10:14:23 +00:00
Nanang Izzuddin 6f520daa20 Re #1556: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4385 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 10:11:59 +00:00
Nanang Izzuddin ff878537a4 Re #1552: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4384 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 10:08:07 +00:00
Nanang Izzuddin 6a25762e3e Re #1551: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4383 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 10:06:06 +00:00
Nanang Izzuddin 89dc94199c Re #1550: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4382 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 10:04:18 +00:00
Nanang Izzuddin 61c42a0769 Re #1549: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4381 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 10:02:04 +00:00
Nanang Izzuddin 6daad56e29 Re #1539: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4380 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 09:57:58 +00:00
Nanang Izzuddin 9fd914b0d9 Re #1535: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4379 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 09:54:51 +00:00
Nanang Izzuddin 0c23c41c80 Re #1532: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4378 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 09:50:59 +00:00
Nanang Izzuddin a235c608ac Re #1530: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4377 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 09:45:52 +00:00
Nanang Izzuddin 72d68ae915 Re #1522: backported to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4376 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 09:41:37 +00:00
Sauw Ming dfd18708e1 Re #1558: backported r4209,r4210 to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4375 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-27 09:28:31 +00:00
Nanang Izzuddin b43138ce99 Re #1568: (PJSIP 1.x) No need to restart media when remote RTP address changed but ICE transport is running.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4346 74dad513-b988-da41-8d7b-12977e46ad98
2013-02-13 08:20:33 +00:00
Nanang Izzuddin 79fb3506ce Re #1568: (only for 1.x) media transport should be (re)started even when media is unchanged.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4338 74dad513-b988-da41-8d7b-12977e46ad98
2013-01-30 04:04:23 +00:00
Sauw Ming b4873f8a1f Re #1568: (PJSIP 1.x) Apply pjsua_media_config before detecting media change
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4337 74dad513-b988-da41-8d7b-12977e46ad98
2013-01-29 08:24:10 +00:00
Sauw Ming 3d0dc6bb4e Re #1568: Fixed is_media_changed() detection when pjsua_media_cfg.no_vad is set to PJ_TRUE and fixed the string duplication of encoding name
Thanks to Hideo and Fredrik for the reports.



git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4334 74dad513-b988-da41-8d7b-12977e46ad98
2013-01-25 06:31:05 +00:00
Nanang Izzuddin 4a32d88622 Re #1568: backported to 1.x branch.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4329 74dad513-b988-da41-8d7b-12977e46ad98
2013-01-23 02:57:30 +00:00
Sauw Ming de259d5b1c Fixed #1584: Custom media transport creation callback is not always called
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4261 74dad513-b988-da41-8d7b-12977e46ad98
2012-09-18 09:41:22 +00:00
Nanang Izzuddin 6080ac4ccc Changed version to 1.14.2-svn
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4144 74dad513-b988-da41-8d7b-12977e46ad98
2012-05-22 12:15:56 +00:00
Nanang Izzuddin 7e1a8756fe Changed version to 1.14.2
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4142 74dad513-b988-da41-8d7b-12977e46ad98
2012-05-22 11:30:26 +00:00
Nanang Izzuddin 2bbf301b1b Fix #1505: pjsua_acc_modify() performs unregistration first when account id, registrar, or forced contact is modified.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4127 74dad513-b988-da41-8d7b-12977e46ad98
2012-05-17 08:04:58 +00:00
Nanang Izzuddin e9984d9969 Fix #1499: Crash in libsrtp when handling certain RTCP packets, more info:
- Applied patch from: http://srtp.cvs.sourceforge.net/viewvc/srtp/srtp/crypto/replay/rdb.c?r1=1.4&r2=1.5.
 - Original libsrtp ticket #3280295:
http://sourceforge.net/tracker/?func=detail&aid=3280295&group_id=38894&atid=423799.



git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4126 74dad513-b988-da41-8d7b-12977e46ad98
2012-05-17 03:51:11 +00:00
Nanang Izzuddin 413f7802b2 Fix #1510: sharing and assertion problem with native ALSA device.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4125 74dad513-b988-da41-8d7b-12977e46ad98
2012-05-17 03:34:35 +00:00
Nanang Izzuddin 05bf6b88f5 Misc (re #1503): Fixed typo in PJMEDIA_JBUF_PRO_DISC_MAX_BURST doxygen.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4124 74dad513-b988-da41-8d7b-12977e46ad98
2012-05-17 03:31:02 +00:00
Benny Prijono 76ae4d5383 Misc fixes (re #1503): parsing PJ_VERSION in setup.py
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4121 74dad513-b988-da41-8d7b-12977e46ad98
2012-05-14 10:42:56 +00:00
Nanang Izzuddin 17672b71a5 Fix #1507: Added TLS support in pjsua_transport_get_info().
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4119 74dad513-b988-da41-8d7b-12977e46ad98
2012-05-11 08:41:28 +00:00
Nanang Izzuddin f47f0bb63a Misc (re #1503): fixed switchboard pjmedia_conf_connect_port() return code on channel count mismatch.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4117 74dad513-b988-da41-8d7b-12977e46ad98
2012-05-03 04:05:10 +00:00
Nanang Izzuddin a50f513484 Fix #1502: break the fill_buffer() loop on EOF when PJMEDIA_FILE_NO_LOOP option is set.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4116 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-30 17:33:03 +00:00
Nanang Izzuddin 665ca37a5d Changed version to 1.14-svn
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4111 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-27 08:42:06 +00:00
Nanang Izzuddin ef6e6bdc49 Changed version to 1.14
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4109 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-27 07:36:13 +00:00
Benny Prijono c6b4404efe Misc (re #1417): fixed error in the configure script when displaying failure message
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4107 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-27 01:22:15 +00:00
Benny Prijono 7256578581 Misc (re #1417): fixed compilation warnings about missing return value in pjlib echo server test application
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4105 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-26 23:45:09 +00:00
Benny Prijono 8cdfe3c9b2 Misc (re #1417): fixed warnings regarding mismatched argument type in stream compilation on gcc/Linux
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4104 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-26 23:43:40 +00:00
Benny Prijono e9b50574aa Misc (re #1417): normalize the error status returned by pj_getaddrinfo() to PJ_ERESOLVE, because this error is treated specially to trigger SIP status code 502. This was suspected to have caused pjsip unit test to fail in the regc test
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4103 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-26 23:42:27 +00:00
Nanang Izzuddin ac0d2e22ae Misc (re #1417): fixed compile error on Symbian 5th ed SDK.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4098 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-26 15:58:49 +00:00
Nanang Izzuddin bfe43ff6cc Misc (re #1417): reverted back accidental jbuf modification in r4004.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4097 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-26 15:42:38 +00:00
Benny Prijono c0a2e0ae8d Fixed #1495: UDP keep-alive is still running even after account is deleted. It cannot be updated with pjsua_acc_modify() either
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4095 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-26 11:53:33 +00:00
Benny Prijono 761d27ebf4 Misc (re #1417): fixed failed reg_test in pjsip unit test due to wrong status code expected and actually received
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4093 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-26 09:26:07 +00:00
Benny Prijono 2c6c6f3fe5 Indirectly related to re #1465: acquire transport reference when invoking transport send(), to prevent transport from being destroyed accidently while sending is in progress, and also to reset the idle timer
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4092 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-26 09:24:50 +00:00
Benny Prijono e539af61fc More re #1465: Set the default idle time to 33 from 30. With 30, some pjsip unit tests fail because the TCP transport is closed prematurely before the test completes. This should not happen in the real life as long as app uses a client transaction to send a request. The unit test uses stateless send which does not add ref_count to the transport, that is why the transport is closed prepaturely before 32 seconds (the transaction timeout interval)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4091 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-26 09:20:07 +00:00
Sauw Ming 06271acf5a Fixed #1494: Use EC options to determine whether to use device/software EC
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4079 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-24 10:26:07 +00:00
Sauw Ming ffe509ef22 Re #1417 (misc): Fixed output path for AEC test for iOS support.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4074 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-24 07:38:41 +00:00
Sauw Ming 0bef1aba2a Re #1417: Fixed error handling if pjsip_timer_init_session() when accepting incoming call and fixed typo in assertion in sip_inv.c
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4067 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-23 10:22:49 +00:00
Nanang Izzuddin 168308f986 Misc (re #1417): removed sip_transport_tls_ossl.c from vs2005 project.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4066 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-23 03:57:20 +00:00
Benny Prijono d7c9c30696 Fixed #1492: The echo options field in the media config and pjsua_set_ec() argument are ignored
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4065 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-21 02:17:07 +00:00
Benny Prijono c50297e31a Fixed #1491: Failed to refresh (presence) subscription if Subscription-State header contains no "expires" parameter
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4064 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-20 09:59:51 +00:00
Nanang Izzuddin ae93d09763 Fix #1490: frame type 15, instead of 14, should be assigned for zero length AMR-NB frames.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4063 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-20 03:19:42 +00:00
Benny Prijono 8e9c6e155b Fixed #1487: Wrong SDP negotiator state if outgoing UPDATE or re-INVITE is challenged with 401 or 407
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4046 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-13 04:28:26 +00:00
Benny Prijono 4d3be48784 Misc re #1417: wrongly mentioned pjsip_apps.c instead of pjsua_app.c in the documentation of pjsua_msg_data
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4045 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-13 04:13:24 +00:00
Nanang Izzuddin 448f23a045 Fix #1484: apply and send re-register when registration timeout/expire setting is changed in pjsua_modify_acc().
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4041 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-12 08:51:22 +00:00
Nanang Izzuddin bf1be63d75 Fix #1483: make sure that the CRC calculation of account proxy setting is done after proxy URI normalization.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4039 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-12 08:04:03 +00:00
Benny Prijono 15d1719fbc More re #1481: Destroying the regc may lead to dangling binding in the register, so instead of destroying the regc, instruct it to release the transport instead
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4037 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-11 09:41:25 +00:00
Benny Prijono f1e64e5d43 Fixed #1481: Immediately destroy the registration instance when TCP/TLS transport gets disconnected
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4033 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-10 05:46:04 +00:00
Benny Prijono 1bfa740df3 More re #1465: introduce separate idle timeout setting for server side TCP/TLS connection and set the default to 600 seconds
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4032 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-10 03:48:22 +00:00
Nanang Izzuddin 724fef1964 Fix #1480: update read buffer pointer after updating buffer in pjmedia_wav_player_port_set_pos().
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4030 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-09 06:56:57 +00:00
Benny Prijono 41a3ea908e Re #1417: removed the obsolete but misleading sip_transport_tls_ossl.c file
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@4004 74dad513-b988-da41-8d7b-12977e46ad98
2012-04-02 08:30:58 +00:00
Nanang Izzuddin 27d72771e5 Fix #1471: Just return PJ_FALSE on any incoming STUN packets after the STUN socket has been disassociated from ICE stream transport.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3991 74dad513-b988-da41-8d7b-12977e46ad98
2012-03-29 04:17:06 +00:00
Nanang Izzuddin bc983ad574 Fix #1470: Make sure the transaction layer module is unloaded when SIP endpoint is destroyed, by rescheduling the unload (using SIP endpoint atexit callback) after unload failure due to any pending/undestroyed transaction.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3989 74dad513-b988-da41-8d7b-12977e46ad98
2012-03-28 07:49:54 +00:00
Nanang Izzuddin 3afc159959 Re #1466: Moved down the atexit callbacks execution in pjmedia & pjsip endpoints to the very end of endpoint destroy sequence.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3988 74dad513-b988-da41-8d7b-12977e46ad98
2012-03-28 07:32:42 +00:00
Benny Prijono 1830ad187e Re #1417 (misc): added that app should call pj_srand() initially in pj_init() documentation
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3987 74dad513-b988-da41-8d7b-12977e46ad98
2012-03-23 08:24:58 +00:00
Nanang Izzuddin d878b9269a Close #1466 (using PJLIB outside PJSUA-LIB context):
- static reference counter for PJLIB init/shutdown.
 - implemented atexit() in PJMEDIA and PJSIP level: pjmedia_endpt_atexit() & pjsip_endpt_atexit().
 - updated pjmedia/transport_srtp.c, pjsip/sip_timer.c, and pjsip/sip_replaces.c to use the new atexit() functions.
 - API change: pjmedia_srtp_init_lib() now requires 'pjmedia_endpt' param.



git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3986 74dad513-b988-da41-8d7b-12977e46ad98
2012-03-22 11:29:20 +00:00
Sauw Ming 71eb919763 Fixed #1468: Add support for iPhone configure script to detect iOS 5.1 SDK
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3978 74dad513-b988-da41-8d7b-12977e46ad98
2012-03-20 07:32:21 +00:00
Nanang Izzuddin 9810d54ea5 Fix #1464: Only use PJSUA lock in PJSUA implementations of INVITE session callbacks when updating 'pjsua_var' is needed, while updating 'pjsua_call' should be enough with call/dialog lock (which is actually being held by the INVITE session layer during invoking its callback).
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3977 74dad513-b988-da41-8d7b-12977e46ad98
2012-03-15 09:37:19 +00:00
Benny Prijono b601e5a6a4 Lower the default TCP/TLS idle time from 600s to 30s to improve battery consumption (fixed #1465)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3976 74dad513-b988-da41-8d7b-12977e46ad98
2012-03-15 08:12:10 +00:00
Benny Prijono a5b50d048a Re #1462: fixed libresample.dylib.1 installation issue
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3974 74dad513-b988-da41-8d7b-12977e46ad98
2012-03-13 02:48:28 +00:00
Benny Prijono 736059b495 Misc: fixed bug with assigning channel count in get_conf_port_info() in the Python module. Thanks Thomas Steinacher for the report. (re #1417)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3973 74dad513-b988-da41-8d7b-12977e46ad98
2012-03-13 02:01:58 +00:00
Benny Prijono dbceba6cfa Re #1462: fixed broken make install caused by previous changes
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3970 74dad513-b988-da41-8d7b-12977e46ad98
2012-03-09 00:30:28 +00:00
Nanang Izzuddin eefc7830ec Fix #1440:
- Use separate buffer for outgoing RTCP. Previously, RTCP generation might override outgoing RTP payload (because of shared buffer).
 - Use exact size for RTCP-XR content buffer. Previously RTCP-XR content buffer size was set to PJMEDIA_MAX_MTU, quite huge wasted space.



git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3969 74dad513-b988-da41-8d7b-12977e46ad98
2012-03-08 08:34:30 +00:00
Benny Prijono 318ccc316b Re #1462: libresample as shared library support on Mac OS X
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3968 74dad513-b988-da41-8d7b-12977e46ad98
2012-03-08 07:44:41 +00:00
Benny Prijono 22ae142460 Closed #1462: Added support for building libresample as shared library for GNU targets
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3967 74dad513-b988-da41-8d7b-12977e46ad98
2012-03-08 06:35:03 +00:00
Benny Prijono 71d74d51b1 Fixed #1460: Allow call to transition to CONFIRMED state even when SDP negotiation is pending if the pending negotiation is an updated offer and not the original one with the INVITE transaction
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3964 74dad513-b988-da41-8d7b-12977e46ad98
2012-03-06 07:18:23 +00:00
Nanang Izzuddin 9fb9efdd2b Fix #1458: removed the problematic sound device direction setting.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3963 74dad513-b988-da41-8d7b-12977e46ad98
2012-03-06 05:37:10 +00:00
Nanang Izzuddin 6b20937730 Fix #1457: removed check for remote SDP media count before calling find_audio_index() in pjsua_media_channel_create_sdp(), so find_audio_index() will also verify the media count in the remote SDP.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3962 74dad513-b988-da41-8d7b-12977e46ad98
2012-03-06 04:34:49 +00:00
Nanang Izzuddin 9c9f099d5c Fix #1456: don't use SRTP internal state (tx_policy/rx_policy) directly for calling pjmedia_transport_srtp_start() in restarting SRTP after getting replay error.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3961 74dad513-b988-da41-8d7b-12977e46ad98
2012-02-28 10:38:32 +00:00
Nanang Izzuddin 187b757b20 Fix #1440: Send and parse RTCP compound packet, containing report (RR/SR/XR), SDES, and BYE.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3960 74dad513-b988-da41-8d7b-12977e46ad98
2012-02-27 14:41:21 +00:00
Benny Prijono a4126d1a94 Fixed #1455: Incoming re-INVITE is unhandled if it comes in CONNECTING state (thanks Olle Frimanson for the report)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3959 74dad513-b988-da41-8d7b-12977e46ad98
2012-02-27 09:12:13 +00:00
Benny Prijono 59a994df3f Fixed #1454: Bug in parsing XML document if node name is followed by newline (thanks Samuel Prevot for the report)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3958 74dad513-b988-da41-8d7b-12977e46ad98
2012-02-25 00:55:37 +00:00
Benny Prijono 28fdeea9e3 Misc (re #1417): prevent buggy libc library from printing "(null)" in SDP for the rtpmap attribute, e.g.: "a=rtpmap:8 PCMA/8000(null)". Thanks Roman Puls for the fix
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3957 74dad513-b988-da41-8d7b-12977e46ad98
2012-02-21 12:31:55 +00:00
Benny Prijono fe82212205 Fixed #1452: Wrong call media state is reported if hold request is challenged with authentication (thanks Bogdan Krakowski for the fix)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3954 74dad513-b988-da41-8d7b-12977e46ad98
2012-02-18 02:12:22 +00:00
Benny Prijono b3dc6fab7e Allow run-time control of automatic switching to TCP when request is larger than 1300 (the PJSIP_DONT_SWITCH_TO_TCP compile time setting) via pjsip_cfg()->endpt.disable_tcp_switch setting. Thanks Johan Lantz for the suggestion.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3952 74dad513-b988-da41-8d7b-12977e46ad98
2012-02-16 05:35:25 +00:00
Nanang Izzuddin 5429ca6f28 Fix #1451: Don't hold the ICE session's mutex when calling pj_ice_sess_cb::on_tx_pkt() callback to avoid deadlock.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3951 74dad513-b988-da41-8d7b-12977e46ad98
2012-02-08 09:29:38 +00:00
Benny Prijono 962d393ccd Updated PortAudio SVN URL (re #1417/Misc)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3947 74dad513-b988-da41-8d7b-12977e46ad98
2012-02-03 07:05:33 +00:00
Nanang Izzuddin 06f998cb27 Misc (re #1417): fixed sample code in PJSUA-API Media Manipulation doxygen, pjsua_player_create() only takes 3 arguments, instead of 4 (thanks Thomas Martin for the report).
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3946 74dad513-b988-da41-8d7b-12977e46ad98
2012-02-02 01:54:19 +00:00
Nanang Izzuddin 470934aa27 Fix #1449: PJ_EPENDING should not be treated as failure in sending STUN binding request.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3944 74dad513-b988-da41-8d7b-12977e46ad98
2012-01-26 04:37:06 +00:00
Nanang Izzuddin 218b4618a5 Close #1448: removed server name setting from TLS transport config.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3943 74dad513-b988-da41-8d7b-12977e46ad98
2012-01-17 07:02:14 +00:00
Nanang Izzuddin efc8f666b5 Close #1014:
- Added configurable ciphers setting in SIP TLS transport and pjsua app.
 - Added API pj_ssl_cipher_is_supported().




git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3942 74dad513-b988-da41-8d7b-12977e46ad98
2012-01-16 05:05:47 +00:00
Nanang Izzuddin a096d0c8c9 Fix #1447: fix internal function write_frame() of the switchboard to copy the whole source frame to the destination port buffer if the destination port is port 0 (previously it only copied as much as samples-per-frame of port 0).
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3941 74dad513-b988-da41-8d7b-12977e46ad98
2012-01-12 06:09:08 +00:00
Benny Prijono 609c74fd35 Fixed #1432: Removed assertion in transaction when event is received in DESTROYED state (thanks Yariv Trabelsi for the report)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3924 74dad513-b988-da41-8d7b-12977e46ad98
2011-12-26 09:21:50 +00:00
Benny Prijono f0bd919a16 Fixed #1431: Support for RFC 4169/Digest Authentication Using AKAv2 (thanks Alex Kolesnichenko for the patch)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3916 74dad513-b988-da41-8d7b-12977e46ad98
2011-12-20 09:56:26 +00:00
Benny Prijono 7432ad4d83 Fixed #1426: Race condition in auto-closing and/or auto-opening of the sound device
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3913 74dad513-b988-da41-8d7b-12977e46ad98
2011-12-19 05:47:55 +00:00
Benny Prijono 397441c03e Fixed #1422: Option to configure or disable RTCP RTT normalization (thanks Lars Helgeson for the patch)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3907 74dad513-b988-da41-8d7b-12977e46ad98
2011-12-12 08:06:58 +00:00
Benny Prijono 67725b6260 Fixed #1416: Allow application to send data after ICE negotiation fails
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3906 74dad513-b988-da41-8d7b-12977e46ad98
2011-12-09 07:19:25 +00:00
Benny Prijono 62ee76adad Fixed #1421 (Audio is missing temporarily if SRTP is enabled due to lock codec feature). The problem occured because when lock codec is called, the stream may not transmit any RTP packets yet, causing the RTCP statistic to return zero as the last RTP sequence number sent. The zero RTP sequence number would cause SRTP to refuse to encode the RTP packet with error replay status
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3900 74dad513-b988-da41-8d7b-12977e46ad98
2011-12-07 05:19:34 +00:00
Benny Prijono feb5acabc3 Fixed #1418 (Library restart fails with PJLIB_UTIL_ESTUNNOTRESPOND error after several times) due to bug in calling pj_sock_select(). Thanks Régis Montoya for the report and testing the fix
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3896 74dad513-b988-da41-8d7b-12977e46ad98
2011-12-05 02:12:38 +00:00
Sauw Ming 3eab787335 Re #1417 (misc fix): Fixed ipjsystest XCode project build settings to define PJ_AUTOCONF and add CFNetwork framework.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3889 74dad513-b988-da41-8d7b-12977e46ad98
2011-11-23 03:35:53 +00:00
Sauw Ming 7f8dece6aa Re #1417 (misc fix): Add OS X Lion support for Python build
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3888 74dad513-b988-da41-8d7b-12977e46ad98
2011-11-19 03:35:48 +00:00
Benny Prijono ae0ec278ac Changed version to 1.12-svn
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3886 74dad513-b988-da41-8d7b-12977e46ad98
2011-11-08 18:22:26 +00:00
Benny Prijono 0d3236cc3f Changed version to 1.12
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3884 74dad513-b988-da41-8d7b-12977e46ad98
2011-11-08 17:11:29 +00:00
Benny Prijono ae05b0e4fd More #1415: added protection when calling log, otherwise assertion will be raised
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3883 74dad513-b988-da41-8d7b-12977e46ad98
2011-11-02 09:14:50 +00:00
Benny Prijono b00ed24a3e Fixed #1415: Handle potential crash if joining worker thread fails in pjsua_destroy()
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3882 74dad513-b988-da41-8d7b-12977e46ad98
2011-11-02 08:48:06 +00:00
Benny Prijono 683d2a99b3 Fixed #1414: Removed assertion in transaction when event other than timer is received in TERMINATED state
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3881 74dad513-b988-da41-8d7b-12977e46ad98
2011-11-02 07:53:38 +00:00
Nanang Izzuddin dd63449940 Fix #1413: Fix G722.1 encoder to handle multiple frames per packet.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3880 74dad513-b988-da41-8d7b-12977e46ad98
2011-11-02 07:50:44 +00:00
Nanang Izzuddin 7b3bf326b9 Fix #1410:
- Fixed bug in ipp_codecs.c pack_amr() in setting up AMR-WB frame size, i.e: using AMR-NB frame size table instead of AMR-WB's.
 - Updated AMR-WB default setting to use two frames-per-packet.



git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3879 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-31 15:48:15 +00:00
Sauw Ming b63b96cdda Fixed #1409: Assertion failure if unable to resolve TURN server
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3877 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-31 10:28:34 +00:00
Sauw Ming 17fd38e141 Fixed #1408: Failed to authenticate to TURN client due to REALM attribute padding
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3876 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-31 10:27:12 +00:00
Benny Prijono 6350a3e117 Fixed #1407: Deadlock in initial resolution of STUN server
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3873 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-28 05:07:22 +00:00
Benny Prijono ac28148a96 Fixed #1405: Unable to reject unknown algorithm in authentication challenge
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3871 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-28 04:20:48 +00:00
Sauw Ming 23fc90f71e Re #1252 (misc): Add codec initialization before opening it in pjmedia stream
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3868 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-27 10:22:39 +00:00
Sauw Ming b42ec89256 Fixed #1341: Handle pjsua_acc_config's newly added fields in pjsua_acc_modify()
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3867 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-27 09:02:36 +00:00
Benny Prijono 262cb5fbef WAV playback is cut in the end if pjmedia_wav_player_port_set_pos() is called. Thanks Eize Slange for the patch (re #1252)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3846 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-25 03:49:59 +00:00
Benny Prijono 579935cffa Misc (re #1252): error compiling the IPP wrapper if AMR-WB is enabled but AMR-NB is disabled. Thanks Olle Frimanson for the report
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3845 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-25 03:27:03 +00:00
Benny Prijono 0227c7a743 Fixed #1391: Missing CSeq check for incoming ACK in an INVITE session (thanks Ilya Kalinin for the report)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3834 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-21 09:39:40 +00:00
Benny Prijono e4e63d9e01 Fixed #1319: When sips scheme is used, TLS must be used even when transport=tcp is specified in the URI (thanks Iñaki Baz Castillo for the report)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3832 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-20 04:01:26 +00:00
Benny Prijono dbf587f70e Misc: failed to create CSV file with TRACE_JB feature in stream.c because Linux does not seem to create the file if it is opened with fopen(, "r+b") and the file does not exist yet. Thanks Dan for the patch (re #1252)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3831 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-19 13:17:08 +00:00
Benny Prijono f425fcb8f9 Renamed enum names to comply with the spec in ticket (re #1216)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3830 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-19 13:08:14 +00:00
Benny Prijono 866c27ae73 Fixed #1216: New pjsua_destroy2() API to allow shutting down the library without sending any outgoing messages
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3829 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-19 12:45:05 +00:00
Benny Prijono f69e2dac7b Misc (re #1252): fixed misleading doxygen documentation that says app may instantiate multiple instances of SIP endpoint
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3828 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-19 10:13:13 +00:00
Sauw Ming cbdaa61cfc Re #1342: Fix wrong #ifdef condition
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3826 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-18 09:41:56 +00:00
Benny Prijono 3e7d5b4daa Set correct endianness for Windows Mobile and Symbian (re #1252, r3766)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3822 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-18 04:26:37 +00:00
Sauw Ming 5983428785 Re #1252: Add the definition of PJ_AUTOCONF in ipjsua
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3821 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-18 04:19:12 +00:00
Sauw Ming e9d79557f6 Re #1252: Add PJLIB endianness preprocessor macro definition in autoconf
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3820 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-18 04:01:18 +00:00
Sauw Ming c658ab4d2f Closed #1389: Add support for iOS 5 build
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3818 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-17 07:22:45 +00:00
Benny Prijono bd81d171ea Support for OpenCORE AMR-NB codec on Windows. This closes #1388
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3817 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-14 06:41:51 +00:00
Benny Prijono 5c476dee84 Committing re #1388: Support for OpenCORE AMR-NB codec (thank you Dan Arrhenius for the contribution!)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3816 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-14 04:15:15 +00:00
Benny Prijono 0519f34aac Fixed #1387: Bug in printing user defined header in multipart message (thanks Luis Martin Gil for the patch)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3815 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-14 02:08:44 +00:00
Nanang Izzuddin 263ef2cdcc Re #1378:
- Implemented new algorithm for JB progressive discard.
 - Added new API and for setting JB discard algorithm at run-time.
 - Updated JB test for the new algorithm.




git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3814 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-13 09:02:41 +00:00
Nanang Izzuddin 4543316a5d Fixed #1386: fixed send_raw_resolver_callback() in sip_util.c, should increment tdata ref count before calling pjsip_tpmgr_send_raw() to avoid tdata gets destroyed prematurely.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3813 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-11 07:26:16 +00:00
Nanang Izzuddin 9f0f0fc58c Fixed #1385: fixed match_offer() of SDP negotiator in comparing rtpmap encoding params (specifying channel count) in preanswer and remote-offer.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3812 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-11 05:06:42 +00:00
Benny Prijono f5c62bdc8c Some more error handling (re #1384: HTTP client source port range)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3811 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-11 04:40:50 +00:00
Benny Prijono 5bf3e706e5 Fixed #1384: HTTP client source port range setting (thanks Johan Lantz for the patch)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3810 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-11 04:37:37 +00:00
Nanang Izzuddin 34dd20dc54 Misc (#1252): Wrong APS/VAS frame header generation for AMR silence/NO_DATA frame caused by using wrong 'OR' operator, was logical 'OR' instead of bitwise (thanks Johan Lantz for the report).
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3809 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-11 03:05:34 +00:00
Benny Prijono c8102910bf Fixed #1383: Update the transport adapter sample in pjsua
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3804 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-09 10:58:38 +00:00
Nanang Izzuddin 76ce26e72e Fix #1378: replaced discard rate decision based on overflow precentage (precentage of excess delay compared to burst-level).
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3779 74dad513-b988-da41-8d7b-12977e46ad98
2011-10-03 06:46:51 +00:00
Benny Prijono 85e4c0e85e Fixed bug in re #1376: pjsua_call_info() could not be called when state is disconnected
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3771 74dad513-b988-da41-8d7b-12977e46ad98
2011-09-22 08:13:15 +00:00
Benny Prijono ed138ae919 More re #1375: fixed bug, the reg_first_retry interval is not copied to account config with pjsua_acc_modify()!
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3770 74dad513-b988-da41-8d7b-12977e46ad98
2011-09-22 07:41:43 +00:00
Benny Prijono 81d0acde01 More re #1375: added log showing the interval when scheduling the registration retry
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3769 74dad513-b988-da41-8d7b-12977e46ad98
2011-09-22 07:33:37 +00:00
Benny Prijono a3cd35091a Fixed #1376: Crash if pjsua_call_get_info() is called with disconnected call
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3768 74dad513-b988-da41-8d7b-12977e46ad98
2011-09-22 06:13:22 +00:00
Benny Prijono 6e475c1909 Remove default endianness for bi-endian systems such as MIPS, ARM, and PowerPC, and raise compilation error instead. Thanks Howard Lin for the suggestion (misc, re #1252)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3766 74dad513-b988-da41-8d7b-12977e46ad98
2011-09-22 02:42:01 +00:00
Benny Prijono 47244d8172 Another fix to pj_stun_sock_op_name() to support PJ_STUN_MAPPED_ADDR_CHANGE. Thanks Howard Lin for the report! (re #1252 (misc))
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3765 74dad513-b988-da41-8d7b-12977e46ad98
2011-09-22 01:31:21 +00:00
Benny Prijono 7e25d1b9ab Added option to control first re-registration retry interval. This closes #1375
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3762 74dad513-b988-da41-8d7b-12977e46ad98
2011-09-21 07:38:22 +00:00
Benny Prijono 2c9fa16c2d Fixed sockaddr address comparison error with memcmp, and use pj_sockaddr_cmp() instead. Thanks Howard Lin for the report (misc, re #1252)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3761 74dad513-b988-da41-8d7b-12977e46ad98
2011-09-21 04:54:27 +00:00
Benny Prijono 6108e28bd8 Added missing PJ_STUN_SOCK_MAPPED_ADDR_CHANGE name to pj_stun_sock_op_name. Thanks Howard Lin for the report (misc, re #1252)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3760 74dad513-b988-da41-8d7b-12977e46ad98
2011-09-21 04:33:39 +00:00
Benny Prijono b65fa69a07 Added endianness test in pjlib-test (Misc, re #1252)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3759 74dad513-b988-da41-8d7b-12977e46ad98
2011-09-21 04:27:58 +00:00
Benny Prijono 1efdead3ce Fixed #1374: Assertion when CANCEL and INVITE final response "crosses the wire"
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3755 74dad513-b988-da41-8d7b-12977e46ad98
2011-09-19 06:43:49 +00:00
Benny Prijono 9fe479c531 Fixed #1371: Soft deadlock when application query call info of other call inside a callback. The following APIs should be safe to be called in this situation:
- pjsua_call_get_info()
 - pjsua_call_get_conf_port()


git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3751 74dad513-b988-da41-8d7b-12977e46ad98
2011-09-16 03:12:27 +00:00
Benny Prijono da58910013 Fixed #1369: Local state is set to HOLD even if hold operation fails
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3749 74dad513-b988-da41-8d7b-12977e46ad98
2011-09-15 10:09:44 +00:00
Nanang Izzuddin 3ff64a70a4 More Symbian MDA fixes (re #1365):
- Added config setting to control sync/async start. Due to problem with async start: any volume query performed immediately after starting the device will always return zero.
 - Fixed get_default_param() to set the flags to zero (was copied from caps, i.e: input/output volume flags without setting the value).
 - Fixed stream_get_param() to also check the input and output volume level.




git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3748 74dad513-b988-da41-8d7b-12977e46ad98
2011-09-09 09:51:10 +00:00
Benny Prijono 8a0218aeea Fixed #1367: Crash if presence PIDF body is missing <basic> element (thanks Matt DiMeo for the patch)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3747 74dad513-b988-da41-8d7b-12977e46ad98
2011-09-09 09:49:41 +00:00
Benny Prijono 9b6228b080 Fixed Symbian build error due to re #1364
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3746 74dad513-b988-da41-8d7b-12977e46ad98
2011-09-08 10:19:01 +00:00
Benny Prijono 3203c13e08 Slightly more clever RTP transport remote address switch: transmission won't switch as long as we're receiving RTP/RTCP packets from the "correct" remote address, to avoid constantly switching to a new source address. Also when the remote peer address is in probation, RT(C)P packets from that address will be silently discarded, to avoid playback confusion. This closes #1366.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3745 74dad513-b988-da41-8d7b-12977e46ad98
2011-09-08 06:47:28 +00:00
Nanang Izzuddin bc44d51965 Fixed #1365: Applied volume setting (input & output) when the MDA audio device is started.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3744 74dad513-b988-da41-8d7b-12977e46ad98
2011-09-08 05:43:54 +00:00
Benny Prijono 0331a1bc11 Added support for forking of reliable provisional response (100rel):
- maintain 100rel state for each call leg (To tag)
 - added SIPp scenario
 - note that multiple SDP negotiation in 100rel response from different call leg is not supported. Especially the case when multple offers are sent in the responses are not supported (we're supposed to send answers in PRACKs, but currently we only respond to the first 100rel with SDP).

This closes #1364


git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3743 74dad513-b988-da41-8d7b-12977e46ad98
2011-09-08 04:37:43 +00:00
Benny Prijono 8a160ef8eb Always enclose Contact URI with double quote to prevent invalid Contact URI if the display part of the AOR contains reserved characters. This fixes #1363
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3742 74dad513-b988-da41-8d7b-12977e46ad98
2011-09-07 11:28:45 +00:00
Benny Prijono 17bf5ffa18 Configurable pj_sockaddr_in padding/sin_zero length. This closes #1359
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3741 74dad513-b988-da41-8d7b-12977e46ad98
2011-08-30 01:45:07 +00:00
Benny Prijono fe8d972113 Dummy checkin for testing the automated testing..
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3706 74dad513-b988-da41-8d7b-12977e46ad98
2011-08-16 09:10:58 +00:00
Benny Prijono ec520b8a55 More re #1264 (automated tests)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3705 74dad513-b988-da41-8d7b-12977e46ad98
2011-08-16 08:57:11 +00:00
Benny Prijono d7e0c75f64 Re #1264 (automated testing for 1.x): enhanced run_continuous.py with: 1) custom group name suffix option 2) one time check option instead of loop 3) force option
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3702 74dad513-b988-da41-8d7b-12977e46ad98
2011-08-16 06:26:15 +00:00
Sauw Ming 39bf2fab53 Re #1342: minor fix for the #ifdef condition
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3693 74dad513-b988-da41-8d7b-12977e46ad98
2011-08-11 09:45:11 +00:00
Sauw Ming 855af302a6 Fixed #1342: disable local host resolution on iPhone OS
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3692 74dad513-b988-da41-8d7b-12977e46ad98
2011-08-11 08:45:38 +00:00
Benny Prijono 233f308f3c Fixed #1337 re: link error with the PLC stuff if G.711 codec is disabled.
This basically is caused by the problem with library order in the Makefile. Since libpjmedia (which contains the PLC code) is specified first before the third party libs (which the codecs reside), the PLC didn't get picked up by the linker. It works if G.711 is enabled, because G.711 lives in libpjmedia.

The real problem is because there is a circular dependency between pjmedia and third party libraries. The real solution would be to break down third party libraries into individual lib and arrange the link order correctly. This would need a bit of work in the Makefile though.

For now, let's just hack pjmedia-test so that it links with the PLC if G.711 is disabled.



git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3681 74dad513-b988-da41-8d7b-12977e46ad98
2011-07-24 09:13:11 +00:00
Perry Ismangil b42cd1b681 Re #1336 tweaks to turn off treeview doxygen generation
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3680 74dad513-b988-da41-8d7b-12977e46ad98
2011-07-23 14:04:33 +00:00
Perry Ismangil d1289453fe Fixed #1336 make doc now creates version specific docs
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3677 74dad513-b988-da41-8d7b-12977e46ad98
2011-07-22 11:52:50 +00:00
Sauw Ming f6e1d07739 Fixed #1335
Fixes assertion when interruptionListener is called from an unregistered thread on iPhone OS.



git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3674 74dad513-b988-da41-8d7b-12977e46ad98
2011-07-21 10:06:17 +00:00
Benny Prijono 521b9f2fc0 Misc (re #1252): wrong doxygen documentation on the key argument of pj_hash_set, which said that it has to be valid throughout the duration of the entry. This is no longer true. Thanks Johan Lantz for pointing this out.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3673 74dad513-b988-da41-8d7b-12977e46ad98
2011-07-20 08:08:46 +00:00
Benny Prijono 8585cf8e69 Misc (re #1252): fixed potential crash if pjmedia_aud_dev_cap_name() is called with invalid capability
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3611 74dad513-b988-da41-8d7b-12977e46ad98
2011-07-07 09:26:26 +00:00
Nanang Izzuddin e4875da904 Fixed #1321: Put OPENSSL_NO_SSL2 macro check for all usages of OpenSSL API SSLv2*().
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3610 74dad513-b988-da41-8d7b-12977e46ad98
2011-07-07 08:39:53 +00:00
Benny Prijono cc4410de58 Misc (re #1252): prevent assertion caused by bad account when scanning accounts for presence timer update. Thanks Matt DiMeo for the patch
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3604 74dad513-b988-da41-8d7b-12977e46ad98
2011-07-07 04:35:00 +00:00
Benny Prijono 6042a50a28 Misc (re #1252): updated icedemo help menu to make it clear that ice negotiation should be started immediately on the remote end. Thanks Andrés Suero for the suggestion
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3603 74dad513-b988-da41-8d7b-12977e46ad98
2011-07-07 01:53:35 +00:00
Benny Prijono 6d03afcc19 Re #1252 (misc fixes): fixed encoding of nc parameter in the HTTP client that caused authentication to fail (thanks Johan Lantz for the pointer)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3600 74dad513-b988-da41-8d7b-12977e46ad98
2011-06-29 12:59:11 +00:00
Benny Prijono 95cd3edd7b Re #1252 (Misc): bug in configure script, should put whitespace after gcc -o. This is fine on most gcc targets but rejected on some iPhone builds
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3599 74dad513-b988-da41-8d7b-12977e46ad98
2011-06-25 02:58:38 +00:00
Benny Prijono 755deb6cfc Fixed #1318: Prevent PJSIP_INV_STATE_CALLING from being reported more than once (thanks Sam Yasin for the report)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3598 74dad513-b988-da41-8d7b-12977e46ad98
2011-06-24 07:35:28 +00:00
Nanang Izzuddin 2da084fab9 Fixed #1317: fixed Symbian ioqueue by avoiding access to CIoqueueCallback member after invoking callback as application may unregister the key (which internally destroy the CIoqueueCallback object) from the callback.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3597 74dad513-b988-da41-8d7b-12977e46ad98
2011-06-22 15:50:57 +00:00
Benny Prijono d87d3d1217 Fixed #1316: Assertion when TURN session is deallocated prematurely (thanks Tony Jago Million for the report)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3596 74dad513-b988-da41-8d7b-12977e46ad98
2011-06-22 10:57:11 +00:00
Nanang Izzuddin 9b138c6480 Fixed #1315: fixed VAS to apply the output volume setting, set in creation param, after the stream is started.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3595 74dad513-b988-da41-8d7b-12977e46ad98
2011-06-22 09:33:55 +00:00
Benny Prijono 3a3bb957e5 Closed #1313 (Account option to disable registration when account is added) and closed #1314 (New callback to notify application when registration or unregistration has been initiated). Thanks Tony Jago Million for the patch
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3594 74dad513-b988-da41-8d7b-12977e46ad98
2011-06-22 08:00:20 +00:00
Nanang Izzuddin d4726c1aee Fixed #1310:
- protected the account validation in the registration callback.



git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3591 74dad513-b988-da41-8d7b-12977e46ad98
2011-06-20 06:22:28 +00:00
Nanang Izzuddin 59386d6386 Fixed #1307:
- Fixed AMR NO_DATA frame length definition in amr_helper.h.
 - Fixed bug packing/parsing AMR SID frames in processing SID type indicator (STI).
 - Enabled native VAD in IPP AMR-NB.



git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3589 74dad513-b988-da41-8d7b-12977e46ad98
2011-06-20 04:06:19 +00:00
Nanang Izzuddin c5ec3efcc9 Re #1308:
- Updated pcap parser component to skip trailer bytes that may exist in some network layers (was raising assertion).
 - Updated pcaputil app to allow dynamic payload type codecs.
 - Updated pcaputil app to be able to play decoded frames directly to audio device, instead of writing to WAV file.




git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3588 74dad513-b988-da41-8d7b-12977e46ad98
2011-06-20 03:54:49 +00:00
Nanang Izzuddin 9c1737180a Re #1306:
- Moved PJSIP_TSX_1XX_RETRANS_DELAY definition to sip_config.h.
 - Updated retransmission mechanism to skip retransmission rescheduling when the interval is zero.



git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3586 74dad513-b988-da41-8d7b-12977e46ad98
2011-06-16 13:15:04 +00:00
Sauw Ming 3ecaee38b3 Closed #1173: PJSUA callback to allow creation of custom media transports by application
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3585 74dad513-b988-da41-8d7b-12977e46ad98
2011-06-16 05:10:45 +00:00
Benny Prijono d90596de10 Fixed #1305: Bug in pjsua_call_hangup_all() may cause deadlock (thanks Kees van der Bent for the report)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3584 74dad513-b988-da41-8d7b-12977e46ad98
2011-06-16 03:49:51 +00:00
Benny Prijono 29063b1bad Fixed #1302: Bug in soft deadlock detection may cause program to block indefinitely (thanks Attila Magyar for the fix)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3576 74dad513-b988-da41-8d7b-12977e46ad98
2011-05-27 21:14:46 +00:00
Benny Prijono 32040808f1 Fixed #1301: Wrong alaw value is generated by the non-table version of pjmedia_linear2alaw() function for some specific PCM values (thanks K. Johnson for the fix)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3575 74dad513-b988-da41-8d7b-12977e46ad98
2011-05-27 07:28:28 +00:00
Nanang Izzuddin 63c0077c7b Fixed #1291:
- fixed bug in SIP invite module, SDP negotiator state should be reverted back after an SDP re-offer is rejected by application.
 - fixed bug in pjsua_call_on_rx_offer(), evaluating call->audio_index should be done after pjsua_media_channel_create_sdp() is successful.




git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3574 74dad513-b988-da41-8d7b-12977e46ad98
2011-05-20 10:29:45 +00:00
Sauw Ming faefe7cfb2 Re #1268: Fixed compilation error problem due to typo.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3572 74dad513-b988-da41-8d7b-12977e46ad98
2011-05-19 09:26:34 +00:00
Sauw Ming 30024e3ec6 Fixed #1268: Option for automatic/manual sending of RTCP SDES/BYE for the stream.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3571 74dad513-b988-da41-8d7b-12977e46ad98
2011-05-19 08:05:23 +00:00
Benny Prijono e3f4038db2 Fixed #1259: Option to use of 100rel in UAS if UAC supports it (thanks Marcus Froeschl for the suggestion)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3570 74dad513-b988-da41-8d7b-12977e46ad98
2011-05-19 04:36:01 +00:00
Nanang Izzuddin 4995e24f62 Re #1258: Updated jitter buffer test data after r3568 fix.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3569 74dad513-b988-da41-8d7b-12977e46ad98
2011-05-18 10:21:35 +00:00
Nanang Izzuddin f73b12a82f Fix #1258: Fixed bug in jitter buffer, i.e: unexpected state switches when prefetch mechanism is active, by separating prefetch mechanism from JB state.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3568 74dad513-b988-da41-8d7b-12977e46ad98
2011-05-18 06:59:23 +00:00
Sauw Ming b6bcfd5557 Fixed #1257: Option for using simple FIFO delay buffer in echo canceller.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3567 74dad513-b988-da41-8d7b-12977e46ad98
2011-05-15 12:54:28 +00:00
Sauw Ming e90d9c21ed Fixed #1256: Remove the "ob" parameter if SIP outbound is disabled.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3566 74dad513-b988-da41-8d7b-12977e46ad98
2011-05-15 12:40:38 +00:00
Benny Prijono 39523ed980 Fixed #1255: Unable to parse the short version of Event header (thanks Marcus Froeschl for the report)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3565 74dad513-b988-da41-8d7b-12977e46ad98
2011-05-15 12:13:24 +00:00
Benny Prijono 416910f464 Misc (re #1252): fixed the assertion when jbuf_set_adaptive() is called with fixed jbuf parameters
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3561 74dad513-b988-da41-8d7b-12977e46ad98
2011-05-10 10:39:57 +00:00
Benny Prijono 53fd6b4518 Fixed #1251: Calling pjmedia_aud_subsys_shutdown() more than once may cause crash (thanks Bill Gardner for the patch)
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3559 74dad513-b988-da41-8d7b-12977e46ad98
2011-05-06 07:25:59 +00:00
Benny Prijono 65f48a11ce Branched 1.10 release version to 1.x
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/1.x@3557 74dad513-b988-da41-8d7b-12977e46ad98
2011-05-06 02:39:43 +00:00
197 changed files with 8082 additions and 5867 deletions

View File

@ -1,6 +1,7 @@
include build.mak
include build/host-$(HOST_NAME).mak
-include user.mak
include version.mak
DIRS = pjlib/build pjlib-util/build pjnath/build third_party/build pjmedia/build pjsip/build pjsip-apps/build $(EXTRA_DIRS)
@ -23,7 +24,7 @@ doc:
exit 1; \
fi
for dir in $(DIRS); do \
if $(MAKE) $(MAKE_FLAGS) -C $$dir/build $@; then \
if $(MAKE) $(MAKE_FLAGS) -C $$dir $@; then \
true; \
else \
exit 1; \
@ -92,7 +93,6 @@ pjsua-test:
cd tests/pjsua && python runall.py
prefix = $(ac_prefix)
include version.mak
install:
mkdir -p $(DESTDIR)$(prefix)/lib

View File

@ -596,10 +596,14 @@ ac_main_obj
ac_host
ac_linux_poll
ac_cross_compile
opencore_amrnb_present
opencore_amrnb_h_present
ac_no_opencore_amrnb
libcrypto_present
libssl_present
openssl_h_present
ac_no_ssl
ac_resample_dll
ac_no_ilbc_codec
ac_no_speex_codec
ac_no_g7221_codec
@ -621,6 +625,7 @@ ac_os_objs
EGREP
GREP
CPP
ac_shlib_suffix
ac_build_mak_vars
ac_pjdir
CC_CFLAGS
@ -716,11 +721,13 @@ enable_g7221_codec
enable_speex_codec
enable_ilbc_codec
enable_libsamplerate
enable_resample_dll
enable_ipp
with_ipp
with_ipp_samples
with_ipp_arch
enable_ssl
enable_opencore_amrnb
'
ac_precious_vars='build_alias
host_alias
@ -1368,12 +1375,17 @@ Optional Features:
--disable-ilbc-codec Exclude iLBC codec in the build
--enable-libsamplerate Link with libsamplerate when available. Note that
PJMEDIA_RESAMPLE_IMP must also be configured
--enable-resample-dll Build libresample as shared library
--enable-ipp Enable Intel IPP support. Specify the Intel IPP
package and samples location using IPPROOT and
IPPSAMPLES env var or with --with-ipp and
--with-ipp-samples options
--disable-ssl Exclude SSL support the build (default: autodetect)
--disable-opencore-amrnb
Exclude OpenCORE AMR-NB support from the build
(default: autodetect)
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@ -3439,7 +3451,7 @@ if test "$AR" = ""; then AR="${CROSS_COMPILE}ar rv"; fi
if test "$LD" = ""; then LD="$CC"; fi
if test "$LDOUT" = ""; then LDOUT="-o"; fi
if test "$LDOUT" = ""; then LDOUT="-o "; fi
if test "$RANLIB" = ""; then RANLIB="${CROSS_COMPILE}ranlib"; fi
@ -3449,7 +3461,7 @@ if test "$LIBEXT" = ""; then LIBEXT='a'; fi
if test "$LIBEXT2" = ""; then LIBEXT2=""; fi
if test "$CC_OUT" = ""; then CC_OUT="-o"; fi
if test "$CC_OUT" = ""; then CC_OUT="-o "; fi
if test "$CC_INC" = ""; then CC_INC="-I"; fi
@ -3480,6 +3492,19 @@ case $host in
esac
case $target in
*mingw* | *cygw* | *win32* | *w32* )
ac_shlib_suffix=dll
;;
*darwin*)
ac_shlib_suffix=dylib
;;
*)
ac_shlib_suffix=so
;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
$as_echo_n "checking for pthread_create in -lpthread... " >&6; }
if test "${ac_cv_lib_pthread_pthread_create+set}" = set; then :
@ -4574,6 +4599,12 @@ $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
esac
if test "x$ac_cv_c_bigendian" = "xyes"; then
CFLAGS="$CFLAGS -DPJ_IS_BIG_ENDIAN=1 -DPJ_IS_LITTLE_ENDIAN=0"
else
CFLAGS="$CFLAGS -DPJ_IS_BIG_ENDIAN=0 -DPJ_IS_LITTLE_ENDIAN=1"
fi
case $target in
*mingw* | *cygw* | *win32* | *w32* )
$as_echo "#define PJ_WIN32 1" >>confdefs.h
@ -5834,6 +5865,20 @@ fi
# Check whether --enable-resample_dll was given.
if test "${enable_resample_dll+set}" = set; then :
enableval=$enable_resample_dll; if test "$enable_resample_dll" = "yes"; then
ac_resample_dll=1
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Building libresample as shared library... yes" >&5
$as_echo "Building libresample as shared library... yes" >&6; }
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Building libresample as shared library... no" >&5
$as_echo "Building libresample as shared library... no" >&6; }
fi
# Check whether --enable-ipp was given.
if test "${enable_ipp+set}" = set; then :
enableval=$enable_ipp;
@ -5982,9 +6027,8 @@ $as_echo "ok" >&6; }
else
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
{ as_fn_set_status run with --help for more info
as_fn_error "Error: unable to recognize your IPP installation. Make sure the paths and ARCH suffix are set correctly
See \`config.log' for more details." "$LINENO" 5; }; }
as_fn_error "Error: unable to recognize your IPP installation. Make sure the paths and ARCH suffix are set correctly, run with --help for more info
See \`config.log' for more details." "$LINENO" 5; }
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
@ -6259,6 +6303,83 @@ fi
# Check whether --enable-opencore_amrnb was given.
if test "${enable_opencore_amrnb+set}" = set; then :
enableval=$enable_opencore_amrnb;
if test "$enable_opencore_amrnb" = "no"; then
ac_no_opencore_amrnb=1
$as_echo "#define PJMEDIA_HAS_OPENCORE_AMRNB_CODEC 0" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Checking if OpenCORE AMR-NB support is disabled... yes" >&5
$as_echo "Checking if OpenCORE AMR-NB support is disabled... yes" >&6; }
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: checking for OpenCORE AMR-NB installations.." >&5
$as_echo "checking for OpenCORE AMR-NB installations.." >&6; }
ac_fn_c_check_header_mongrel "$LINENO" "opencore-amrnb/interf_enc.h" "ac_cv_header_opencore_amrnb_interf_enc_h" "$ac_includes_default"
if test "x$ac_cv_header_opencore_amrnb_interf_enc_h" = x""yes; then :
opencore_amrnb_h_present=1
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Encoder_Interface_init in -lopencore-amrnb" >&5
$as_echo_n "checking for Encoder_Interface_init in -lopencore-amrnb... " >&6; }
if test "${ac_cv_lib_opencore_amrnb_Encoder_Interface_init+set}" = set; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lopencore-amrnb $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char Encoder_Interface_init ();
int
main ()
{
return Encoder_Interface_init ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_opencore_amrnb_Encoder_Interface_init=yes
else
ac_cv_lib_opencore_amrnb_Encoder_Interface_init=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_opencore_amrnb_Encoder_Interface_init" >&5
$as_echo "$ac_cv_lib_opencore_amrnb_Encoder_Interface_init" >&6; }
if test "x$ac_cv_lib_opencore_amrnb_Encoder_Interface_init" = x""yes; then :
opencore_amrnb_present=1 && LIBS="$LIBS -lopencore-amrnb"
fi
if test "x$opencore_amrnb_h_present" = "x1" -a "x$opencore_amrnb_present" = "x1"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: OpenCORE AMR-NB library found, AMR-NB support enabled" >&5
$as_echo "OpenCORE AMR-NB library found, AMR-NB support enabled" >&6; }
$as_echo "#define PJMEDIA_HAS_OPENCORE_AMRNB_CODEC 1" >>confdefs.h
else
ac_no_opencore_amrnb=1
$as_echo "#define PJMEDIA_HAS_OPENCORE_AMRNB_CODEC 0" >>confdefs.h
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if select() needs correct nfds" >&5

View File

@ -52,7 +52,7 @@ if test "$AR" = ""; then AR="${CROSS_COMPILE}ar rv"; fi
AC_SUBST(AR)
if test "$LD" = ""; then LD="$CC"; fi
AC_SUBST(LD)
if test "$LDOUT" = ""; then LDOUT="-o"; fi
if test "$LDOUT" = ""; then LDOUT="-o "; fi
AC_SUBST(LDOUT)
if test "$RANLIB" = ""; then RANLIB="${CROSS_COMPILE}ranlib"; fi
AC_SUBST(RANLIB)
@ -62,7 +62,7 @@ if test "$LIBEXT" = ""; then LIBEXT='a'; fi
AC_SUBST(LIBEXT)
if test "$LIBEXT2" = ""; then LIBEXT2=""; fi
AC_SUBST(LIBEXT2)
if test "$CC_OUT" = ""; then CC_OUT="-o"; fi
if test "$CC_OUT" = ""; then CC_OUT="-o "; fi
AC_SUBST(CC_OUT)
if test "$CC_INC" = ""; then CC_INC="-I"; fi
AC_SUBST(CC_INC)
@ -92,6 +92,19 @@ case $host in
;;
esac
AC_SUBST(ac_shlib_suffix)
case $target in
*mingw* | *cygw* | *win32* | *w32* )
ac_shlib_suffix=dll
;;
*darwin*)
ac_shlib_suffix=dylib
;;
*)
ac_shlib_suffix=so
;;
esac
AC_CHECK_LIB(pthread,pthread_create)
AC_CHECK_LIB(wsock32,puts)
AC_CHECK_LIB(ws2_32,puts)
@ -127,6 +140,12 @@ dnl Endianness detection
dnl
AC_C_BIGENDIAN
if test "x$ac_cv_c_bigendian" = "xyes"; then
CFLAGS="$CFLAGS -DPJ_IS_BIG_ENDIAN=1 -DPJ_IS_LITTLE_ENDIAN=0"
else
CFLAGS="$CFLAGS -DPJ_IS_BIG_ENDIAN=0 -DPJ_IS_LITTLE_ENDIAN=1"
fi
dnl
dnl Legacy macros
dnl
@ -725,6 +744,17 @@ AC_ARG_ENABLE(libsamplerate,
AC_MSG_RESULT([Skipping libsamplerate detection])
)
dnl # Include libsamplerate
AC_SUBST(ac_resample_dll)
AC_ARG_ENABLE(resample_dll,
AC_HELP_STRING([--enable-resample-dll],
[Build libresample as shared library]),
[if test "$enable_resample_dll" = "yes"; then
[ac_resample_dll=1]
AC_MSG_RESULT([Building libresample as shared library... yes])
fi],
AC_MSG_RESULT([Building libresample as shared library... no])
)
dnl ########################################################
dnl # Intel IPP support
@ -848,7 +878,7 @@ if test "x$enable_ipp" != "xno"; then
]],
[ippStaticInit();])],
[AC_MSG_RESULT(ok)],
[AC_MSG_FAILURE(Error: unable to recognize your IPP installation. Make sure the paths and ARCH suffix are set correctly, run with --help for more info)])
[AC_MSG_FAILURE([Error: unable to recognize your IPP installation. Make sure the paths and ARCH suffix are set correctly, run with --help for more info])])
CFLAGS="$SAVED_CFLAGS"
LDFLAGS="$SAVED_LDFLAGS"
@ -997,6 +1027,33 @@ AC_ARG_ENABLE(ssl,
fi
])
dnl # Include opencore-amrnb support
AC_SUBST(ac_no_opencore_amrnb)
AC_ARG_ENABLE(opencore_amrnb,
AC_HELP_STRING([--disable-opencore-amrnb],
[Exclude OpenCORE AMR-NB support from the build (default: autodetect)])
,
[
if test "$enable_opencore_amrnb" = "no"; then
[ac_no_opencore_amrnb=1]
AC_DEFINE(PJMEDIA_HAS_OPENCORE_AMRNB_CODEC,0)
AC_MSG_RESULT([Checking if OpenCORE AMR-NB support is disabled... yes])
fi
],
[
AC_MSG_RESULT([checking for OpenCORE AMR-NB installations..])
AC_SUBST(opencore_amrnb_h_present)
AC_SUBST(opencore_amrnb_present)
AC_CHECK_HEADER(opencore-amrnb/interf_enc.h,[opencore_amrnb_h_present=1])
AC_CHECK_LIB(opencore-amrnb,Encoder_Interface_init,[opencore_amrnb_present=1 && LIBS="$LIBS -lopencore-amrnb"])
if test "x$opencore_amrnb_h_present" = "x1" -a "x$opencore_amrnb_present" = "x1"; then
AC_MSG_RESULT([OpenCORE AMR-NB library found, AMR-NB support enabled])
AC_DEFINE(PJMEDIA_HAS_OPENCORE_AMRNB_CODEC,1)
else
[ac_no_opencore_amrnb=1]
AC_DEFINE(PJMEDIA_HAS_OPENCORE_AMRNB_CODEC,0)
fi
])
dnl ##########################################
dnl #

View File

@ -1,3 +1,7 @@
export PJDIR := @ac_pjdir@
include $(PJDIR)/version.mak
export PJ_DIR := $(PJDIR)
# @configure_input@
export MACHINE_NAME := auto
export OS_NAME := auto
@ -6,15 +10,25 @@ export CC_NAME := gcc
export TARGET_NAME := @target@
export CROSS_COMPILE := @ac_cross_compile@
export LINUX_POLL := @ac_linux_poll@
export SHLIB_SUFFIX := @ac_shlib_suffix@
export ac_prefix := @prefix@
LIB_SUFFIX = $(TARGET_NAME).a
# Determine which party libraries to use
export APP_THIRD_PARTY_LIBS := -lresample-$(TARGET_NAME) -lmilenage-$(TARGET_NAME) -lsrtp-$(TARGET_NAME)
export APP_THIRD_PARTY_LIBS := -lmilenage-$(TARGET_NAME) -lsrtp-$(TARGET_NAME)
export APP_THIRD_PARTY_EXT :=
export APP_THIRD_PARTY_LIB_FILES = $(PJ_DIR)/third_party/lib/libresample-$(LIB_SUFFIX) $(PJ_DIR)/third_party/lib/libmilenage-$(LIB_SUFFIX) $(PJ_DIR)/third_party/lib/libsrtp-$(LIB_SUFFIX)
export APP_THIRD_PARTY_LIB_FILES := $(PJ_DIR)/third_party/lib/libmilenage-$(LIB_SUFFIX) $(PJ_DIR)/third_party/lib/libsrtp-$(LIB_SUFFIX)
ifeq (@ac_resample_dll@,1)
export PJ_RESAMPLE_DLL := 1
export APP_THIRD_PARTY_LIBS := -lresample $(APP_THIRD_PARTY_LIBS)
export APP_THIRD_PARTY_LIB_FILES := $(PJ_DIR)/third_party/lib/libresample.$(SHLIB_SUFFIX).$(PJ_VERSION_MAJOR) $(PJ_DIR)/third_party/lib/libresample.$(SHLIB_SUFFIX) $(APP_THIRD_PARTY_LIB_FILES)
else
export APP_THIRD_PARTY_LIBS := -lresample-$(TARGET_NAME) $(APP_THIRD_PARTY_LIBS)
export APP_THIRD_PARTY_LIB_FILES := $(PJ_DIR)/third_party/lib/libresample-$(LIB_SUFFIX) $(APP_THIRD_PARTY_LIB_FILES)
endif
ifneq (@ac_no_gsm_codec@,1)
ifeq (@ac_external_gsm@,1)
@ -59,7 +73,6 @@ endif
@ac_build_mak_vars@
# CFLAGS, LDFLAGS, and LIBS to be used by applications
export PJDIR := @ac_pjdir@
export APP_CC := @CC@
export APP_CXX := @CXX@
export APP_CFLAGS := -DPJ_AUTOCONF=1\
@ -104,7 +117,6 @@ export APP_LIB_FILES = $(PJ_DIR)/pjsip/lib/libpjsua-$(LIB_SUFFIX) \
# Here are the variabels to use if application is using the library
# from within the source distribution
export PJ_DIR := $(PJDIR)
export PJ_CC := $(APP_CC)
export PJ_CXX := $(APP_CXX)
export PJ_CFLAGS := $(APP_CFLAGS)

View File

@ -10,6 +10,11 @@ endif
#
LIB = $($(APP)_LIB)
#
# The full path of output lib file (e.g. ../lib/libapp.a).
#
SHLIB = $($(APP)_SHLIB)
#
# The full path of output executable file (e.g. ../bin/app.exe).
#
@ -82,6 +87,11 @@ $(LIB): $(OBJDIRS) $(OBJS) $($(APP)_EXTRA_DEP)
$(AR) $(LIB) $(OBJS)
$(RANLIB) $(LIB)
$(SHLIB): $(OBJDIRS) $(OBJS) $($(APP)_EXTRA_DEP)
if test ! -d $(LIBDIR); then $(subst @@,$(subst /,$(HOST_PSEP),$(LIBDIR)),$(HOST_MKDIR)); fi
$(LD) $(LDOUT)$(subst /,$(HOST_PSEP),$(SHLIB)) \
$(subst /,$(HOST_PSEP),$(OBJS)) $($(APP)_LDFLAGS)
$(EXE): $(OBJDIRS) $(OBJS) $($(APP)_EXTRA_DEP)
if test ! -d $(BINDIR); then $(subst @@,$(subst /,$(HOST_PSEP),$(BINDIR)),$(HOST_MKDIR)); fi
$(LD) $(LDOUT)$(subst /,$(HOST_PSEP),$(EXE)) \

View File

@ -25,7 +25,10 @@ fi
# Set the main iPhone developer directory, if not set
if test "x${DEVPATH}" = "x"; then
DEVPATH=/Developer/Platforms/iPhoneOS.platform/Developer
DEVPATH=/Applications/XCode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer
if test ! -d $DEVPATH; then
DEVPATH=/Developer/Platforms/iPhoneOS.platform/Developer
fi
echo "$F: DEVPATH is not specified, using ${DEVPATH}"
fi
@ -71,20 +74,29 @@ fi
# full path as it's not normally in user's PATH
if test "${CC}" = ""; then
for archpath in `ls -d ${SDKPATH}/usr/lib/gcc/arm-apple-darwin*`; do
archname=`basename ${archpath}`
for gccver in `ls ${archpath}`; do
gccpath="${DEVPATH}/usr/bin/${archname}-gcc-${gccver}"
if test -e ${gccpath}; then
export CC="${gccpath}"
# break
fi
done
if test ! "${CC}" = ""; then
echo "$F: CC is not specified, choosing ${CC}"
break
# Try to use llvm-gcc if available
gccpath="${DEVPATH}/usr/bin/llvm-gcc"
if test -e ${gccpath}; then
export CC="${gccpath}"
if test "${ARCH}" = ""; then
export ARCH="-arch armv7"
echo "$F: ARCH is not specified, choosing ${ARCH}"
fi
done
else
for archpath in `ls -d ${SDKPATH}/usr/lib/gcc/arm-apple-darwin*`; do
archname=`basename ${archpath}`
for gccver in `ls ${archpath}`; do
gccpath="${DEVPATH}/usr/bin/${archname}-gcc-${gccver}"
if test -e ${gccpath}; then
export CC="${gccpath}"
fi
done
done
fi
if test ! "${CC}" = ""; then
echo "$F: CC is not specified, choosing ${CC}"
fi
fi
if test "${CC}" = ""; then

View File

@ -3,6 +3,7 @@
export UTIL_TEST_OBJS = main.o
include ../../build.mak
include ../../version.mak
include $(PJDIR)/build/common.mak
RULES_MAK := $(PJDIR)/build/rules.mak
@ -55,10 +56,14 @@ TARGETS := pjlib-util pjlib-util-test
all: $(TARGETS)
doc:
cd .. && rm -rf docs/html docs/latex && doxygen docs/doxygen.cfg
@if [ -n "$(WWWDIR)" ]; then \
echo "Copying to $(WWWDIR)/pjlib-util/docs/html.." ; \
cp -a ../docs/html/* $(WWWDIR)/pjlib-util/docs/html/ ; \
cd .. && rm -rf docs/$(PJ_VERSION) && doxygen docs/doxygen.cfg
@if [ -n "$(WWWDIR)" ] && ! [ -d "$(WWWDIR)/docs/$(PJ_VERSION)/pjlib-util/docs/html" ] ; then \
echo "Creating docs/$(PJ_VERSION)/pjlib-util/docs/html" ; \
mkdir -p $(WWWDIR)/docs/$(PJ_VERSION)/pjlib-util/docs/html ; \
fi
@if [ -n "$(WWWDIR)" ] && [ -d "$(WWWDIR)/docs/$(PJ_VERSION)/pjlib-util/docs/html" ] ; then \
echo "Copying docs/$(PJ_VERSION) to $(WWWDIR)/docs/$(PJ_VERSION)/pjlib-util/docs/html.." ; \
cp -v -a ../docs/$(PJ_VERSION)/html/* $(WWWDIR)/docs/$(PJ_VERSION)/pjlib-util/docs/html/ ; \
fi
dep: depend
@ -69,7 +74,7 @@ distclean: realclean
pjlib-util:
$(MAKE) -f $(RULES_MAK) APP=PJLIB_UTIL app=pjlib-util $(PJLIB_UTIL_LIB)
pjlib-util-test:
pjlib-util-test: pjlib-util
$(MAKE) -f $(RULES_MAK) APP=UTIL_TEST app=pjlib-util-test $(UTIL_TEST_EXE)
.PHONY: ../lib/pjlib-util.ko

View File

@ -23,14 +23,14 @@ PROJECT_NAME = "PJLIB-UTIL Reference"
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER =
PROJECT_NUMBER = $(PJ_VERSION)
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY = docs
OUTPUT_DIRECTORY = docs/$(PJ_VERSION)
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
@ -578,7 +578,7 @@ ENUM_VALUES_PER_LINE = 4
# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
# probably better off using the HTML help feature.
GENERATE_TREEVIEW = YES
GENERATE_TREEVIEW = NO
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
# used to set the initial width (in pixels) of the frame in which the tree

View File

@ -1,6 +1,6 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>$title</title>
<title>$title ($projectnumber)</title>
<link href="/style/style.css" rel="stylesheet" type="text/css">
</head><body>
<!--#include virtual="/header.html" -->

View File

@ -188,6 +188,36 @@ typedef struct pj_http_req_param
*/
pj_http_auth_cred auth_cred;
/**
* Optional source port range to use when binding the socket.
* This can be used if the source port needs to be within a certain range
* for instance due to strict firewall settings. The port used will be
* randomized within the range.
*
* Note that if authentication is configured, the authentication response
* will be a new transaction
*
* Default is 0 (The OS will select the source port automatically)
*/
pj_uint16_t source_port_range_start;
/**
* Optional source port range to use when binding.
* The size of the port restriction range
*
* Default is 0 (The OS will select the source port automatically))
*/
pj_uint16_t source_port_range_size;
/**
* Max number of retries if binding to a port fails.
* Note that this does not adress the scenario where a request times out
* or errors. This needs to be taken care of by the on_complete callback.
*
* Default is 3
*/
pj_uint16_t max_retries;
} pj_http_req_param;
/**

View File

@ -26,15 +26,17 @@
#include <pj/pool.h>
#include <pj/string.h>
#include <pj/timer.h>
#include <pj/rand.h>
#include <pjlib-util/base64.h>
#include <pjlib-util/errno.h>
#include <pjlib-util/md5.h>
#include <pjlib-util/scanner.h>
#include <pjlib-util/string.h>
#define THIS_FILE "http_client.c"
#if 0
/* Enable some tracing */
#define THIS_FILE "http_client.c"
#define TRACE_(arg) PJ_LOG(3,arg)
#else
#define TRACE_(arg)
@ -764,6 +766,7 @@ PJ_DEF(void) pj_http_req_param_default(pj_http_req_param *param)
pj_strset2(&param->version, (char*)HTTP_1_0);
param->timeout.msec = PJ_HTTP_DEFAULT_TIMEOUT;
pj_time_val_normalize(&param->timeout);
param->max_retries = 3;
}
/* Get the location of '@' character to indicate the end of
@ -1004,11 +1007,13 @@ PJ_DEF(void*) pj_http_req_get_user_data(pj_http_req *http_req)
return http_req->param.user_data;
}
PJ_DEF(pj_status_t) pj_http_req_start(pj_http_req *http_req)
static pj_status_t start_http_req(pj_http_req *http_req,
pj_bool_t notify_on_fail)
{
pj_sock_t sock = PJ_INVALID_SOCKET;
pj_status_t status;
pj_activesock_cb asock_cb;
int retry = 0;
PJ_ASSERT_RETURN(http_req, PJ_EINVAL);
/* Http request is not idle, a request was initiated before and
@ -1031,7 +1036,7 @@ PJ_DEF(pj_status_t) pj_http_req_start(pj_http_req *http_req)
(http_req->param.addr_family==pj_AF_INET() &&
http_req->addr.ipv4.sin_addr.s_addr==PJ_INADDR_NONE))
{
return status; // cannot resolve host name
goto on_return;
}
http_req->resolved = PJ_TRUE;
}
@ -1045,6 +1050,32 @@ PJ_DEF(pj_status_t) pj_http_req_start(pj_http_req *http_req)
asock_cb.on_data_read = &http_on_data_read;
asock_cb.on_data_sent = &http_on_data_sent;
asock_cb.on_connect_complete = &http_on_connect;
do
{
pj_sockaddr_in bound_addr;
pj_uint16_t port = 0;
/* If we are using port restriction.
* Get a random port within the range
*/
if (http_req->param.source_port_range_start != 0) {
port = (pj_uint16_t)
(http_req->param.source_port_range_start +
(pj_rand() % http_req->param.source_port_range_size));
}
pj_sockaddr_in_init(&bound_addr, NULL, port);
status = pj_sock_bind(sock, &bound_addr, sizeof(bound_addr));
} while (status != PJ_SUCCESS && (retry++ < http_req->param.max_retries));
if (status != PJ_SUCCESS) {
PJ_PERROR(1,(THIS_FILE, status,
"Unable to bind to the requested port"));
pj_sock_close(sock);
goto on_return;
}
// TODO: should we set whole data to 0 by default?
// or add it in the param?
@ -1052,8 +1083,7 @@ PJ_DEF(pj_status_t) pj_http_req_start(pj_http_req *http_req)
NULL, http_req->ioqueue,
&asock_cb, http_req, &http_req->asock);
if (status != PJ_SUCCESS) {
if (sock != PJ_INVALID_SOCKET)
pj_sock_close(sock);
pj_sock_close(sock);
goto on_return; // error creating activesock
}
@ -1074,7 +1104,9 @@ PJ_DEF(pj_status_t) pj_http_req_start(pj_http_req *http_req)
pj_sockaddr_get_len(&http_req->addr));
if (status == PJ_SUCCESS) {
http_req->state = SENDING_REQUEST;
return http_req_start_sending(http_req);
status = http_req_start_sending(http_req);
if (status != PJ_SUCCESS)
goto on_return;
} else if (status != PJ_EPENDING) {
goto on_return; // error connecting
}
@ -1082,10 +1114,21 @@ PJ_DEF(pj_status_t) pj_http_req_start(pj_http_req *http_req)
return PJ_SUCCESS;
on_return:
http_req_end_request(http_req);
http_req->error = status;
if (notify_on_fail)
pj_http_req_cancel(http_req, PJ_TRUE);
else
http_req_end_request(http_req);
return status;
}
/* Starts an asynchronous HTTP request to the URL specified. */
PJ_DEF(pj_status_t) pj_http_req_start(pj_http_req *http_req)
{
return start_http_req(http_req, PJ_FALSE);
}
/* Respond to basic authentication challenge */
static pj_status_t auth_respond_basic(pj_http_req *hreq)
{
@ -1345,7 +1388,7 @@ static pj_status_t auth_respond_digest(pj_http_req *hreq)
*/
const pj_str_t STR_MD5 = { "MD5", 3 };
const pj_str_t qop = pj_str("auth");
const pj_str_t nc = pj_str("1");
const pj_str_t nc = pj_str("00000001");
const pj_str_t cnonce = pj_str("b39971");
auth_create_digest_response(&digest_response, cred,
@ -1433,7 +1476,7 @@ static void restart_req_with_auth(pj_http_req *hreq)
http_req_end_request(hreq);
status = pj_http_req_start(hreq);
status = start_http_req(hreq, PJ_TRUE);
if (status != PJ_SUCCESS)
goto on_error;

View File

@ -368,8 +368,20 @@ PJ_DEF(pj_status_t) pj_pcap_read_udp(pj_pcap_file *file,
*udp_payload_size = sz;
// Some layers may have trailer, e.g: link eth2.
/* Check that we've read all the packets */
PJ_ASSERT_RETURN(sz_read == rec_incl, PJ_EBUG);
//PJ_ASSERT_RETURN(sz_read == rec_incl, PJ_EBUG);
/* Skip trailer */
while (sz_read < rec_incl) {
sz = rec_incl - sz_read;
status = read_file(file, &tmp.eth, &sz);
if (status != PJ_SUCCESS) {
TRACE_((file->obj_name, "Error reading trailer: %d", status));
return status;
}
sz_read += sz;
}
return PJ_SUCCESS;
}

View File

@ -180,7 +180,8 @@ struct pj_dns_resolver
unsigned char udp_rx_pkt[UDPSZ];/**< UDP receive buffer. */
unsigned char udp_tx_pkt[UDPSZ];/**< UDP receive buffer. */
pj_ssize_t udp_len; /**< Length of received packet. */
pj_ioqueue_op_key_t udp_op_key; /**< UDP read operation key. */
pj_ioqueue_op_key_t udp_op_rx_key; /**< UDP read operation key. */
pj_ioqueue_op_key_t udp_op_tx_key; /**< UDP write operation key. */
pj_sockaddr_in udp_src_addr; /**< Source address of packet */
int udp_addr_len; /**< Source address length. */
@ -223,6 +224,63 @@ static pj_status_t select_nameservers(pj_dns_resolver *resolver,
unsigned servers[]);
/* Close UDP socket */
static void close_sock(pj_dns_resolver *resv)
{
/* Close existing socket */
if (resv->udp_key != NULL) {
pj_ioqueue_unregister(resv->udp_key);
resv->udp_key = NULL;
resv->udp_sock = PJ_INVALID_SOCKET;
} else if (resv->udp_sock != PJ_INVALID_SOCKET) {
pj_sock_close(resv->udp_sock);
resv->udp_sock = PJ_INVALID_SOCKET;
}
}
/* Initialize UDP socket */
static pj_status_t init_sock(pj_dns_resolver *resv)
{
pj_ioqueue_callback socket_cb;
pj_status_t status;
/* Create the UDP socket */
status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &resv->udp_sock);
if (status != PJ_SUCCESS)
return status;
/* Bind to any address/port */
status = pj_sock_bind_in(resv->udp_sock, 0, 0);
if (status != PJ_SUCCESS)
return status;
/* Register to ioqueue */
pj_bzero(&socket_cb, sizeof(socket_cb));
socket_cb.on_read_complete = &on_read_complete;
status = pj_ioqueue_register_sock(resv->pool, resv->ioqueue,
resv->udp_sock, resv, &socket_cb,
&resv->udp_key);
if (status != PJ_SUCCESS)
return status;
pj_ioqueue_op_key_init(&resv->udp_op_rx_key, sizeof(resv->udp_op_rx_key));
pj_ioqueue_op_key_init(&resv->udp_op_tx_key, sizeof(resv->udp_op_tx_key));
/* Start asynchronous read to the UDP socket */
resv->udp_len = sizeof(resv->udp_rx_pkt);
resv->udp_addr_len = sizeof(resv->udp_src_addr);
status = pj_ioqueue_recvfrom(resv->udp_key, &resv->udp_op_rx_key,
resv->udp_rx_pkt, &resv->udp_len,
PJ_IOQUEUE_ALWAYS_ASYNC,
&resv->udp_src_addr, &resv->udp_addr_len);
if (status != PJ_EPENDING)
return status;
return PJ_SUCCESS;
}
/* Initialize DNS settings with default values */
PJ_DEF(void) pj_dns_settings_default(pj_dns_settings *s)
{
@ -247,7 +305,6 @@ PJ_DEF(pj_status_t) pj_dns_resolver_create( pj_pool_factory *pf,
{
pj_pool_t *pool;
pj_dns_resolver *resv;
pj_ioqueue_callback socket_cb;
pj_status_t status;
/* Sanity check */
@ -302,37 +359,11 @@ PJ_DEF(pj_status_t) pj_dns_resolver_create( pj_pool_factory *pf,
resv->hquerybyres = pj_hash_create(pool, Q_HASH_TABLE_SIZE);
pj_list_init(&resv->query_free_nodes);
/* Create the UDP socket */
status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &resv->udp_sock);
/* Initialize the UDP socket */
status = init_sock(resv);
if (status != PJ_SUCCESS)
goto on_error;
/* Bind to any address/port */
status = pj_sock_bind_in(resv->udp_sock, 0, 0);
if (status != PJ_SUCCESS)
goto on_error;
/* Register to ioqueue */
pj_bzero(&socket_cb, sizeof(socket_cb));
socket_cb.on_read_complete = &on_read_complete;
status = pj_ioqueue_register_sock(pool, resv->ioqueue, resv->udp_sock,
resv, &socket_cb, &resv->udp_key);
if (status != PJ_SUCCESS)
goto on_error;
pj_ioqueue_op_key_init(&resv->udp_op_key, sizeof(resv->udp_op_key));
/* Start asynchronous read to the UDP socket */
resv->udp_len = sizeof(resv->udp_rx_pkt);
resv->udp_addr_len = sizeof(resv->udp_src_addr);
status = pj_ioqueue_recvfrom(resv->udp_key, &resv->udp_op_key,
resv->udp_rx_pkt, &resv->udp_len,
PJ_IOQUEUE_ALWAYS_ASYNC,
&resv->udp_src_addr, &resv->udp_addr_len);
if (status != PJ_EPENDING)
goto on_error;
/* Looks like everything is okay */
*p_resolver = resv;
return PJ_SUCCESS;
@ -392,14 +423,7 @@ PJ_DEF(pj_status_t) pj_dns_resolver_destroy( pj_dns_resolver *resolver,
resolver->timer = NULL;
}
if (resolver->udp_key != NULL) {
pj_ioqueue_unregister(resolver->udp_key);
resolver->udp_key = NULL;
resolver->udp_sock = PJ_INVALID_SOCKET;
} else if (resolver->udp_sock != PJ_INVALID_SOCKET) {
pj_sock_close(resolver->udp_sock);
resolver->udp_sock = PJ_INVALID_SOCKET;
}
close_sock(resolver);
if (resolver->own_ioqueue && resolver->ioqueue) {
pj_ioqueue_destroy(resolver->ioqueue);
@ -561,15 +585,6 @@ static pj_status_t transmit_query(pj_dns_resolver *resolver,
pj_time_val delay;
pj_status_t status;
/* Create DNS query packet */
pkt_size = sizeof(resolver->udp_tx_pkt);
name = pj_str(q->key.name);
status = pj_dns_make_query(resolver->udp_tx_pkt, &pkt_size,
q->id, q->key.qtype, &name);
if (status != PJ_SUCCESS) {
return status;
}
/* Select which nameserver(s) to send requests to. */
server_cnt = PJ_ARRAY_SIZE(servers);
status = select_nameservers(resolver, &server_cnt, servers);
@ -595,6 +610,28 @@ static pj_status_t transmit_query(pj_dns_resolver *resolver,
return status;
}
/* Check if the socket is available for sending */
if (pj_ioqueue_is_pending(resolver->udp_key, &resolver->udp_op_tx_key)) {
++q->transmit_cnt;
PJ_LOG(4,(resolver->name.ptr,
"Socket busy in transmitting DNS %s query for %s%s",
pj_dns_get_type_name(q->key.qtype),
q->key.name,
(q->transmit_cnt < resolver->settings.qretr_count?
", will try again later":"")));
return PJ_SUCCESS;
}
/* Create DNS query packet */
pkt_size = sizeof(resolver->udp_tx_pkt);
name = pj_str(q->key.name);
status = pj_dns_make_query(resolver->udp_tx_pkt, &pkt_size,
q->id, q->key.qtype, &name);
if (status != PJ_SUCCESS) {
pj_timer_heap_cancel(resolver->timer, &q->timer_entry);
return status;
}
/* Get current time. */
pj_gettimeofday(&now);
@ -603,13 +640,16 @@ static pj_status_t transmit_query(pj_dns_resolver *resolver,
pj_ssize_t sent = (pj_ssize_t) pkt_size;
struct nameserver *ns = &resolver->ns[servers[i]];
pj_sock_sendto(resolver->udp_sock, resolver->udp_tx_pkt, &sent, 0,
&resolver->ns[servers[i]].addr, sizeof(pj_sockaddr_in));
status = pj_ioqueue_sendto(resolver->udp_key,
&resolver->udp_op_tx_key,
resolver->udp_tx_pkt, &sent, 0,
&resolver->ns[servers[i]].addr,
sizeof(pj_sockaddr_in));
PJ_LOG(4,(resolver->name.ptr,
PJ_PERROR(4,(resolver->name.ptr, status,
"%s %d bytes to NS %d (%s:%d): DNS %s query for %s",
(q->transmit_cnt==0? "Transmitting":"Re-transmitting"),
(int)sent, servers[i],
(int)pkt_size, servers[i],
pj_inet_ntoa(ns->addr.sin_addr),
(int)pj_ntohs(ns->addr.sin_port),
pj_dns_get_type_name(q->key.qtype),
@ -1248,6 +1288,9 @@ static void on_timeout( pj_timer_heap_t *timer_heap,
pj_hash_set(NULL, resolver->hquerybyid, &q->id, sizeof(q->id), 0, NULL);
pj_hash_set(NULL, resolver->hquerybyres, &q->key, sizeof(q->key), 0, NULL);
/* Workaround for deadlock problem in #1565 (similar to #1108) */
pj_mutex_unlock(resolver->mutex);
/* Call application callback, if any. */
if (q->cb)
(*q->cb)(q->user_data, PJ_ETIMEDOUT, NULL);
@ -1260,6 +1303,9 @@ static void on_timeout( pj_timer_heap_t *timer_heap,
cq = cq->next;
}
/* Workaround for deadlock problem in #1565 (similar to #1108) */
pj_mutex_lock(resolver->mutex);
/* Clear data */
q->timer_entry.id = 0;
q->user_data = NULL;

View File

@ -393,7 +393,6 @@ PJ_DEF(void) pj_scan_get_quotes(pj_scanner *scanner,
}
/* break from main loop if we have odd number of backslashes */
if (((unsigned)(q-r) & 0x01) == 1) {
++s;
break;
}
++s;

View File

@ -19,6 +19,7 @@
*/
#include <pjlib-util/stun_simple.h>
#include <pjlib-util/errno.h>
#include <pj/compat/socket.h>
#include <pj/log.h>
#include <pj/os.h>
#include <pj/pool.h>
@ -44,7 +45,7 @@ PJ_DEF(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf,
{
unsigned srv_cnt;
pj_sockaddr_in srv_addr[2];
int i, j, send_cnt = 0;
int i, send_cnt = 0, nfds;
pj_pool_t *pool;
struct query_rec {
struct {
@ -113,6 +114,17 @@ PJ_DEF(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf,
TRACE_((THIS_FILE, " Done initialization."));
#if defined(PJ_SELECT_NEEDS_NFDS) && PJ_SELECT_NEEDS_NFDS!=0
nfds = -1;
for (i=0; i<sock_cnt; ++i) {
if (sock[i] > nfds) {
nfds = sock[i];
}
}
#else
nfds = FD_SETSIZE-1;
#endif
/* Main retransmission loop. */
for (send_cnt=0; send_cnt<MAX_REQUEST; ++send_cnt) {
pj_time_val next_tx, now;
@ -123,6 +135,7 @@ PJ_DEF(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf,
/* Send messages to servers that has not given us response. */
for (i=0; i<sock_cnt && status==PJ_SUCCESS; ++i) {
unsigned j;
for (j=0; j<srv_cnt && status==PJ_SUCCESS; ++j) {
pjstun_msg_hdr *msg_hdr = (pjstun_msg_hdr*) out_msg;
pj_ssize_t sent_len;
@ -169,7 +182,7 @@ PJ_DEF(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf,
PJ_FD_SET(sock[i], &r);
}
select_rc = pj_sock_select(PJ_IOQUEUE_MAX_HANDLES, &r, NULL, NULL, &timeout);
select_rc = pj_sock_select(nfds+1, &r, NULL, NULL, &timeout);
TRACE_((THIS_FILE, " select() rc=%d", select_rc));
if (select_rc < 1)
continue;

View File

@ -100,13 +100,13 @@ static pj_xml_node *xml_parse_node( pj_pool_t *pool, pj_scanner *scanner)
pj_scan_get_char(scanner);
/* Get node name. */
pj_scan_get_until_chr( scanner, " />\t", &node->name);
pj_scan_get_until_chr( scanner, " />\t\r\n", &node->name);
/* Get attributes. */
while (*scanner->curptr != '>' && *scanner->curptr != '/') {
pj_xml_attr *attr = alloc_attr(pool);
pj_scan_get_until_chr( scanner, "=> \t", &attr->name);
pj_scan_get_until_chr( scanner, "=> \t\r\n", &attr->name);
if (*scanner->curptr == '=') {
pj_scan_get_char( scanner );
pj_scan_get_quotes(scanner, "\"'", "\"'", 2, &attr->value);

View File

@ -1,4 +1,5 @@
include ../../build.mak
include ../../version.mak
include $(PJDIR)/build/common.mak
RULES_MAK := $(PJDIR)/build/rules.mak
@ -57,12 +58,15 @@ export CC_OUT CC AR RANLIB HOST_MV HOST_RM HOST_RMDIR HOST_MKDIR OBJEXT LD LDOUT
all: $(TARGETS)
doc:
cd .. && rm -rf docs/html docs/latex && doxygen docs/doxygen.cfg
@if [ -n "$(WWWDIR)" ]; then \
echo "Copying to $(WWWDIR)/pjlib/docs/html.." ; \
cp -a ../docs/html/* $(WWWDIR)/pjlib/docs/html/ ; \
cd .. && rm -rf docs/$(PJ_VERSION) && doxygen docs/doxygen.cfg
@if [ -n "$(WWWDIR)" ] && ! [ -d "$(WWWDIR)/docs/$(PJ_VERSION)/pjlib/docs/html" ] ; then \
echo "Creating docs/$(PJ_VERSION)/pjlib/docs/html" ; \
mkdir -p $(WWWDIR)/docs/$(PJ_VERSION)/pjlib/docs/html ; \
fi
@if [ -n "$(WWWDIR)" ] && [ -d "$(WWWDIR)/docs/$(PJ_VERSION)/pjlib/docs/html" ] ; then \
echo "Copying docs/$(PJ_VERSION) to $(WWWDIR)/docs/$(PJ_VERSION)/pjlib/docs/html.." ; \
cp -v -a ../docs/$(PJ_VERSION)/html/* $(WWWDIR)/docs/$(PJ_VERSION)/pjlib/docs/html/ ; \
fi
print:
$(MAKE) -f $(RULES_MAK) APP=PJLIB app=pjlib print_lib
$(MAKE) -f $(RULES_MAK) APP=TEST app=pjlib-test print_bin
@ -83,7 +87,7 @@ pjlib: ../include/pj/config_site.h
../include/pj/config_site.h:
touch ../include/pj/config_site.h
pjlib-test:
pjlib-test: pjlib
$(MAKE) -f $(RULES_MAK) APP=TEST app=pjlib-test $(TEST_EXE)
.PHONY: ../lib/pjlib.ko

View File

@ -23,14 +23,14 @@ PROJECT_NAME = "PJLIB Reference"
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER =
PROJECT_NUMBER = $(PJ_VERSION)
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY = docs
OUTPUT_DIRECTORY = docs/$(PJ_VERSION)
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
@ -578,7 +578,7 @@ ENUM_VALUES_PER_LINE = 4
# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
# probably better off using the HTML help feature.
GENERATE_TREEVIEW = YES
GENERATE_TREEVIEW = NO
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
# used to set the initial width (in pixels) of the frame in which the tree

View File

@ -1,6 +1,6 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>$title</title>
<title>$title ($projectnumber)</title>
<link href="/style/style.css" rel="stylesheet" type="text/css">
</head><body>
<!--#include virtual="/header.html" -->

View File

@ -177,6 +177,8 @@
# include "Availability.h"
/* Use CFHost API for pj_getaddrinfo() (see ticket #1246) */
# define PJ_GETADDRINFO_USE_CFHOST 1
/* Disable local host resolution in pj_gethostip() (see ticket #1342) */
# define PJ_GETHOSTIP_DISABLE_LOCAL_RESOLUTION 1
# ifdef __IPHONE_4_0
/* Is multitasking support available? (see ticket #1107) */
# define PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT 1

View File

@ -108,6 +108,11 @@
# define NULL 0
#endif
/* Endianness */
#ifndef PJ_IS_LITTLE_ENDIAN
# define PJ_IS_LITTLE_ENDIAN 1
# define PJ_IS_BIG_ENDIAN 0
#endif
/* Doesn't seem to allow more than this */
#define PJ_IOQUEUE_MAX_HANDLES 8

View File

@ -98,6 +98,12 @@
*/
#define PJ_SELECT_NEEDS_NFDS 0
/* Endianness */
#ifndef PJ_IS_LITTLE_ENDIAN
# define PJ_IS_LITTLE_ENDIAN 1
# define PJ_IS_BIG_ENDIAN 0
#endif
/* Default threading is enabled, unless it's overridden. */
#ifndef PJ_HAS_THREADS
# define PJ_HAS_THREADS (1)

View File

@ -165,7 +165,7 @@
#elif defined(PJ_M_IA64) || defined(__ia64__) || defined(_IA64) || \
defined(__IA64__) || defined( _M_IA64)
/*
* Intel IA64 processor, little endian
* Intel IA64 processor, default to little endian
*/
# undef PJ_M_IA64
# define PJ_M_IA64 1
@ -203,15 +203,14 @@
#elif defined(PJ_M_MIPS) || defined(__mips__) || defined(__mips) || \
defined(__MIPS__) || defined(MIPS) || defined(_MIPS_)
/*
* MIPS, default to little endian
* MIPS, bi-endian, so raise error if endianness is not configured
*/
# undef PJ_M_MIPS
# define PJ_M_MIPS 1
# define PJ_M_NAME "mips"
# define PJ_HAS_PENTIUM 0
# if !defined(PJ_IS_LITTLE_ENDIAN) && !defined(PJ_IS_BIG_ENDIAN)
# define PJ_IS_LITTLE_ENDIAN 1
# define PJ_IS_BIG_ENDIAN 0
# if !PJ_IS_LITTLE_ENDIAN && !PJ_IS_BIG_ENDIAN
# error Endianness must be declared for this processor
# endif
@ -229,29 +228,29 @@
#elif defined (PJ_M_ARMV4) || defined(ARM) || defined(_ARM_) || \
defined(ARMV4) || defined(__arm__)
/*
* ARM, default to little endian
* ARM, bi-endian, so raise error if endianness is not configured
*/
# undef PJ_M_ARMV4
# define PJ_M_ARMV4 1
# define PJ_M_NAME "armv4"
# define PJ_HAS_PENTIUM 0
# if !defined(PJ_IS_LITTLE_ENDIAN) && !defined(PJ_IS_BIG_ENDIAN)
# define PJ_IS_LITTLE_ENDIAN 1
# define PJ_IS_BIG_ENDIAN 0
# if !PJ_IS_LITTLE_ENDIAN && !PJ_IS_BIG_ENDIAN
# error Endianness must be declared for this processor
# endif
#elif defined (PJ_M_POWERPC) || defined(__powerpc) || defined(__powerpc__) || \
defined(__POWERPC__) || defined(__ppc__) || defined(_M_PPC) || \
defined(_ARCH_PPC)
/*
* PowerPC, big endian
* PowerPC, bi-endian, so raise error if endianness is not configured
*/
# undef PJ_M_POWERPC
# define PJ_M_POWERPC 1
# define PJ_M_NAME "powerpc"
# define PJ_HAS_PENTIUM 0
# define PJ_IS_LITTLE_ENDIAN 0
# define PJ_IS_BIG_ENDIAN 1
# if !PJ_IS_LITTLE_ENDIAN && !PJ_IS_BIG_ENDIAN
# error Endianness must be declared for this processor
# endif
#elif defined (PJ_M_NIOS2) || defined(__nios2) || defined(__nios2__) || \
defined(__NIOS2__) || defined(__M_NIOS2) || defined(_ARCH_NIOS2)
@ -1123,13 +1122,13 @@ PJ_BEGIN_DECL
#define PJ_VERSION_NUM_MAJOR 1
/** PJLIB version minor number. */
#define PJ_VERSION_NUM_MINOR 10
#define PJ_VERSION_NUM_MINOR 16
/** PJLIB version revision number. */
#define PJ_VERSION_NUM_REV 0
/**
* Extra suffix for the version (e.g. "-trunk"), or empty for
* Extra suffix for the version (e.g. "-svn"), or empty for
* web release version.
*/
#define PJ_VERSION_NUM_EXTRA "-svn"

View File

@ -82,6 +82,17 @@ PJ_DECL(unsigned) pj_GUID_STRING_LENGTH(void);
*/
PJ_DECL(pj_str_t*) pj_generate_unique_string(pj_str_t *str);
/**
* Create a globally unique string in lowercase, which length is
* PJ_GUID_STRING_LENGTH characters. Caller is responsible for preallocating
* the storage used in the string.
*
* @param str The string to store the result.
*
* @return The string.
*/
PJ_DECL(pj_str_t*) pj_generate_unique_string_lower(pj_str_t *str);
/**
* Generate a unique string.
*
@ -90,6 +101,14 @@ PJ_DECL(pj_str_t*) pj_generate_unique_string(pj_str_t *str);
*/
PJ_DECL(void) pj_create_unique_string(pj_pool_t *pool, pj_str_t *str);
/**
* Generate a unique string in lowercase.
*
* @param pool Pool to allocate memory from.
* @param str The string.
*/
PJ_DECL(void) pj_create_unique_string_lower(pj_pool_t *pool, pj_str_t *str);
/**
* @}

View File

@ -75,8 +75,8 @@ PJ_DECL(pj_uint32_t) pj_hash_calc(pj_uint32_t hval,
* string is stored in \c result.
*
* @param hval The initial hash value, normally zero.
* @param result Buffer to store the result, which must be enough to hold
* the string.
* @param result Optional. Buffer to store the result, which must be enough
* to hold the string.
* @param key The input key to be converted and calculated.
*
* @return The hash value.
@ -115,6 +115,17 @@ PJ_DECL(void *) pj_hash_get( pj_hash_table_t *ht,
pj_uint32_t *hval );
/**
* Variant of #pj_hash_get() with the key being converted to lowercase when
* calculating the hash value.
*
* @see pj_hash_get()
*/
PJ_DECL(void *) pj_hash_get_lower( pj_hash_table_t *ht,
const void *key, unsigned keylen,
pj_uint32_t *hval );
/**
* Associate/disassociate a value with the specified key. If value is not
* NULL and entry already exists, the entry's value will be overwritten.
@ -125,8 +136,8 @@ PJ_DECL(void *) pj_hash_get( pj_hash_table_t *ht,
* @param pool the pool to allocate the new entry if a new entry has to be
* created.
* @param ht the hash table.
* @param key the key, which MUST point to buffer that remains valid
* for the duration of the entry.
* @param key the key. If pool is not specified, the key MUST point to
* buffer that remains valid for the duration of the entry.
* @param keylen the length of the key, or PJ_HASH_KEY_STRING to use the
* string length of the key.
* @param hval if the value is not zero, then the hash table will use
@ -141,6 +152,17 @@ PJ_DECL(void) pj_hash_set( pj_pool_t *pool, pj_hash_table_t *ht,
void *value );
/**
* Variant of #pj_hash_set() with the key being converted to lowercase when
* calculating the hash value.
*
* @see pj_hash_set()
*/
PJ_DECL(void) pj_hash_set_lower( pj_pool_t *pool, pj_hash_table_t *ht,
const void *key, unsigned keylen,
pj_uint32_t hval, void *value );
/**
* Associate/disassociate a value with the specified key. This function works
* like #pj_hash_set(), except that it doesn't use pool (hence the np -- no
@ -164,6 +186,18 @@ PJ_DECL(void) pj_hash_set_np(pj_hash_table_t *ht,
pj_uint32_t hval, pj_hash_entry_buf entry_buf,
void *value);
/**
* Variant of #pj_hash_set_np() with the key being converted to lowercase
* when calculating the hash value.
*
* @see pj_hash_set_np()
*/
PJ_DECL(void) pj_hash_set_np_lower(pj_hash_table_t *ht,
const void *key, unsigned keylen,
pj_uint32_t hval,
pj_hash_entry_buf entry_buf,
void *value);
/**
* Get the total number of entries in the hash table.
*

View File

@ -509,7 +509,7 @@ PJ_INLINE(void*) pj_pool_zalloc(pj_pool_t *pool, pj_size_t size)
* Internal functions
*/
PJ_IDECL(void*) pj_pool_alloc_from_block(pj_pool_block *block, pj_size_t size);
PJ_DECL(void*) pj_pool_allocate_find(pj_pool_t *pool, unsigned size);
PJ_DECL(void*) pj_pool_allocate_find(pj_pool_t *pool, pj_size_t size);

View File

@ -47,7 +47,7 @@ PJ_IDEF(void*) pj_pool_alloc_from_block( pj_pool_block *block, pj_size_t size )
if (size & (PJ_POOL_ALIGNMENT-1)) {
size = (size + PJ_POOL_ALIGNMENT) & ~(PJ_POOL_ALIGNMENT-1);
}
if ((unsigned)(block->end - block->cur) >= size) {
if ((pj_size_t)(block->end - block->cur) >= size) {
void *ptr = block->cur;
block->cur += size;
return ptr;

View File

@ -493,6 +493,13 @@ typedef struct pj_in_addr
*/
#define PJ_INET6_ADDRSTRLEN 46
/**
* The size of sin_zero field in pj_sockaddr_in structure. Most OSes
* use 8, but others such as the BSD TCP/IP stack in eCos uses 24.
*/
#ifndef PJ_SOCKADDR_IN_SIN_ZERO_LEN
# define PJ_SOCKADDR_IN_SIN_ZERO_LEN 8
#endif
/**
* This structure describes Internet socket address.
@ -512,7 +519,7 @@ struct pj_sockaddr_in
#endif
pj_uint16_t sin_port; /**< Transport layer port number. */
pj_in_addr sin_addr; /**< IP address. */
char sin_zero[8]; /**< Padding. */
char sin_zero[PJ_SOCKADDR_IN_SIN_ZERO_LEN]; /**< Padding.*/
};

View File

@ -331,16 +331,38 @@ PJ_DECL(pj_status_t) pj_ssl_cipher_get_availables(pj_ssl_cipher ciphers[],
unsigned *cipher_num);
/**
* Check if the specified cipher is supported by SSL/TLS backend.
*
* @param cipher The cipher.
*
* @return PJ_TRUE when supported.
*/
PJ_DECL(pj_bool_t) pj_ssl_cipher_is_supported(pj_ssl_cipher cipher);
/**
* Get cipher name string.
*
* @param cipher The cipher.
*
* @return The cipher name or NULL if cipher is not recognized.
* @return The cipher name or NULL if cipher is not recognized/
* supported.
*/
PJ_DECL(const char*) pj_ssl_cipher_name(pj_ssl_cipher cipher);
/**
* Get cipher ID from cipher name string.
*
* @param cipher_name The cipher name string.
*
* @return The cipher ID or PJ_TLS_UNKNOWN_CIPHER if the cipher
* name string is not recognized/supported.
*/
PJ_DECL(pj_ssl_cipher) pj_ssl_cipher_id(const char *cipher_name);
/**
* This structure contains the callbacks to be called by the secure socket.
*/
@ -520,6 +542,11 @@ typedef struct pj_ssl_sock_info
*/
pj_uint32_t verify_status;
/**
* Last native error returned by the backend.
*/
unsigned long last_native_err;
} pj_ssl_sock_info;

View File

@ -290,6 +290,9 @@ typedef int pj_exception_id_t;
* in random string generation, and to initialize operating system dependent
* functionality (such as WSAStartup() in Windows).
*
* Apart from calling pj_init(), application typically should also initialize
* the random seed by calling pj_srand().
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t) pj_init(void);

View File

@ -17,11 +17,32 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <pj/ctype.h>
#include <pj/guid.h>
#include <pj/pool.h>
PJ_DEF(pj_str_t*) pj_generate_unique_string_lower(pj_str_t *str)
{
int i;
pj_generate_unique_string(str);
for (i = 0; i < str->slen; i++)
str->ptr[i] = (char)pj_tolower(str->ptr[i]);
return str;
}
PJ_DEF(void) pj_create_unique_string(pj_pool_t *pool, pj_str_t *str)
{
str->ptr = (char*)pj_pool_alloc(pool, PJ_GUID_STRING_LENGTH);
pj_generate_unique_string(str);
}
PJ_DEF(void) pj_create_unique_string_lower(pj_pool_t *pool, pj_str_t *str)
{
int i;
pj_create_unique_string(pool, str);
for (i = 0; i < str->slen; i++)
str->ptr[i] = (char)pj_tolower(str->ptr[i]);
}

View File

@ -79,16 +79,21 @@ PJ_DEF(pj_uint32_t) pj_hash_calc_tolower( pj_uint32_t hval,
#if defined(PJ_HASH_USE_OWN_TOLOWER) && PJ_HASH_USE_OWN_TOLOWER != 0
for (i=0; i<key->slen; ++i) {
pj_uint8_t c = key->ptr[i];
char lower;
if (c & 64)
result[i] = (char)(c | 32);
lower = (char)(c | 32);
else
result[i] = (char)c;
hval = hval * PJ_HASH_MULTIPLIER + result[i];
lower = (char)c;
if (result)
result[i] = lower;
hval = hval * PJ_HASH_MULTIPLIER + lower;
}
#else
for (i=0; i<key->slen; ++i) {
result[i] = (char)pj_tolower(key->ptr[i]);
hval = hval * PJ_HASH_MULTIPLIER + result[i];
char lower = (char)pj_tolower(key->ptr[i]);
if (result)
result[i] = lower;
hval = hval * PJ_HASH_MULTIPLIER + lower;
}
#endif
@ -128,7 +133,7 @@ PJ_DEF(pj_hash_table_t*) pj_hash_create(pj_pool_t *pool, unsigned size)
static pj_hash_entry **find_entry( pj_pool_t *pool, pj_hash_table_t *ht,
const void *key, unsigned keylen,
void *val, pj_uint32_t *hval,
void *entry_buf)
void *entry_buf, pj_bool_t lower)
{
pj_uint32_t hash;
pj_hash_entry **p_entry, *entry;
@ -146,14 +151,20 @@ static pj_hash_entry **find_entry( pj_pool_t *pool, pj_hash_table_t *ht,
if (keylen==PJ_HASH_KEY_STRING) {
const pj_uint8_t *p = (const pj_uint8_t*)key;
for ( ; *p; ++p ) {
hash = hash * PJ_HASH_MULTIPLIER + *p;
if (lower)
hash = hash * PJ_HASH_MULTIPLIER + pj_tolower(*p);
else
hash = hash * PJ_HASH_MULTIPLIER + *p;
}
keylen = p - (const unsigned char*)key;
} else {
const pj_uint8_t *p = (const pj_uint8_t*)key,
*end = p + keylen;
for ( ; p!=end; ++p) {
hash = hash * PJ_HASH_MULTIPLIER + *p;
if (lower)
hash = hash * PJ_HASH_MULTIPLIER + pj_tolower(*p);
else
hash = hash * PJ_HASH_MULTIPLIER + *p;
}
}
@ -168,9 +179,11 @@ static pj_hash_entry **find_entry( pj_pool_t *pool, pj_hash_table_t *ht,
p_entry = &entry->next, entry = *p_entry)
{
if (entry->hash==hash && entry->keylen==keylen &&
pj_memcmp(entry->key, key, keylen)==0)
((lower && pj_ansi_strnicmp((const char*)entry->key,
(const char*)key, keylen)==0) ||
(!lower && pj_memcmp(entry->key, key, keylen)==0)))
{
break;
break;
}
}
@ -214,17 +227,27 @@ PJ_DEF(void *) pj_hash_get( pj_hash_table_t *ht,
pj_uint32_t *hval)
{
pj_hash_entry *entry;
entry = *find_entry( NULL, ht, key, keylen, NULL, hval, NULL);
entry = *find_entry( NULL, ht, key, keylen, NULL, hval, NULL, PJ_FALSE);
return entry ? entry->value : NULL;
}
PJ_DEF(void) pj_hash_set( pj_pool_t *pool, pj_hash_table_t *ht,
const void *key, unsigned keylen, pj_uint32_t hval,
void *value )
PJ_DEF(void *) pj_hash_get_lower( pj_hash_table_t *ht,
const void *key, unsigned keylen,
pj_uint32_t *hval)
{
pj_hash_entry *entry;
entry = *find_entry( NULL, ht, key, keylen, NULL, hval, NULL, PJ_TRUE);
return entry ? entry->value : NULL;
}
static void hash_set( pj_pool_t *pool, pj_hash_table_t *ht,
const void *key, unsigned keylen, pj_uint32_t hval,
void *value, void *entry_buf, pj_bool_t lower )
{
pj_hash_entry **p_entry;
p_entry = find_entry( pool, ht, key, keylen, value, &hval, NULL);
p_entry = find_entry( pool, ht, key, keylen, value, &hval, entry_buf,
lower);
if (*p_entry) {
if (value == NULL) {
/* delete entry */
@ -241,29 +264,35 @@ PJ_DEF(void) pj_hash_set( pj_pool_t *pool, pj_hash_table_t *ht,
}
}
PJ_DEF(void) pj_hash_set( pj_pool_t *pool, pj_hash_table_t *ht,
const void *key, unsigned keylen, pj_uint32_t hval,
void *value )
{
hash_set(pool, ht, key, keylen, hval, value, NULL, PJ_FALSE);
}
PJ_DEF(void) pj_hash_set_lower( pj_pool_t *pool, pj_hash_table_t *ht,
const void *key, unsigned keylen,
pj_uint32_t hval, void *value )
{
hash_set(pool, ht, key, keylen, hval, value, NULL, PJ_TRUE);
}
PJ_DEF(void) pj_hash_set_np( pj_hash_table_t *ht,
const void *key, unsigned keylen,
pj_uint32_t hval, pj_hash_entry_buf entry_buf,
void *value)
{
pj_hash_entry **p_entry;
hash_set(NULL, ht, key, keylen, hval, value, (void *)entry_buf, PJ_FALSE);
}
p_entry = find_entry( NULL, ht, key, keylen, value, &hval,
(void*)entry_buf );
if (*p_entry) {
if (value == NULL) {
/* delete entry */
PJ_LOG(6, ("hashtbl", "%p: p_entry %p deleted", ht, *p_entry));
*p_entry = (*p_entry)->next;
--ht->count;
} else {
/* overwrite */
(*p_entry)->value = value;
PJ_LOG(6, ("hashtbl", "%p: p_entry %p value set to %p", ht,
*p_entry, value));
}
}
PJ_DEF(void) pj_hash_set_np_lower( pj_hash_table_t *ht,
const void *key, unsigned keylen,
pj_uint32_t hval,
pj_hash_entry_buf entry_buf,
void *value)
{
hash_set(NULL, ht, key, keylen, hval, value, (void *)entry_buf, PJ_TRUE);
}
PJ_DEF(unsigned) pj_hash_count( pj_hash_table_t *ht )

View File

@ -283,7 +283,7 @@ void ioqueue_dispatch_write_event(pj_ioqueue_t *ioqueue, pj_ioqueue_key_t *h)
/* Socket is writable. */
struct write_operation *write_op;
pj_ssize_t sent;
pj_status_t send_rc;
pj_status_t send_rc = PJ_SUCCESS;
/* Get the first in the queue. */
write_op = h->write_list.next;
@ -312,8 +312,8 @@ void ioqueue_dispatch_write_event(pj_ioqueue_t *ioqueue, pj_ioqueue_key_t *h)
*/
//write_op->op = 0;
} else if (write_op->op == PJ_IOQUEUE_OP_SEND_TO) {
int retry;
for (retry=0; retry<2; ++retry) {
int retry = 2;
while (--retry >= 0) {
send_rc = pj_sock_sendto(h->fd,
write_op->buf+write_op->written,
&sent, write_op->flags,
@ -945,7 +945,11 @@ PJ_DEF(pj_status_t) pj_ioqueue_sendto( pj_ioqueue_key_t *key,
PJ_ASSERT_RETURN(key && op_key && data && length, PJ_EINVAL);
PJ_CHECK_STACK();
#if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0
retry_on_restart:
#endif
/* Check if key is closing. */
if (IS_CLOSING(key))
return PJ_ECANCELLED;

View File

@ -340,6 +340,7 @@ CPjSocket *CIoqueueCallback::HandleAcceptCompletion()
//
void CIoqueueCallback::RunL()
{
pj_ioqueue_t *ioq = ioqueue_;
Type cur_type = type_;
type_ = TYPE_NONE;
@ -399,7 +400,7 @@ void CIoqueueCallback::RunL()
}
}
ioqueue_->eventCount++;
ioq->eventCount++;
}
//

View File

@ -165,9 +165,6 @@ static pj_status_t if_enum_by_af(int af,
return PJ_RETURN_OS_ERROR(oserr);
}
/* Done with socket */
pj_sock_close(sock);
/* Interface interfaces */
ifr = (struct ifreq*) ifc.ifc_req;
count = ifc.ifc_len / sizeof(struct ifreq);
@ -177,6 +174,7 @@ static pj_status_t if_enum_by_af(int af,
*p_cnt = 0;
for (i=0; i<count; ++i) {
struct ifreq *itf = &ifr[i];
struct ifreq iff = *itf;
struct sockaddr *ad = &itf->ifr_addr;
TRACE_((THIS_FILE, " checking interface %s", itf->ifr_name));
@ -188,13 +186,19 @@ static pj_status_t if_enum_by_af(int af,
continue;
}
if ((itf->ifr_flags & IFF_UP)==0) {
if (ioctl(sock, SIOCGIFFLAGS, &iff) != 0) {
TRACE_((THIS_FILE, " ioctl(SIOCGIFFLAGS) failed: %s",
get_os_errmsg()));
continue; /* Failed to get flags, continue */
}
if ((iff.ifr_flags & IFF_UP)==0) {
TRACE_((THIS_FILE, " interface is down"));
continue; /* Skip when interface is down */
}
#if PJ_IP_HELPER_IGNORE_LOOPBACK_IF
if (itf->ifr_flags & IFF_LOOPBACK) {
if (iff.ifr_flags & IFF_LOOPBACK) {
TRACE_((THIS_FILE, " loopback interface"));
continue; /* Skip loopback interface */
}
@ -220,10 +224,14 @@ static pj_status_t if_enum_by_af(int af,
(*p_cnt)++;
}
/* Done with socket */
pj_sock_close(sock);
TRACE_((THIS_FILE, "done, found %d address(es)", *p_cnt));
return (*p_cnt != 0) ? PJ_SUCCESS : PJ_ENOTFOUND;
}
#elif defined(PJ_HAS_NET_IF_H) && PJ_HAS_NET_IF_H != 0
/* Note: this does not work with IPv6 */
static pj_status_t if_enum_by_af(int af, unsigned *p_cnt, pj_sockaddr ifs[])

View File

@ -75,6 +75,9 @@ struct pj_sem_t
int max;
};
/* Flag and reference counter for PJLIB instance */
static int initialized;
/* Flags to indicate which TLS variables have been used */
static int tls_vars[PJ_MAX_TLS];
@ -83,8 +86,6 @@ static unsigned atexit_count;
static void (*atexit_func[32])(void);
/////////////////////////////////////////////////////////////////////////////
//
// CPjTimeoutTimer implementation
@ -335,6 +336,12 @@ PJ_DEF(pj_status_t) pj_init(void)
char stack_ptr;
pj_status_t status;
/* Check if PJLIB have been initialized */
if (initialized) {
++initialized;
return PJ_SUCCESS;
}
pj_ansi_strcpy(main_thread.obj_name, "pjthread");
// Init main thread
@ -368,6 +375,10 @@ PJ_DEF(pj_status_t) pj_init(void)
stack_ptr = '\0';
#endif
/* Flag PJLIB as initialized */
++initialized;
pj_assert(initialized == 1);
PJ_LOG(5,(THIS_FILE, "PJLIB initialized."));
return PJ_SUCCESS;
@ -390,6 +401,11 @@ PJ_DEF(pj_status_t) pj_atexit(pj_exit_callback func)
PJ_DEF(void) pj_shutdown(void)
{
/* Only perform shutdown operation when 'initialized' reaches zero */
pj_assert(initialized > 0);
if (--initialized != 0)
return;
/* Call atexit() functions */
while (atexit_count > 0) {
(*atexit_func[atexit_count-1])();

View File

@ -102,6 +102,11 @@ struct pj_event_t
#endif /* PJ_HAS_EVENT_OBJ */
/*
* Flag and reference counter for PJLIB instance.
*/
static int initialized;
#if PJ_HAS_THREADS
static pj_thread_t main_thread;
static long thread_tls_id;
@ -127,6 +132,12 @@ PJ_DEF(pj_status_t) pj_init(void)
pj_str_t guid;
pj_status_t rc;
/* Check if PJLIB have been initialized */
if (initialized) {
++initialized;
return PJ_SUCCESS;
}
#if PJ_HAS_THREADS
/* Init this thread's TLS. */
if ((rc=pj_thread_init()) != 0) {
@ -167,6 +178,10 @@ PJ_DEF(pj_status_t) pj_init(void)
}
#endif
/* Flag PJLIB as initialized */
++initialized;
pj_assert(initialized == 1);
PJ_LOG(4,(THIS_FILE, "pjlib %s for POSIX initialized",
PJ_VERSION));
@ -192,6 +207,11 @@ PJ_DEF(void) pj_shutdown()
{
int i;
/* Only perform shutdown operation when 'initialized' reaches zero */
pj_assert(initialized > 0);
if (--initialized != 0)
return;
/* Call atexit() functions */
for (i=atexit_count-1; i>=0; --i) {
(*atexit_func[i])();

View File

@ -116,6 +116,11 @@ struct pj_atomic_t
long value;
};
/*
* Flag and reference counter for PJLIB instance.
*/
static int initialized;
/*
* Static global variables.
*/
@ -142,6 +147,12 @@ PJ_DEF(pj_status_t) pj_init(void)
pj_str_t guid;
pj_status_t rc;
/* Check if PJLIB have been initialized */
if (initialized) {
++initialized;
return PJ_SUCCESS;
}
/* Init Winsock.. */
if (WSAStartup(MAKEWORD(2,0), &wsa) != 0) {
return PJ_RETURN_OS_ERROR(WSAGetLastError());
@ -187,6 +198,10 @@ PJ_DEF(pj_status_t) pj_init(void)
}
#endif
/* Flag PJLIB as initialized */
++initialized;
pj_assert(initialized == 1);
PJ_LOG(4,(THIS_FILE, "pjlib %s for win32 initialized",
PJ_VERSION));
@ -213,6 +228,11 @@ PJ_DEF(void) pj_shutdown()
{
int i;
/* Only perform shutdown operation when 'initialized' reaches zero */
pj_assert(initialized > 0);
if (--initialized != 0)
return;
/* Display stack usage */
#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
{
@ -559,6 +579,9 @@ PJ_DEF(pj_status_t) pj_thread_join(pj_thread_t *p)
PJ_CHECK_STACK();
PJ_ASSERT_RETURN(p, PJ_EINVAL);
if (p == pj_thread_this())
return PJ_ECANCELLED;
PJ_LOG(6, (pj_thread_this()->obj_name, "Joining thread %s", p->obj_name));
rc = WaitForSingleObject(rec->hthread, INFINITE);

View File

@ -242,6 +242,9 @@ PJ_DEF(const pj_sys_info*) pj_get_sys_info(void)
} else {
si.os_name = pj_str("Unknown");
}
/* Avoid compile warning on Symbian. */
goto get_sdk_info;
}
#endif

View File

@ -88,7 +88,7 @@ static pj_pool_block *pj_pool_create_block( pj_pool_t *pool, pj_size_t size)
* If no space is available in all the blocks, a new block might be created
* (depending on whether the pool is allowed to resize).
*/
PJ_DEF(void*) pj_pool_allocate_find(pj_pool_t *pool, unsigned size)
PJ_DEF(void*) pj_pool_allocate_find(pj_pool_t *pool, pj_size_t size)
{
pj_pool_block *block = pool->block_list.next;
void *p;
@ -121,7 +121,7 @@ PJ_DEF(void*) pj_pool_allocate_find(pj_pool_t *pool, unsigned size)
if (pool->increment_size <
size + sizeof(pj_pool_block) + PJ_POOL_ALIGNMENT)
{
unsigned count;
pj_size_t count;
count = (size + pool->increment_size + sizeof(pj_pool_block) +
PJ_POOL_ALIGNMENT) /
pool->increment_size;

View File

@ -178,7 +178,11 @@ static pj_pool_t* cpool_create_pool(pj_pool_factory *pf,
pj_pool_init_int(pool, name, increment_sz, callback);
/* Update pool manager's free capacity. */
cp->capacity -= pj_pool_get_capacity(pool);
if (cp->capacity > pj_pool_get_capacity(pool)) {
cp->capacity -= pj_pool_get_capacity(pool);
} else {
cp->capacity = 0;
}
PJ_LOG(6, (pool->obj_name, "pool reused, size=%u", pool->capacity));
}
@ -199,7 +203,7 @@ static pj_pool_t* cpool_create_pool(pj_pool_factory *pf,
static void cpool_release_pool( pj_pool_factory *pf, pj_pool_t *pool)
{
pj_caching_pool *cp = (pj_caching_pool*)pf;
unsigned pool_capacity;
pj_size_t pool_capacity;
unsigned i;
PJ_CHECK_STACK();

View File

@ -718,7 +718,6 @@ PJ_DEF(pj_status_t) pj_sock_recvfrom(pj_sock_t sock,
{
PJ_CHECK_STACK();
PJ_ASSERT_RETURN(buf && len, PJ_EINVAL);
PJ_ASSERT_RETURN(from && fromlen, (*len=-1, PJ_EINVAL));
*len = recvfrom(sock, (char*)buf, *len, flags,
(struct sockaddr*)from, (socklen_t*)fromlen);
@ -726,7 +725,9 @@ PJ_DEF(pj_status_t) pj_sock_recvfrom(pj_sock_t sock,
if (*len < 0)
return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
else {
PJ_SOCKADDR_RESET_LEN(from);
if (from) {
PJ_SOCKADDR_RESET_LEN(from);
}
return PJ_SUCCESS;
}
}

View File

@ -784,6 +784,8 @@ PJ_DEF(pj_status_t) pj_gethostip(int af, pj_sockaddr *addr)
addr->addr.sa_family = (pj_uint16_t)af;
PJ_SOCKADDR_RESET_LEN(addr);
#if !defined(PJ_GETHOSTIP_DISABLE_LOCAL_RESOLUTION) || \
PJ_GETHOSTIP_DISABLE_LOCAL_RESOLUTION == 0
/* Get hostname's IP address */
count = 1;
status = pj_getaddrinfo(af, pj_gethostname(), &count, &ai);
@ -797,7 +799,10 @@ PJ_DEF(pj_status_t) pj_gethostip(int af, pj_sockaddr *addr)
TRACE_((THIS_FILE, "hostname IP is %s",
pj_sockaddr_print(&ai.ai_addr, strip, sizeof(strip), 0)));
}
#else
PJ_UNUSED_ARG(ai);
PJ_UNUSED_ARG(count);
#endif
/* Get default interface (interface for default route) */
if (cand_cnt < PJ_ARRAY_SIZE(cand_addr)) {

View File

@ -21,89 +21,6 @@
#include <pj/errno.h>
#include <pj/string.h>
/* Cipher name structure */
typedef struct cipher_name_t {
pj_ssl_cipher cipher;
const char *name;
} cipher_name_t;
/* Cipher name constants */
static cipher_name_t cipher_names[] =
{
{PJ_TLS_NULL_WITH_NULL_NULL, "NULL"},
/* TLS/SSLv3 */
{PJ_TLS_RSA_WITH_NULL_MD5, "TLS_RSA_WITH_NULL_MD5"},
{PJ_TLS_RSA_WITH_NULL_SHA, "TLS_RSA_WITH_NULL_SHA"},
{PJ_TLS_RSA_WITH_NULL_SHA256, "TLS_RSA_WITH_NULL_SHA256"},
{PJ_TLS_RSA_WITH_RC4_128_MD5, "TLS_RSA_WITH_RC4_128_MD5"},
{PJ_TLS_RSA_WITH_RC4_128_SHA, "TLS_RSA_WITH_RC4_128_SHA"},
{PJ_TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA"},
{PJ_TLS_RSA_WITH_AES_128_CBC_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA"},
{PJ_TLS_RSA_WITH_AES_256_CBC_SHA, "TLS_RSA_WITH_AES_256_CBC_SHA"},
{PJ_TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS_RSA_WITH_AES_128_CBC_SHA256"},
{PJ_TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS_RSA_WITH_AES_256_CBC_SHA256"},
{PJ_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA, "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"},
{PJ_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"},
{PJ_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"},
{PJ_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"},
{PJ_TLS_DH_DSS_WITH_AES_128_CBC_SHA, "TLS_DH_DSS_WITH_AES_128_CBC_SHA"},
{PJ_TLS_DH_RSA_WITH_AES_128_CBC_SHA, "TLS_DH_RSA_WITH_AES_128_CBC_SHA"},
{PJ_TLS_DHE_DSS_WITH_AES_128_CBC_SHA, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"},
{PJ_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"},
{PJ_TLS_DH_DSS_WITH_AES_256_CBC_SHA, "TLS_DH_DSS_WITH_AES_256_CBC_SHA"},
{PJ_TLS_DH_RSA_WITH_AES_256_CBC_SHA, "TLS_DH_RSA_WITH_AES_256_CBC_SHA"},
{PJ_TLS_DHE_DSS_WITH_AES_256_CBC_SHA, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"},
{PJ_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"},
{PJ_TLS_DH_DSS_WITH_AES_128_CBC_SHA256, "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"},
{PJ_TLS_DH_RSA_WITH_AES_128_CBC_SHA256, "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"},
{PJ_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"},
{PJ_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"},
{PJ_TLS_DH_DSS_WITH_AES_256_CBC_SHA256, "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"},
{PJ_TLS_DH_RSA_WITH_AES_256_CBC_SHA256, "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"},
{PJ_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"},
{PJ_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"},
{PJ_TLS_DH_anon_WITH_RC4_128_MD5, "TLS_DH_anon_WITH_RC4_128_MD5"},
{PJ_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA, "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"},
{PJ_TLS_DH_anon_WITH_AES_128_CBC_SHA, "TLS_DH_anon_WITH_AES_128_CBC_SHA"},
{PJ_TLS_DH_anon_WITH_AES_256_CBC_SHA, "TLS_DH_anon_WITH_AES_256_CBC_SHA"},
{PJ_TLS_DH_anon_WITH_AES_128_CBC_SHA256, "TLS_DH_anon_WITH_AES_128_CBC_SHA256"},
{PJ_TLS_DH_anon_WITH_AES_256_CBC_SHA256, "TLS_DH_anon_WITH_AES_256_CBC_SHA256"},
/* TLS (deprecated) */
{PJ_TLS_RSA_EXPORT_WITH_RC4_40_MD5, "TLS_RSA_EXPORT_WITH_RC4_40_MD5"},
{PJ_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5"},
{PJ_TLS_RSA_WITH_IDEA_CBC_SHA, "TLS_RSA_WITH_IDEA_CBC_SHA"},
{PJ_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA"},
{PJ_TLS_RSA_WITH_DES_CBC_SHA, "TLS_RSA_WITH_DES_CBC_SHA"},
{PJ_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA, "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"},
{PJ_TLS_DH_DSS_WITH_DES_CBC_SHA, "TLS_DH_DSS_WITH_DES_CBC_SHA"},
{PJ_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA, "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"},
{PJ_TLS_DH_RSA_WITH_DES_CBC_SHA, "TLS_DH_RSA_WITH_DES_CBC_SHA"},
{PJ_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"},
{PJ_TLS_DHE_DSS_WITH_DES_CBC_SHA, "TLS_DHE_DSS_WITH_DES_CBC_SHA"},
{PJ_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"},
{PJ_TLS_DHE_RSA_WITH_DES_CBC_SHA, "TLS_DHE_RSA_WITH_DES_CBC_SHA"},
{PJ_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5, "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5"},
{PJ_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA"},
{PJ_TLS_DH_anon_WITH_DES_CBC_SHA, "TLS_DH_anon_WITH_DES_CBC_SHA"},
/* SSLv3 */
{PJ_SSL_FORTEZZA_KEA_WITH_NULL_SHA, "SSL_FORTEZZA_KEA_WITH_NULL_SHA"},
{PJ_SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA,"SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA"},
{PJ_SSL_FORTEZZA_KEA_WITH_RC4_128_SHA, "SSL_FORTEZZA_KEA_WITH_RC4_128_SHA"},
/* SSLv2 */
{PJ_SSL_CK_RC4_128_WITH_MD5, "SSL_CK_RC4_128_WITH_MD5"},
{PJ_SSL_CK_RC4_128_EXPORT40_WITH_MD5, "SSL_CK_RC4_128_EXPORT40_WITH_MD5"},
{PJ_SSL_CK_RC2_128_CBC_WITH_MD5, "SSL_CK_RC2_128_CBC_WITH_MD5"},
{PJ_SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5, "SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5"},
{PJ_SSL_CK_IDEA_128_CBC_WITH_MD5, "SSL_CK_IDEA_128_CBC_WITH_MD5"},
{PJ_SSL_CK_DES_64_CBC_WITH_MD5, "SSL_CK_DES_64_CBC_WITH_MD5"},
{PJ_SSL_CK_DES_192_EDE3_CBC_WITH_MD5, "SSL_CK_DES_192_EDE3_CBC_WITH_MD5"}
};
/*
* Initialize the SSL socket configuration with the default values.
*/
@ -129,23 +46,6 @@ PJ_DEF(void) pj_ssl_sock_param_default(pj_ssl_sock_param *param)
}
/* Get cipher name string */
PJ_DEF(const char*) pj_ssl_cipher_name(pj_ssl_cipher cipher)
{
unsigned i, n;
n = PJ_ARRAY_SIZE(cipher_names);
for (i = 0; i < n; ++i) {
if (cipher == cipher_names[i].cipher)
return cipher_names[i].name;
}
return NULL;
}
PJ_DEF(pj_status_t) pj_ssl_cert_get_verify_status_strings(
pj_uint32_t verify_status,
const char *error_strings[],

View File

@ -39,6 +39,9 @@
/* Workaround for ticket #985 */
#define DELAYED_CLOSE_TIMEOUT 200
/* Maximum ciphers */
#define MAX_CIPHERS 100
/*
* Include OpenSSL headers
*/
@ -102,9 +105,10 @@ typedef struct read_data_t
ssock->param.read_buffer_size)
/*
* Structure of SSL socket write buffer.
* Structure of SSL socket write data.
*/
typedef struct write_data_t {
PJ_DECL_LIST_MEMBER(struct write_data_t);
pj_ioqueue_op_key_t key;
pj_size_t record_len;
pj_ioqueue_op_key_t *app_key;
@ -118,23 +122,14 @@ typedef struct write_data_t {
} write_data_t;
/*
* Structure of SSL socket write state.
* Structure of SSL socket write buffer (circular buffer).
*/
typedef struct write_state_t {
typedef struct send_buf_t {
char *buf;
pj_size_t max_len;
char *start;
pj_size_t len;
write_data_t *last_data;
} write_state_t;
/*
* Structure of write data pending.
*/
typedef struct write_pending_t {
PJ_DECL_LIST_MEMBER(struct write_pending_t);
write_data_t data;
} write_pending_t;
} send_buf_t;
/*
* Secure socket structure definition.
@ -155,6 +150,8 @@ struct pj_ssl_sock_t
pj_timer_entry timer;
pj_status_t verify_status;
unsigned long last_err;
pj_sock_t sock;
pj_activesock_t *asock;
@ -168,10 +165,12 @@ struct pj_ssl_sock_t
void **asock_rbuf;
read_data_t *ssock_rbuf;
write_state_t write_state;
write_pending_t write_pending;
write_pending_t write_pending_empty;
pj_lock_t *write_mutex; /* protect write BIO and write_state */
write_data_t write_pending;/* list of pending write to OpenSSL */
write_data_t write_pending_empty; /* cache for write_pending */
pj_bool_t flushing_write_pend; /* flag of flushing is ongoing*/
send_buf_t send_buf;
write_data_t send_pending; /* list of pending write to network */
pj_lock_t *write_mutex; /* protect write BIO and send_buf */
SSL_CTX *ossl_ctx;
SSL *ossl_ssl;
@ -192,6 +191,8 @@ struct pj_ssl_cert_t
};
static write_data_t* alloc_send_data(pj_ssl_sock_t *ssock, pj_size_t len);
static void free_send_data(pj_ssl_sock_t *ssock, write_data_t *wdata);
static pj_status_t flush_delayed_send(pj_ssl_sock_t *ssock);
/*
@ -209,17 +210,38 @@ static pj_status_t flush_delayed_send(pj_ssl_sock_t *ssock);
#define PJ_SSL_ERRNO_SPACE_SIZE PJ_ERRNO_SPACE_SIZE
#define STATUS_FROM_SSL_ERR(err, status) { \
status = ERR_GET_LIB(err)*300 + ERR_GET_REASON(err);\
pj_assert(status < PJ_SSL_ERRNO_SPACE_SIZE);\
if (status) status += PJ_SSL_ERRNO_START;\
/* Expected maximum value of reason component in OpenSSL error code */
#define MAX_OSSL_ERR_REASON 1200
static pj_status_t STATUS_FROM_SSL_ERR(pj_ssl_sock_t *ssock,
unsigned long err)
{
pj_status_t status;
/* General SSL error, dig more from OpenSSL error queue */
if (err == SSL_ERROR_SSL)
err = ERR_get_error();
/* OpenSSL error range is much wider than PJLIB errno space, so
* if it exceeds the space, only the error reason will be kept.
* Note that the last native error will be kept as is and can be
* retrieved via SSL socket info.
*/
status = ERR_GET_LIB(err)*MAX_OSSL_ERR_REASON + ERR_GET_REASON(err);
if (status > PJ_SSL_ERRNO_SPACE_SIZE)
status = ERR_GET_REASON(err);
status += PJ_SSL_ERRNO_START;
ssock->last_err = err;
return status;
}
#define GET_SSL_STATUS(status) { \
unsigned long e = ERR_get_error();\
STATUS_FROM_SSL_ERR(e, status);\
static pj_status_t GET_SSL_STATUS(pj_ssl_sock_t *ssock)
{
return STATUS_FROM_SSL_ERR(ssock, ERR_get_error());
}
/*
* Get error string of OpenSSL.
*/
@ -232,8 +254,8 @@ static pj_str_t ssl_strerror(pj_status_t status,
if (ssl_err) {
unsigned long l, r;
ssl_err -= PJ_SSL_ERRNO_START;
l = ssl_err/300;
r = ssl_err%300;
l = ssl_err / MAX_OSSL_ERR_REASON;
r = ssl_err % MAX_OSSL_ERR_REASON;
ssl_err = ERR_PACK(l, 0, r);
}
@ -241,12 +263,7 @@ static pj_str_t ssl_strerror(pj_status_t status,
{
const char *tmp = NULL;
if (ssl_err >= 300)
tmp = ERR_reason_error_string(ssl_err);
else
tmp = X509_verify_cert_error_string(ssl_err);
tmp = ERR_reason_error_string(ssl_err);
if (tmp) {
pj_ansi_strncpy(buf, tmp, bufsize);
errstr = pj_str(buf);
@ -269,8 +286,11 @@ static pj_str_t ssl_strerror(pj_status_t status,
static int openssl_init_count;
/* OpenSSL available ciphers */
static pj_ssl_cipher openssl_ciphers[100];
static unsigned openssl_cipher_num;
static struct openssl_ciphers_t {
pj_ssl_cipher id;
const char *name;
} openssl_ciphers[MAX_CIPHERS];
/* OpenSSL application data index */
static int sslsock_idx;
@ -310,8 +330,10 @@ static pj_status_t init_openssl(void)
meth = (SSL_METHOD*)TLSv1_server_method();
if (!meth)
meth = (SSL_METHOD*)SSLv3_server_method();
#ifndef OPENSSL_NO_SSL2
if (!meth)
meth = (SSL_METHOD*)SSLv2_server_method();
#endif
pj_assert(meth);
ctx=SSL_CTX_new(meth);
@ -327,9 +349,9 @@ static pj_status_t init_openssl(void)
for (i = 0; i < n; ++i) {
SSL_CIPHER *c;
c = sk_SSL_CIPHER_value(sk_cipher,i);
openssl_ciphers[i] = (pj_ssl_cipher)
(pj_uint32_t)c->id & 0x00FFFFFF;
//printf("%3u: %08x=%s\n", i+1, c->id, SSL_CIPHER_get_name(c));
openssl_ciphers[i].id = (pj_ssl_cipher)
(pj_uint32_t)c->id & 0x00FFFFFF;
openssl_ciphers[i].name = SSL_CIPHER_get_name(c);
}
SSL_free(ssl);
@ -488,9 +510,11 @@ static pj_status_t create_ssl(pj_ssl_sock_t *ssock)
case PJ_SSL_SOCK_PROTO_TLS1:
ssl_method = (SSL_METHOD*)TLSv1_method();
break;
#ifndef OPENSSL_NO_SSL2
case PJ_SSL_SOCK_PROTO_SSL2:
ssl_method = (SSL_METHOD*)SSLv2_method();
break;
#endif
case PJ_SSL_SOCK_PROTO_SSL3:
ssl_method = (SSL_METHOD*)SSLv3_method();
break;
@ -507,8 +531,7 @@ static pj_status_t create_ssl(pj_ssl_sock_t *ssock)
/* Create SSL context */
ctx = SSL_CTX_new(ssl_method);
if (ctx == NULL) {
GET_SSL_STATUS(status);
return status;
return GET_SSL_STATUS(ssock);
}
/* Apply credentials */
@ -519,7 +542,7 @@ static pj_status_t create_ssl(pj_ssl_sock_t *ssock)
rc = SSL_CTX_load_verify_locations(ctx, cert->CA_file.ptr, NULL);
if (rc != 1) {
GET_SSL_STATUS(status);
status = GET_SSL_STATUS(ssock);
PJ_LOG(1,(ssock->pool->obj_name, "Error loading CA list file "
"'%s'", cert->CA_file.ptr));
SSL_CTX_free(ctx);
@ -541,7 +564,7 @@ static pj_status_t create_ssl(pj_ssl_sock_t *ssock)
rc = SSL_CTX_use_certificate_chain_file(ctx, cert->cert_file.ptr);
if(rc != 1) {
GET_SSL_STATUS(status);
status = GET_SSL_STATUS(ssock);
PJ_LOG(1,(ssock->pool->obj_name, "Error loading certificate "
"chain file '%s'", cert->cert_file.ptr));
SSL_CTX_free(ctx);
@ -557,7 +580,7 @@ static pj_status_t create_ssl(pj_ssl_sock_t *ssock)
SSL_FILETYPE_PEM);
if(rc != 1) {
GET_SSL_STATUS(status);
status = GET_SSL_STATUS(ssock);
PJ_LOG(1,(ssock->pool->obj_name, "Error adding private key "
"from '%s'", cert->privkey_file.ptr));
SSL_CTX_free(ctx);
@ -570,8 +593,7 @@ static pj_status_t create_ssl(pj_ssl_sock_t *ssock)
ssock->ossl_ctx = ctx;
ssock->ossl_ssl = SSL_new(ssock->ossl_ctx);
if (ssock->ossl_ssl == NULL) {
GET_SSL_STATUS(status);
return status;
return GET_SSL_STATUS(ssock);
}
/* Set SSL sock as application data of SSL instance */
@ -703,9 +725,7 @@ static pj_status_t set_cipher_list(pj_ssl_sock_t *ssock)
/* Finally, set chosen cipher list */
ret = SSL_set_cipher_list(ssock->ossl_ssl, buf);
if (ret < 1) {
pj_status_t status;
GET_SSL_STATUS(status);
return status;
return GET_SSL_STATUS(ssock);
}
return PJ_SUCCESS;
@ -1010,6 +1030,13 @@ static pj_bool_t on_handshake_complete(pj_ssl_sock_t *ssock,
* reconnect in the callback.
*/
if (status != PJ_SUCCESS) {
/* Server disconnected us, possibly due to SSL nego failure */
if (status == PJ_EEOF) {
unsigned long err;
err = ERR_get_error();
if (err != SSL_ERROR_NONE)
status = STATUS_FROM_SSL_ERR(ssock, err);
}
reset_ssl_sock_state(ssock);
}
if (ssock->param.cb.on_connect_complete) {
@ -1023,6 +1050,179 @@ static pj_bool_t on_handshake_complete(pj_ssl_sock_t *ssock,
return PJ_TRUE;
}
static write_data_t* alloc_send_data(pj_ssl_sock_t *ssock, pj_size_t len)
{
send_buf_t *send_buf = &ssock->send_buf;
pj_size_t avail_len, skipped_len = 0;
char *reg1, *reg2;
pj_size_t reg1_len, reg2_len;
write_data_t *p;
/* Check buffer availability */
avail_len = send_buf->max_len - send_buf->len;
if (avail_len < len)
return NULL;
/* If buffer empty, reset start pointer and return it */
if (send_buf->len == 0) {
send_buf->start = send_buf->buf;
send_buf->len = len;
p = (write_data_t*)send_buf->start;
goto init_send_data;
}
/* Free space may be wrapped/splitted into two regions, so let's
* analyze them if any region can hold the write data.
*/
reg1 = send_buf->start + send_buf->len;
if (reg1 >= send_buf->buf + send_buf->max_len)
reg1 -= send_buf->max_len;
reg1_len = send_buf->max_len - send_buf->len;
if (reg1 + reg1_len > send_buf->buf + send_buf->max_len) {
reg1_len = send_buf->buf + send_buf->max_len - reg1;
reg2 = send_buf->buf;
reg2_len = send_buf->start - send_buf->buf;
} else {
reg2 = NULL;
reg2_len = 0;
}
/* More buffer availability check, note that the write data must be in
* a contigue buffer.
*/
avail_len = PJ_MAX(reg1_len, reg2_len);
if (avail_len < len)
return NULL;
/* Get the data slot */
if (reg1_len >= len) {
p = (write_data_t*)reg1;
} else {
p = (write_data_t*)reg2;
skipped_len = reg1_len;
}
/* Update buffer length */
send_buf->len += len + skipped_len;
init_send_data:
/* Init the new send data */
pj_bzero(p, sizeof(*p));
pj_list_init(p);
pj_list_push_back(&ssock->send_pending, p);
return p;
}
static void free_send_data(pj_ssl_sock_t *ssock, write_data_t *wdata)
{
send_buf_t *buf = &ssock->send_buf;
write_data_t *spl = &ssock->send_pending;
pj_assert(!pj_list_empty(&ssock->send_pending));
/* Free slot from the buffer */
if (spl->next == wdata && spl->prev == wdata) {
/* This is the only data, reset the buffer */
buf->start = buf->buf;
buf->len = 0;
} else if (spl->next == wdata) {
/* This is the first data, shift start pointer of the buffer and
* adjust the buffer length.
*/
buf->start = (char*)wdata->next;
if (wdata->next > wdata) {
buf->len -= ((char*)wdata->next - buf->start);
} else {
/* Overlapped */
unsigned right_len, left_len;
right_len = buf->buf + buf->max_len - (char*)wdata;
left_len = (char*)wdata->next - buf->buf;
buf->len -= (right_len + left_len);
}
} else if (spl->prev == wdata) {
/* This is the last data, just adjust the buffer length */
if (wdata->prev < wdata) {
unsigned jump_len;
jump_len = (char*)wdata -
((char*)wdata->prev + wdata->prev->record_len);
buf->len -= (wdata->record_len + jump_len);
} else {
/* Overlapped */
unsigned right_len, left_len;
right_len = buf->buf + buf->max_len -
((char*)wdata->prev + wdata->prev->record_len);
left_len = (char*)wdata + wdata->record_len - buf->buf;
buf->len -= (right_len + left_len);
}
}
/* For data in the middle buffer, just do nothing on the buffer. The slot
* will be freed later when freeing the first/last data.
*/
/* Remove the data from send pending list */
pj_list_erase(wdata);
}
#if 0
/* Just for testing send buffer alloc/free */
#include <pj/rand.h>
pj_status_t pj_ssl_sock_ossl_test_send_buf(pj_pool_t *pool)
{
enum { MAX_CHUNK_NUM = 20 };
unsigned chunk_size, chunk_cnt, i;
write_data_t *wdata[MAX_CHUNK_NUM] = {0};
pj_time_val now;
pj_ssl_sock_t *ssock = NULL;
pj_ssl_sock_param param;
pj_status_t status;
pj_gettimeofday(&now);
pj_srand((unsigned)now.sec);
pj_ssl_sock_param_default(&param);
status = pj_ssl_sock_create(pool, &param, &ssock);
if (status != PJ_SUCCESS) {
return status;
}
if (ssock->send_buf.max_len == 0) {
ssock->send_buf.buf = (char*)
pj_pool_alloc(ssock->pool,
ssock->param.send_buffer_size);
ssock->send_buf.max_len = ssock->param.send_buffer_size;
ssock->send_buf.start = ssock->send_buf.buf;
ssock->send_buf.len = 0;
}
chunk_size = ssock->param.send_buffer_size / MAX_CHUNK_NUM / 2;
chunk_cnt = 0;
for (i = 0; i < MAX_CHUNK_NUM; i++) {
wdata[i] = alloc_send_data(ssock, pj_rand() % chunk_size + 321);
if (wdata[i])
chunk_cnt++;
else
break;
}
while (chunk_cnt) {
i = pj_rand() % MAX_CHUNK_NUM;
if (wdata[i]) {
free_send_data(ssock, wdata[i]);
wdata[i] = NULL;
chunk_cnt--;
}
}
if (ssock->send_buf.len != 0)
status = PJ_EBUG;
pj_ssl_sock_close(ssock);
return status;
}
#endif
/* Flush write BIO to network socket. Note that any access to write BIO
* MUST be serialized, so mutex protection must cover any call to OpenSSL
* API (that possibly generate data for write BIO) along with the call to
@ -1036,76 +1236,39 @@ static pj_status_t flush_write_bio(pj_ssl_sock_t *ssock,
{
char *data;
pj_ssize_t len;
write_state_t *write_st = &ssock->write_state;
write_data_t *wdata;
pj_size_t avail_len, needed_len, skipped_len = 0;
pj_size_t needed_len;
pj_status_t status;
pj_lock_acquire(ssock->write_mutex);
/* Check if there is data in write BIO, flush it if any */
if (!BIO_pending(ssock->ossl_wbio))
if (!BIO_pending(ssock->ossl_wbio)) {
pj_lock_release(ssock->write_mutex);
return PJ_SUCCESS;
}
/* Get data and its length */
len = BIO_get_mem_data(ssock->ossl_wbio, &data);
if (len == 0)
if (len == 0) {
pj_lock_release(ssock->write_mutex);
return PJ_SUCCESS;
}
/* Calculate buffer size needed, and align it to 8 */
needed_len = len + sizeof(write_data_t);
needed_len = ((needed_len + 7) >> 3) << 3;
/* Check buffer availability */
avail_len = write_st->max_len - write_st->len;
if (avail_len < needed_len)
/* Allocate buffer for send data */
wdata = alloc_send_data(ssock, needed_len);
if (wdata == NULL) {
pj_lock_release(ssock->write_mutex);
return PJ_ENOMEM;
/* More buffer availability check, note that the write data must be in
* a contigue buffer.
*/
if (write_st->len == 0) {
write_st->start = write_st->buf;
wdata = (write_data_t*)write_st->start;
} else {
char *reg1, *reg2;
pj_size_t reg1_len, reg2_len;
/* Unused slots may be wrapped/splitted into two regions, so let's
* analyze them if any region can hold the write data.
*/
reg1 = write_st->start + write_st->len;
if (reg1 >= write_st->buf + write_st->max_len)
reg1 -= write_st->max_len;
reg1_len = write_st->max_len - write_st->len;
if (reg1 + reg1_len > write_st->buf + write_st->max_len) {
reg1_len = write_st->buf + write_st->max_len - reg1;
reg2 = write_st->buf;
reg2_len = write_st->start - write_st->buf;
} else {
reg2 = NULL;
reg2_len = 0;
}
avail_len = PJ_MAX(reg1_len, reg2_len);
if (avail_len < needed_len)
return PJ_ENOMEM;
/* Get write data pointer and update buffer length */
if (reg1_len >= needed_len) {
wdata = (write_data_t*)reg1;
} else {
wdata = (write_data_t*)reg2;
/* Unused slot in region 1 is skipped as current write data
* doesn't fit it.
*/
skipped_len = reg1_len;
}
}
/* Copy the data and set its properties into the buffer */
pj_bzero(wdata, sizeof(write_data_t));
/* Copy the data and set its properties into the send data */
pj_ioqueue_op_key_init(&wdata->key, sizeof(pj_ioqueue_op_key_t));
wdata->key.user_data = wdata;
wdata->app_key = send_key;
wdata->record_len = needed_len;
wdata->data_len = len;
@ -1113,6 +1276,12 @@ static pj_status_t flush_write_bio(pj_ssl_sock_t *ssock,
wdata->flags = flags;
pj_memcpy(&wdata->data, data, len);
/* Reset write BIO */
BIO_reset(ssock->ossl_wbio);
/* Ticket #1573: Don't hold mutex while calling PJLIB socket send(). */
pj_lock_release(ssock->write_mutex);
/* Send it */
if (ssock->param.sock_type == pj_SOCK_STREAM()) {
status = pj_activesock_send(ssock->asock, &wdata->key,
@ -1126,24 +1295,13 @@ static pj_status_t flush_write_bio(pj_ssl_sock_t *ssock,
ssock->addr_len);
}
/* Oh no, EWOULDBLOCK! */
if (status == PJ_STATUS_FROM_OS(OSERR_EWOULDBLOCK)) {
/* Just return PJ_SUCCESS here, the pending data will be sent in next
* call of this function since the data is still stored in write BIO.
if (status != PJ_EPENDING) {
/* When the sending is not pending, remove the wdata from send
* pending list.
*/
return PJ_SUCCESS;
}
/* Reset write BIO after flushed */
BIO_reset(ssock->ossl_wbio);
if (status == PJ_EPENDING) {
/* Update write state */
pj_assert(skipped_len==0 || write_st->last_data);
write_st->len += needed_len + skipped_len;
if (write_st->last_data)
write_st->last_data->record_len += skipped_len;
write_st->last_data = wdata;
pj_lock_acquire(ssock->write_mutex);
free_send_data(ssock, wdata);
pj_lock_release(ssock->write_mutex);
}
return status;
@ -1182,31 +1340,28 @@ static pj_status_t do_handshake(pj_ssl_sock_t *ssock)
pj_status_t status;
int err;
pj_lock_acquire(ssock->write_mutex);
/* Perform SSL handshake */
pj_lock_acquire(ssock->write_mutex);
err = SSL_do_handshake(ssock->ossl_ssl);
if (err < 0) {
err = SSL_get_error(ssock->ossl_ssl, err);
if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ)
{
/* Handshake fails */
GET_SSL_STATUS(status);
pj_lock_release(ssock->write_mutex);
return status;
}
}
pj_lock_release(ssock->write_mutex);
/* SSL_do_handshake() may put some pending data into SSL write BIO,
* flush it if any.
*/
status = flush_write_bio(ssock, &ssock->handshake_op_key, 0, 0);
if (status != PJ_SUCCESS && status != PJ_EPENDING) {
pj_lock_release(ssock->write_mutex);
return status;
}
pj_lock_release(ssock->write_mutex);
if (err < 0) {
err = SSL_get_error(ssock->ossl_ssl, err);
if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ)
{
/* Handshake fails */
status = STATUS_FROM_SSL_ERR(ssock, err);
return status;
}
}
/* Check if handshake has been completed */
if (SSL_is_init_finished(ssock->ossl_ssl)) {
@ -1239,7 +1394,7 @@ static pj_bool_t asock_on_data_read (pj_activesock_t *asock,
/* Consume the whole data */
nwritten = BIO_write(ssock->ossl_rbio, data, size);
if (nwritten < size) {
GET_SSL_STATUS(status);
status = GET_SSL_STATUS(ssock);
goto on_error;
}
}
@ -1313,7 +1468,7 @@ static pj_bool_t asock_on_data_read (pj_activesock_t *asock,
if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ)
{
/* Reset SSL socket state, then return PJ_FALSE */
GET_SSL_STATUS(status);
status = STATUS_FROM_SSL_ERR(ssock, err);
reset_ssl_sock_state(ssock);
goto on_error;
}
@ -1325,9 +1480,15 @@ static pj_bool_t asock_on_data_read (pj_activesock_t *asock,
/* Update certificates */
update_certs_info(ssock);
pj_lock_acquire(ssock->write_mutex);
// Ticket #1573: Don't hold mutex while calling
// PJLIB socket send().
//pj_lock_acquire(ssock->write_mutex);
status = flush_delayed_send(ssock);
pj_lock_release(ssock->write_mutex);
//pj_lock_release(ssock->write_mutex);
/* If flushing is ongoing, treat it as success */
if (status == PJ_EBUSY)
status = PJ_SUCCESS;
if (status != PJ_SUCCESS && status != PJ_EPENDING) {
PJ_PERROR(1,(ssock->pool->obj_name, status,
@ -1387,11 +1548,14 @@ static pj_bool_t asock_on_data_sent (pj_activesock_t *asock,
} else if (send_key != &ssock->handshake_op_key) {
/* Some data has been sent, notify application */
write_data_t *wdata = (write_data_t*)send_key;
write_data_t *wdata = (write_data_t*)send_key->user_data;
if (ssock->param.cb.on_data_sent) {
pj_bool_t ret;
pj_ssize_t sent_len;
sent_len = (sent > 0)? wdata->plain_data_len : sent;
ret = (*ssock->param.cb.on_data_sent)(ssock, wdata->app_key,
wdata->plain_data_len);
sent_len);
if (!ret) {
/* We've been destroyed */
return PJ_FALSE;
@ -1400,12 +1564,7 @@ static pj_bool_t asock_on_data_sent (pj_activesock_t *asock,
/* Update write buffer state */
pj_lock_acquire(ssock->write_mutex);
ssock->write_state.start += wdata->record_len;
ssock->write_state.len -= wdata->record_len;
if (ssock->write_state.last_data == wdata) {
pj_assert(ssock->write_state.len == 0);
ssock->write_state.last_data = NULL;
}
free_send_data(ssock, wdata);
pj_lock_release(ssock->write_mutex);
} else {
@ -1516,13 +1675,13 @@ static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock,
goto on_return;
/* Prepare write/send state */
pj_assert(ssock->write_state.max_len == 0);
ssock->write_state.buf = (char*)
pj_pool_alloc(ssock->pool,
ssock->param.send_buffer_size);
ssock->write_state.max_len = ssock->param.send_buffer_size;
ssock->write_state.start = ssock->write_state.buf;
ssock->write_state.len = 0;
pj_assert(ssock->send_buf.max_len == 0);
ssock->send_buf.buf = (char*)
pj_pool_alloc(ssock->pool,
ssock->param.send_buffer_size);
ssock->send_buf.max_len = ssock->param.send_buffer_size;
ssock->send_buf.start = ssock->send_buf.buf;
ssock->send_buf.len = 0;
/* Start handshake timer */
if (ssock->param.timer_heap && (ssock->param.timeout.sec != 0 ||
@ -1595,13 +1754,13 @@ static pj_bool_t asock_on_connect_complete (pj_activesock_t *asock,
goto on_return;
/* Prepare write/send state */
pj_assert(ssock->write_state.max_len == 0);
ssock->write_state.buf = (char*)
pj_assert(ssock->send_buf.max_len == 0);
ssock->send_buf.buf = (char*)
pj_pool_alloc(ssock->pool,
ssock->param.send_buffer_size);
ssock->write_state.max_len = ssock->param.send_buffer_size;
ssock->write_state.start = ssock->write_state.buf;
ssock->write_state.len = 0;
ssock->send_buf.max_len = ssock->param.send_buffer_size;
ssock->send_buf.start = ssock->send_buf.buf;
ssock->send_buf.len = 0;
#ifdef SSL_set_tlsext_host_name
/* Set server name to connect */
@ -1701,18 +1860,57 @@ PJ_DEF(pj_status_t) pj_ssl_cipher_get_availables(pj_ssl_cipher ciphers[],
shutdown_openssl();
}
if (openssl_cipher_num == 0)
if (openssl_cipher_num == 0) {
*cipher_num = 0;
return PJ_ENOTFOUND;
}
*cipher_num = PJ_MIN(*cipher_num, openssl_cipher_num);
for (i = 0; i < *cipher_num; ++i)
ciphers[i] = openssl_ciphers[i];
ciphers[i] = openssl_ciphers[i].id;
return PJ_SUCCESS;
}
/* Get cipher name string */
PJ_DEF(const char*) pj_ssl_cipher_name(pj_ssl_cipher cipher)
{
unsigned i;
if (openssl_cipher_num == 0) {
init_openssl();
shutdown_openssl();
}
for (i = 0; i < openssl_cipher_num; ++i) {
if (cipher == openssl_ciphers[i].id)
return openssl_ciphers[i].name;
}
return NULL;
}
/* Check if the specified cipher is supported by SSL/TLS backend. */
PJ_DEF(pj_bool_t) pj_ssl_cipher_is_supported(pj_ssl_cipher cipher)
{
unsigned i;
if (openssl_cipher_num == 0) {
init_openssl();
shutdown_openssl();
}
for (i = 0; i < openssl_cipher_num; ++i) {
if (cipher == openssl_ciphers[i].id)
return PJ_TRUE;
}
return PJ_FALSE;
}
/*
* Create SSL socket instance.
*/
@ -1735,7 +1933,10 @@ PJ_DEF(pj_status_t) pj_ssl_sock_create (pj_pool_t *pool,
ssock->ssl_state = SSL_STATE_NULL;
pj_list_init(&ssock->write_pending);
pj_list_init(&ssock->write_pending_empty);
pj_list_init(&ssock->send_pending);
pj_timer_entry_init(&ssock->timer, 0, ssock, &on_timer);
pj_ioqueue_op_key_init(&ssock->handshake_op_key,
sizeof(pj_ioqueue_op_key_t));
/* Create secure socket mutex */
status = pj_lock_create_recursive_mutex(pool, pool->obj_name,
@ -1856,6 +2057,9 @@ PJ_DEF(pj_status_t) pj_ssl_sock_get_info (pj_ssl_sock_t *ssock,
info->verify_status = ssock->verify_status;
}
/* Last known OpenSSL error code */
info->last_native_err = ssock->last_err;
return PJ_SUCCESS;
}
@ -1965,10 +2169,7 @@ PJ_DEF(pj_status_t) pj_ssl_sock_start_recvfrom2 (pj_ssl_sock_t *ssock,
return PJ_ENOTSUP;
}
/* Write plain data to SSL and flush write BIO. Note that accessing
* write BIO must be serialized, so a call to this function must be
* protected by write mutex of SSL socket.
*/
/* Write plain data to SSL and flush write BIO. */
static pj_status_t ssl_write(pj_ssl_sock_t *ssock,
pj_ioqueue_op_key_t *send_key,
const void *data,
@ -1983,7 +2184,9 @@ static pj_status_t ssl_write(pj_ssl_sock_t *ssock,
* negotitation may be on progress, so sending data should be delayed
* until re-negotiation is completed.
*/
pj_lock_acquire(ssock->write_mutex);
nwritten = SSL_write(ssock->ossl_ssl, data, size);
pj_lock_release(ssock->write_mutex);
if (nwritten == size) {
/* All data written, flush write BIO to network socket */
@ -2002,7 +2205,7 @@ static pj_status_t ssl_write(pj_ssl_sock_t *ssock,
status = PJ_EBUSY;
} else {
/* Some problem occured */
GET_SSL_STATUS(status);
status = STATUS_FROM_SSL_ERR(ssock, err);
}
} else {
/* nwritten < *size, shouldn't happen, unless write BIO cannot hold
@ -2014,56 +2217,81 @@ static pj_status_t ssl_write(pj_ssl_sock_t *ssock,
return status;
}
/* Flush delayed data sending in the write pending list. Note that accessing
* write pending list must be serialized, so a call to this function must be
* protected by write mutex of SSL socket.
*/
/* Flush delayed data sending in the write pending list. */
static pj_status_t flush_delayed_send(pj_ssl_sock_t *ssock)
{
/* Check for another ongoing flush */
if (ssock->flushing_write_pend)
return PJ_EBUSY;
pj_lock_acquire(ssock->write_mutex);
/* Again, check for another ongoing flush */
if (ssock->flushing_write_pend) {
pj_lock_release(ssock->write_mutex);
return PJ_EBUSY;
}
/* Set ongoing flush flag */
ssock->flushing_write_pend = PJ_TRUE;
while (!pj_list_empty(&ssock->write_pending)) {
write_pending_t *wp;
write_data_t *wp;
pj_status_t status;
wp = ssock->write_pending.next;
status = ssl_write(ssock, &wp->data.key, wp->data.data.ptr,
wp->data.plain_data_len, wp->data.flags);
if (status != PJ_SUCCESS)
return status;
/* Ticket #1573: Don't hold mutex while calling socket send. */
pj_lock_release(ssock->write_mutex);
status = ssl_write(ssock, &wp->key, wp->data.ptr,
wp->plain_data_len, wp->flags);
if (status != PJ_SUCCESS) {
/* Reset ongoing flush flag first. */
ssock->flushing_write_pend = PJ_FALSE;
return status;
}
pj_lock_acquire(ssock->write_mutex);
pj_list_erase(wp);
pj_list_push_back(&ssock->write_pending_empty, wp);
}
/* Reset ongoing flush flag */
ssock->flushing_write_pend = PJ_FALSE;
pj_lock_release(ssock->write_mutex);
return PJ_SUCCESS;
}
/* Sending is delayed, push back the sending data into pending list. Note that
* accessing write pending list must be serialized, so a call to this function
* must be protected by write mutex of SSL socket.
*/
/* Sending is delayed, push back the sending data into pending list. */
static pj_status_t delay_send (pj_ssl_sock_t *ssock,
pj_ioqueue_op_key_t *send_key,
const void *data,
pj_ssize_t size,
unsigned flags)
{
write_pending_t *wp;
write_data_t *wp;
pj_lock_acquire(ssock->write_mutex);
/* Init write pending instance */
if (!pj_list_empty(&ssock->write_pending_empty)) {
wp = ssock->write_pending_empty.next;
pj_list_erase(wp);
} else {
wp = PJ_POOL_ZALLOC_T(ssock->pool, write_pending_t);
wp = PJ_POOL_ZALLOC_T(ssock->pool, write_data_t);
}
wp->data.app_key = send_key;
wp->data.plain_data_len = size;
wp->data.data.ptr = data;
wp->data.flags = flags;
wp->app_key = send_key;
wp->plain_data_len = size;
wp->data.ptr = data;
wp->flags = flags;
pj_list_push_back(&ssock->write_pending, wp);
pj_lock_release(ssock->write_mutex);
/* Must return PJ_EPENDING */
return PJ_EPENDING;
@ -2083,14 +2311,15 @@ PJ_DEF(pj_status_t) pj_ssl_sock_send (pj_ssl_sock_t *ssock,
PJ_ASSERT_RETURN(ssock && data && size && (*size>0), PJ_EINVAL);
PJ_ASSERT_RETURN(ssock->ssl_state==SSL_STATE_ESTABLISHED, PJ_EINVALIDOP);
pj_lock_acquire(ssock->write_mutex);
// Ticket #1573: Don't hold mutex while calling PJLIB socket send().
//pj_lock_acquire(ssock->write_mutex);
/* Flush delayed send first. Sending data might be delayed when
* re-negotiation is on-progress.
*/
status = flush_delayed_send(ssock);
if (status == PJ_EBUSY) {
/* Re-negotiation is on progress, delay sending */
/* Re-negotiation or flushing is on progress, delay sending */
status = delay_send(ssock, send_key, data, *size, flags);
goto on_return;
} else if (status != PJ_SUCCESS) {
@ -2105,7 +2334,7 @@ PJ_DEF(pj_status_t) pj_ssl_sock_send (pj_ssl_sock_t *ssock,
}
on_return:
pj_lock_release(ssock->write_mutex);
//pj_lock_release(ssock->write_mutex);
return status;
}
@ -2329,7 +2558,7 @@ PJ_DEF(pj_status_t) pj_ssl_sock_renegotiate(pj_ssl_sock_t *ssock)
ret = SSL_renegotiate(ssock->ossl_ssl);
if (ret <= 0) {
GET_SSL_STATUS(status);
status = GET_SSL_STATUS(ssock);
} else {
status = do_handshake(ssock);
}

View File

@ -32,6 +32,104 @@
#define THIS_FILE "ssl_sock_symbian.cpp"
/* Cipher name structure */
typedef struct cipher_name_t {
pj_ssl_cipher cipher;
const char *name;
} cipher_name_t;
/* Cipher name constants */
static cipher_name_t cipher_names[] =
{
{PJ_TLS_NULL_WITH_NULL_NULL, "NULL"},
/* TLS/SSLv3 */
{PJ_TLS_RSA_WITH_NULL_MD5, "TLS_RSA_WITH_NULL_MD5"},
{PJ_TLS_RSA_WITH_NULL_SHA, "TLS_RSA_WITH_NULL_SHA"},
{PJ_TLS_RSA_WITH_NULL_SHA256, "TLS_RSA_WITH_NULL_SHA256"},
{PJ_TLS_RSA_WITH_RC4_128_MD5, "TLS_RSA_WITH_RC4_128_MD5"},
{PJ_TLS_RSA_WITH_RC4_128_SHA, "TLS_RSA_WITH_RC4_128_SHA"},
{PJ_TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA"},
{PJ_TLS_RSA_WITH_AES_128_CBC_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA"},
{PJ_TLS_RSA_WITH_AES_256_CBC_SHA, "TLS_RSA_WITH_AES_256_CBC_SHA"},
{PJ_TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS_RSA_WITH_AES_128_CBC_SHA256"},
{PJ_TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS_RSA_WITH_AES_256_CBC_SHA256"},
{PJ_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA, "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"},
{PJ_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"},
{PJ_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"},
{PJ_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"},
{PJ_TLS_DH_DSS_WITH_AES_128_CBC_SHA, "TLS_DH_DSS_WITH_AES_128_CBC_SHA"},
{PJ_TLS_DH_RSA_WITH_AES_128_CBC_SHA, "TLS_DH_RSA_WITH_AES_128_CBC_SHA"},
{PJ_TLS_DHE_DSS_WITH_AES_128_CBC_SHA, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"},
{PJ_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"},
{PJ_TLS_DH_DSS_WITH_AES_256_CBC_SHA, "TLS_DH_DSS_WITH_AES_256_CBC_SHA"},
{PJ_TLS_DH_RSA_WITH_AES_256_CBC_SHA, "TLS_DH_RSA_WITH_AES_256_CBC_SHA"},
{PJ_TLS_DHE_DSS_WITH_AES_256_CBC_SHA, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"},
{PJ_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"},
{PJ_TLS_DH_DSS_WITH_AES_128_CBC_SHA256, "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"},
{PJ_TLS_DH_RSA_WITH_AES_128_CBC_SHA256, "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"},
{PJ_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"},
{PJ_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"},
{PJ_TLS_DH_DSS_WITH_AES_256_CBC_SHA256, "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"},
{PJ_TLS_DH_RSA_WITH_AES_256_CBC_SHA256, "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"},
{PJ_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"},
{PJ_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"},
{PJ_TLS_DH_anon_WITH_RC4_128_MD5, "TLS_DH_anon_WITH_RC4_128_MD5"},
{PJ_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA, "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"},
{PJ_TLS_DH_anon_WITH_AES_128_CBC_SHA, "TLS_DH_anon_WITH_AES_128_CBC_SHA"},
{PJ_TLS_DH_anon_WITH_AES_256_CBC_SHA, "TLS_DH_anon_WITH_AES_256_CBC_SHA"},
{PJ_TLS_DH_anon_WITH_AES_128_CBC_SHA256, "TLS_DH_anon_WITH_AES_128_CBC_SHA256"},
{PJ_TLS_DH_anon_WITH_AES_256_CBC_SHA256, "TLS_DH_anon_WITH_AES_256_CBC_SHA256"},
/* TLS (deprecated) */
{PJ_TLS_RSA_EXPORT_WITH_RC4_40_MD5, "TLS_RSA_EXPORT_WITH_RC4_40_MD5"},
{PJ_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5"},
{PJ_TLS_RSA_WITH_IDEA_CBC_SHA, "TLS_RSA_WITH_IDEA_CBC_SHA"},
{PJ_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA"},
{PJ_TLS_RSA_WITH_DES_CBC_SHA, "TLS_RSA_WITH_DES_CBC_SHA"},
{PJ_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA, "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"},
{PJ_TLS_DH_DSS_WITH_DES_CBC_SHA, "TLS_DH_DSS_WITH_DES_CBC_SHA"},
{PJ_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA, "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"},
{PJ_TLS_DH_RSA_WITH_DES_CBC_SHA, "TLS_DH_RSA_WITH_DES_CBC_SHA"},
{PJ_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"},
{PJ_TLS_DHE_DSS_WITH_DES_CBC_SHA, "TLS_DHE_DSS_WITH_DES_CBC_SHA"},
{PJ_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"},
{PJ_TLS_DHE_RSA_WITH_DES_CBC_SHA, "TLS_DHE_RSA_WITH_DES_CBC_SHA"},
{PJ_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5, "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5"},
{PJ_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA"},
{PJ_TLS_DH_anon_WITH_DES_CBC_SHA, "TLS_DH_anon_WITH_DES_CBC_SHA"},
/* SSLv3 */
{PJ_SSL_FORTEZZA_KEA_WITH_NULL_SHA, "SSL_FORTEZZA_KEA_WITH_NULL_SHA"},
{PJ_SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA,"SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA"},
{PJ_SSL_FORTEZZA_KEA_WITH_RC4_128_SHA, "SSL_FORTEZZA_KEA_WITH_RC4_128_SHA"},
/* SSLv2 */
{PJ_SSL_CK_RC4_128_WITH_MD5, "SSL_CK_RC4_128_WITH_MD5"},
{PJ_SSL_CK_RC4_128_EXPORT40_WITH_MD5, "SSL_CK_RC4_128_EXPORT40_WITH_MD5"},
{PJ_SSL_CK_RC2_128_CBC_WITH_MD5, "SSL_CK_RC2_128_CBC_WITH_MD5"},
{PJ_SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5, "SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5"},
{PJ_SSL_CK_IDEA_128_CBC_WITH_MD5, "SSL_CK_IDEA_128_CBC_WITH_MD5"},
{PJ_SSL_CK_DES_64_CBC_WITH_MD5, "SSL_CK_DES_64_CBC_WITH_MD5"},
{PJ_SSL_CK_DES_192_EDE3_CBC_WITH_MD5, "SSL_CK_DES_192_EDE3_CBC_WITH_MD5"}
};
/* Get cipher name string */
static const char* get_cipher_name(pj_ssl_cipher cipher)
{
unsigned i, n;
n = PJ_ARRAY_SIZE(cipher_names);
for (i = 0; i < n; ++i) {
if (cipher == cipher_names[i].cipher)
return cipher_names[i].name;
}
return "CIPHER_UNKNOWN";
}
typedef void (*CPjSSLSocket_cb)(int err, void *key);
class CPjSSLSocketReader : public CActive
@ -115,7 +213,8 @@ public:
int Connect(CPjSSLSocket_cb cb, void *key, const TInetAddr &local_addr,
const TInetAddr &rem_addr,
const TDesC8 &servername = TPtrC8(NULL,0));
const TDesC8 &servername = TPtrC8(NULL,0),
const TDesC8 &ciphers = TPtrC8(NULL,0));
int Send(CPjSSLSocket_cb cb, void *key, const TDesC8 &aDesc, TUint flags);
int SendSync(const TDesC8 &aDesc, TUint flags);
@ -146,6 +245,7 @@ private:
TBuf<32> ssl_proto_;
TInetAddr rem_addr_;
TPtrC8 servername_;
TPtrC8 ciphers_;
TInetAddr local_addr_;
TSockXfrLength sent_len_;
@ -186,7 +286,8 @@ private:
int CPjSSLSocket::Connect(CPjSSLSocket_cb cb, void *key,
const TInetAddr &local_addr,
const TInetAddr &rem_addr,
const TDesC8 &servername)
const TDesC8 &servername,
const TDesC8 &ciphers)
{
pj_status_t status;
@ -213,7 +314,11 @@ int CPjSSLSocket::Connect(CPjSSLSocket_cb cb, void *key,
cb_ = cb;
key_ = key;
rem_addr_ = rem_addr;
/* Note: the following members only keep the pointer, not the data */
servername_.Set(servername);
ciphers_.Set(ciphers);
rSock.Connect(rem_addr_, iStatus);
SetActive();
state_ = SSL_STATE_CONNECTING;
@ -318,6 +423,8 @@ void CPjSSLSocket::RunL()
if (servername_.Length() > 0)
securesock_->SetOpt(KSoSSLDomainName, KSolInetSSL,
servername_);
if (ciphers_.Length() > 0)
securesock_->SetAvailableCipherSuites(ciphers_);
// FlushSessionCache() seems to also fire signals to all
// completed AOs (something like CActiveScheduler::RunIfReady())
@ -441,9 +548,8 @@ struct pj_ssl_sock_t
pj_ssl_sock_proto proto;
pj_time_val timeout;
unsigned ciphers_num;
pj_ssl_cipher *ciphers;
pj_str_t servername;
pj_str_t ciphers;
pj_ssl_cert_info remote_cert_info;
};
@ -579,15 +685,20 @@ static void update_certs_info(pj_ssl_sock_t *ssock)
}
/* Available ciphers */
static unsigned ciphers_num_ = 0;
static struct ciphers_t
{
pj_ssl_cipher id;
const char *name;
} ciphers_[64];
/*
* Get cipher list supported by SSL/TLS backend.
*/
PJ_DEF(pj_status_t) pj_ssl_cipher_get_availables (pj_ssl_cipher ciphers[],
unsigned *cipher_num)
{
/* Available ciphers */
static pj_ssl_cipher ciphers_[64];
static unsigned ciphers_num_ = 0;
unsigned i;
PJ_ASSERT_RETURN(ciphers && cipher_num, PJ_EINVAL);
@ -605,25 +716,69 @@ PJ_DEF(pj_status_t) pj_ssl_cipher_get_availables (pj_ssl_cipher ciphers[],
ciphers_num_ = ciphers_buf.Length() / 2;
if (ciphers_num_ > PJ_ARRAY_SIZE(ciphers_))
ciphers_num_ = PJ_ARRAY_SIZE(ciphers_);
for (i = 0; i < ciphers_num_; ++i)
ciphers_[i] = (pj_ssl_cipher)(ciphers_buf[i*2]*10 +
ciphers_buf[i*2+1]);
for (i = 0; i < ciphers_num_; ++i) {
ciphers_[i].id = (pj_ssl_cipher)(ciphers_buf[i*2]*10 +
ciphers_buf[i*2+1]);
ciphers_[i].name = get_cipher_name(ciphers_[i].id);
}
}
delete secure_sock;
}
if (ciphers_num_ == 0) {
*cipher_num = 0;
return PJ_ENOTFOUND;
}
*cipher_num = PJ_MIN(*cipher_num, ciphers_num_);
for (i = 0; i < *cipher_num; ++i)
ciphers[i] = ciphers_[i];
ciphers[i] = ciphers_[i].id;
return PJ_SUCCESS;
}
/* Get cipher name string */
PJ_DEF(const char*) pj_ssl_cipher_name(pj_ssl_cipher cipher)
{
unsigned i;
if (ciphers_num_ == 0) {
pj_ssl_cipher c[1];
i = 0;
pj_ssl_cipher_get_availables(c, &i);
}
for (i = 0; i < ciphers_num_; ++i) {
if (cipher == ciphers_[i].id)
return ciphers_[i].name;
}
return NULL;
}
/* Check if the specified cipher is supported by SSL/TLS backend. */
PJ_DEF(pj_bool_t) pj_ssl_cipher_is_supported(pj_ssl_cipher cipher)
{
unsigned i;
if (ciphers_num_ == 0) {
pj_ssl_cipher c[1];
i = 0;
pj_ssl_cipher_get_availables(c, &i);
}
for (i = 0; i < ciphers_num_; ++i) {
if (cipher == ciphers_[i].id)
return PJ_TRUE;
}
return PJ_FALSE;
}
/*
* Create SSL socket instance.
*/
@ -652,14 +807,15 @@ PJ_DEF(pj_status_t) pj_ssl_sock_create (pj_pool_t *pool,
ssock->cb = param->cb;
ssock->user_data = param->user_data;
ssock->timeout = param->timeout;
ssock->ciphers_num = param->ciphers_num;
if (param->ciphers_num > 0) {
unsigned i;
ssock->ciphers = (pj_ssl_cipher*)
pj_pool_calloc(pool, param->ciphers_num,
sizeof(pj_ssl_cipher));
for (i = 0; i < param->ciphers_num; ++i)
ssock->ciphers[i] = param->ciphers[i];
/* Cipher list in Symbian is represented as array of two-octets. */
ssock->ciphers.slen = param->ciphers_num*2;
ssock->ciphers.ptr = (char*)pj_pool_alloc(pool, ssock->ciphers.slen);
pj_uint8_t *c = (pj_uint8_t*)ssock->ciphers.ptr;
for (unsigned i = 0; i < param->ciphers_num; ++i) {
*c++ = (pj_uint8_t)(param->ciphers[i] & 0xFF00) >> 8;
*c++ = (pj_uint8_t)(param->ciphers[i] & 0xFF);
}
}
pj_strdup_with_null(pool, &ssock->servername, &param->server_name);
@ -1246,9 +1402,13 @@ PJ_DEF(pj_status_t) pj_ssl_sock_start_connect (pj_ssl_sock_t *ssock,
TPtrC8 servername_((TUint8*)ssock->servername.ptr,
ssock->servername.slen);
/* Convert cipher list to Symbian descriptor */
TPtrC8 ciphers_((TUint8*)ssock->ciphers.ptr,
ssock->ciphers.slen);
/* Try to connect */
status = sock->Connect(&connect_cb, ssock, localaddr_, remaddr_,
servername_);
servername_, ciphers_);
if (status != PJ_SUCCESS && status != PJ_EPENDING) {
delete sock;
return status;

View File

@ -497,15 +497,16 @@ PJ_DEF(unsigned) pj_timer_heap_poll( pj_timer_heap_t *ht,
PJ_ASSERT_RETURN(ht, 0);
lock_timer_heap(ht);
if (!ht->cur_size && next_delay) {
next_delay->sec = next_delay->msec = PJ_MAXINT32;
unlock_timer_heap(ht);
return 0;
}
count = 0;
pj_gettickcount(&now);
lock_timer_heap(ht);
while ( ht->cur_size &&
PJ_TIME_VAL_LTE(ht->heap[0]->_timer_value, now) &&
count < ht->max_entries_per_poll )

View File

@ -213,6 +213,7 @@ static int udp_ping_pong_test(void)
for (i=0; i<10 && last_rx1 == srv1->rx_cnt && last_rx2 == srv2->rx_cnt; ++i) {
pj_time_val delay = {0, 10};
#ifdef PJ_SYMBIAN
PJ_UNUSED_ARG(delay);
pj_symbianos_poll(-1, 100);
#else
pj_ioqueue_poll(ioqueue, &delay);

View File

@ -363,7 +363,7 @@ static int compliance_test_0(pj_bool_t allow_concur)
#ifdef PJ_SYMBIAN
callback_call_count = 0;
pj_symbianos_poll(-1, 1000);
pj_symbianos_poll(-1, PJ_TIME_VAL_MSEC(timeout));
status = callback_call_count;
#else
status = pj_ioqueue_poll(ioque, &timeout);
@ -412,7 +412,7 @@ static int compliance_test_0(pj_bool_t allow_concur)
if (pending_op == 0) {
pj_time_val timeout = {1, 0};
#ifdef PJ_SYMBIAN
status = pj_symbianos_poll(-1, 1000);
status = pj_symbianos_poll(-1, PJ_TIME_VAL_MSEC(timeout));
#else
status = pj_ioqueue_poll(ioque, &timeout);
#endif
@ -542,7 +542,7 @@ static int compliance_test_1(pj_bool_t allow_concur)
#ifdef PJ_SYMBIAN
callback_call_count = 0;
pj_symbianos_poll(-1, 1000);
pj_symbianos_poll(-1, PJ_TIME_VAL_MSEC(timeout));
status = callback_call_count;
#else
status = pj_ioqueue_poll(ioque, &timeout);
@ -576,7 +576,7 @@ static int compliance_test_1(pj_bool_t allow_concur)
if (pending_op == 0) {
pj_time_val timeout = {1, 0};
#ifdef PJ_SYMBIAN
status = pj_symbianos_poll(-1, 1000);
status = pj_symbianos_poll(-1, PJ_TIME_VAL_MSEC(timeout));
#else
status = pj_ioqueue_poll(ioque, &timeout);
#endif
@ -771,7 +771,7 @@ static int compliance_test_2(pj_bool_t allow_concur)
pj_time_val timeout = {1, 0};
#ifdef PJ_SYMBIAN
status = pj_symbianos_poll(-1, 1000);
status = pj_symbianos_poll(-1, PJ_TIME_VAL_MSEC(timeout));
#else
status = pj_ioqueue_poll(ioque, &timeout);
#endif
@ -797,7 +797,7 @@ static int compliance_test_2(pj_bool_t allow_concur)
if (pending_op == 0) {
pj_time_val timeout = {1, 0};
#ifdef PJ_SYMBIAN
status = pj_symbianos_poll(-1, 1000);
status = pj_symbianos_poll(-1, PJ_TIME_VAL_MSEC(timeout));
#else
status = pj_ioqueue_poll(ioque, &timeout);
#endif

View File

@ -267,7 +267,7 @@ static int compliance_test(pj_bool_t allow_concur)
TRACE_("poll...");
#ifdef PJ_SYMBIAN
rc = pj_symbianos_poll(-1, 5000);
rc = pj_symbianos_poll(-1, PJ_TIME_VAL_MSEC(timeout));
#else
rc = pj_ioqueue_poll(ioque, &timeout);
#endif
@ -783,7 +783,7 @@ static int bench_test(pj_bool_t allow_concur, int bufsize,
do {
pj_time_val timeout = { 1, 0 };
#ifdef PJ_SYMBIAN
rc = pj_symbianos_poll(-1, 1000);
rc = pj_symbianos_poll(-1, PJ_TIME_VAL_MSEC(timeout));
#else
rc = pj_ioqueue_poll(ioque, &timeout);
#endif
@ -812,6 +812,7 @@ static int bench_test(pj_bool_t allow_concur, int bufsize,
do {
pj_time_val timeout = { 0, 10 };
#ifdef PJ_SYMBIAN
PJ_UNUSED_ARG(timeout);
rc = pj_symbianos_poll(-1, 100);
#else
rc = pj_ioqueue_poll(ioque, &timeout);

View File

@ -22,11 +22,81 @@
#include <pj/os.h>
#if INCLUDE_OS_TEST
static int endianness_test32(void)
{
union t
{
pj_uint32_t u32;
pj_uint16_t u16[2];
pj_uint8_t u8[4];
} t;
PJ_LOG(3,("", " Testing endianness.."));
t.u32 = 0x11223344;
#if defined(PJ_IS_LITTLE_ENDIAN) && PJ_IS_LITTLE_ENDIAN
PJ_LOG(3,("", " Library is set to little endian"));
# if defined(PJ_IS_BIG_ENDIAN) && PJ_IS_BIG_ENDIAN
# error Error: Both PJ_IS_LITTLE_ENDIAN and PJ_IS_BIG_ENDIAN are set!
# endif
if ((t.u16[0] & 0xFFFF) != 0x3344 ||
(t.u16[1] & 0xFFFF) != 0x1122)
{
PJ_LOG(3,("", " Error: wrong 16bit values 0x%x and 0x%x",
(t.u16[0] & 0xFFFF), (t.u16[1] & 0xFFFF)));
return 10;
}
if ((t.u8[0] & 0xFF) != 0x44 ||
(t.u8[1] & 0xFF) != 0x33 ||
(t.u8[2] & 0xFF) != 0x22 ||
(t.u8[3] & 0xFF) != 0x11)
{
PJ_LOG(3,("", " Error: wrong 8bit values"));
return 12;
}
#elif defined(PJ_IS_BIG_ENDIAN) && PJ_IS_BIG_ENDIAN
PJ_LOG(3,("", " Library is set to big endian"));
if ((t.u16[0] & 0xFFFF) != 0x1122 ||
(t.u16[1] & 0xFFFF) != 0x3344)
{
PJ_LOG(3,("", " Error: wrong 16bit values 0x%x and 0x%x",
(t.u16[0] & 0xFFFF), (t.u16[1] & 0xFFFF)));
return 20;
}
if ((t.u8[0] & 0xFF) != 0x11 ||
(t.u8[1] & 0xFF) != 0x22 ||
(t.u8[2] & 0xFF) != 0x33 ||
(t.u8[3] & 0xFF) != 0x44)
{
PJ_LOG(3,("", " Error: wrong 8bit values"));
return 22;
}
# if defined(PJ_IS_LITTLE_ENDIAN) && PJ_IS_LITTLE_ENDIAN
# error Error: Both PJ_IS_LITTLE_ENDIAN and PJ_IS_BIG_ENDIAN are set!
# endif
#else
# error Error: Endianness is not set properly!
#endif
return 0;
}
int os_test(void)
{
const pj_sys_info *si;
int rc = 0;
PJ_LOG(3,("", " Sys info:"));
si = pj_get_sys_info();
PJ_LOG(3,("", " machine: %s", si->machine.ptr));
PJ_LOG(3,("", " os_name: %s", si->os_name.ptr));
@ -35,6 +105,8 @@ int os_test(void)
PJ_LOG(3,("", " sdk_ver: 0x%x", si->sdk_ver));
PJ_LOG(3,("", " info: %s", si->info.ptr));
rc = endianness_test32();
return rc;
}

View File

@ -510,7 +510,7 @@ static int send_recv_test(int sock_type,
}
if (srclen != addrlen)
return -151;
if (pj_memcmp(&addr, srcaddr, srclen) != 0) {
if (pj_sockaddr_cmp(&addr, srcaddr) != 0) {
char srcaddr_str[32], addr_str[32];
strcpy(srcaddr_str, pj_inet_ntoa(srcaddr->sin_addr));
strcpy(addr_str, pj_inet_ntoa(addr.sin_addr));

View File

@ -1329,11 +1329,34 @@ on_return:
return status;
}
#if 0 && (!defined(PJ_SYMBIAN) || PJ_SYMBIAN==0)
pj_status_t pj_ssl_sock_ossl_test_send_buf(pj_pool_t *pool);
static int ossl_test_send_buf()
{
pj_pool_t *pool;
pj_status_t status;
pool = pj_pool_create(mem, "send_buf", 256, 256, NULL);
status = pj_ssl_sock_ossl_test_send_buf(pool);
pj_pool_release(pool);
return status;
}
#else
static int ossl_test_send_buf()
{
return 0;
}
#endif
int ssl_sock_test(void)
{
int ret;
PJ_LOG(3,("", "..test ossl send buf"));
ret = ossl_test_send_buf();
if (ret != 0)
return ret;
PJ_LOG(3,("", "..get cipher list test"));
ret = get_cipher_list();
if (ret != 0)

View File

@ -22,6 +22,7 @@
static pj_ioqueue_key_t *key;
static pj_atomic_t *total_bytes;
static pj_bool_t thread_quit_flag;
struct op_key
{
@ -145,12 +146,12 @@ static int worker_thread(void *arg)
on_read_complete(key, &read_op.op_key_, length);
}
for (;;) {
while (!thread_quit_flag) {
pj_time_val timeout;
timeout.sec = 0; timeout.msec = 10;
rc = pj_ioqueue_poll(ioqueue, &timeout);
}
PJ_UNREACHED(return 0;)
return 0;
}
int udp_echo_srv_ioqueue(void)

View File

@ -21,6 +21,7 @@
#include <pjlib.h>
static pj_atomic_t *total_bytes;
static pj_bool_t thread_quit_flag = 0;
static int worker_thread(void *arg)
{
@ -28,7 +29,7 @@ static int worker_thread(void *arg)
char buf[512];
pj_status_t last_recv_err = PJ_SUCCESS, last_write_err = PJ_SUCCESS;
for (;;) {
while (!thread_quit_flag) {
pj_ssize_t len;
pj_status_t rc;
pj_sockaddr_in addr;
@ -56,7 +57,7 @@ static int worker_thread(void *arg)
continue;
}
}
PJ_UNREACHED(return 0;)
return 0;
}

View File

@ -19,11 +19,11 @@
#
# 3. Success conditions, started with '!', followed by condition name
# and its maximum tolerable value, in frames unit. Recognized condition
# names are: burst, discard, lost, empty, delay. These conditions will
# be verified with jitter buffer statistics after all session test data
# are executed.
# names are: burst, discard, lost, empty, delay, delay_min. These
# conditions will be verified with jitter buffer statistics after all
# session test data are executed.
# Example:
# !delay 10 <- maximum average delay of jbuf is 10 frames
# !delay 10 <- average delay of jbuf is 10 frames
#
# 4. Session test data, containing sequence of jitter buffer events,
# an event is represented by a character as follow:
@ -295,7 +295,7 @@ PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG
!discard 50 <- frames discarded for delay adaptation
!lost 50 <- ticket #1188, normal frame after discarded frame is flagged 'lost' to align signal
!empty 0
!delay 25 <- average delay, JB is able to adapt the delay
!delay_min 2 <- minimum delay, JB is able to adapt the delay
PPPPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPPPP PPPPPPPPPP
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
@ -311,13 +311,30 @@ PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
.
= Fixed mode prefetch 5, with two empty events
%fixed 5
!burst 1
!discard 0
!lost 0
!discard 4 <- the burst level is about 1, but prefetching will cause delay by 5 frames prefetching, delay adjustment may take place later on
!lost 4 <- progressive discard drops frames as if they were lost
!empty 10
!delay 5
G
@ -329,8 +346,8 @@ PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
= Fixed mode prefetch 5, with random burst
%fixed 5
!burst 3
!discard 0
!lost 0
!discard 4 <- (see above test scenario)
!lost 4 <- (see above test scenario)
!empty 5
!delay 5
PGPGPPGGPPPPGGPGGGPG PGGGGPPPGPPGPPPGGPGG PGPGPPGGPPPPGGPGGGPG
@ -349,7 +366,7 @@ PGGGGPPPGPPGPPPGGPGG PGPGPPGGPPGGPPPGGGPG PGGGGPPPGPPGPPPGGPGG
!discard 50 <- frames discarded for delay adaptation
!lost 50 <- ticket #1188, normal frame after discarded frame is flagged 'lost' to align signal
!empty 0
!delay 20 <- average delay, twice of minimal prefetch
!delay_min 20 <- minimum delay, twice of minimal prefetch
PPPPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPPPP PPPPPPPPPP
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
@ -369,7 +386,7 @@ PGPGPGPGPGPGPGPGPGPG PGPGPGPGPGPGPGPGPGPG PGPGPGPGPG
= Large PUT burst at beginning, then normal with burst level 10 and periodic burst spikes
%adaptive 0 0 40
!burst 10
!burst 12
!discard 300 <- not so relevant for long period session with many delay adjustments needed (i.e: for first burst and periodic spikes)
!lost 300 <- ticket #1188, normal frame after discarded frame is flagged 'lost' to align signal
!empty 60 <- delay adjustment effect, as there is actually no drift

View File

@ -1,4 +1,5 @@
include ../../build.mak
include ../../version.mak
THIRD_PARTY:=$(PJDIR)/third_party
@ -122,11 +123,14 @@ TARGETS := pjmedia pjmedia-audiodev pjmedia-codec pjsdp pjmedia-test
all: $(TARGETS)
doc:
cd .. && rm -rf docs/html docs/latex && doxygen docs/doxygen.cfg
@if [ -n "$(WWWDIR)" ]; then \
echo "Copying to $(WWWDIR)/pjmedia/docs/html.." ; \
rm -rf $(WWWDIR)/pjmedia/docs/html/* ; \
cp -a ../docs/html/* $(WWWDIR)/pjmedia/docs/html/ ; \
cd .. && rm -rf docs/$(PJ_VERSION) && doxygen docs/doxygen.cfg
@if [ -n "$(WWWDIR)" ] && ! [ -d "$(WWWDIR)/docs/$(PJ_VERSION)/pjmedia/docs/html" ] ; then \
echo "Creating docs/$(PJ_VERSION)/pjmedia/docs/html" ; \
mkdir -p $(WWWDIR)/docs/$(PJ_VERSION)/pjmedia/docs/html ; \
fi
@if [ -n "$(WWWDIR)" ] && [ -d "$(WWWDIR)/docs/$(PJ_VERSION)/pjmedia/docs/html" ] ; then \
echo "Copying docs/$(PJ_VERSION) to $(WWWDIR)/docs/$(PJ_VERSION)/pjmedia/docs/html.." ; \
cp -v -a ../docs/$(PJ_VERSION)/html/* $(WWWDIR)/docs/$(PJ_VERSION)/pjmedia/docs/html/ ; \
fi
dep: depend
@ -146,7 +150,9 @@ pjmedia-audiodev:
pjsdp:
$(MAKE) -f $(RULES_MAK) APP=PJSDP app=pjsdp $(PJSDP_LIB)
pjmedia-test: $(PJMEDIA_LIB)
$(PJMEDIA_LIB): pjmedia
pjmedia-test: $(PJMEDIA_LIB) pjmedia
$(MAKE) -f $(RULES_MAK) APP=PJMEDIA_TEST app=pjmedia-test $(PJMEDIA_TEST_EXE)
.PHONY: ../lib/pjmedia.ko

View File

@ -29,6 +29,7 @@ AC_NO_SPEEX_CODEC=@ac_no_speex_codec@
AC_NO_ILBC_CODEC=@ac_no_ilbc_codec@
AC_NO_G722_CODEC=@ac_no_g722_codec@
AC_NO_G7221_CODEC=@ac_no_g7221_codec@
AC_NO_OPENCORE_AMRNB=@ac_no_opencore_amrnb@
export CODEC_OBJS=
@ -81,6 +82,12 @@ export CODEC_OBJS += g7221.o
export G7221_CFLAGS += -I$(THIRD_PARTY)
endif
ifeq ($(AC_NO_OPENCORE_AMRNB),1)
export CFLAGS += -DPJMEDIA_HAS_OPENCORE_AMRNB_CODEC=0
else
export CODEC_OBJS += opencore_amrnb.o
endif
#
# PortAudio

File diff suppressed because it is too large Load Diff

View File

@ -23,14 +23,14 @@ PROJECT_NAME = "PJMEDIA Reference"
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER =
PROJECT_NUMBER = $(PJ_VERSION)
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY = docs
OUTPUT_DIRECTORY = docs/$(PJ_VERSION)
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this

View File

@ -1,6 +1,6 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>$title</title>
<title>$title ($projectnumber)</title>
<link href="/style/style.css" rel="stylesheet" type="text/css">
</head><body>
<!--#include virtual="/header.html" -->

View File

@ -144,6 +144,21 @@ PJ_BEGIN_DECL
#endif
/**
* This setting controls whether the Symbian audio with built-in multimedia
* framework backend should be started synchronously. Note that synchronous
* start will block the application/UI, e.g: about 40ms for each direction
* on N95. While asynchronous start may cause invalid value (always zero)
* returned in input/output volume query, if the query is performed when
* the internal start procedure is not completely finished.
*
* Default: 1 (yes)
*/
#ifndef PJMEDIA_AUDIO_DEV_MDA_USE_SYNC_START
# define PJMEDIA_AUDIO_DEV_MDA_USE_SYNC_START 1
#endif
/**
* This setting controls whether the Audio Device API should support
* device implementation that is based on the old sound device API

View File

@ -33,6 +33,7 @@
#include <pjmedia-codec/g7221.h>
#include <pjmedia-codec/ipp_codecs.h>
#include <pjmedia-codec/passthrough.h>
#include <pjmedia-codec/opencore_amrnb.h>
#endif /* __PJMEDIA_CODEC_PJMEDIA_CODEC_H__ */

View File

@ -567,7 +567,7 @@ const pj_int16_t* const pjmedia_codec_amrwb_ordermaps[9] =
* Constant of AMR-NB frame lengths in bytes.
*/
const pj_uint8_t pjmedia_codec_amrnb_framelen[16] =
{12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 5};
{12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0};
/**
* Constant of AMR-NB frame lengths in bits.
*/
@ -583,7 +583,7 @@ const pj_uint16_t pjmedia_codec_amrnb_bitrates[8] =
* Constant of AMR-WB frame lengths in bytes.
*/
const pj_uint8_t pjmedia_codec_amrwb_framelen[16] =
{17, 23, 32, 37, 40, 46, 50, 58, 60, 5, 0, 0, 0, 0, 0, 5};
{17, 23, 32, 37, 40, 46, 50, 58, 60, 5, 0, 0, 0, 0, 0, 0};
/**
* Constant of AMR-WB frame lengths in bits.
*/
@ -606,6 +606,7 @@ typedef struct pjmedia_codec_amr_bit_info {
pj_int8_t mode; /**< AMR mode. */
pj_uint8_t start_bit; /**< Frame start bit. */
pj_uint8_t good_quality:1; /**< Flag if frame is good/degraded. */
pj_uint8_t STI:1; /**< STI mode (first/update). */
} pjmedia_codec_amr_bit_info;
#pragma pack()
@ -1020,9 +1021,7 @@ PJ_INLINE (pj_status_t) pjmedia_codec_amr_pack(
} else if (info->frame_type == SID_FT) {
/* SID */
pj_uint8_t STI = 0;
amr_bits[35] = (pj_uint8_t)(STI & 1);
amr_bits[35] |= info->STI;
if (setting->amr_nb) {
amr_bits[36] = (pj_uint8_t)((info->mode >> 2) & 1);
@ -1163,6 +1162,7 @@ PJ_INLINE(pj_status_t) pjmedia_codec_amr_parse(
info->mode = (pj_int8_t)((FT < SID_FT)? FT : -1);
info->good_quality = (pj_uint8_t)(Q == 1);
info->start_bit = 0;
info->STI = 0;
frames[cnt].timestamp = ts_;
frames[cnt].type = PJMEDIA_FRAME_TYPE_AUDIO;
@ -1186,6 +1186,13 @@ PJ_INLINE(pj_status_t) pjmedia_codec_amr_parse(
frames[cnt].buf = r;
info->start_bit = r_bitptr;
if (FT == SID_FT) {
unsigned sti_bitptr;
sti_bitptr = r_bitptr + 35;
info->STI = (pj_uint8_t)
(r[sti_bitptr >> 3] >> (7 - (sti_bitptr % 8))) & 1;
}
if (setting->octet_aligned) {
r += framelen_tbl[FT];
frames[cnt].size = framelen_tbl[FT];

View File

@ -312,6 +312,39 @@
# define PJMEDIA_HAS_G7221_CODEC 0
#endif
/**
* Enable OpenCORE AMR-NB codec.
* See https://trac.pjsip.org/repos/ticket/1388 for some info.
*
* Default: 0
*/
#ifndef PJMEDIA_HAS_OPENCORE_AMRNB_CODEC
# define PJMEDIA_HAS_OPENCORE_AMRNB_CODEC 0
#endif
/**
* Link with libopencore-amrXX via pragma comment on Visual Studio.
* This option only makes sense if PJMEDIA_HAS_OPENCORE_AMRNB_CODEC
* is enabled.
*
* Default: 1
*/
#ifndef PJMEDIA_AUTO_LINK_OPENCORE_AMR_LIBS
# define PJMEDIA_AUTO_LINK_OPENCORE_AMR_LIBS 1
#endif
/**
* Link with libopencore-amrXX.a that has been produced with gcc.
* This option only makes sense if PJMEDIA_HAS_OPENCORE_AMRNB_CODEC
* and PJMEDIA_AUTO_LINK_OPENCORE_AMR_LIBS are enabled.
*
* Default: 1
*/
#ifndef PJMEDIA_OPENCORE_AMR_BUILT_WITH_GCC
# define PJMEDIA_OPENCORE_AMR_BUILT_WITH_GCC 1
#endif
/**
* Default G.722.1 codec encoder and decoder level adjustment.
* If the value is non-zero, then PCM input samples to the encoder will

View File

@ -69,6 +69,11 @@
#undef PJMEDIA_HAS_G7221_CODEC
#endif
/* OpenCORE AMR-NB codec */
#ifndef PJMEDIA_HAS_OPENCORE_AMRNB_CODEC
#undef PJMEDIA_HAS_OPENCORE_AMRNB_CODEC
#endif
#endif /* __PJMEDIA_CODEC_CONFIG_AUTO_H_ */

View File

@ -0,0 +1,89 @@
/* $Id$ */
/*
* Copyright (C) 2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2011 Dan Arrhenius <dan@keystream.se>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJMEDIA_CODEC_OPENCORE_AMRNB_H__
#define __PJMEDIA_CODEC_OPENCORE_AMRNB_H__
#include <pjmedia-codec/types.h>
/**
* @defgroup PJMED_OC_AMRNB OpenCORE AMR-NB Codec
* @ingroup PJMEDIA_CODEC_CODECS
* @brief AMRCodec wrapper for OpenCORE AMR-NB codec
* @{
*/
PJ_BEGIN_DECL
/**
* Settings. Use #pjmedia_codec_opencore_amrnb_set_config() to
* activate.
*/
typedef struct pjmedia_codec_amrnb_config
{
/**
* Control whether to use octent align.
*/
pj_bool_t octet_align;
/**
* Set the bitrate.
*/
unsigned bitrate;
} pjmedia_codec_amrnb_config;
/**
* Initialize and register AMR-NB codec factory to pjmedia endpoint.
*
* @param endpt The pjmedia endpoint.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t) pjmedia_codec_opencore_amrnb_init(pjmedia_endpt* endpt);
/**
* Unregister AMR-NB codec factory from pjmedia endpoint and deinitialize
* the OpenCORE codec library.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t) pjmedia_codec_opencore_amrnb_deinit(void);
/**
* Set AMR-NB parameters.
*
* @param cfg The settings;
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t) pjmedia_codec_opencore_amrnb_set_config(
const pjmedia_codec_amrnb_config* cfg);
PJ_END_DECL
/**
* @}
*/
#endif /* __PJMEDIA_CODEC_OPENCORE_AMRNB_H__ */

View File

@ -309,6 +309,18 @@ typedef struct pjmedia_codec_param
} pjmedia_codec_param;
/**
* Duplicate codec parameter.
*
* @param pool The pool.
* @param src The codec parameter to be duplicated.
*
* @return Duplicated codec parameter.
*/
PJ_DECL(pjmedia_codec_param*) pjmedia_codec_param_clone(
pj_pool_t *pool,
const pjmedia_codec_param *src);
/*
* Forward declaration for pjmedia_codec.

View File

@ -387,7 +387,7 @@
/**
* Number of packets received from different source IP address from the
* Number of RTP packets received from different source IP address from the
* remote address required to make the stream switch transmission
* to the source address.
*/
@ -396,6 +396,16 @@
#endif
/**
* Number of RTCP packets received from different source IP address from the
* remote address required to make the stream switch RTCP transmission
* to the source address.
*/
#ifndef PJMEDIA_RTCP_NAT_PROBATION_CNT
# define PJMEDIA_RTCP_NAT_PROBATION_CNT 3
#endif
/**
* Specify whether RTCP should be advertised in SDP. This setting would
* affect whether RTCP candidate will be added in SDP when ICE is used.
@ -443,6 +453,19 @@
# define PJMEDIA_RTCP_STAT_HAS_RAW_JITTER 0
#endif
/**
* Specify the factor with wich RTCP RTT statistics should be normalized
* if exceptionally high. For e.g. mobile networks with potentially large
* fluctuations, this might be unwanted.
*
* Use (0) to disable this feature.
*
* Default: 3.
*/
#ifndef PJMEDIA_RTCP_NORMALIZE_FACTOR
# define PJMEDIA_RTCP_NORMALIZE_FACTOR 3
#endif
/**
* Specify whether RTCP statistics includes IP Delay Variation statistics.
@ -466,7 +489,7 @@
* if it is enabled on run-time on per stream basis. See
* PJMEDIA_STREAM_ENABLE_XR setting for more info.
*
* Default: 1 (yes).
* Default: 0 (no).
*/
#ifndef PJMEDIA_HAS_RTCP_XR
# define PJMEDIA_HAS_RTCP_XR 0
@ -484,6 +507,19 @@
# define PJMEDIA_STREAM_ENABLE_XR 0
#endif
/**
* Specify the buffer length for storing any received RTCP SDES text
* in a stream session. Usually RTCP contains only the mandatory SDES
* field, i.e: CNAME.
*
* Default: 64 bytes.
*/
#ifndef PJMEDIA_RTCP_RX_SDES_BUF_LEN
# define PJMEDIA_RTCP_RX_SDES_BUF_LEN 64
#endif
/**
* Specify how long (in miliseconds) the stream should suspend the
* silence detector/voice activity detector (VAD) during the initial
@ -876,7 +912,64 @@
* Default: 5 seconds
*/
#ifndef PJMEDIA_STREAM_KA_INTERVAL
# define PJMEDIA_STREAM_KA_INTERVAL 5
# define PJMEDIA_STREAM_KA_INTERVAL 5
#endif
/**
* Minimum gap between two consecutive discards in jitter buffer,
* in milliseconds.
*
* Default: 200 ms
*/
#ifndef PJMEDIA_JBUF_DISC_MIN_GAP
# define PJMEDIA_JBUF_DISC_MIN_GAP 200
#endif
/**
* Minimum burst level reference used for calculating discard duration
* in jitter buffer progressive discard algorithm, in frames.
*
* Default: 1 frame
*/
#ifndef PJMEDIA_JBUF_PRO_DISC_MIN_BURST
# define PJMEDIA_JBUF_PRO_DISC_MIN_BURST 1
#endif
/**
* Maximum burst level reference used for calculating discard duration
* in jitter buffer progressive discard algorithm, in frames.
*
* Default: 200 frames
*/
#ifndef PJMEDIA_JBUF_PRO_DISC_MAX_BURST
# define PJMEDIA_JBUF_PRO_DISC_MAX_BURST 100
#endif
/**
* Duration for progressive discard algotithm in jitter buffer to discard
* an excessive frame when burst is equal to or lower than
* PJMEDIA_JBUF_PRO_DISC_MIN_BURST, in milliseconds.
*
* Default: 2000 ms
*/
#ifndef PJMEDIA_JBUF_PRO_DISC_T1
# define PJMEDIA_JBUF_PRO_DISC_T1 2000
#endif
/**
* Duration for progressive discard algotithm in jitter buffer to discard
* an excessive frame when burst is equal to or greater than
* PJMEDIA_JBUF_PRO_DISC_MAX_BURST, in milliseconds.
*
* Default: 10000 ms
*/
#ifndef PJMEDIA_JBUF_PRO_DISC_T2
# define PJMEDIA_JBUF_PRO_DISC_T2 10000
#endif

View File

@ -63,6 +63,19 @@ PJ_BEGIN_DECL
/** Opaque declaration for delay buffer. */
typedef struct pjmedia_delay_buf pjmedia_delay_buf;
/**
* Delay buffer options.
*/
typedef enum pjmedia_delay_buf_flag
{
/**
* Use simple FIFO mechanism for the delay buffer, i.e.
* without WSOLA for expanding and shrinking audio samples.
*/
PJMEDIA_DELAY_BUF_SIMPLE_FIFO = 1
} pjmedia_delay_buf_flag;
/**
* Create the delay buffer. Once the delay buffer is created, it will
* enter learning state unless the delay argument is specified, which
@ -79,7 +92,12 @@ typedef struct pjmedia_delay_buf pjmedia_delay_buf;
* in ms, if this value is negative or less than
* one frame time, default maximum delay used is
* 400 ms.
* @param options Option flags, must be zero for now.
* @param options Options. If PJMEDIA_DELAY_BUF_SIMPLE_FIFO is
* specified, then a simple FIFO mechanism
* will be used instead of the adaptive
* implementation (which uses WSOLA to expand
* or shrink audio samples).
* See #pjmedia_delay_buf_flag for other options.
* @param p_b Pointer to receive the delay buffer instance.
*
* @return PJ_SUCCESS if the delay buffer has been

View File

@ -88,7 +88,20 @@ typedef enum pjmedia_echo_flag
* for the echo canceller, but application will guarantee that echo
* canceller will not be called by different threads at the same time.
*/
PJMEDIA_ECHO_NO_LOCK = 16
PJMEDIA_ECHO_NO_LOCK = 16,
/**
* If PJMEDIA_ECHO_USE_SIMPLE_FIFO flag is specified, the delay buffer
* created for the echo canceller will use simple FIFO mechanism, i.e.
* without using WSOLA to expand and shrink audio samples.
*/
PJMEDIA_ECHO_USE_SIMPLE_FIFO = 32,
/**
* If PJMEDIA_ECHO_USE_SW_ECHO flag is specified, software echo canceller
* will be used instead of device EC.
*/
PJMEDIA_ECHO_USE_SW_ECHO = 64
} pjmedia_echo_flag;

View File

@ -59,6 +59,12 @@ typedef enum pjmedia_endpt_flag
} pjmedia_endpt_flag;
/**
* Type of callback to register to pjmedia_endpt_atexit().
*/
typedef void (*pjmedia_endpt_exit_callback)(pjmedia_endpt *endpt);
/**
* Create an instance of media endpoint.
*
@ -204,6 +210,23 @@ PJ_DECL(pj_status_t) pjmedia_endpt_create_sdp( pjmedia_endpt *endpt,
PJ_DECL(pj_status_t) pjmedia_endpt_dump(pjmedia_endpt *endpt);
/**
* Register cleanup function to be called by media endpoint when
* #pjmedia_endpt_destroy() is called. Note that application should not
* use or access any endpoint resource (such as pool, ioqueue) from within
* the callback as such resource may have been released when the callback
* function is invoked.
*
* @param endpt The media endpoint.
* @param func The function to be registered.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t) pjmedia_endpt_atexit(pjmedia_endpt *endpt,
pjmedia_endpt_exit_callback func);
PJ_END_DECL

View File

@ -48,7 +48,7 @@ PJ_BEGIN_DECL
/**
* Types of frame returned by the jitter buffer.
*/
enum pjmedia_jb_frame_type
typedef enum pjmedia_jb_frame_type
{
PJMEDIA_JB_MISSING_FRAME = 0, /**< No frame because it's missing */
PJMEDIA_JB_NORMAL_FRAME = 1, /**< Normal frame is being returned */
@ -56,19 +56,47 @@ enum pjmedia_jb_frame_type
because JB is bufferring. */
PJMEDIA_JB_ZERO_EMPTY_FRAME = 3 /**< Zero frame is being returned
because JB is empty. */
};
} pjmedia_jb_frame_type;
/**
* @see pjmedia_jb_frame_type.
* Enumeration of jitter buffer discard algorithm. The jitter buffer
* continuously calculates the jitter level to get the optimum latency at
* any time and in order to adjust the latency, the jitter buffer may need
* to discard some frames.
*/
typedef enum pjmedia_jb_frame_type pjmedia_jb_frame_type;
typedef enum pjmedia_jb_discard_algo
{
/**
* Jitter buffer should not discard any frame, except when the jitter
* buffer is full and a new frame arrives, one frame will be discarded
* to make space for the new frame.
*/
PJMEDIA_JB_DISCARD_NONE = 0,
/**
* Only discard one frame in at least 200ms when the latency is considered
* much higher than it should be. When the jitter buffer is full and a new
* frame arrives, one frame will be discarded to make space for the new
* frame.
*/
PJMEDIA_JB_DISCARD_STATIC,
/**
* The discard rate is dynamically calculated based on actual parameters
* such as jitter level and latency. When the jitter buffer is full and
* a new frame arrives, one frame will be discarded to make space for the
* new frame.
*/
PJMEDIA_JB_DISCARD_PROGRESSIVE
} pjmedia_jb_discard_algo;
/**
* This structure describes jitter buffer state.
*/
struct pjmedia_jb_state
typedef struct pjmedia_jb_state
{
/* Setting */
unsigned frame_size; /**< Individual frame size, in bytes. */
@ -89,13 +117,7 @@ struct pjmedia_jb_state
unsigned lost; /**< Number of lost frames. */
unsigned discard; /**< Number of discarded frames. */
unsigned empty; /**< Number of empty on GET events. */
};
/**
* @see pjmedia_jb_state
*/
typedef struct pjmedia_jb_state pjmedia_jb_state;
} pjmedia_jb_state;
/**
@ -113,7 +135,9 @@ typedef struct pjmedia_jbuf pjmedia_jbuf;
/**
* Create an adaptive jitter buffer according to the specification. If
* application wants to have a fixed jitter buffer, it may call
* #pjmedia_jbuf_set_fixed() after the jitter buffer is created.
* #pjmedia_jbuf_set_fixed() after the jitter buffer is created. Also
* if application wants to alter the discard algorithm, which the default
* PJMEDIA_JB_DISCARD_PROGRESSIVE, it may call #pjmedia_jbuf_set_discard().
*
* This function may allocate large chunk of memory to keep the frames in
* the buffer.
@ -179,6 +203,19 @@ PJ_DECL(pj_status_t) pjmedia_jbuf_set_adaptive( pjmedia_jbuf *jb,
unsigned max_prefetch);
/**
* Set the jitter buffer discard algorithm. The default discard algorithm,
* set in jitter buffer creation, is PJMEDIA_JB_DISCARD_PROGRESSIVE.
*
* @param jb The jitter buffer.
* @param algo The discard algorithm to be used.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t) pjmedia_jbuf_set_discard(pjmedia_jbuf *jb,
pjmedia_jb_discard_algo algo);
/**
* Destroy jitter buffer instance.
*

View File

@ -54,29 +54,26 @@ PJ_BEGIN_DECL
* #pjmedia_stream_get_stat() function.
*/
#pragma pack(1)
/**
* RTCP sender report.
*/
struct pjmedia_rtcp_sr
typedef struct pjmedia_rtcp_sr
{
pj_uint32_t ntp_sec; /**< NTP time, seconds part. */
pj_uint32_t ntp_frac; /**< NTP time, fractions part. */
pj_uint32_t rtp_ts; /**< RTP timestamp. */
pj_uint32_t sender_pcount; /**< Sender packet cound. */
pj_uint32_t sender_bcount; /**< Sender octet/bytes count. */
};
} pjmedia_rtcp_sr;
/**
* @see pjmedia_rtcp_sr
*/
typedef struct pjmedia_rtcp_sr pjmedia_rtcp_sr;
/**
* RTCP receiver report.
*/
struct pjmedia_rtcp_rr
typedef struct pjmedia_rtcp_rr
{
pj_uint32_t ssrc; /**< SSRC identification. */
#if defined(PJ_IS_BIG_ENDIAN) && PJ_IS_BIG_ENDIAN!=0
@ -94,18 +91,13 @@ struct pjmedia_rtcp_rr
pj_uint32_t jitter; /**< Jitter. */
pj_uint32_t lsr; /**< Last SR. */
pj_uint32_t dlsr; /**< Delay since last SR. */
};
/**
* @see pjmedia_rtcp_rr
*/
typedef struct pjmedia_rtcp_rr pjmedia_rtcp_rr;
} pjmedia_rtcp_rr;
/**
* RTCP common header.
*/
struct pjmedia_rtcp_common
typedef struct pjmedia_rtcp_common
{
#if defined(PJ_IS_BIG_ENDIAN) && PJ_IS_BIG_ENDIAN!=0
unsigned version:2; /**< packet type */
@ -120,12 +112,8 @@ struct pjmedia_rtcp_common
#endif
unsigned length:16; /**< packet length */
pj_uint32_t ssrc; /**< SSRC identification */
};
} pjmedia_rtcp_common;
/**
* @see pjmedia_rtcp_common
*/
typedef struct pjmedia_rtcp_common pjmedia_rtcp_common;
/**
* This structure declares default RTCP packet (SR) that is sent by pjmedia.
@ -152,26 +140,35 @@ typedef struct pjmedia_rtcp_rr_pkt
#pragma pack()
/**
* RTCP SDES structure.
*/
typedef struct pjmedia_rtcp_sdes
{
pj_str_t cname; /**< RTCP SDES type CNAME. */
pj_str_t name; /**< RTCP SDES type NAME. */
pj_str_t email; /**< RTCP SDES type EMAIL. */
pj_str_t phone; /**< RTCP SDES type PHONE. */
pj_str_t loc; /**< RTCP SDES type LOC. */
pj_str_t tool; /**< RTCP SDES type TOOL. */
pj_str_t note; /**< RTCP SDES type NOTE. */
} pjmedia_rtcp_sdes;
/**
* NTP time representation.
*/
struct pjmedia_rtcp_ntp_rec
typedef struct pjmedia_rtcp_ntp_rec
{
pj_uint32_t hi; /**< High order 32-bit part. */
pj_uint32_t lo; /**< Lo order 32-bit part. */
};
/**
* @see pjmedia_rtcp_ntp_rec
*/
typedef struct pjmedia_rtcp_ntp_rec pjmedia_rtcp_ntp_rec;
} pjmedia_rtcp_ntp_rec;
/**
* Unidirectional RTP stream statistics.
*/
struct pjmedia_rtcp_stream_stat
typedef struct pjmedia_rtcp_stream_stat
{
pj_time_val update; /**< Time of last update. */
unsigned update_cnt; /**< Number of updates (to calculate avg) */
@ -190,20 +187,14 @@ struct pjmedia_rtcp_stream_stat
} loss_type; /**< Types of loss detected. */
pj_math_stat jitter; /**< Jitter statistics (in usec) */
};
/**
* @see pjmedia_rtcp_stream_stat
*/
typedef struct pjmedia_rtcp_stream_stat pjmedia_rtcp_stream_stat;
} pjmedia_rtcp_stream_stat;
/**
* Bidirectional RTP stream statistics.
*/
struct pjmedia_rtcp_stat
typedef struct pjmedia_rtcp_stat
{
pj_time_val start; /**< Time when session was created */
@ -226,20 +217,19 @@ struct pjmedia_rtcp_stat
receiving direction
(in usec). */
#endif
};
pjmedia_rtcp_sdes peer_sdes; /**< Peer SDES. */
char peer_sdes_buf_[PJMEDIA_RTCP_RX_SDES_BUF_LEN];
/**< Peer SDES buffer. */
/**
* @see pjmedia_rtcp_stat
*/
typedef struct pjmedia_rtcp_stat pjmedia_rtcp_stat;
} pjmedia_rtcp_stat;
/**
* RTCP session is used to monitor the RTP session of one endpoint. There
* should only be one RTCP session for a bidirectional RTP streams.
*/
struct pjmedia_rtcp_session
typedef struct pjmedia_rtcp_session
{
char *name; /**< Name identification. */
pjmedia_rtcp_sr_pkt rtcp_sr_pkt;/**< Cached RTCP SR packet. */
@ -278,12 +268,7 @@ struct pjmedia_rtcp_session
*/
pjmedia_rtcp_xr_session xr_session;
#endif
};
/**
* @see pjmedia_rtcp_session
*/
typedef struct pjmedia_rtcp_session pjmedia_rtcp_session;
} pjmedia_rtcp_session;
/**
@ -438,6 +423,46 @@ PJ_DECL(void) pjmedia_rtcp_build_rtcp( pjmedia_rtcp_session *session,
void **rtcp_pkt, int *len);
/**
* Build an RTCP SDES (source description) packet. This packet can be
* appended to other RTCP packets, e.g: RTCP RR/SR, to compose a compound
* RTCP packet.
*
* @param session The RTCP session.
* @param buf The buffer to receive RTCP SDES packet.
* @param length On input, it will contain the buffer length.
* On output, it will contain the generated RTCP SDES
* packet length.
* @param sdes The source description, see #pjmedia_rtcp_sdes.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t) pjmedia_rtcp_build_rtcp_sdes(
pjmedia_rtcp_session *session,
void *buf,
pj_size_t *length,
const pjmedia_rtcp_sdes *sdes);
/**
* Build an RTCP BYE packet. This packet can be appended to other RTCP
* packets, e.g: RTCP RR/SR, to compose a compound RTCP packet.
*
* @param session The RTCP session.
* @param buf The buffer to receive RTCP BYE packet.
* @param length On input, it will contain the buffer length.
* On output, it will contain the generated RTCP BYE
* packet length.
* @param reason Optional, the BYE reason.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t) pjmedia_rtcp_build_rtcp_bye(
pjmedia_rtcp_session *session,
void *buf,
pj_size_t *length,
const pj_str_t *reason);
/**
* Call this function if RTCP XR needs to be enabled/disabled in the
* RTCP session.

View File

@ -200,6 +200,17 @@ typedef struct pjmedia_rtcp_xr_rb_voip_mtc
jitter buffer */
} pjmedia_rtcp_xr_rb_voip_mtc;
/**
* Constant of RTCP-XR content size.
*/
#define PJMEDIA_RTCP_XR_BUF_SIZE \
sizeof(pjmedia_rtcp_xr_rb_rr_time) + \
sizeof(pjmedia_rtcp_xr_rb_dlrr) + \
sizeof(pjmedia_rtcp_xr_rb_stats) + \
sizeof(pjmedia_rtcp_xr_rb_voip_mtc)
/**
* This structure declares RTCP XR (Extended Report) packet.
*/
@ -221,7 +232,8 @@ typedef struct pjmedia_rtcp_xr_pkt
pj_uint32_t ssrc; /**< SSRC identification */
} common;
pj_int8_t buf[PJMEDIA_MAX_MTU];/**< Content buffer */
pj_int8_t buf[PJMEDIA_RTCP_XR_BUF_SIZE];
/**< Content buffer */
} pjmedia_rtcp_xr_pkt;
#pragma pack()

View File

@ -231,6 +231,26 @@ PJ_DECL(pj_status_t) pjmedia_session_resume_stream(pjmedia_session *session,
unsigned index,
pjmedia_dir dir);
/**
* Send RTCP SDES for the session.
*
* @param session The media session.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t)
pjmedia_session_send_rtcp_sdes( const pjmedia_session *session );
/**
* Send RTCP BYE for the session.
*
* @param session The media session.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t)
pjmedia_session_send_rtcp_bye( const pjmedia_session *session );
/**
* Enumerate media streams in the session.
*

View File

@ -75,6 +75,8 @@ enum pjmedia_snd_port_option
/**
* This structure specifies the parameters to create the sound port.
* Use pjmedia_snd_port_param_default() to initialize this structure with
* default values (mostly zeroes)
*/
typedef struct pjmedia_snd_port_param
{
@ -87,8 +89,21 @@ typedef struct pjmedia_snd_port_param
* Sound port creation options.
*/
unsigned options;
/**
* Echo cancellation options/flags.
*/
unsigned ec_options;
} pjmedia_snd_port_param;
/**
* Initialize pjmedia_snd_port_param with default values.
*
* @param prm The parameter.
*/
PJ_DECL(void) pjmedia_snd_port_param_default(pjmedia_snd_port_param *prm);
/**
* This opaque type describes sound device port connection.
* Sound device port is not a media port, but it is used to connect media

View File

@ -133,6 +133,9 @@ struct pjmedia_stream_info
(see #PJMEDIA_STREAM_ENABLE_KA)
is enabled? */
#endif
pj_bool_t rtcp_sdes_bye_disabled;
/**< Disable automatic sending of RTCP
SDES and BYE. */
};
@ -371,6 +374,26 @@ pjmedia_stream_set_dtmf_callback(pjmedia_stream *stream,
int digit),
void *user_data);
/**
* Send RTCP SDES for the media stream.
*
* @param stream The media stream.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t)
pjmedia_stream_send_rtcp_sdes( pjmedia_stream *stream );
/**
* Send RTCP BYE for the media stream.
*
* @param stream The media stream.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t)
pjmedia_stream_send_rtcp_bye( pjmedia_stream *stream );
/**
* @}
*/

View File

@ -533,7 +533,7 @@ PJ_INLINE(void) pjmedia_transport_info_init(pjmedia_transport_info *info)
* for example to fill in the "c=" and "m=" line of local SDP.
*
* @param tp The transport.
* @param info Media socket info to be initialized.
* @param info Media transport info to be initialized.
*
* @return PJ_SUCCESS on success.
*/
@ -547,6 +547,29 @@ PJ_INLINE(pj_status_t) pjmedia_transport_get_info(pjmedia_transport *tp,
}
/**
* Utility API to get transport type specific info from the specified media
* transport info.
*
* @param info Media transport info.
* @param type Media transport type.
*
* @return Pointer to media transport specific info, or NULL if
* specific info for the transport type is not found.
*/
PJ_INLINE(void*) pjmedia_transport_info_get_spc_info(
pjmedia_transport_info *info,
pjmedia_transport_type type)
{
unsigned i;
for (i = 0; i < info->specific_info_cnt; ++i) {
if (info->spc_info[i].type == type)
return (void*)info->spc_info[i].buffer;
}
return NULL;
}
/**
* Attach callbacks to be called on receipt of incoming RTP/RTCP packets.
* This is just a simple wrapper which calls <tt>attach()</tt> member of

View File

@ -49,15 +49,18 @@ PJ_BEGIN_DECL
* @param endpt The media endpoint.
* @param name Optional name to identify this media transport
* for logging purposes.
* @param transport The underlying media transport to send and receive
* RTP/RTCP packets.
* @param base_tp The base/underlying media transport to send and
* receive RTP/RTCP packets.
* @param del_base Specify whether the base transport should also be
* destroyed when destroy() is called upon us.
* @param p_tp Pointer to receive the media transport instance.
*
* @return PJ_SUCCESS on success, or the appropriate error code.
*/
PJ_DECL(pj_status_t) pjmedia_tp_adapter_create( pjmedia_endpt *endpt,
const char *name,
pjmedia_transport *transport,
pjmedia_transport *base_tp,
pj_bool_t del_base,
pjmedia_transport **p_tp);
PJ_END_DECL

View File

@ -200,8 +200,12 @@ typedef struct pjmedia_srtp_info
* will also invoke this function. This function will also register SRTP
* library deinitialization to #pj_atexit(), so the deinitialization
* of SRTP library will be performed automatically by PJLIB destructor.
*
* @param endpt The media endpoint instance.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t) pjmedia_srtp_init_lib(void);
PJ_DECL(pj_status_t) pjmedia_srtp_init_lib(pjmedia_endpt *endpt);
/**

View File

@ -232,7 +232,7 @@ static pj_status_t add_dev (struct alsa_factory *af, const char *dev_name)
pj_bzero(adi, sizeof(*adi));
/* Set device name */
strcpy(adi->name, dev_name);
strncpy(adi->name, dev_name, sizeof(adi->name));
/* Check the number of playback channels */
adi->output_count = (pb_result>=0) ? 1 : 0;
@ -547,6 +547,7 @@ static pj_status_t open_playback (struct alsa_stream* stream,
int result;
unsigned int rate;
snd_pcm_uframes_t tmp_buf_size;
snd_pcm_uframes_t tmp_period_size;
if (param->play_id < 0 || param->play_id >= stream->af->dev_cnt)
return PJMEDIA_EAUD_INVDEV;
@ -613,10 +614,11 @@ static pj_status_t open_playback (struct alsa_stream* stream,
param->channel_count;
TRACE_((THIS_FILE, "open_playback: set period size: %d",
stream->pb_frames));
tmp_period_size = stream->pb_frames;
snd_pcm_hw_params_set_period_size_near (stream->pb_pcm, params,
&stream->pb_frames, NULL);
&tmp_period_size, NULL);
TRACE_((THIS_FILE, "open_playback: period size set to: %d",
stream->pb_frames));
tmp_period_size));
/* Set the sound device buffer size and latency */
if (param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY)
@ -663,6 +665,7 @@ static pj_status_t open_capture (struct alsa_stream* stream,
int result;
unsigned int rate;
snd_pcm_uframes_t tmp_buf_size;
snd_pcm_uframes_t tmp_period_size;
if (param->rec_id < 0 || param->rec_id >= stream->af->dev_cnt)
return PJMEDIA_EAUD_INVDEV;
@ -729,10 +732,11 @@ static pj_status_t open_capture (struct alsa_stream* stream,
param->channel_count;
TRACE_((THIS_FILE, "open_capture: set period size: %d",
stream->ca_frames));
tmp_period_size = stream->ca_frames;
snd_pcm_hw_params_set_period_size_near (stream->ca_pcm, params,
&stream->ca_frames, NULL);
&tmp_period_size, NULL);
TRACE_((THIS_FILE, "open_capture: period size set to: %d",
stream->ca_frames));
tmp_period_size));
/* Set the sound device buffer size and latency */
if (param->flags & PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY)

View File

@ -145,7 +145,7 @@ PJ_DEF(const char*) pjmedia_aud_dev_cap_name(pjmedia_aud_dev_cap cap,
break;
}
if (i==32) {
if (i==PJ_ARRAY_SIZE(cap_infos)) {
*p_desc = "??";
return "??";
}
@ -488,11 +488,13 @@ PJ_DEF(pj_status_t) pjmedia_aud_subsys_shutdown(void)
}
--aud_subsys.init_count;
for (i=0; i<aud_subsys.drv_cnt; ++i) {
deinit_driver(i);
}
if (aud_subsys.init_count == 0) {
for (i=0; i<aud_subsys.drv_cnt; ++i) {
deinit_driver(i);
}
aud_subsys.pf = NULL;
aud_subsys.pf = NULL;
}
return PJ_SUCCESS;
}

View File

@ -1111,7 +1111,17 @@ static void interruptionListener(void *inClientData, UInt32 inInterruption)
{
struct stream_list *it, *itBegin;
pj_status_t status;
pj_thread_desc thread_desc;
pj_thread_t *thread;
/* Register the thread with PJLIB, this is must for any external threads
* which need to use the PJLIB framework.
*/
if (!pj_thread_is_registered()) {
pj_bzero(thread_desc, sizeof(pj_thread_desc));
status = pj_thread_register("intListener", thread_desc, &thread);
}
PJ_LOG(3, (THIS_FILE, "Session interrupted! --- %s ---",
inInterruption == kAudioSessionBeginInterruption ?
"Begin Interruption" : "End Interruption"));
@ -1954,6 +1964,11 @@ static pj_status_t ca_stream_set_cap(pjmedia_aud_stream *s,
strm->cf->io_comp = io_comp;
strm->param.ec_enabled = *(pj_bool_t*)pval;
PJ_LOG(4, (THIS_FILE, "Using %s audio unit",
(desc.componentSubType ==
kAudioUnitSubType_RemoteIO? "RemoteIO":
"VoiceProcessingIO")));
return PJ_SUCCESS;
}
#endif

View File

@ -1086,7 +1086,7 @@ static void PlayCb(TAPSCommBuffer &buf, void *user_data)
buf.iBuffer.Append((TUint8*)sf->data, len);
} else {
enum {NO_DATA_FT = 15 };
pj_uint8_t amr_header = 4 || (NO_DATA_FT << 3);
pj_uint8_t amr_header = 4 | (NO_DATA_FT << 3);
buf.iBuffer.Append(amr_header);
}
@ -1095,7 +1095,7 @@ static void PlayCb(TAPSCommBuffer &buf, void *user_data)
} else { /* PJMEDIA_FRAME_TYPE_NONE */
enum {NO_DATA_FT = 15 };
pj_uint8_t amr_header = 4 || (NO_DATA_FT << 3);
pj_uint8_t amr_header = 4 | (NO_DATA_FT << 3);
buf.iBuffer.Append(amr_header);

View File

@ -239,6 +239,7 @@ private:
TPtr8 iFramePtr_;
TInt lastError_;
pj_uint32_t timeStamp_;
CActiveSchedulerWait startAsw_;
// cache variable
// to avoid calculating frame length repeatedly
@ -363,6 +364,13 @@ pj_status_t CPjAudioInputEngine::StartRecord()
lastError_ = KRequestPending;
iInputStream_->Open(&iStreamSettings);
#if defined(PJMEDIA_AUDIO_DEV_MDA_USE_SYNC_START) && \
PJMEDIA_AUDIO_DEV_MDA_USE_SYNC_START != 0
startAsw_.Start();
#endif
// Success
PJ_LOG(4,(THIS_FILE, "Sound capture started."));
return PJ_SUCCESS;
@ -386,6 +394,10 @@ void CPjAudioInputEngine::Stop()
iInputStream_ = NULL;
}
if (startAsw_.IsStarted()) {
startAsw_.AsyncStop();
}
state_ = STATE_INACTIVE;
}
@ -399,12 +411,25 @@ TPtr8 & CPjAudioInputEngine::GetFrame()
void CPjAudioInputEngine::MaiscOpenComplete(TInt aError)
{
if (startAsw_.IsStarted()) {
startAsw_.AsyncStop();
}
lastError_ = aError;
if (aError != KErrNone) {
snd_perror("Error in MaiscOpenComplete()", aError);
return;
}
/* Apply input volume setting if specified */
if (parentStrm_->param.flags &
PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING)
{
stream_set_cap(&parentStrm_->base,
PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING,
&parentStrm_->param.input_vol);
}
// set stream priority to normal and time sensitive
iInputStream_->SetPriority(EPriorityNormal,
EMdaPriorityPreferenceTime);
@ -414,7 +439,12 @@ void CPjAudioInputEngine::MaiscOpenComplete(TInt aError)
TRAPD(err2, iInputStream_->ReadL(frm));
if (err2) {
PJ_LOG(4,(THIS_FILE, "Exception in iInputStream_->ReadL()"));
lastError_ = err2;
return;
}
// input stream opened succesfully, set status to Active
state_ = STATE_ACTIVE;
}
void CPjAudioInputEngine::MaiscBufferCopied(TInt aError,
@ -547,6 +577,7 @@ private:
TPtrC8 frame_;
TInt lastError_;
unsigned timestamp_;
CActiveSchedulerWait startAsw_;
CPjAudioOutputEngine(struct mda_stream *parent_strm,
pjmedia_aud_play_cb play_cb,
@ -638,6 +669,13 @@ pj_status_t CPjAudioOutputEngine::StartPlay()
// Open stream.
lastError_ = KRequestPending;
iOutputStream_->Open(&iStreamSettings);
#if defined(PJMEDIA_AUDIO_DEV_MDA_USE_SYNC_START) && \
PJMEDIA_AUDIO_DEV_MDA_USE_SYNC_START != 0
startAsw_.Start();
#endif
// Success
PJ_LOG(4,(THIS_FILE, "Sound playback started"));
@ -662,17 +700,22 @@ void CPjAudioOutputEngine::Stop()
iOutputStream_ = NULL;
}
if (startAsw_.IsStarted()) {
startAsw_.AsyncStop();
}
state_ = STATE_INACTIVE;
}
void CPjAudioOutputEngine::MaoscOpenComplete(TInt aError)
{
if (startAsw_.IsStarted()) {
startAsw_.AsyncStop();
}
lastError_ = aError;
if (aError==KErrNone) {
// output stream opened succesfully, set status to Active
state_ = STATE_ACTIVE;
// set stream properties, 16bit 8KHz mono
TMdaAudioDataSettings iSettings;
iSettings.iChannels =
@ -683,8 +726,17 @@ void CPjAudioOutputEngine::MaoscOpenComplete(TInt aError)
iOutputStream_->SetAudioPropertiesL(iSettings.iSampleRate,
iSettings.iChannels);
// set volume to 1/2th of stream max volume
iOutputStream_->SetVolume(iOutputStream_->MaxVolume()/2);
/* Apply output volume setting if specified */
if (parentStrm_->param.flags &
PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING)
{
stream_set_cap(&parentStrm_->base,
PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING,
&parentStrm_->param.output_vol);
} else {
// set volume to 1/2th of stream max volume
iOutputStream_->SetVolume(iOutputStream_->MaxVolume()/2);
}
// set stream priority to normal and time sensitive
iOutputStream_->SetPriority(EPriorityNormal,
@ -718,6 +770,9 @@ void CPjAudioOutputEngine::MaoscOpenComplete(TInt aError)
// until whole data buffer is written.
frame_.Set(frameBuf_, frameBufSize_);
iOutputStream_->WriteL(frame_);
// output stream opened succesfully, set status to Active
state_ = STATE_ACTIVE;
} else {
snd_perror("Error in MaoscOpenComplete()", aError);
}
@ -881,7 +936,8 @@ static pj_status_t factory_default_param(pjmedia_aud_dev_factory *f,
param->channel_count = 1;
param->samples_per_frame = af->dev_info.default_samples_per_sec * 20 / 1000;
param->bits_per_sample = BITS_PER_SAMPLE;
param->flags = af->dev_info.caps;
// Don't set the flags without specifying the flags value.
//param->flags = af->dev_info.caps;
return PJ_SUCCESS;
}
@ -956,6 +1012,20 @@ static pj_status_t stream_get_param(pjmedia_aud_stream *s,
pj_memcpy(pi, &strm->param, sizeof(*pi));
/* Update the output volume setting */
if (stream_get_cap(s, PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING,
&pi->output_vol) == PJ_SUCCESS)
{
pi->flags |= PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING;
}
/* Update the input volume setting */
if (stream_get_cap(s, PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING,
&pi->input_vol) == PJ_SUCCESS)
{
pi->flags |= PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING;
}
return PJ_SUCCESS;
}
@ -1034,7 +1104,7 @@ static pj_status_t stream_set_cap(pjmedia_aud_stream *s,
}
break;
case PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING:
if (strm->param.dir & PJMEDIA_DIR_CAPTURE) {
if (strm->param.dir & PJMEDIA_DIR_PLAYBACK) {
PJ_ASSERT_RETURN(strm->out_engine, PJ_EINVAL);
TInt max_vol = strm->out_engine->GetMaxVolume();

View File

@ -1130,7 +1130,7 @@ static void PlayCb(CVoIPDataBuffer *buf, void *user_data)
buffer.Append((TUint8*)sf->data, len);
} else {
enum {NO_DATA_FT = 15 };
pj_uint8_t amr_header = 4 || (NO_DATA_FT << 3);
pj_uint8_t amr_header = 4 | (NO_DATA_FT << 3);
buffer.Append(amr_header);
}
@ -1139,7 +1139,7 @@ static void PlayCb(CVoIPDataBuffer *buf, void *user_data)
} else { /* PJMEDIA_FRAME_TYPE_NONE */
enum {NO_DATA_FT = 15 };
pj_uint8_t amr_header = 4 || (NO_DATA_FT << 3);
pj_uint8_t amr_header = 4 | (NO_DATA_FT << 3);
buffer.Append(amr_header);
@ -1746,12 +1746,6 @@ static pj_status_t factory_create_stream(pjmedia_aud_dev_factory *f,
return PJ_RETURN_OS_ERROR(err);
}
/* Apply output volume setting if specified */
if (param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING) {
stream_set_cap(&strm->base, PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING,
&param->output_vol);
}
/* Done */
strm->base.op = &stream_op;
*p_aud_strm = &strm->base;
@ -1945,10 +1939,21 @@ static pj_status_t stream_start(pjmedia_aud_stream *strm)
} while (!stream->engine->IsStarted() &&
(now.MicroSecondsFrom(start) < VAS_WAIT_START * 1000));
if (stream->engine->IsStarted())
if (stream->engine->IsStarted()) {
/* Apply output volume setting if specified */
if (stream->param.flags &
PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING)
{
stream_set_cap(strm,
PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING,
&stream->param.output_vol);
}
return PJ_SUCCESS;
else
} else {
return PJ_ETIMEDOUT;
}
}
return PJ_EINVALIDOP;

View File

@ -748,15 +748,14 @@ static pj_status_t codec_encode( pjmedia_codec *codec,
struct pjmedia_frame *output)
{
codec_private_t *codec_data = (codec_private_t*) codec->codec_data;
const Word16 *pcm_input;
Word16 mlt_coefs[MAX_SAMPLES_PER_FRAME];
Word16 mag_shift;
unsigned nsamples, processed;
/* Check frame in & out size */
PJ_ASSERT_RETURN((pj_uint16_t)input->size ==
(codec_data->samples_per_frame<<1),
PJMEDIA_CODEC_EPCMTOOSHORT);
PJ_ASSERT_RETURN(output_buf_len >= codec_data->frame_size,
nsamples = input->size >> 1;
PJ_ASSERT_RETURN(nsamples % codec_data->samples_per_frame == 0,
PJMEDIA_CODEC_EPCMFRMINLEN);
PJ_ASSERT_RETURN(output_buf_len >= codec_data->frame_size * nsamples /
codec_data->samples_per_frame,
PJMEDIA_CODEC_EFRMTOOSHORT);
/* Apply silence detection if VAD is enabled */
@ -788,41 +787,52 @@ static pj_status_t codec_encode( pjmedia_codec *codec,
}
}
/* Encoder adjust the input signal level */
if (codec_data->pcm_shift) {
unsigned i;
pcm_input = (const Word16*)input->buf;
for (i=0; i<codec_data->samples_per_frame; ++i) {
codec_data->enc_frame[i] =
(pj_int16_t)(pcm_input[i] >> codec_data->pcm_shift);
processed = 0;
output->size = 0;
while (processed < nsamples) {
Word16 mlt_coefs[MAX_SAMPLES_PER_FRAME];
Word16 mag_shift;
const Word16 *pcm_input;
pj_int8_t *out_bits;
pcm_input = (const Word16*)input->buf + processed;
out_bits = (pj_int8_t*)output->buf + output->size;
/* Encoder adjust the input signal level */
if (codec_data->pcm_shift) {
unsigned i;
for (i=0; i<codec_data->samples_per_frame; ++i) {
codec_data->enc_frame[i] =
(Word16)(pcm_input[i] >> codec_data->pcm_shift);
}
pcm_input = codec_data->enc_frame;
}
pcm_input = codec_data->enc_frame;
} else {
pcm_input = (const Word16*)input->buf;
/* Convert input samples to rmlt coefs */
mag_shift = samples_to_rmlt_coefs(pcm_input,
codec_data->enc_old_frame,
mlt_coefs,
codec_data->samples_per_frame);
/* Encode the mlt coefs. Note that encoder output stream is
* 16 bit array, so we need to take care about endianness.
*/
encoder(codec_data->frame_size_bits,
codec_data->number_of_regions,
mlt_coefs,
mag_shift,
(Word16*)out_bits);
/* Encoder output are in native host byte order, while ITU says
* it must be in network byte order (MSB first).
*/
swap_bytes((pj_uint16_t*)out_bits, codec_data->frame_size/2);
processed += codec_data->samples_per_frame;
output->size += codec_data->frame_size;
}
/* Convert input samples to rmlt coefs */
mag_shift = samples_to_rmlt_coefs(pcm_input,
codec_data->enc_old_frame,
mlt_coefs,
codec_data->samples_per_frame);
/* Encode the mlt coefs. Note that encoder output stream is 16 bit array,
* so we need to take care about endianness.
*/
encoder(codec_data->frame_size_bits,
codec_data->number_of_regions,
mlt_coefs,
mag_shift,
output->buf);
/* Encoder output are in native host byte order, while ITU says
* it must be in network byte order (MSB first).
*/
swap_bytes((pj_uint16_t*)output->buf, codec_data->frame_size/2);
output->type = PJMEDIA_FRAME_TYPE_AUDIO;
output->size = codec_data->frame_size;
output->timestamp = input->timestamp;
return PJ_SUCCESS;

View File

@ -42,6 +42,7 @@
#define THIS_FILE "ipp_codecs.c"
/* Prototypes for IPP codecs factory */
static pj_status_t ipp_test_alloc( pjmedia_codec_factory *factory,
const pjmedia_codec_info *id );
@ -237,9 +238,8 @@ static struct ipp_codec {
ipp_codec[] =
{
# if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR
/* AMR-NB SID seems to produce noise, so let's just disable its VAD. */
{1, "AMR", PJMEDIA_RTP_PT_AMR, &USC_GSMAMR_Fxns, 8000, 1, 160,
7400, 12200, 2, 0, 1,
7400, 12200, 2, 1, 1,
&predecode_amr, &parse_amr, &pack_amr,
{1, {{{"octet-align", 11}, {"1", 1}}} }
},
@ -247,7 +247,7 @@ ipp_codec[] =
# if PJMEDIA_HAS_INTEL_IPP_CODEC_AMRWB
{1, "AMR-WB", PJMEDIA_RTP_PT_AMRWB, &USC_AMRWB_Fxns, 16000, 1, 320,
15850, 23850, 1, 1, 1,
15850, 23850, 2, 1, 1,
&predecode_amr, &parse_amr, &pack_amr,
{1, {{{"octet-align", 11}, {"1", 1}}} }
},
@ -437,7 +437,7 @@ static pj_status_t parse_g723(ipp_private_t *codec_data, void *pkt,
#endif /* PJMEDIA_HAS_INTEL_IPP_CODEC_G723_1 */
#if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR
#if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR || PJMEDIA_HAS_INTEL_IPP_CODEC_AMRWB
#include <pjmedia-codec/amr_helper.h>
@ -487,9 +487,7 @@ static void predecode_amr( ipp_private_t *codec_data,
} else if (frame.size == 5) {
/* SID */
if (info->good_quality) {
pj_bool_t STI;
STI = (((pj_uint8_t*)frame.buf)[35 >> 3] & 0x10) != 0;
usc_frame->frametype = STI? 2 : 1;
usc_frame->frametype = info->STI? 2 : 1;
} else {
usc_frame->frametype = setting->amr_nb ? 6 : 7;
}
@ -511,8 +509,11 @@ static pj_status_t pack_amr(ipp_private_t *codec_data, void *pkt,
pj_uint8_t *r; /* Read cursor */
pj_uint8_t SID_FT;
pjmedia_codec_amr_pack_setting *setting;
const pj_uint8_t *framelen_tbl;
setting = &((amr_settings_t*)codec_data->codec_setting)->enc_setting;
framelen_tbl = setting->amr_nb? pjmedia_codec_amrnb_framelen:
pjmedia_codec_amrwb_framelen;
SID_FT = (pj_uint8_t)(setting->amr_nb? 8 : 9);
@ -533,11 +534,11 @@ static pj_status_t pack_amr(ipp_private_t *codec_data, void *pkt,
info->frame_type = (pj_uint8_t)(info_ & 0x0F);
info->good_quality = (pj_uint8_t)((info_ & 0x80) == 0);
info->mode = (pj_int8_t) ((info_ >> 8) & 0x0F);
info->STI = (pj_uint8_t)((info_ >> 5) & 1);
frames[nframes].buf = r + 2;
frames[nframes].size = info->frame_type <= SID_FT ?
pjmedia_codec_amrnb_framelen[info->frame_type] :
0;
framelen_tbl[info->frame_type] : 0;
r += frames[nframes].size + 2;
@ -1418,6 +1419,7 @@ static pj_status_t ipp_codec_encode( pjmedia_codec *codec,
/* Two octets for AMR frame info, 0=LSB:
* bit 0-3 : frame type
* bit 5 : STI flag
* bit 6 : last frame flag
* bit 7 : quality flag
* bit 8-11 : mode
@ -1441,6 +1443,9 @@ static pj_status_t ipp_codec_encode( pjmedia_codec *codec,
/* Quality */
if (out.frametype == 6 || out.frametype == 7)
*info |= 0x80;
/* STI */
if (out.frametype != 1)
*info |= 0x20;
} else {
/* Untransmited */
*info = 15;

View File

@ -0,0 +1,820 @@
/* $Id */
/*
* Copyright (C) 2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2011 Dan Arrhenius <dan@keystream.se>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* AMR-NB codec implementation with OpenCORE AMRNB library
*/
#include <pjmedia-codec/g722.h>
#include <pjmedia/codec.h>
#include <pjmedia/errno.h>
#include <pjmedia/endpoint.h>
#include <pjmedia/plc.h>
#include <pjmedia/port.h>
#include <pjmedia/silencedet.h>
#include <pj/assert.h>
#include <pj/log.h>
#include <pj/pool.h>
#include <pj/string.h>
#include <pj/os.h>
#include <pj/math.h>
#if defined(PJMEDIA_HAS_OPENCORE_AMRNB_CODEC) && \
(PJMEDIA_HAS_OPENCORE_AMRNB_CODEC != 0)
#include <opencore-amrnb/interf_enc.h>
#include <opencore-amrnb/interf_dec.h>
#include <pjmedia-codec/amr_helper.h>
#include <pjmedia-codec/opencore_amrnb.h>
#define THIS_FILE "opencore_amrnb.c"
/* Tracing */
#define PJ_TRACE 0
#if PJ_TRACE
# define TRACE_(expr) PJ_LOG(4,expr)
#else
# define TRACE_(expr)
#endif
/* Use PJMEDIA PLC */
#define USE_PJMEDIA_PLC 1
/* Prototypes for AMR-NB factory */
static pj_status_t amr_test_alloc(pjmedia_codec_factory *factory,
const pjmedia_codec_info *id );
static pj_status_t amr_default_attr(pjmedia_codec_factory *factory,
const pjmedia_codec_info *id,
pjmedia_codec_param *attr );
static pj_status_t amr_enum_codecs(pjmedia_codec_factory *factory,
unsigned *count,
pjmedia_codec_info codecs[]);
static pj_status_t amr_alloc_codec(pjmedia_codec_factory *factory,
const pjmedia_codec_info *id,
pjmedia_codec **p_codec);
static pj_status_t amr_dealloc_codec(pjmedia_codec_factory *factory,
pjmedia_codec *codec );
/* Prototypes for AMR-NB implementation. */
static pj_status_t amr_codec_init(pjmedia_codec *codec,
pj_pool_t *pool );
static pj_status_t amr_codec_open(pjmedia_codec *codec,
pjmedia_codec_param *attr );
static pj_status_t amr_codec_close(pjmedia_codec *codec );
static pj_status_t amr_codec_modify(pjmedia_codec *codec,
const pjmedia_codec_param *attr );
static pj_status_t amr_codec_parse(pjmedia_codec *codec,
void *pkt,
pj_size_t pkt_size,
const pj_timestamp *ts,
unsigned *frame_cnt,
pjmedia_frame frames[]);
static pj_status_t amr_codec_encode(pjmedia_codec *codec,
const struct pjmedia_frame *input,
unsigned output_buf_len,
struct pjmedia_frame *output);
static pj_status_t amr_codec_decode(pjmedia_codec *codec,
const struct pjmedia_frame *input,
unsigned output_buf_len,
struct pjmedia_frame *output);
static pj_status_t amr_codec_recover(pjmedia_codec *codec,
unsigned output_buf_len,
struct pjmedia_frame *output);
/* Definition for AMR-NB codec operations. */
static pjmedia_codec_op amr_op =
{
&amr_codec_init,
&amr_codec_open,
&amr_codec_close,
&amr_codec_modify,
&amr_codec_parse,
&amr_codec_encode,
&amr_codec_decode,
&amr_codec_recover
};
/* Definition for AMR-NB codec factory operations. */
static pjmedia_codec_factory_op amr_factory_op =
{
&amr_test_alloc,
&amr_default_attr,
&amr_enum_codecs,
&amr_alloc_codec,
&amr_dealloc_codec
};
/* AMR-NB factory */
static struct amr_codec_factory
{
pjmedia_codec_factory base;
pjmedia_endpt *endpt;
pj_pool_t *pool;
} amr_codec_factory;
/* AMR-NB codec private data. */
struct amr_data
{
pj_pool_t *pool;
void *encoder;
void *decoder;
pj_bool_t plc_enabled;
pj_bool_t vad_enabled;
int enc_mode;
pjmedia_codec_amr_pack_setting enc_setting;
pjmedia_codec_amr_pack_setting dec_setting;
#if USE_PJMEDIA_PLC
pjmedia_plc *plc;
#endif
pj_timestamp last_tx;
};
static pjmedia_codec_amrnb_config def_config =
{
PJ_FALSE, /* octet align */
5900 /* bitrate */
};
/*
* Initialize and register AMR-NB codec factory to pjmedia endpoint.
*/
PJ_DEF(pj_status_t) pjmedia_codec_opencore_amrnb_init( pjmedia_endpt *endpt )
{
pjmedia_codec_mgr *codec_mgr;
pj_status_t status;
if (amr_codec_factory.pool != NULL)
return PJ_SUCCESS;
/* Create AMR-NB codec factory. */
amr_codec_factory.base.op = &amr_factory_op;
amr_codec_factory.base.factory_data = NULL;
amr_codec_factory.endpt = endpt;
amr_codec_factory.pool = pjmedia_endpt_create_pool(endpt, "amrnb", 1000,
1000);
if (!amr_codec_factory.pool)
return PJ_ENOMEM;
/* Get the codec manager. */
codec_mgr = pjmedia_endpt_get_codec_mgr(endpt);
if (!codec_mgr) {
status = PJ_EINVALIDOP;
goto on_error;
}
/* Register codec factory to endpoint. */
status = pjmedia_codec_mgr_register_factory(codec_mgr,
&amr_codec_factory.base);
if (status != PJ_SUCCESS)
goto on_error;
/* Done. */
return PJ_SUCCESS;
on_error:
pj_pool_release(amr_codec_factory.pool);
amr_codec_factory.pool = NULL;
return status;
}
/*
* Unregister AMR-NB codec factory from pjmedia endpoint and deinitialize
* the AMR-NB codec library.
*/
PJ_DEF(pj_status_t) pjmedia_codec_opencore_amrnb_deinit(void)
{
pjmedia_codec_mgr *codec_mgr;
pj_status_t status;
if (amr_codec_factory.pool == NULL)
return PJ_SUCCESS;
/* Get the codec manager. */
codec_mgr = pjmedia_endpt_get_codec_mgr(amr_codec_factory.endpt);
if (!codec_mgr) {
pj_pool_release(amr_codec_factory.pool);
amr_codec_factory.pool = NULL;
return PJ_EINVALIDOP;
}
/* Unregister AMR-NB codec factory. */
status = pjmedia_codec_mgr_unregister_factory(codec_mgr,
&amr_codec_factory.base);
/* Destroy pool. */
pj_pool_release(amr_codec_factory.pool);
amr_codec_factory.pool = NULL;
return status;
}
PJ_DEF(pj_status_t) pjmedia_codec_opencore_amrnb_set_config(
const pjmedia_codec_amrnb_config *config)
{
unsigned nbitrates;
def_config = *config;
/* Normalize bitrate. */
nbitrates = PJ_ARRAY_SIZE(pjmedia_codec_amrnb_bitrates);
if (def_config.bitrate < pjmedia_codec_amrnb_bitrates[0])
def_config.bitrate = pjmedia_codec_amrnb_bitrates[0];
else if (def_config.bitrate > pjmedia_codec_amrnb_bitrates[nbitrates-1])
def_config.bitrate = pjmedia_codec_amrnb_bitrates[nbitrates-1];
else
{
unsigned i;
for (i = 0; i < nbitrates; ++i) {
if (def_config.bitrate <= pjmedia_codec_amrnb_bitrates[i])
break;
}
def_config.bitrate = pjmedia_codec_amrnb_bitrates[i];
}
return PJ_SUCCESS;
}
/*
* Check if factory can allocate the specified codec.
*/
static pj_status_t amr_test_alloc( pjmedia_codec_factory *factory,
const pjmedia_codec_info *info )
{
PJ_UNUSED_ARG(factory);
/* Check payload type. */
if (info->pt != PJMEDIA_RTP_PT_AMR)
return PJMEDIA_CODEC_EUNSUP;
/* Ignore the rest, since it's static payload type. */
return PJ_SUCCESS;
}
/*
* Generate default attribute.
*/
static pj_status_t amr_default_attr( pjmedia_codec_factory *factory,
const pjmedia_codec_info *id,
pjmedia_codec_param *attr )
{
PJ_UNUSED_ARG(factory);
PJ_UNUSED_ARG(id);
pj_bzero(attr, sizeof(pjmedia_codec_param));
attr->info.clock_rate = 8000;
attr->info.channel_cnt = 1;
attr->info.avg_bps = def_config.bitrate;
attr->info.max_bps = pjmedia_codec_amrnb_bitrates[7];
attr->info.pcm_bits_per_sample = 16;
attr->info.frm_ptime = 20;
attr->info.pt = PJMEDIA_RTP_PT_AMR;
attr->setting.frm_per_pkt = 2;
attr->setting.vad = 1;
attr->setting.plc = 1;
if (def_config.octet_align) {
attr->setting.dec_fmtp.cnt = 1;
attr->setting.dec_fmtp.param[0].name = pj_str("octet-align");
attr->setting.dec_fmtp.param[0].val = pj_str("1");
}
/* Default all other flag bits disabled. */
return PJ_SUCCESS;
}
/*
* Enum codecs supported by this factory (i.e. only AMR-NB!).
*/
static pj_status_t amr_enum_codecs( pjmedia_codec_factory *factory,
unsigned *count,
pjmedia_codec_info codecs[])
{
PJ_UNUSED_ARG(factory);
PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL);
pj_bzero(&codecs[0], sizeof(pjmedia_codec_info));
codecs[0].encoding_name = pj_str("AMR");
codecs[0].pt = PJMEDIA_RTP_PT_AMR;
codecs[0].type = PJMEDIA_TYPE_AUDIO;
codecs[0].clock_rate = 8000;
codecs[0].channel_cnt = 1;
*count = 1;
return PJ_SUCCESS;
}
/*
* Allocate a new AMR-NB codec instance.
*/
static pj_status_t amr_alloc_codec( pjmedia_codec_factory *factory,
const pjmedia_codec_info *id,
pjmedia_codec **p_codec)
{
pj_pool_t *pool;
pjmedia_codec *codec;
struct amr_data *amr_data;
pj_status_t status;
PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
PJ_ASSERT_RETURN(factory == &amr_codec_factory.base, PJ_EINVAL);
pool = pjmedia_endpt_create_pool(amr_codec_factory.endpt, "amrnb-inst",
512, 512);
codec = PJ_POOL_ZALLOC_T(pool, pjmedia_codec);
PJ_ASSERT_RETURN(codec != NULL, PJ_ENOMEM);
codec->op = &amr_op;
codec->factory = factory;
amr_data = PJ_POOL_ZALLOC_T(pool, struct amr_data);
codec->codec_data = amr_data;
amr_data->pool = pool;
#if USE_PJMEDIA_PLC
/* Create PLC */
status = pjmedia_plc_create(pool, 8000, 160, 0, &amr_data->plc);
if (status != PJ_SUCCESS) {
return status;
}
#else
PJ_UNUSED_ARG(status);
#endif
*p_codec = codec;
return PJ_SUCCESS;
}
/*
* Free codec.
*/
static pj_status_t amr_dealloc_codec( pjmedia_codec_factory *factory,
pjmedia_codec *codec )
{
struct amr_data *amr_data;
PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL);
PJ_ASSERT_RETURN(factory == &amr_codec_factory.base, PJ_EINVAL);
amr_data = (struct amr_data*) codec->codec_data;
/* Close codec, if it's not closed. */
amr_codec_close(codec);
pj_pool_release(amr_data->pool);
amr_data = NULL;
return PJ_SUCCESS;
}
/*
* Init codec.
*/
static pj_status_t amr_codec_init( pjmedia_codec *codec,
pj_pool_t *pool )
{
PJ_UNUSED_ARG(codec);
PJ_UNUSED_ARG(pool);
return PJ_SUCCESS;
}
/*
* Open codec.
*/
static pj_status_t amr_codec_open( pjmedia_codec *codec,
pjmedia_codec_param *attr )
{
struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
pjmedia_codec_amr_pack_setting *setting;
unsigned i;
pj_uint8_t octet_align = 0;
pj_int8_t enc_mode;
const pj_str_t STR_FMTP_OCTET_ALIGN = {"octet-align", 11};
PJ_ASSERT_RETURN(codec && attr, PJ_EINVAL);
PJ_ASSERT_RETURN(amr_data != NULL, PJ_EINVALIDOP);
enc_mode = pjmedia_codec_amr_get_mode(attr->info.avg_bps);
pj_assert(enc_mode >= 0 && enc_mode <= 7);
/* Check octet-align */
for (i = 0; i < attr->setting.dec_fmtp.cnt; ++i) {
if (pj_stricmp(&attr->setting.dec_fmtp.param[i].name,
&STR_FMTP_OCTET_ALIGN) == 0)
{
octet_align = (pj_uint8_t)
(pj_strtoul(&attr->setting.dec_fmtp.param[i].val));
break;
}
}
/* Check mode-set */
for (i = 0; i < attr->setting.enc_fmtp.cnt; ++i) {
const pj_str_t STR_FMTP_MODE_SET = {"mode-set", 8};
if (pj_stricmp(&attr->setting.enc_fmtp.param[i].name,
&STR_FMTP_MODE_SET) == 0)
{
const char *p;
pj_size_t l;
pj_int8_t diff = 99;
/* Encoding mode is chosen based on local default mode setting:
* - if local default mode is included in the mode-set, use it
* - otherwise, find the closest mode to local default mode;
* if there are two closest modes, prefer to use the higher
* one, e.g: local default mode is 4, the mode-set param
* contains '2,3,5,6', then 5 will be chosen.
*/
p = pj_strbuf(&attr->setting.enc_fmtp.param[i].val);
l = pj_strlen(&attr->setting.enc_fmtp.param[i].val);
while (l--) {
if (*p>='0' && *p<='7') {
pj_int8_t tmp = *p - '0' - enc_mode;
if (PJ_ABS(diff) > PJ_ABS(tmp) ||
(PJ_ABS(diff) == PJ_ABS(tmp) && tmp > diff))
{
diff = tmp;
if (diff == 0) break;
}
}
++p;
}
PJ_ASSERT_RETURN(diff != 99, PJMEDIA_CODEC_EFAILED);
enc_mode = enc_mode + diff;
break;
}
}
amr_data->vad_enabled = (attr->setting.vad != 0);
amr_data->plc_enabled = (attr->setting.plc != 0);
amr_data->enc_mode = enc_mode;
amr_data->encoder = Encoder_Interface_init(amr_data->vad_enabled);
if (amr_data->encoder == NULL) {
TRACE_((THIS_FILE, "Encoder_Interface_init() failed"));
amr_codec_close(codec);
return PJMEDIA_CODEC_EFAILED;
}
setting = &amr_data->enc_setting;
pj_bzero(setting, sizeof(pjmedia_codec_amr_pack_setting));
setting->amr_nb = 1;
setting->reorder = 0;
setting->octet_aligned = octet_align;
setting->cmr = 15;
amr_data->decoder = Decoder_Interface_init();
if (amr_data->decoder == NULL) {
TRACE_((THIS_FILE, "Decoder_Interface_init() failed"));
amr_codec_close(codec);
return PJMEDIA_CODEC_EFAILED;
}
setting = &amr_data->dec_setting;
pj_bzero(setting, sizeof(pjmedia_codec_amr_pack_setting));
setting->amr_nb = 1;
setting->reorder = 0;
setting->octet_aligned = octet_align;
TRACE_((THIS_FILE, "AMR-NB codec allocated: vad=%d, plc=%d, bitrate=%d",
amr_data->vad_enabled, amr_data->plc_enabled,
pjmedia_codec_amrnb_bitrates[amr_data->enc_mode]));
return PJ_SUCCESS;
}
/*
* Close codec.
*/
static pj_status_t amr_codec_close( pjmedia_codec *codec )
{
struct amr_data *amr_data;
PJ_ASSERT_RETURN(codec, PJ_EINVAL);
amr_data = (struct amr_data*) codec->codec_data;
PJ_ASSERT_RETURN(amr_data != NULL, PJ_EINVALIDOP);
if (amr_data->encoder) {
Encoder_Interface_exit(amr_data->encoder);
amr_data->encoder = NULL;
}
if (amr_data->decoder) {
Decoder_Interface_exit(amr_data->decoder);
amr_data->decoder = NULL;
}
TRACE_((THIS_FILE, "AMR-NB codec closed"));
return PJ_SUCCESS;
}
/*
* Modify codec settings.
*/
static pj_status_t amr_codec_modify( pjmedia_codec *codec,
const pjmedia_codec_param *attr )
{
struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
pj_bool_t prev_vad_state;
pj_assert(amr_data != NULL);
pj_assert(amr_data->encoder != NULL && amr_data->decoder != NULL);
prev_vad_state = amr_data->vad_enabled;
amr_data->vad_enabled = (attr->setting.vad != 0);
amr_data->plc_enabled = (attr->setting.plc != 0);
if (prev_vad_state != amr_data->vad_enabled) {
/* Reinit AMR encoder to update VAD setting */
TRACE_((THIS_FILE, "Reiniting AMR encoder to update VAD setting."));
Encoder_Interface_exit(amr_data->encoder);
amr_data->encoder = Encoder_Interface_init(amr_data->vad_enabled);
if (amr_data->encoder == NULL) {
TRACE_((THIS_FILE, "Encoder_Interface_init() failed"));
amr_codec_close(codec);
return PJMEDIA_CODEC_EFAILED;
}
}
TRACE_((THIS_FILE, "AMR-NB codec modified: vad=%d, plc=%d",
amr_data->vad_enabled, amr_data->plc_enabled));
return PJ_SUCCESS;
}
/*
* Get frames in the packet.
*/
static pj_status_t amr_codec_parse( pjmedia_codec *codec,
void *pkt,
pj_size_t pkt_size,
const pj_timestamp *ts,
unsigned *frame_cnt,
pjmedia_frame frames[])
{
struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
pj_uint8_t cmr;
pj_status_t status;
status = pjmedia_codec_amr_parse(pkt, pkt_size, ts, &amr_data->dec_setting,
frames, frame_cnt, &cmr);
if (status != PJ_SUCCESS)
return status;
/* Check for Change Mode Request. */
if (cmr <= 7 && amr_data->enc_mode != cmr) {
amr_data->enc_mode = cmr;
TRACE_((THIS_FILE, "AMR-NB encoder switched mode to %d (%dbps)",
amr_data->enc_mode,
pjmedia_codec_amrnb_bitrates[amr_data->enc_mode]));
}
return PJ_SUCCESS;
}
/*
* Encode frame.
*/
static pj_status_t amr_codec_encode( pjmedia_codec *codec,
const struct pjmedia_frame *input,
unsigned output_buf_len,
struct pjmedia_frame *output)
{
struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
unsigned char *bitstream;
pj_int16_t *speech;
unsigned nsamples, samples_per_frame;
enum {MAX_FRAMES_PER_PACKET = 16};
pjmedia_frame frames[MAX_FRAMES_PER_PACKET];
pj_uint8_t *p;
unsigned i, out_size = 0, nframes = 0;
pj_size_t payload_len;
unsigned dtx_cnt, sid_cnt;
pj_status_t status;
int size;
pj_assert(amr_data != NULL);
PJ_ASSERT_RETURN(input && output, PJ_EINVAL);
nsamples = input->size >> 1;
samples_per_frame = 160;
PJ_ASSERT_RETURN(nsamples % samples_per_frame == 0,
PJMEDIA_CODEC_EPCMFRMINLEN);
nframes = nsamples / samples_per_frame;
PJ_ASSERT_RETURN(nframes <= MAX_FRAMES_PER_PACKET,
PJMEDIA_CODEC_EFRMTOOSHORT);
/* Encode the frames */
speech = (pj_int16_t*)input->buf;
bitstream = (unsigned char*)output->buf;
while (nsamples >= samples_per_frame) {
size = Encoder_Interface_Encode (amr_data->encoder, amr_data->enc_mode,
speech, bitstream, 0);
if (size == 0) {
output->size = 0;
output->buf = NULL;
output->type = PJMEDIA_FRAME_TYPE_NONE;
TRACE_((THIS_FILE, "AMR-NB encode() failed"));
return PJMEDIA_CODEC_EFAILED;
}
nsamples -= 160;
speech += samples_per_frame;
bitstream += size;
out_size += size;
TRACE_((THIS_FILE, "AMR-NB encode(): mode=%d, size=%d",
amr_data->enc_mode, out_size));
}
/* Pack payload */
p = (pj_uint8_t*)output->buf + output_buf_len - out_size;
pj_memmove(p, output->buf, out_size);
dtx_cnt = sid_cnt = 0;
for (i = 0; i < nframes; ++i) {
pjmedia_codec_amr_bit_info *info = (pjmedia_codec_amr_bit_info*)
&frames[i].bit_info;
info->frame_type = (pj_uint8_t)((*p >> 3) & 0x0F);
info->good_quality = (pj_uint8_t)((*p >> 2) & 0x01);
info->mode = (pj_int8_t)amr_data->enc_mode;
info->start_bit = 0;
frames[i].buf = p + 1;
frames[i].size = (info->frame_type <= 8)?
pjmedia_codec_amrnb_framelen[info->frame_type] : 0;
p += frames[i].size + 1;
/* Count the number of SID and DTX frames */
if (info->frame_type == 15) /* DTX*/
++dtx_cnt;
else if (info->frame_type == 8) /* SID */
++sid_cnt;
}
/* VA generates DTX frames as DTX+SID frames switching quickly and it
* seems that the SID frames occur too often (assuming the purpose is
* only for keeping NAT alive?). So let's modify the behavior a bit.
* Only an SID frame will be sent every PJMEDIA_CODEC_MAX_SILENCE_PERIOD
* milliseconds.
*/
if (sid_cnt + dtx_cnt == nframes) {
pj_int32_t dtx_duration;
dtx_duration = pj_timestamp_diff32(&amr_data->last_tx,
&input->timestamp);
if (PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 ||
dtx_duration < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*8000/1000)
{
output->size = 0;
output->type = PJMEDIA_FRAME_TYPE_NONE;
output->timestamp = input->timestamp;
return PJ_SUCCESS;
}
}
payload_len = output_buf_len;
status = pjmedia_codec_amr_pack(frames, nframes, &amr_data->enc_setting,
output->buf, &payload_len);
if (status != PJ_SUCCESS) {
output->size = 0;
output->buf = NULL;
output->type = PJMEDIA_FRAME_TYPE_NONE;
TRACE_((THIS_FILE, "Failed to pack AMR payload, status=%d", status));
return status;
}
output->size = payload_len;
output->type = PJMEDIA_FRAME_TYPE_AUDIO;
output->timestamp = input->timestamp;
amr_data->last_tx = input->timestamp;
return PJ_SUCCESS;
}
/*
* Decode frame.
*/
static pj_status_t amr_codec_decode( pjmedia_codec *codec,
const struct pjmedia_frame *input,
unsigned output_buf_len,
struct pjmedia_frame *output)
{
struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
pjmedia_frame input_;
pjmedia_codec_amr_bit_info *info;
/* VA AMR-NB decoding buffer: AMR-NB max frame size + 1 byte header. */
unsigned char bitstream[32];
pj_assert(amr_data != NULL);
PJ_ASSERT_RETURN(input && output, PJ_EINVAL);
if (output_buf_len < 320)
return PJMEDIA_CODEC_EPCMTOOSHORT;
input_.buf = &bitstream[1];
input_.size = 31; /* AMR-NB max frame size */
pjmedia_codec_amr_predecode(input, &amr_data->dec_setting, &input_);
info = (pjmedia_codec_amr_bit_info*)&input_.bit_info;
/* VA AMRNB decoder requires frame info in the first byte. */
bitstream[0] = (info->frame_type << 3) | (info->good_quality << 2);
TRACE_((THIS_FILE, "AMR-NB decode(): mode=%d, ft=%d, size=%d",
info->mode, info->frame_type, input_.size));
/* Decode */
Decoder_Interface_Decode(amr_data->decoder, bitstream,
(pj_int16_t*)output->buf, 0);
output->size = 320;
output->type = PJMEDIA_FRAME_TYPE_AUDIO;
output->timestamp = input->timestamp;
#if USE_PJMEDIA_PLC
if (amr_data->plc_enabled)
pjmedia_plc_save(amr_data->plc, (pj_int16_t*)output->buf);
#endif
return PJ_SUCCESS;
}
/*
* Recover lost frame.
*/
#if USE_PJMEDIA_PLC
/*
* Recover lost frame.
*/
static pj_status_t amr_codec_recover( pjmedia_codec *codec,
unsigned output_buf_len,
struct pjmedia_frame *output)
{
struct amr_data *amr_data = codec->codec_data;
TRACE_((THIS_FILE, "amr_codec_recover"));
PJ_ASSERT_RETURN(amr_data->plc_enabled, PJ_EINVALIDOP);
PJ_ASSERT_RETURN(output_buf_len >= 320, PJMEDIA_CODEC_EPCMTOOSHORT);
pjmedia_plc_generate(amr_data->plc, (pj_int16_t*)output->buf);
output->size = 320;
output->type = PJMEDIA_FRAME_TYPE_AUDIO;
return PJ_SUCCESS;
}
#endif
#if defined(_MSC_VER) && PJMEDIA_AUTO_LINK_OPENCORE_AMR_LIBS
# if PJMEDIA_OPENCORE_AMR_BUILT_WITH_GCC
# pragma comment( lib, "libopencore-amrnb.a")
# else
# error Unsupported OpenCORE AMR library, fix here
# endif
#endif
#endif

View File

@ -259,13 +259,16 @@ static pj_status_t pack_amr ( codec_private_t *codec_data,
pj_bzero(info, sizeof(*info));
if (len == 0) {
info->frame_type = (pj_uint8_t)(enc_setting->amr_nb? 14 : 15);
/* DTX */
info->frame_type = 15;
} else {
info->frame_type = pjmedia_codec_amr_get_mode2(enc_setting->amr_nb,
len);
}
info->good_quality = 1;
info->mode = setting->enc_mode;
if (info->frame_type == SID_FT)
info->STI = (sf->data[4] >> 4) & 1;
frames[i].buf = sf->data;
frames[i].size = len;

View File

@ -128,6 +128,12 @@ PJ_DEF(pj_uint8_t) pjmedia_linear2alaw(
} else {
mask = 0x55; /* sign bit = 0 */
pcm_val = -pcm_val - 8;
/* https://trac.pjsip.org/repos/ticket/1301
* Thank you K Johnson - Zetron - 27 May 2011
*/
if (pcm_val < 0)
pcm_val = 0;
}
/* Convert the scaled magnitude to segment number. */

View File

@ -31,6 +31,7 @@
struct pjmedia_clock
{
pj_pool_t *pool;
pj_timestamp freq;
pj_timestamp interval;
pj_timestamp next_tick;
@ -70,8 +71,8 @@ PJ_DEF(pj_status_t) pjmedia_clock_create( pj_pool_t *pool,
PJ_EINVAL);
clock = PJ_POOL_ALLOC_T(pool, pjmedia_clock);
clock->pool = pj_pool_create(pool->factory, "clock%p", 512, 512, NULL);
status = pj_get_timestamp_freq(&clock->freq);
if (status != PJ_SUCCESS)
return status;
@ -94,16 +95,6 @@ PJ_DEF(pj_status_t) pjmedia_clock_create( pj_pool_t *pool,
if (status != PJ_SUCCESS)
return status;
if ((clock->options & PJMEDIA_CLOCK_NO_ASYNC) == 0) {
status = pj_thread_create(pool, "clock", &clock_thread, clock,
0, 0, &clock->thread);
if (status != PJ_SUCCESS) {
pj_lock_destroy(clock->lock);
return status;
}
}
*p_clock = clock;
return PJ_SUCCESS;
@ -127,12 +118,20 @@ PJ_DEF(pj_status_t) pjmedia_clock_start(pjmedia_clock *clock)
if (status != PJ_SUCCESS)
return status;
pj_lock_acquire(clock->lock);
clock->next_tick.u64 = now.u64 + clock->interval.u64;
clock->running = PJ_TRUE;
pj_lock_release(clock->lock);
clock->quitting = PJ_FALSE;
return status;
if ((clock->options & PJMEDIA_CLOCK_NO_ASYNC) == 0 && !clock->thread) {
status = pj_thread_create(clock->pool, "clock", &clock_thread, clock,
0, 0, &clock->thread);
if (status != PJ_SUCCESS) {
clock->running = PJ_FALSE;
return status;
}
}
return PJ_SUCCESS;
}
@ -144,6 +143,17 @@ PJ_DEF(pj_status_t) pjmedia_clock_stop(pjmedia_clock *clock)
PJ_ASSERT_RETURN(clock != NULL, PJ_EINVAL);
clock->running = PJ_FALSE;
clock->quitting = PJ_TRUE;
if (clock->thread) {
if (pj_thread_join(clock->thread) == PJ_SUCCESS) {
pj_thread_destroy(clock->thread);
clock->thread = NULL;
pj_pool_reset(clock->pool);
} else {
clock->quitting = PJ_FALSE;
}
}
return PJ_SUCCESS;
}
@ -254,6 +264,10 @@ static int clock_thread(void *arg)
if (clock->cb)
(*clock->cb)(&clock->timestamp, clock->user_data);
/* Best effort way to detect if we've been destroyed in the callback */
if (clock->quitting)
break;
/* Increment timestamp */
clock->timestamp.u64 += clock->timestamp_inc;
@ -288,6 +302,11 @@ PJ_DEF(pj_status_t) pjmedia_clock_destroy(pjmedia_clock *clock)
clock->lock = NULL;
}
if (clock->pool) {
pj_pool_t *pool = clock->pool;
clock->pool = NULL;
pj_pool_release(pool);
}
return PJ_SUCCESS;
}

View File

@ -40,6 +40,39 @@ struct pjmedia_codec_default_param
static void sort_codecs(pjmedia_codec_mgr *mgr);
/*
* Duplicate codec parameter.
*/
PJ_DEF(pjmedia_codec_param*) pjmedia_codec_param_clone(
pj_pool_t *pool,
const pjmedia_codec_param *src)
{
pjmedia_codec_param *p;
unsigned i;
PJ_ASSERT_RETURN(pool && src, NULL);
p = PJ_POOL_ZALLOC_T(pool, pjmedia_codec_param);
/* Update codec param */
pj_memcpy(p, src, sizeof(pjmedia_codec_param));
for (i = 0; i < src->setting.dec_fmtp.cnt; ++i) {
pj_strdup(pool, &p->setting.dec_fmtp.param[i].name,
&src->setting.dec_fmtp.param[i].name);
pj_strdup(pool, &p->setting.dec_fmtp.param[i].val,
&src->setting.dec_fmtp.param[i].val);
}
for (i = 0; i < src->setting.enc_fmtp.cnt; ++i) {
pj_strdup(pool, &p->setting.enc_fmtp.param[i].name,
&src->setting.enc_fmtp.param[i].name);
pj_strdup(pool, &p->setting.enc_fmtp.param[i].val,
&src->setting.enc_fmtp.param[i].val);
}
return p;
}
/*
* Initialize codec manager.
*/

View File

@ -540,7 +540,7 @@ PJ_DEF(pj_status_t) pjmedia_conf_connect_port( pjmedia_conf *conf,
/* Channel count must match. */
if (src_port->info->channel_count != dst_port->info->channel_count) {
pj_mutex_unlock(conf->mutex);
return PJMEDIA_ENCCLOCKRATE;
return PJMEDIA_ENCCHANNEL;
}
/* Source and sink ptime must be equal or a multiplication factor. */
@ -1073,11 +1073,14 @@ static pj_status_t write_frame(struct conf_port *cport_dst,
while (f_start < f_end) {
unsigned nsamples_to_copy, nsamples_req;
/* Copy frame to listener's TX buffer. */
/* Copy frame to listener's TX buffer.
* Note that if the destination is port 0, just copy the whole
* available samples.
*/
nsamples_to_copy = f_end - f_start;
nsamples_req = cport_dst->info->samples_per_frame -
(frm_dst->size>>1);
if (nsamples_to_copy > nsamples_req)
if (cport_dst->slot && nsamples_to_copy > nsamples_req)
nsamples_to_copy = nsamples_req;
/* Adjust TX level. */
@ -1110,16 +1113,19 @@ static pj_status_t write_frame(struct conf_port *cport_dst,
/* Check if it's time to deliver the TX buffer to listener,
* i.e: samples count in TX buffer equal to listener's
* samples per frame.
* samples per frame. Note that for destination port 0 this
* function will just populate all samples in the TX buffer.
*/
if ((frm_dst->size >> 1) == cport_dst->info->samples_per_frame)
if (cport_dst->slot == 0) {
/* Update TX timestamp. */
pj_add_timestamp32(&cport_dst->ts_tx, nsamples_to_copy);
} else if ((frm_dst->size >> 1) ==
cport_dst->info->samples_per_frame)
{
if (cport_dst->slot) {
pjmedia_port_put_frame(cport_dst->port, frm_dst);
pjmedia_port_put_frame(cport_dst->port, frm_dst);
/* Reset TX buffer. */
frm_dst->size = 0;
}
/* Reset TX buffer. */
frm_dst->size = 0;
/* Update TX timestamp. */
pj_add_timestamp32(&cport_dst->ts_tx,

View File

@ -1800,13 +1800,16 @@ static pj_status_t get_frame(pjmedia_port *this_port,
for (i=0, ci=0; i<conf->max_ports && ci < conf->port_cnt; ++i) {
struct conf_port *conf_port = conf->ports[i];
/* Skip empty slot. */
/* Skip empty port. */
if (!conf_port)
continue;
/* Var "ci" is to count how many ports have been visited so far. */
++ci;
/* Reset buffer & auto adjustment level for mixed signal */
/* Reset buffer (only necessary if the port has transmitter) and
* reset auto adjustment level for mixed signal.
*/
conf_port->mix_adj = NORMAL_LEVEL;
if (conf_port->transmitter_cnt) {
pj_bzero(conf_port->mix_buf,
@ -1817,7 +1820,7 @@ static pj_status_t get_frame(pjmedia_port *this_port,
/* Get frames from all ports, and "mix" the signal
* to mix_buf of all listeners of the port.
*/
for (i=0, ci=0; i<conf->max_ports && ci<conf->port_cnt; ++i) {
for (i=0, ci=0; i < conf->max_ports && ci < conf->port_cnt; ++i) {
struct conf_port *conf_port = conf->ports[i];
pj_int32_t level = 0;
@ -1945,23 +1948,33 @@ static pj_status_t get_frame(pjmedia_port *this_port,
mix_buf = listener->mix_buf;
/* Mixing signals,
* and calculate appropriate level adjustment if there is
* any overflowed level in the mixed signal.
*/
for (k=0; k<conf->samples_per_frame; ++k) {
mix_buf[k] += p_in[k];
/* Check if normalization adjustment needed. */
if (IS_OVERFLOW(mix_buf[k])) {
/* NORMAL_LEVEL * MAX_LEVEL / mix_buf[k]; */
int tmp_adj = (MAX_LEVEL<<7) / mix_buf[k];
if (tmp_adj<0) tmp_adj = -tmp_adj;
if (listener->transmitter_cnt > 1) {
/* Mixing signals,
* and calculate appropriate level adjustment if there is
* any overflowed level in the mixed signal.
*/
for (k=0; k < conf->samples_per_frame; ++k) {
mix_buf[k] += p_in[k];
/* Check if normalization adjustment needed. */
if (IS_OVERFLOW(mix_buf[k])) {
/* NORMAL_LEVEL * MAX_LEVEL / mix_buf[k]; */
int tmp_adj = (MAX_LEVEL<<7) / mix_buf[k];
if (tmp_adj<0) tmp_adj = -tmp_adj;
if (tmp_adj<listener->mix_adj)
listener->mix_adj = tmp_adj;
if (tmp_adj<listener->mix_adj)
listener->mix_adj = tmp_adj;
} /* if any overflow in the mixed signals */
} /* loop mixing signals */
} /* if any overflow in the mixed signals */
} /* loop mixing signals */
} else {
/* Only 1 transmitter:
* just copy the samples to the mix buffer
* no mixing and level adjustment needed
*/
for (k=0; k<conf->samples_per_frame; ++k) {
mix_buf[k] = p_in[k];
}
}
} /* loop the listeners of conf port */
} /* loop of all conf ports */

View File

@ -99,9 +99,6 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_create( pj_pool_t *pool,
PJ_ASSERT_RETURN(pool && samples_per_frame && clock_rate && channel_count &&
p_b, PJ_EINVAL);
PJ_ASSERT_RETURN(options==0, PJ_EINVAL);
PJ_UNUSED_ARG(options);
if (!name) {
name = "delaybuf";
@ -126,11 +123,16 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_create( pj_pool_t *pool,
if (status != PJ_SUCCESS)
return status;
/* Create WSOLA */
status = pjmedia_wsola_create(pool, clock_rate, samples_per_frame, 1,
PJMEDIA_WSOLA_NO_FADING, &b->wsola);
if (status != PJ_SUCCESS)
return status;
if (!(options & PJMEDIA_DELAY_BUF_SIMPLE_FIFO)) {
/* Create WSOLA */
status = pjmedia_wsola_create(pool, clock_rate, samples_per_frame, 1,
PJMEDIA_WSOLA_NO_FADING, &b->wsola);
if (status != PJ_SUCCESS)
return status;
PJ_LOG(5, (b->obj_name, "Using delay buffer with WSOLA."));
} else {
PJ_LOG(5, (b->obj_name, "Using simple FIFO delay buffer."));
}
/* Finally, create mutex */
status = pj_lock_create_recursive_mutex(pool, b->obj_name,
@ -147,15 +149,17 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_create( pj_pool_t *pool,
PJ_DEF(pj_status_t) pjmedia_delay_buf_destroy(pjmedia_delay_buf *b)
{
pj_status_t status;
pj_status_t status = PJ_SUCCESS;
PJ_ASSERT_RETURN(b, PJ_EINVAL);
pj_lock_acquire(b->lock);
status = pjmedia_wsola_destroy(b->wsola);
if (status == PJ_SUCCESS)
b->wsola = NULL;
if (b->wsola) {
status = pjmedia_wsola_destroy(b->wsola);
if (status == PJ_SUCCESS)
b->wsola = NULL;
}
pj_lock_release(b->lock);
@ -264,12 +268,14 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_put(pjmedia_delay_buf *b,
pj_lock_acquire(b->lock);
update(b, OP_PUT);
if (b->wsola) {
update(b, OP_PUT);
status = pjmedia_wsola_save(b->wsola, frame, PJ_FALSE);
if (status != PJ_SUCCESS) {
pj_lock_release(b->lock);
return status;
status = pjmedia_wsola_save(b->wsola, frame, PJ_FALSE);
if (status != PJ_SUCCESS) {
pj_lock_release(b->lock);
return status;
}
}
/* Overflow checking */
@ -277,13 +283,15 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_put(pjmedia_delay_buf *b,
b->max_cnt)
{
unsigned erase_cnt;
/* shrink one frame or just the diff? */
//erase_cnt = b->samples_per_frame;
erase_cnt = pjmedia_circ_buf_get_len(b->circ_buf) +
b->samples_per_frame - b->max_cnt;
shrink_buffer(b, erase_cnt);
if (b->wsola) {
/* shrink one frame or just the diff? */
//erase_cnt = b->samples_per_frame;
erase_cnt = pjmedia_circ_buf_get_len(b->circ_buf) +
b->samples_per_frame - b->max_cnt;
shrink_buffer(b, erase_cnt);
}
/* Check if shrinking failed or erased count is less than requested,
* delaybuf needs to drop eldest samples, this is bad since the voice
@ -297,9 +305,9 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_put(pjmedia_delay_buf *b,
pjmedia_circ_buf_adv_read_ptr(b->circ_buf, erase_cnt);
PJ_LOG(4,(b->obj_name,"Shrinking failed or insufficient, dropping"
" %d eldest samples, buf_cnt=%d", erase_cnt,
pjmedia_circ_buf_get_len(b->circ_buf)));
PJ_LOG(4,(b->obj_name,"%sDropping %d eldest samples, buf_cnt=%d",
(b->wsola? "Shrinking failed or insufficient. ": ""),
erase_cnt, pjmedia_circ_buf_get_len(b->circ_buf)));
}
}
@ -312,13 +320,14 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_put(pjmedia_delay_buf *b,
PJ_DEF(pj_status_t) pjmedia_delay_buf_get( pjmedia_delay_buf *b,
pj_int16_t frame[])
{
pj_status_t status;
pj_status_t status = PJ_SUCCESS;
PJ_ASSERT_RETURN(b && frame, PJ_EINVAL);
pj_lock_acquire(b->lock);
update(b, OP_GET);
if (b->wsola)
update(b, OP_GET);
/* Starvation checking */
if (pjmedia_circ_buf_get_len(b->circ_buf) < b->samples_per_frame) {
@ -326,24 +335,29 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_get( pjmedia_delay_buf *b,
PJ_LOG(4,(b->obj_name,"Underflow, buf_cnt=%d, will generate 1 frame",
pjmedia_circ_buf_get_len(b->circ_buf)));
status = pjmedia_wsola_generate(b->wsola, frame);
if (b->wsola) {
status = pjmedia_wsola_generate(b->wsola, frame);
if (status == PJ_SUCCESS) {
TRACE__((b->obj_name,"Successfully generate 1 frame"));
if (pjmedia_circ_buf_get_len(b->circ_buf) == 0) {
pj_lock_release(b->lock);
return PJ_SUCCESS;
}
if (status == PJ_SUCCESS) {
TRACE__((b->obj_name,"Successfully generate 1 frame"));
if (pjmedia_circ_buf_get_len(b->circ_buf) == 0) {
pj_lock_release(b->lock);
return PJ_SUCCESS;
}
/* Put generated frame into buffer */
pjmedia_circ_buf_write(b->circ_buf, frame, b->samples_per_frame);
/* Put generated frame into buffer */
pjmedia_circ_buf_write(b->circ_buf, frame,
b->samples_per_frame);
}
}
} else {
if (!b->wsola || status != PJ_SUCCESS) {
unsigned buf_len = pjmedia_circ_buf_get_len(b->circ_buf);
/* Give all what delay buffer has, then pad with zeroes */
PJ_LOG(4,(b->obj_name,"Error generating frame, status=%d",
status));
if (b->wsola)
PJ_LOG(4,(b->obj_name,"Error generating frame, status=%d",
status));
pjmedia_circ_buf_read(b->circ_buf, frame, buf_len);
pjmedia_zero_samples(&frame[buf_len],
@ -378,7 +392,8 @@ PJ_DEF(pj_status_t) pjmedia_delay_buf_reset(pjmedia_delay_buf *b)
pjmedia_circ_buf_reset(b->circ_buf);
/* Reset WSOLA */
pjmedia_wsola_reset(b->wsola, 0);
if (b->wsola)
pjmedia_wsola_reset(b->wsola, 0);
pj_lock_release(b->lock);

View File

@ -144,6 +144,7 @@ PJ_DEF(pj_status_t) pjmedia_echo_create2(pj_pool_t *pool,
pjmedia_echo_state **p_echo )
{
unsigned ptime, lat_cnt;
unsigned delay_buf_opt = 0;
pjmedia_echo_state *ec;
pj_status_t status;
@ -211,10 +212,12 @@ PJ_DEF(pj_status_t) pjmedia_echo_create2(pj_pool_t *pool,
}
/* Create delay buffer to compensate drifts */
if (options & PJMEDIA_ECHO_USE_SIMPLE_FIFO)
delay_buf_opt |= PJMEDIA_DELAY_BUF_SIMPLE_FIFO;
status = pjmedia_delay_buf_create(ec->pool, ec->obj_name, clock_rate,
samples_per_frame, channel_count,
(PJMEDIA_SOUND_BUFFER_COUNT+1) * ptime,
0, &ec->delay_buf);
delay_buf_opt, &ec->delay_buf);
if (status != PJ_SUCCESS) {
pj_pool_release(pool);
return status;

View File

@ -23,6 +23,7 @@
#include <pjmedia-audiodev/audiodev.h>
#include <pj/assert.h>
#include <pj/ioqueue.h>
#include <pj/lock.h>
#include <pj/log.h>
#include <pj/os.h>
#include <pj/pool.h>
@ -56,6 +57,14 @@ static int PJ_THREAD_FUNC worker_proc(void*);
#define MAX_THREADS 16
/* List of media endpoint exit callback. */
typedef struct exit_cb
{
PJ_DECL_LIST_MEMBER (struct exit_cb);
pjmedia_endpt_exit_callback func;
} exit_cb;
/** Concrete declaration of media endpoint. */
struct pjmedia_endpt
{
@ -85,6 +94,9 @@ struct pjmedia_endpt
/** Is telephone-event enable */
pj_bool_t has_telephone_event;
/** List of exit callback. */
exit_cb exit_cb_list;
};
/**
@ -128,6 +140,9 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create(pj_pool_factory *pf,
if (status != PJ_SUCCESS)
goto on_error;
/* Initialize exit callback list. */
pj_list_init(&endpt->exit_cb_list);
/* Create ioqueue if none is specified. */
if (endpt->ioqueue == NULL) {
@ -188,6 +203,7 @@ PJ_DEF(pjmedia_codec_mgr*) pjmedia_endpt_get_codec_mgr(pjmedia_endpt *endpt)
*/
PJ_DEF(pj_status_t) pjmedia_endpt_destroy (pjmedia_endpt *endpt)
{
exit_cb *ecb;
unsigned i;
PJ_ASSERT_RETURN(endpt, PJ_EINVAL);
@ -213,6 +229,14 @@ PJ_DEF(pj_status_t) pjmedia_endpt_destroy (pjmedia_endpt *endpt)
pjmedia_codec_mgr_destroy(&endpt->codec_mgr);
pjmedia_aud_subsys_shutdown();
/* Call all registered exit callbacks */
ecb = endpt->exit_cb_list.next;
while (ecb != &endpt->exit_cb_list) {
(*ecb->func)(endpt);
ecb = ecb->next;
}
pj_pool_release (endpt->pool);
return PJ_SUCCESS;
@ -450,7 +474,7 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create_sdp( pjmedia_endpt *endpt,
rtpmap.param.slen = 1;
} else {
rtpmap.param.ptr = NULL;
rtpmap.param.ptr = "";
rtpmap.param.slen = 0;
}
@ -628,3 +652,23 @@ PJ_DEF(pj_status_t) pjmedia_endpt_dump(pjmedia_endpt *endpt)
return PJ_SUCCESS;
}
PJ_DEF(pj_status_t) pjmedia_endpt_atexit( pjmedia_endpt *endpt,
pjmedia_endpt_exit_callback func)
{
exit_cb *new_cb;
PJ_ASSERT_RETURN(endpt && func, PJ_EINVAL);
if (endpt->quit_flag)
return PJ_EINVALIDOP;
new_cb = PJ_POOL_ZALLOC_T(endpt->pool, exit_cb);
new_cb->func = func;
pj_enter_critical_section();
pj_list_push_back(&endpt->exit_cb_list, new_cb);
pj_leave_critical_section();
return PJ_SUCCESS;
}

View File

@ -330,7 +330,8 @@ static pj_status_t g711_alloc_codec( pjmedia_codec_factory *factory,
#if !PLC_DISABLED
/* Create PLC, always with 10ms ptime */
status = pjmedia_plc_create(g711_factory.pool, 8000, 80,
status = pjmedia_plc_create(g711_factory.pool, 8000,
SAMPLES_PER_FRAME,
0, &codec_priv->plc);
if (status != PJ_SUCCESS) {
pj_mutex_unlock(g711_factory.mutex);
@ -340,7 +341,7 @@ static pj_status_t g711_alloc_codec( pjmedia_codec_factory *factory,
/* Create VAD */
status = pjmedia_silence_det_create(g711_factory.pool,
8000, 80,
8000, SAMPLES_PER_FRAME,
&codec_priv->vad);
if (status != PJ_SUCCESS) {
pj_mutex_unlock(g711_factory.mutex);

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