Changeset 3106
- Timestamp:
- Feb 24, 2010 5:43:34 AM (15 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 1 added
- 27 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/build.symbian/pjlib.mmp
r3046 r3106 50 50 SOURCE rand.c 51 51 SOURCE rbtree.c 52 SOURCE ssl_sock_common.c 53 SOURCE ssl_sock_dump.c 52 54 SOURCE sock_common.c 53 55 SOURCE sock_qos_common.c … … 73 75 SOURCE os_timestamp_posix.c 74 76 SOURCE pool_policy_new.cpp 75 SOURCE ssl_sock_common.c76 77 SOURCE ssl_sock_symbian.cpp 77 78 SOURCE sock_symbian.cpp -
pjproject/trunk/build.symbian/pjlib_test.mmp
r3046 r3106 70 70 SYSTEMINCLUDE \epoc32\include\libc 71 71 72 LIBRARY esock.lib insock.lib charconv.lib euser.lib estlib.lib securesocket.lib 72 LIBRARY esock.lib insock.lib charconv.lib euser.lib estlib.lib 73 LIBRARY securesocket.lib x509.lib crypto.lib x500.lib 74 73 75 #ifdef WINSCW 74 76 STATICLIBRARY eexe.lib ecrt0.lib -
pjproject/trunk/build.symbian/symbian_ua.mmp
r3046 r3106 72 72 #endif 73 73 74 LIBRARY esock.lib insock.lib charconv.lib euser.lib estlib.lib commdb.lib apengine.lib securesocket.lib 74 LIBRARY esock.lib insock.lib charconv.lib euser.lib estlib.lib commdb.lib apengine.lib 75 LIBRARY securesocket.lib x509.lib crypto.lib x500.lib 75 76 76 77 // The default 8KB seems to be insufficient with all bells and -
pjproject/trunk/pjlib/build/Makefile
r2970 r3106 27 27 pool.o pool_buf.o pool_caching.o pool_dbg.o rand.o \ 28 28 rbtree.o sock_common.o sock_qos_common.o sock_qos_bsd.o \ 29 ssl_sock_common.o ssl_sock_ossl.o string.o timer.o types.o 29 ssl_sock_common.o ssl_sock_ossl.o ssl_sock_dump.o \ 30 string.o timer.o types.o 30 31 export PJLIB_CFLAGS += $(_CFLAGS) 31 32 -
pjproject/trunk/pjlib/build/cacert.pem
r2971 r3106 1 1 -----BEGIN CERTIFICATE----- 2 MIIDXzCCAkegAwIBAgIJAPqAwYU5OQLXMA0GCSqGSIb3DQEBBQUAMEYxCzAJBgNV 3 BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMQ4wDAYDVQQKDAVwanNpcDESMBAG 4 A1UEAwwJcGpzaXAubGFiMB4XDTA5MTAyMjE3MTczN1oXDTE5MTAyMDE3MTczN1ow 5 RjELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxDjAMBgNVBAoMBXBq 6 c2lwMRIwEAYDVQQDDAlwanNpcC5sYWIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw 7 ggEKAoIBAQDWWvnL+oSC0Q6OwGLt2YuhXTEzIVv3B+SGQ7tajB6H3WXVeq+1NmU9 8 Yzca33g4FRrU7n4smYmKLzm1aniBhNmJjA+t+gbyizKnLMaCLoG52tUoULcANGKU 9 aGwlmvZFugDn2eVg6UfUfRzEGbV3q3a/PzSsOEPwsMeF3YMQJPhkoyPQLtWgUXgP 10 89Nyq3XjGGtw/qmUgQjE8a6/P0yXc+myI0hmApmZ9nB3YmlB5W3q6WoU2gGhLXf4 11 12rH/LgdnPhM4ijS554Kv9EcUDdQTTrm6bYg66tj+qTet7DolUOlTZ3vKpuCK3tt 12 eK9CbNPVzsMsB3yCALSLzQ347pIwfLaJAgMBAAGjUDBOMB0GA1UdDgQWBBRE/VNp 13 kNQmLEXKQ+NM4bOVj95zYTAfBgNVHSMEGDAWgBRE/VNpkNQmLEXKQ+NM4bOVj95z 14 YTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQCj/gzJKTOZDEBD+zr7 15 lvbVctiYE9o8ObxZQsnl/6zI2V9H/2yc1sqQyjBupzw6c37ehvk30yIyUfD3ts87 16 2xaJ5VgtgUI3FI5DQ+ASyQXmDawUEmXIGqHb2gDrXBQLd6uMpvNDNW+7TouuniyA 17 F12JUCNITeXaVJ0c8d4A9J9DlszBfYUzI45yIQu1gbpnpH74Sp/hG77EMxrRau+x 18 EFFmV7gAmkCgOBnXm8jTKqNre/GfLfO7w2xoLsubSLnK46U3iLGBIJJRVGu3UQuN 19 k1o7CiIKf0SSWj1bQI99ipTj8obBKRqj1nSbgKF/U6FIfd8DGcVvbJCSAG2czzyA 20 5tdA 2 MIICNDCCAZ2gAwIBAgIJAIa9mZggMk2WMA0GCSqGSIb3DQEBBAUAMDMxEjAQBgNV 3 BAMTCXBqc2lwLmxhYjEdMBsGCSqGSIb3DQEJARYOdGVzdEBwanNpcC5sYWIwHhcN 4 MTAwMjEwMDkwNTQ0WhcNMjAwMjA4MDkwNTQ0WjAzMRIwEAYDVQQDEwlwanNpcC5s 5 YWIxHTAbBgkqhkiG9w0BCQEWDnRlc3RAcGpzaXAubGFiMIGfMA0GCSqGSIb3DQEB 6 AQUAA4GNADCBiQKBgQDI9T0Pf+1gKOTOAGEpZ481Q6xfm5vz6n1+6udxzQtfPKlQ 7 rPD5x5im2u3tmy6ABxZeY5tCdeikBPiGlc5bRIRng6KM8kidkg3gEhwhRUxHCMWb 8 mBpkz7rFERf/pWAOCqYCiy1RT8QrK+XOFoFdJhdF85UPDEUw+pHEsYetTDs9RQID 9 AQABo1AwTjBMBgNVHREERTBDgglwanNpcC5sYWKCDXNpcC5wanNpcC5sYWKBDnRl 10 c3RAcGpzaXAubGFihhFzaXA6c2lwLnBqc2lwLmxhYocEfwAAATANBgkqhkiG9w0B 11 AQQFAAOBgQCLPl/WF1QvjT36kVLH0nxfHwDOJuAzlh6nv9rYBviOLw9FTEMgW6hA 12 oG55YSdVjTnMynTMOH/kVp4Vxlk46A8neE+/LI8RPh6lJh52vb+iPAtBpsQoq06T 13 +u4DfJcN8Y/jy+QAn78jryKjwKuZWfuWny9gxsLWMUbH5Bc6v6wfQQ== 21 14 -----END CERTIFICATE----- -
pjproject/trunk/pjlib/build/pjlib.dsp
r3052 r3106 341 341 # Begin Source File 342 342 343 SOURCE=..\src\pj\ssl_sock_dump.c 344 # End Source File 345 # Begin Source File 346 343 347 SOURCE=..\src\pj\ssl_sock_ossl.c 344 348 # End Source File -
pjproject/trunk/pjlib/build/pjlib.vcproj
r3052 r3106 5647 5647 <File 5648 5648 RelativePath="..\src\pj\ssl_sock_common.c" 5649 > 5650 </File> 5651 <File 5652 RelativePath="..\src\pj\ssl_sock_dump.c" 5649 5653 > 5650 5654 </File> -
pjproject/trunk/pjlib/build/privkey.pem
r2971 r3106 1 1 -----BEGIN RSA PRIVATE KEY----- 2 MIIEpQIBAAKCAQEA1lr5y/qEgtEOjsBi7dmLoV0xMyFb9wfkhkO7Woweh91l1Xqv 3 tTZlPWM3Gt94OBUa1O5+LJmJii85tWp4gYTZiYwPrfoG8osypyzGgi6BudrVKFC3 4 ADRilGhsJZr2RboA59nlYOlH1H0cxBm1d6t2vz80rDhD8LDHhd2DECT4ZKMj0C7V 5 oFF4D/PTcqt14xhrcP6plIEIxPGuvz9Ml3PpsiNIZgKZmfZwd2JpQeVt6ulqFNoB 6 oS13+Ndqx/y4HZz4TOIo0ueeCr/RHFA3UE065um2IOurY/qk3rew6JVDpU2d7yqb 7 git7bXivQmzT1c7DLAd8ggC0i80N+O6SMHy2iQIDAQABAoIBAQCAke7Ujz2d7WDq 8 9LAh8+NRdUFGZtLvd9d1RPkCVZsWaRBknIL5kVfmGzV5M+K62MXQRACAJdOeg7b8 9 fpErNpD4dH8PHjG+lwlZxnyGpvh+jqhd1xP81m7ujzeW0ry2k9tpNYPkveespyJy 10 6Oy0i67dBT9FsTXnD1GNlJDBRTuLuEkTTBqbn/2s3+gUfChJ4HPmYMeO9HU4PcfM 11 yUsHatBiIkXiCKdDZVMDr5AUVD0Wo3uHPGJ8ZreURAjH+ldG09+/EsVoPberbrDZ 12 ZxJ70VKG+ZZTY8HZr9OsZhDZDrHiw9PdG7Hvg7bCvv+gDzZ/z8F+7YHjRjmD5Tp5 13 Ex5hDco1AoGBAPfdfzwmqb79AXwYH0HZkkl2EXpzbR9LRgvWlOMSN3GlZhusvGQR 14 up6iGk9QnmoEtQS2IAuK4JT3r+yoM/20Nadq5ZUpkZ49SHuZ6+eZpotv3Fh8Oay8 15 TAi2vBGM7EQPUOjPOWMRaYGBz3FT/GvUGPTeQ8jYt1gy8F18+A8xD8pTAoGBAN1j 16 7+yTly+M47U6mIUXcwoelaS4f/kMcwKHO0O182S4ktfjzc3TpQbHm68ws1rB3iFZ 17 SFOP/d04tVxZqPBhN2SpXRHGqTJxXthdTbu3scLMedlf4jY11SRiHX4PDnoBQ1GJ 18 NpdkMoex25Fw3AqSVpP61zo8sJkqpqjFfeQDbfgzAoGBAKyGx1ZmDwc6cjsfSzp5 19 p+JsRVQ3XcBHk9UPooi/mEoJd55RyLvav0xFxwxoMCvZZOqHnpyKKTJniVOv7Khu 20 NF55AJ6n1Y0QWRB3ngWSJKOv0+7fYQHD+yShlRyeO6JQCuBRxT8Y0phrc6oNbIjd 21 lBV1VDdL6aqBol9gagWg/72zAoGBAK1rAx1F3z+YFSZ459AZNjvPCVkmTNhBMDXi 22 yEGZ3TYgfqYuA6AfET3mTcVFWLjW87EbxtPuDuWi7i2Q7gydmk53fDfYbeDdfXXu 23 YF2S3uPAWBI2UXQ1ZuhBEukT0jsvkhPkb6bXDd3NLDkZNsPxLXBtJPqxX4QbLME3 24 Mg3RweqRAoGAJ4iXP2b4XWhg17qpDtpn8nhFxLNdhxdaDSKRL8oKQLteds3wS0fi 25 ZlaU1P9a3ygTpNquKlmdLJTQEDAVjV5DDlrQAPxtSSytHulNzXRMQFaeydar3Ssv 26 J07BPdQs6JEgV071rGGzBcL8ulo7qCdnGxU6GmhLkS4MBbTuqR6jmgU= 2 MIICXgIBAAKBgQDI9T0Pf+1gKOTOAGEpZ481Q6xfm5vz6n1+6udxzQtfPKlQrPD5 3 x5im2u3tmy6ABxZeY5tCdeikBPiGlc5bRIRng6KM8kidkg3gEhwhRUxHCMWbmBpk 4 z7rFERf/pWAOCqYCiy1RT8QrK+XOFoFdJhdF85UPDEUw+pHEsYetTDs9RQIDAQAB 5 AoGAGV+1xQY/H7wqH8S2f/begzg3RJ8uUt8R13urm5frTqwnKNOdXbyRDshn8G9+ 6 sJW0gliLWxnuNP+Xrc6ujqGZIguK/yAxJ3LprAN2Ay1lW2ONyZNMquBeIY5Txhyy 7 SnU7U+NQYgA3+w9T7O7YQ575TTDm2gri558jIx8t55Wo9sUCQQDtjfGZ3sYXwpxR 8 MvtdtfwDxSKhf6glT6dn7/37KITBZXFy6Eb/tHrEEUuwR46g30vTd2JElCB+QExu 9 4sZDt813AkEA2I/WXdGVRXtHzVivf3AnqWyXfrfAAXlBmEkgPyIPwE1+mxeNxkU7 10 TRn0MOqAfbQW4+GRIYCKSBLodRnRq2iKIwJBAJLYa8DyNQH7CyYmnbwQAvlRo1ax 11 0v89ff6CHD5ljar/SmH9s+XdawZIqsENet13KyhNZDGAX5WrqZPiGy1BMYECQQC1 12 FREawfUfdEZF3rJgzVdcxACpZNyYXtwKipr8L28cTbBf3wIdmCZOAjW98VgfxEaf 13 pi3E5ca7HZRi1oQL4A4hAkEA5koHCQYl+5PDjbLtxl0VyVCpmT9BrcZ99MS+ZEaW 14 2+HpKIhXrEFxePQaWbCaW7gjKmKUwC0qqu0moedqJC3mzg== 27 15 -----END RSA PRIVATE KEY----- -
pjproject/trunk/pjlib/include/pj/ssl_sock.h
r2998 r3106 61 61 62 62 63 typedef enum pj_ssl_cert_verify_flag_t 64 { 65 /** 66 * No error in verification. 67 */ 68 PJ_SSL_CERT_ESUCCESS = 0, 69 70 /** 71 * The issuer certificate cannot be found. 72 */ 73 PJ_SSL_CERT_EISSUER_NOT_FOUND = (1 << 0), 74 75 /** 76 * The certificate is untrusted. 77 */ 78 PJ_SSL_CERT_EUNTRUSTED = (1 << 1), 79 80 /** 81 * The certificate has expired or not yet valid. 82 */ 83 PJ_SSL_CERT_EVALIDITY_PERIOD = (1 << 2), 84 85 /** 86 * One or more fields of the certificate cannot be decoded due to 87 * invalid format. 88 */ 89 PJ_SSL_CERT_EINVALID_FORMAT = (1 << 3), 90 91 /** 92 * The certificate cannot be used for the specified purpose. 93 */ 94 PJ_SSL_CERT_EINVALID_PURPOSE = (1 << 4), 95 96 /** 97 * The issuer info in the certificate does not match to the (candidate) 98 * issuer certificate, e.g: issuer name not match to subject name 99 * of (candidate) issuer certificate. 100 */ 101 PJ_SSL_CERT_EISSUER_MISMATCH = (1 << 5), 102 103 /** 104 * The CRL certificate cannot be found or cannot be read properly. 105 */ 106 PJ_SSL_CERT_ECRL_FAILURE = (1 << 6), 107 108 /** 109 * The certificate has been revoked. 110 */ 111 PJ_SSL_CERT_EREVOKED = (1 << 7), 112 113 /** 114 * The certificate chain length is too long. 115 */ 116 PJ_SSL_CERT_ECHAIN_TOO_LONG = (1 << 8), 117 118 /** 119 * The server identity does not match to any identities specified in 120 * the certificate, e.g: subjectAltName extension, subject common name. 121 * This flag will only be set by application as SSL socket does not 122 * perform server identity verification. 123 */ 124 PJ_SSL_CERT_EIDENTITY_NOT_MATCH = (1 << 30), 125 126 /** 127 * Unknown verification error. 128 */ 129 PJ_SSL_CERT_EUNKNOWN = (1 << 31) 130 131 } pj_ssl_cert_verify_flag_t; 132 133 134 typedef enum pj_ssl_cert_name_type 135 { 136 PJ_SSL_CERT_NAME_UNKNOWN = 0, 137 PJ_SSL_CERT_NAME_RFC822, 138 PJ_SSL_CERT_NAME_DNS, 139 PJ_SSL_CERT_NAME_URI, 140 PJ_SSL_CERT_NAME_IP 141 } pj_ssl_cert_name_type; 142 63 143 /** 64 144 * Describe structure of certificate info. 65 145 */ 66 146 typedef struct pj_ssl_cert_info { 67 pj_str_t subject; /**< Subject. */ 68 pj_str_t issuer; /**< Issuer. */ 69 unsigned version; /**< Certificate version. */ 70 pj_time_val validity_start; /**< Validity start. */ 71 pj_time_val validity_end; /**< Validity end. */ 72 pj_bool_t validity_use_gmt; /**< Flag if validity date/time 73 use GMT. */ 147 148 unsigned version; /**< Certificate version */ 149 150 pj_uint8_t serial_no[20]; /**< Serial number, array of 151 octets, first index is 152 MSB */ 153 154 struct { 155 pj_str_t cn; /**< Common name */ 156 pj_str_t info; /**< One line subject, fields 157 are separated by slash */ 158 } subject; /**< Subject */ 159 160 struct { 161 pj_str_t cn; /**< Common name */ 162 pj_str_t info; /**< One line subject, fields 163 are separated by slash.*/ 164 } issuer; /**< Issuer */ 165 166 struct { 167 pj_time_val start; /**< Validity start */ 168 pj_time_val end; /**< Validity end */ 169 pj_bool_t gmt; /**< Flag if validity date/time 170 use GMT */ 171 } validity; /**< Validity */ 172 173 struct { 174 unsigned cnt; /**< # of entry */ 175 struct { 176 pj_ssl_cert_name_type type; 177 /**< Name type */ 178 pj_str_t name; /**< The name */ 179 } *entry; /**< Subject alt name entry */ 180 } subj_alt_name; /**< Subject alternative 181 name extension */ 182 74 183 } pj_ssl_cert_info; 75 184 … … 92 201 const pj_str_t *privkey_pass, 93 202 pj_ssl_cert_t **p_cert); 203 204 205 /** 206 * Dump SSL certificate info. 207 * 208 * @param ci The certificate info. 209 * @param prefix Prefix string for each line. 210 * @param buf The buffer where certificate info will be printed on. 211 * @param buf_size The buffer size. 212 * 213 * @return PJ_SUCCESS when successful. 214 */ 215 PJ_DECL(pj_status_t) pj_ssl_cert_info_dump(const pj_ssl_cert_info *ci, 216 const char *prefix, 217 char *buf, 218 pj_size_t buf_size); 219 220 221 /** 222 * Get SSL certificate verification error messages from verification status. 223 * 224 * @param verify_status The SSL certificate verification status. 225 * @param error_strings Array of strings to receive the verification error 226 * messages. 227 * @param count On input it specifies maximum error messages should be 228 * retrieved. On output it specifies the number of error 229 * messages retrieved. 230 * 231 * @return PJ_SUCCESS when successful. 232 */ 233 PJ_DECL(pj_status_t) pj_ssl_cert_verify_error_st(pj_uint32_t verify_status, 234 const char *error_strings[], 235 unsigned *count); 94 236 95 237 … … 364 506 * Describes active local certificate info. 365 507 */ 366 pj_ssl_cert_info local_cert_info;508 pj_ssl_cert_info *local_cert_info; 367 509 368 510 /** 369 511 * Describes active remote certificate info. 370 512 */ 371 pj_ssl_cert_info remote_cert_info; 372 513 pj_ssl_cert_info *remote_cert_info; 514 515 /** 516 * Status of peer certificate verification. 517 */ 518 pj_uint32_t verify_status; 519 373 520 } pj_ssl_sock_info; 374 521 … … 524 671 525 672 /** 526 * When secure socket is acting as client (perform outgoing connection)527 * and it needs to verify server name (e.g: host or domain name) by528 * matching it to the name specified in the server certificate. This529 * setting is useful when the server is hosting multiple domains for530 * the same listening socket.673 * Server name indication. When secure socket is acting as client 674 * (perform outgoing connection) and the server may host multiple 675 * 'virtual' servers at a single underlying network address, setting 676 * this will allow client to tell the server a name of the server 677 * it is contacting. 531 678 * 532 679 * Default value is zero/not-set. -
pjproject/trunk/pjlib/src/pj/ssl_sock_common.c
r2998 r3106 18 18 */ 19 19 #include <pj/ssl_sock.h> 20 #include <pj/assert.h> 20 21 #include <pj/errno.h> 21 22 #include <pj/string.h> … … 129 130 130 131 132 /* Get cipher name string */ 131 133 PJ_DEF(const char*) pj_ssl_cipher_name(pj_ssl_cipher cipher) 132 134 { … … 141 143 return NULL; 142 144 } 145 146 147 148 149 PJ_DEF(pj_status_t) pj_ssl_cert_verify_error_st(pj_uint32_t verify_status, 150 const char *error_strings[], 151 unsigned *count) 152 { 153 unsigned i = 0, shift_idx = 0; 154 unsigned unknown = 0; 155 pj_uint32_t errs; 156 157 PJ_ASSERT_RETURN(error_strings && count, PJ_EINVAL); 158 159 if (verify_status == PJ_SSL_CERT_ESUCCESS && *count) { 160 error_strings[0] = "OK"; 161 *count = 1; 162 return PJ_SUCCESS; 163 } 164 165 errs = verify_status; 166 167 while (errs && i < *count) { 168 pj_uint32_t err; 169 const char *p = NULL; 170 171 if ((errs & 1) == 0) { 172 shift_idx++; 173 errs >>= 1; 174 continue; 175 } 176 177 err = (1 << shift_idx); 178 179 switch (err) { 180 case PJ_SSL_CERT_EISSUER_NOT_FOUND: 181 p = "The issuer certificate cannot be found"; 182 break; 183 case PJ_SSL_CERT_EUNTRUSTED: 184 p = "The certificate is untrusted"; 185 break; 186 case PJ_SSL_CERT_EVALIDITY_PERIOD: 187 p = "The certificate has expired or not yet valid"; 188 break; 189 case PJ_SSL_CERT_EINVALID_FORMAT: 190 p = "One or more fields of the certificate cannot be decoded " 191 "due to invalid format"; 192 break; 193 case PJ_SSL_CERT_EISSUER_MISMATCH: 194 p = "The issuer info in the certificate does not match to the " 195 "(candidate) issuer certificate"; 196 break; 197 case PJ_SSL_CERT_ECRL_FAILURE: 198 p = "The CRL certificate cannot be found or cannot be read " 199 "properly"; 200 break; 201 case PJ_SSL_CERT_EREVOKED: 202 p = "The certificate has been revoked"; 203 break; 204 case PJ_SSL_CERT_EINVALID_PURPOSE: 205 p = "The certificate or CA certificate cannot be used for the " 206 "specified purpose"; 207 break; 208 case PJ_SSL_CERT_ECHAIN_TOO_LONG: 209 p = "The certificate chain length is too long"; 210 break; 211 case PJ_SSL_CERT_EIDENTITY_NOT_MATCH: 212 p = "The server identity does not match to any identities " 213 "specified in the certificate"; 214 break; 215 case PJ_SSL_CERT_EUNKNOWN: 216 default: 217 unknown++; 218 break; 219 } 220 221 /* Set error string */ 222 if (p) 223 error_strings[i++] = p; 224 225 /* Next */ 226 shift_idx++; 227 errs >>= 1; 228 } 229 230 /* Unknown error */ 231 if (unknown && i < *count) 232 error_strings[i++] = "Unknown verification error"; 233 234 *count = i; 235 236 return PJ_SUCCESS; 237 } -
pjproject/trunk/pjlib/src/pj/ssl_sock_ossl.c
r3020 r3106 46 46 #include <openssl/ssl.h> 47 47 #include <openssl/err.h> 48 #include <openssl/x509v3.h> 48 49 49 50 … … 153 154 pj_ioqueue_op_key_t handshake_op_key; 154 155 pj_timer_entry timer; 156 pj_status_t verify_status; 155 157 156 158 pj_sock_t sock; … … 208 210 #define PJ_SSL_ERRNO_SPACE_SIZE PJ_ERRNO_SPACE_SIZE 209 211 212 #define STATUS_FROM_SSL_ERR(err, status) { \ 213 status = ERR_GET_LIB(err)*300 + ERR_GET_REASON(err);\ 214 pj_assert(status < PJ_SSL_ERRNO_SPACE_SIZE);\ 215 if (status) status += PJ_SSL_ERRNO_START;\ 216 } 217 210 218 #define GET_SSL_STATUS(status) { \ 211 219 unsigned long e = ERR_get_error();\ 212 status = ERR_GET_LIB(e)*300 + ERR_GET_REASON(e);\ 213 pj_assert(status < PJ_SSL_ERRNO_SPACE_SIZE);\ 214 if (status) status += PJ_SSL_ERRNO_START;\ 220 STATUS_FROM_SSL_ERR(e, status);\ 215 221 } 216 222 … … 236 242 { 237 243 const char *tmp = NULL; 238 tmp = ERR_reason_error_string(ssl_err); 244 245 if (ssl_err >= 300) 246 tmp = ERR_reason_error_string(ssl_err); 247 else 248 tmp = X509_verify_cert_error_string(ssl_err); 239 249 240 250 if (tmp) { … … 263 273 static pj_ssl_cipher openssl_ciphers[100]; 264 274 static unsigned openssl_cipher_num; 275 276 /* OpenSSL application data index */ 277 static int sslsock_idx; 265 278 266 279 … … 330 343 } 331 344 345 /* Create OpenSSL application data index for SSL socket */ 346 sslsock_idx = SSL_get_ex_new_index(0, "SSL socket", NULL, NULL, NULL); 347 332 348 return PJ_SUCCESS; 333 349 } … … 356 372 357 373 358 /* Create and initialize new SSL context */ 359 static pj_status_t create_ssl_ctx(pj_ssl_sock_t *ssock, SSL_CTX **p_ctx) 374 /* SSL password callback. */ 375 static int verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) 376 { 377 pj_ssl_sock_t *ssock; 378 SSL *ossl_ssl; 379 int err; 380 381 /* Get SSL instance */ 382 ossl_ssl = X509_STORE_CTX_get_ex_data(x509_ctx, 383 SSL_get_ex_data_X509_STORE_CTX_idx()); 384 pj_assert(ossl_ssl); 385 386 /* Get SSL socket instance */ 387 ssock = SSL_get_ex_data(ossl_ssl, sslsock_idx); 388 pj_assert(ssock); 389 390 /* Store verification status */ 391 err = X509_STORE_CTX_get_error(x509_ctx); 392 switch (err) { 393 case X509_V_OK: 394 break; 395 396 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: 397 ssock->verify_status |= PJ_SSL_CERT_EISSUER_NOT_FOUND; 398 break; 399 400 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: 401 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: 402 case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: 403 case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: 404 ssock->verify_status |= PJ_SSL_CERT_EINVALID_FORMAT; 405 break; 406 407 case X509_V_ERR_CERT_NOT_YET_VALID: 408 case X509_V_ERR_CERT_HAS_EXPIRED: 409 ssock->verify_status |= PJ_SSL_CERT_EVALIDITY_PERIOD; 410 break; 411 412 case X509_V_ERR_UNABLE_TO_GET_CRL: 413 case X509_V_ERR_CRL_NOT_YET_VALID: 414 case X509_V_ERR_CRL_HAS_EXPIRED: 415 case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: 416 case X509_V_ERR_CRL_SIGNATURE_FAILURE: 417 case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: 418 case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: 419 ssock->verify_status |= PJ_SSL_CERT_ECRL_FAILURE; 420 break; 421 422 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: 423 case X509_V_ERR_CERT_UNTRUSTED: 424 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: 425 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: 426 ssock->verify_status |= PJ_SSL_CERT_EUNTRUSTED; 427 break; 428 429 case X509_V_ERR_CERT_SIGNATURE_FAILURE: 430 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: 431 case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: 432 case X509_V_ERR_AKID_SKID_MISMATCH: 433 case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: 434 case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: 435 ssock->verify_status |= PJ_SSL_CERT_EISSUER_MISMATCH; 436 break; 437 438 case X509_V_ERR_CERT_REVOKED: 439 ssock->verify_status |= PJ_SSL_CERT_EREVOKED; 440 break; 441 442 case X509_V_ERR_INVALID_PURPOSE: 443 case X509_V_ERR_CERT_REJECTED: 444 case X509_V_ERR_INVALID_CA: 445 ssock->verify_status |= PJ_SSL_CERT_EINVALID_PURPOSE; 446 break; 447 448 case X509_V_ERR_CERT_CHAIN_TOO_LONG: /* not really used */ 449 case X509_V_ERR_PATH_LENGTH_EXCEEDED: 450 ssock->verify_status |= PJ_SSL_CERT_ECHAIN_TOO_LONG; 451 break; 452 453 /* Unknown errors */ 454 case X509_V_ERR_OUT_OF_MEM: 455 default: 456 ssock->verify_status |= PJ_SSL_CERT_EUNKNOWN; 457 break; 458 } 459 460 /* When verification is not requested just return ok here, however 461 * application can still get the verification status. 462 */ 463 if (PJ_FALSE == ssock->param.verify_peer) 464 preverify_ok = 1; 465 466 return preverify_ok; 467 } 468 469 /* Setting SSL sock cipher list */ 470 static pj_status_t set_cipher_list(pj_ssl_sock_t *ssock); 471 472 473 /* Create and initialize new SSL context and instance */ 474 static pj_status_t create_ssl(pj_ssl_sock_t *ssock) 360 475 { 361 476 SSL_METHOD *ssl_method; … … 365 480 pj_status_t status; 366 481 367 pj_assert(ssock && p_ctx);482 pj_assert(ssock); 368 483 369 484 cert = ssock->cert; … … 394 509 } 395 510 396 /* Create SSL context for the listener*/511 /* Create SSL context */ 397 512 ctx = SSL_CTX_new(ssl_method); 398 513 if (ctx == NULL) { … … 456 571 } 457 572 573 /* Create SSL instance */ 574 ssock->ossl_ctx = ctx; 575 ssock->ossl_ssl = SSL_new(ssock->ossl_ctx); 576 if (ssock->ossl_ssl == NULL) { 577 GET_SSL_STATUS(status); 578 return status; 579 } 580 581 /* Set SSL sock as application data of SSL instance */ 582 SSL_set_ex_data(ssock->ossl_ssl, sslsock_idx, ssock); 458 583 459 584 /* SSL verification options */ 460 if (ssock->param.verify_peer) { 461 mode = SSL_VERIFY_PEER; 462 } else { 463 mode = SSL_VERIFY_NONE; 464 } 465 585 mode = SSL_VERIFY_PEER; 466 586 if (ssock->is_server && ssock->param.require_client_cert) 467 mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_PEER; 468 469 SSL_CTX_set_verify(ctx, mode, NULL); 470 471 *p_ctx = ctx; 587 mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; 588 589 SSL_set_verify(ssock->ossl_ssl, mode, &verify_cb); 590 591 /* Set cipher list */ 592 status = set_cipher_list(ssock); 593 if (status != PJ_SUCCESS) 594 return status; 595 596 /* Setup SSL BIOs */ 597 ssock->ossl_rbio = BIO_new(BIO_s_mem()); 598 ssock->ossl_wbio = BIO_new(BIO_s_mem()); 599 BIO_set_close(ssock->ossl_rbio, BIO_CLOSE); 600 BIO_set_close(ssock->ossl_wbio, BIO_CLOSE); 601 SSL_set_bio(ssock->ossl_ssl, ssock->ossl_rbio, ssock->ossl_wbio); 472 602 473 603 return PJ_SUCCESS; … … 475 605 476 606 477 /* Destroy SSL context */ 478 static void destroy_ssl_ctx(SSL_CTX *ctx) 479 { 480 SSL_CTX_free(ctx); 607 /* Destroy SSL context and instance */ 608 static void destroy_ssl(pj_ssl_sock_t *ssock) 609 { 610 /* Destroy SSL instance */ 611 if (ssock->ossl_ssl) { 612 SSL_shutdown(ssock->ossl_ssl); 613 SSL_free(ssock->ossl_ssl); /* this will also close BIOs */ 614 ssock->ossl_ssl = NULL; 615 } 616 617 /* Destroy SSL context */ 618 if (ssock->ossl_ctx) { 619 SSL_CTX_free(ssock->ossl_ctx); 620 ssock->ossl_ctx = NULL; 621 } 481 622 482 623 /* Potentially shutdown OpenSSL library if this is the last … … 492 633 ssock->ssl_state = SSL_STATE_NULL; 493 634 494 if (ssock->ossl_ssl) { 495 SSL_shutdown(ssock->ossl_ssl); 496 SSL_free(ssock->ossl_ssl); /* this will also close BIOs */ 497 ssock->ossl_ssl = NULL; 498 } 499 if (ssock->ossl_ctx) { 500 destroy_ssl_ctx(ssock->ossl_ctx); 501 ssock->ossl_ctx = NULL; 502 } 635 destroy_ssl(ssock); 636 503 637 if (ssock->asock) { 504 638 pj_activesock_close(ssock->asock); … … 640 774 641 775 642 /* Get certificate info from OpenSSL X509 */ 776 /* Get Common Name field string from a general name string */ 777 static void get_cn_from_gen_name(const pj_str_t *gen_name, pj_str_t *cn) 778 { 779 pj_str_t CN_sign = {"/CN=", 4}; 780 char *p, *q; 781 782 pj_bzero(cn, sizeof(cn)); 783 784 p = pj_strstr(gen_name, &CN_sign); 785 if (!p) 786 return; 787 788 p += 4; /* shift pointer to value part */ 789 pj_strset(cn, p, gen_name->slen - (p - gen_name->ptr)); 790 q = pj_strchr(cn, '/'); 791 if (q) 792 cn->slen = q - p; 793 } 794 795 796 /* Get certificate info from OpenSSL X509, in case the certificate info 797 * hal already populated, this function will check if the contents need 798 * to be updated by inspecting the issuer and the serial number. 799 */ 643 800 static void get_cert_info(pj_pool_t *pool, pj_ssl_cert_info *ci, X509 *x) 644 801 { 645 pj_ssl_cert_info info; 646 char buf1[256]; 647 char buf2[256]; 648 649 pj_assert(pool && ci); 650 651 if (!x) { 652 pj_bzero(ci, sizeof(pj_ssl_cert_info)); 802 pj_bool_t update_needed; 803 char buf[512]; 804 pj_uint8_t serial_no[64] = {0}; /* should be >= sizeof(ci->serial_no) */ 805 pj_uint8_t *p; 806 unsigned len; 807 GENERAL_NAMES *names = NULL; 808 809 pj_assert(pool && ci && x); 810 811 /* Get issuer */ 812 X509_NAME_oneline(X509_get_issuer_name(x), buf, sizeof(buf)); 813 814 /* Get serial no */ 815 p = (pj_uint8_t*) M_ASN1_STRING_data(X509_get_serialNumber(x)); 816 len = M_ASN1_STRING_length(X509_get_serialNumber(x)); 817 if (len > sizeof(ci->serial_no)) 818 len = sizeof(ci->serial_no); 819 pj_memcpy(serial_no + sizeof(ci->serial_no) - len, p, len); 820 821 /* Check if the contents need to be updated. */ 822 update_needed = pj_strcmp2(&ci->issuer.info, buf) || 823 pj_memcmp(ci->serial_no, serial_no, sizeof(ci->serial_no)); 824 if (!update_needed) 653 825 return; 654 } 655 656 pj_bzero(&info, sizeof(info)); 657 658 /* Populate cert info */ 659 info.subject = pj_str(X509_NAME_oneline(X509_get_subject_name(x),buf1, 660 sizeof(buf1))); 661 info.issuer = pj_str(X509_NAME_oneline(X509_get_issuer_name(x), buf2, 662 sizeof(buf2))); 663 info.version = X509_get_version(x) + 1; 664 parse_ossl_asn1_time(&info.validity_start, &info.validity_use_gmt, 826 827 /* Update cert info */ 828 829 pj_bzero(ci, sizeof(pj_ssl_cert_info)); 830 831 /* Version */ 832 ci->version = X509_get_version(x) + 1; 833 834 /* Issuer */ 835 pj_strdup2(pool, &ci->issuer.info, buf); 836 get_cn_from_gen_name(&ci->issuer.info, &ci->issuer.cn); 837 838 /* Serial number */ 839 pj_memcpy(ci->serial_no, serial_no, sizeof(ci->serial_no)); 840 841 /* Subject */ 842 pj_strdup2(pool, &ci->subject.info, 843 X509_NAME_oneline(X509_get_subject_name(x), 844 buf, sizeof(buf))); 845 get_cn_from_gen_name(&ci->subject.info, &ci->subject.cn); 846 847 /* Validity */ 848 parse_ossl_asn1_time(&ci->validity.start, &ci->validity.gmt, 665 849 X509_get_notBefore(x)); 666 parse_ossl_asn1_time(& info.validity_end, &info.validity_use_gmt,850 parse_ossl_asn1_time(&ci->validity.end, &ci->validity.gmt, 667 851 X509_get_notAfter(x)); 668 852 669 /* Update certificate info */ 670 if (pj_strcmp(&ci->subject, &info.subject)) 671 pj_strdup(pool, &ci->subject, &info.subject); 672 if (pj_strcmp(&ci->issuer, &info.issuer)) 673 pj_strdup(pool, &ci->issuer, &info.issuer); 674 ci->version = info.version; 675 ci->validity_start = info.validity_start; 676 ci->validity_end = info.validity_end; 677 ci->validity_use_gmt = info.validity_use_gmt; 853 /* Subject Alternative Name extension */ 854 if (ci->version >= 3) { 855 names = (GENERAL_NAMES*) X509_get_ext_d2i(x, NID_subject_alt_name, 856 NULL, NULL); 857 } 858 if (names) { 859 unsigned i, cnt; 860 861 cnt = sk_GENERAL_NAME_num(names); 862 ci->subj_alt_name.entry = pj_pool_calloc(pool, cnt, 863 sizeof(*ci->subj_alt_name.entry)); 864 865 for (i = 0; i < cnt; ++i) { 866 unsigned char *p = 0; 867 pj_ssl_cert_name_type type = PJ_SSL_CERT_NAME_UNKNOWN; 868 const GENERAL_NAME *name; 869 870 name = sk_GENERAL_NAME_value(names, i); 871 872 switch (name->type) { 873 case GEN_EMAIL: 874 len = ASN1_STRING_to_UTF8(&p, name->d.ia5); 875 type = PJ_SSL_CERT_NAME_RFC822; 876 break; 877 case GEN_DNS: 878 len = ASN1_STRING_to_UTF8(&p, name->d.ia5); 879 type = PJ_SSL_CERT_NAME_DNS; 880 break; 881 case GEN_URI: 882 len = ASN1_STRING_to_UTF8(&p, name->d.ia5); 883 type = PJ_SSL_CERT_NAME_URI; 884 break; 885 case GEN_IPADD: 886 p = ASN1_STRING_data(name->d.ip); 887 len = ASN1_STRING_length(name->d.ip); 888 type = PJ_SSL_CERT_NAME_IP; 889 break; 890 default: 891 break; 892 } 893 894 if (p && len && type != PJ_SSL_CERT_NAME_UNKNOWN) { 895 ci->subj_alt_name.entry[ci->subj_alt_name.cnt].type = type; 896 if (type == PJ_SSL_CERT_NAME_IP) { 897 int af = pj_AF_INET(); 898 if (len == sizeof(pj_in6_addr)) af = pj_AF_INET6(); 899 pj_inet_ntop2(af, p, buf, sizeof(buf)); 900 pj_strdup2(pool, 901 &ci->subj_alt_name.entry[ci->subj_alt_name.cnt].name, 902 buf); 903 } else { 904 pj_strdup2(pool, 905 &ci->subj_alt_name.entry[ci->subj_alt_name.cnt].name, 906 (char*)p); 907 OPENSSL_free(p); 908 } 909 ci->subj_alt_name.cnt++; 910 } 911 } 912 } 678 913 } 679 914 … … 690 925 /* Active local certificate */ 691 926 x = SSL_get_certificate(ssock->ossl_ssl); 692 get_cert_info(ssock->pool, &ssock->local_cert_info, x); 693 /* Don't free local's X509! */ 927 if (x) { 928 get_cert_info(ssock->pool, &ssock->local_cert_info, x); 929 /* Don't free local's X509! */ 930 } else { 931 pj_bzero(&ssock->local_cert_info, sizeof(pj_ssl_cert_info)); 932 } 694 933 695 934 /* Active remote certificate */ 696 935 x = SSL_get_peer_certificate(ssock->ossl_ssl); 697 get_cert_info(ssock->pool, &ssock->remote_cert_info, x); 698 /* Free peer's X509 */ 699 X509_free(x); 936 if (x) { 937 get_cert_info(ssock->pool, &ssock->remote_cert_info, x); 938 /* Free peer's X509 */ 939 X509_free(x); 940 } else { 941 pj_bzero(&ssock->remote_cert_info, sizeof(pj_ssl_cert_info)); 942 } 700 943 } 701 944 … … 1232 1475 1233 1476 /* Create SSL context */ 1234 status = create_ssl _ctx(ssock, &ssock->ossl_ctx);1477 status = create_ssl(ssock); 1235 1478 if (status != PJ_SUCCESS) 1236 1479 goto on_return; 1237 1238 /* Create SSL instance */1239 ssock->ossl_ssl = SSL_new(ssock->ossl_ctx);1240 if (ssock->ossl_ssl == NULL) {1241 GET_SSL_STATUS(status);1242 goto on_return;1243 }1244 1245 /* Set cipher list */1246 status = set_cipher_list(ssock);1247 if (status != PJ_SUCCESS)1248 goto on_return;1249 1250 /* Setup SSL BIOs */1251 ssock->ossl_rbio = BIO_new(BIO_s_mem());1252 ssock->ossl_wbio = BIO_new(BIO_s_mem());1253 BIO_set_close(ssock->ossl_rbio, BIO_CLOSE);1254 BIO_set_close(ssock->ossl_wbio, BIO_CLOSE);1255 SSL_set_bio(ssock->ossl_ssl, ssock->ossl_rbio, ssock->ossl_wbio);1256 1480 1257 1481 /* Prepare read buffer */ … … 1352 1576 1353 1577 /* Create SSL context */ 1354 status = create_ssl _ctx(ssock, &ssock->ossl_ctx);1578 status = create_ssl(ssock); 1355 1579 if (status != PJ_SUCCESS) 1356 1580 goto on_return; 1357 1358 /* Create SSL instance */1359 ssock->ossl_ssl = SSL_new(ssock->ossl_ctx);1360 if (ssock->ossl_ssl == NULL) {1361 GET_SSL_STATUS(status);1362 goto on_return;1363 }1364 1365 /* Set cipher list */1366 status = set_cipher_list(ssock);1367 if (status != PJ_SUCCESS)1368 goto on_return;1369 1370 /* Setup SSL BIOs */1371 ssock->ossl_rbio = BIO_new(BIO_s_mem());1372 ssock->ossl_wbio = BIO_new(BIO_s_mem());1373 BIO_set_close(ssock->ossl_rbio, BIO_CLOSE);1374 BIO_set_close(ssock->ossl_wbio, BIO_CLOSE);1375 SSL_set_bio(ssock->ossl_ssl, ssock->ossl_rbio, ssock->ossl_wbio);1376 1581 1377 1582 /* Prepare read buffer */ … … 1652 1857 1653 1858 if (info->established) { 1859 const SSL_CIPHER *cipher; 1860 1654 1861 /* Current cipher */ 1655 const SSL_CIPHER *cipher;1656 1657 1862 cipher = SSL_get_current_cipher(ssock->ossl_ssl); 1658 1863 info->cipher = (cipher->id & 0x00FFFFFF); … … 1662 1867 1663 1868 /* Certificates info */ 1664 info->local_cert_info = ssock->local_cert_info; 1665 info->remote_cert_info = ssock->remote_cert_info; 1869 info->local_cert_info = &ssock->local_cert_info; 1870 info->remote_cert_info = &ssock->remote_cert_info; 1871 1872 /* Verification status */ 1873 info->verify_status = ssock->verify_status; 1666 1874 } 1667 1875 -
pjproject/trunk/pjlib/src/pj/ssl_sock_symbian.cpp
r2998 r3106 128 128 return KErrNotFound; 129 129 } 130 const CX509Certificate *GetPeerCert() { 131 if (securesock_) 132 return securesock_->ServerCert(); 133 return NULL; 134 } 130 135 131 136 private: … … 410 415 struct pj_ssl_sock_t 411 416 { 417 pj_pool_t *pool; 412 418 pj_ssl_sock_cb cb; 413 419 void *user_data; … … 435 441 pj_ssl_cipher *ciphers; 436 442 pj_str_t servername; 443 pj_ssl_cert_info remote_cert_info; 437 444 }; 445 446 447 static pj_str_t get_cert_name(pj_pool_t *pool, 448 const CX500DistinguishedName &name) 449 { 450 TInt i; 451 char buf[1024]; 452 TUint8 *p; 453 TInt l = sizeof(buf); 454 455 p = (TUint8*)buf; 456 for(i = 0; i < name.Count(); ++i) { 457 const CX520AttributeTypeAndValue &attr = name.Element(i); 458 459 /* Print element separator */ 460 *p++ = '/'; 461 if (0 == --l) break; 462 463 /* Print the type. */ 464 TPtr8 type(p, l); 465 type.Copy(attr.Type()); 466 p += type.Length(); 467 l -= type.Length(); 468 if (0 >= --l) break; 469 470 /* Print equal sign */ 471 *p++ = '='; 472 if (0 == --l) break; 473 474 /* Print the value. Let's just get the raw data here */ 475 TPtr8 value(p, l); 476 value.Copy(attr.EncodedValue().Mid(2)); 477 p += value.Length(); 478 l -= value.Length(); 479 if (0 >= --l) break; 480 } 481 482 pj_str_t src, res; 483 pj_strset(&src, buf, sizeof(buf) - l); 484 pj_strdup(pool, &res, &src); 485 486 return res; 487 } 488 489 /* Get certificate info from CX509Certificate. 490 */ 491 static void get_cert_info(pj_pool_t *pool, pj_ssl_cert_info *ci, 492 const CX509Certificate *x) 493 { 494 unsigned len; 495 496 pj_assert(pool && ci && x); 497 498 pj_bzero(ci, sizeof(*ci)); 499 500 /* Version */ 501 ci->version = x->Version(); 502 503 /* Serial number */ 504 len = x->SerialNumber().Length(); 505 if (len > sizeof(ci->serial_no)) 506 len = sizeof(ci->serial_no); 507 pj_memcpy(ci->serial_no + sizeof(ci->serial_no) - len, 508 x->SerialNumber().Ptr(), len); 509 510 /* Subject */ 511 { 512 HBufC *subject = NULL; 513 TRAPD(err, subject = x->SubjectL()); 514 if (err == KErrNone) { 515 TPtr16 ptr16(subject->Des()); 516 len = ptr16.Length(); 517 TPtr8 ptr8((TUint8*)pj_pool_alloc(pool, len), len); 518 ptr8.Copy(ptr16); 519 pj_strset(&ci->subject.cn, (char*)ptr8.Ptr(), ptr8.Length()); 520 } 521 ci->subject.info = get_cert_name(pool, x->SubjectName()); 522 } 523 524 /* Issuer */ 525 { 526 HBufC *issuer = NULL; 527 TRAPD(err, issuer = x->IssuerL()); 528 if (err == KErrNone) { 529 TPtr16 ptr16(issuer->Des()); 530 len = ptr16.Length(); 531 TPtr8 ptr8((TUint8*)pj_pool_alloc(pool, len), len); 532 ptr8.Copy(ptr16); 533 pj_strset(&ci->issuer.cn, (char*)ptr8.Ptr(), ptr8.Length()); 534 } 535 ci->issuer.info = get_cert_name(pool, x->IssuerName()); 536 } 537 538 /* Validity */ 539 const CValidityPeriod &valid_period = x->ValidityPeriod(); 540 TTime base_time(TDateTime(1970, EJanuary, 0, 0, 0, 0, 0)); 541 TTimeIntervalSeconds tmp_sec; 542 valid_period.Start().SecondsFrom(base_time, tmp_sec); 543 ci->validity.start.sec = tmp_sec.Int(); 544 valid_period.Finish().SecondsFrom(base_time, tmp_sec); 545 ci->validity.end.sec = tmp_sec.Int(); 546 } 547 548 549 /* Update certificates info. This function should be called after handshake 550 * or renegotiation successfully completed. 551 */ 552 static void update_certs_info(pj_ssl_sock_t *ssock) 553 { 554 const CX509Certificate *x; 555 556 pj_assert(ssock && ssock->sock && 557 ssock->sock->GetState() == CPjSSLSocket::SSL_STATE_ESTABLISHED); 558 559 /* Active remote certificate */ 560 x = ssock->sock->GetPeerCert(); 561 if (x) { 562 get_cert_info(ssock->pool, &ssock->remote_cert_info, x); 563 } else { 564 pj_bzero(&ssock->remote_cert_info, sizeof(pj_ssl_cert_info)); 565 } 566 } 438 567 439 568 … … 505 634 506 635 /* Init secure socket */ 636 ssock->pool = pool; 507 637 ssock->sock_af = param->sock_af; 508 638 ssock->sock_type = param->sock_type; … … 644 774 /* Remote address */ 645 775 pj_sockaddr_cp((pj_sockaddr_t*)&info->remote_addr, 646 (pj_sockaddr_t*)&ssock->rem_addr); 776 (pj_sockaddr_t*)&ssock->rem_addr); 777 778 /* Certificates info */ 779 info->remote_cert_info = &ssock->remote_cert_info; 647 780 } 648 781 … … 729 862 status = reader->Read(&read_cb, ssock, *ssock->read_state.read_buf, 730 863 ssock->read_state.flags); 731 if (status != PJ_EPENDING) { 732 /* Notify error */ 733 (*ssock->cb.on_data_read)(ssock, NULL, 0, status, NULL); 734 } 735 } 736 864 } 865 866 /* Connection closed or something goes wrong */ 737 867 if (status != PJ_SUCCESS && status != PJ_EPENDING) { 738 /* Connection closed or something goes wrong */ 868 /* Notify error */ 869 if (ssock->cb.on_data_read) { 870 pj_bool_t ret = (*ssock->cb.on_data_read)(ssock, NULL, 0, 871 status, NULL); 872 if (!ret) { 873 /* We've been destroyed */ 874 return; 875 } 876 } 877 739 878 delete ssock->read_state.read_buf; 740 879 delete ssock->read_state.orig_buf; … … 1002 1141 if (status == PJ_SUCCESS) { 1003 1142 ssock->established = PJ_TRUE; 1143 update_certs_info(ssock); 1004 1144 } else { 1005 1145 delete ssock->sock; -
pjproject/trunk/pjlib/src/pjlib-test/ssl_sock.c
r3018 r3106 23 23 24 24 #define CERT_DIR "../build/" 25 #define CERT_CA_FILE NULL25 #define CERT_CA_FILE CERT_DIR "cacert.pem" 26 26 #define CERT_FILE CERT_DIR "cacert.pem" 27 27 #define CERT_PRIVKEY_FILE CERT_DIR "privkey.pem" … … 84 84 }; 85 85 86 static void dump_ cert_info(const char *prefix, const pj_ssl_cert_info *ci)86 static void dump_ssl_info(const pj_ssl_sock_info *si) 87 87 { 88 const char *wdays[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; 89 pj_parsed_time pt1; 90 pj_parsed_time pt2; 91 92 pj_time_decode(&ci->validity_start, &pt1); 93 pj_time_decode(&ci->validity_end, &pt2); 94 95 PJ_LOG(3, ("", "%sSubject : %.*s", prefix, ci->subject.slen, ci->subject.ptr)); 96 PJ_LOG(3, ("", "%sIssuer : %.*s", prefix, ci->issuer.slen, ci->issuer.ptr)); 97 PJ_LOG(3, ("", "%sVersion : v%d", prefix, ci->version)); 98 PJ_LOG(3, ("", "%sValid from : %s %4d-%02d-%02d %02d:%02d:%02d.%03d %s", 99 prefix, wdays[pt1.wday], pt1.year, pt1.mon+1, pt1.day, 100 pt1.hour, pt1.min, pt1.sec, pt1.msec, 101 (ci->validity_use_gmt? "GMT":""))); 102 PJ_LOG(3, ("", "%sValid to : %s %4d-%02d-%02d %02d:%02d:%02d.%03d %s", 103 prefix, wdays[pt2.wday], pt2.year, pt2.mon+1, pt2.day, 104 pt2.hour, pt2.min, pt2.sec, pt2.msec, 105 (ci->validity_use_gmt? "GMT":""))); 88 const char *tmp_st; 89 90 /* Print cipher name */ 91 tmp_st = pj_ssl_cipher_name(si->cipher); 92 if (tmp_st == NULL) 93 tmp_st = "[Unknown]"; 94 PJ_LOG(3, ("", ".....Cipher: %s", tmp_st)); 95 96 /* Print remote certificate info and verification result */ 97 if (si->remote_cert_info && si->remote_cert_info->subject.info.slen) 98 { 99 char buf[2048]; 100 const char *verif_msgs[32]; 101 unsigned verif_msg_cnt; 102 103 /* Dump remote TLS certificate info */ 104 PJ_LOG(3, ("", ".....Remote certificate info:")); 105 pj_ssl_cert_info_dump(si->remote_cert_info, " ", buf, sizeof(buf)); 106 PJ_LOG(3,("", "\n%s", buf)); 107 108 /* Dump remote TLS certificate verification result */ 109 verif_msg_cnt = PJ_ARRAY_SIZE(verif_msgs); 110 pj_ssl_cert_verify_error_st(si->verify_status, 111 verif_msgs, &verif_msg_cnt); 112 PJ_LOG(3,("", ".....Remote certificate verification result: %s", 113 (verif_msg_cnt == 1? verif_msgs[0]:""))); 114 if (verif_msg_cnt > 1) { 115 unsigned i; 116 for (i = 0; i < verif_msg_cnt; ++i) 117 PJ_LOG(3,("", "..... - %s", verif_msgs[i])); 118 } 119 } 106 120 } 107 121 … … 131 145 PJ_LOG(3, ("", "...Connected %s -> %s!", buf1, buf2)); 132 146 133 if (st->is_verbose) { 134 const char *tmp_st; 135 136 /* Print cipher name */ 137 tmp_st = pj_ssl_cipher_name(info.cipher); 138 if (tmp_st == NULL) 139 tmp_st = "[Unknown]"; 140 PJ_LOG(3, ("", ".....Cipher: %s", tmp_st)); 141 142 /* Print certificates info */ 143 if (info.local_cert_info.subject.slen) { 144 PJ_LOG(3, ("", ".....Local certificate info:")); 145 dump_cert_info(".......", &info.local_cert_info); 146 } 147 if (info.remote_cert_info.subject.slen) { 148 PJ_LOG(3, ("", ".....Remote certificate info:")); 149 dump_cert_info(".......", &info.remote_cert_info); 150 } 151 } 147 if (st->is_verbose) 148 dump_ssl_info(&info); 152 149 153 150 /* Start reading data */ … … 199 196 struct test_state *st; 200 197 void *read_buf[1]; 198 pj_ssl_sock_info info; 199 char buf[64]; 201 200 pj_status_t status; 202 201 … … 208 207 pj_ssl_sock_set_user_data(newsock, st); 209 208 210 if (st->is_verbose) { 211 pj_ssl_sock_info info; 212 char buf[64]; 213 const char *tmp_st; 214 215 status = pj_ssl_sock_get_info(newsock, &info); 216 if (status != PJ_SUCCESS) { 217 app_perror("...ERROR pj_ssl_sock_get_info()", status); 218 goto on_return; 219 } 220 221 pj_sockaddr_print(src_addr, buf, sizeof(buf), 1); 222 PJ_LOG(3, ("", "...Accepted connection from %s", buf)); 223 224 /* Print cipher name */ 225 tmp_st = pj_ssl_cipher_name(info.cipher); 226 if (tmp_st == NULL) 227 tmp_st = "[Unknown]"; 228 PJ_LOG(3, ("", ".....Cipher: %s", tmp_st)); 229 230 /* Print certificates info */ 231 if (info.local_cert_info.subject.slen) { 232 PJ_LOG(3, ("", ".....Local certificate info:")); 233 dump_cert_info(".......", &info.local_cert_info); 234 } 235 if (info.remote_cert_info.subject.slen) { 236 PJ_LOG(3, ("", ".....Remote certificate info:")); 237 dump_cert_info(".......", &info.remote_cert_info); 238 } 239 } 209 status = pj_ssl_sock_get_info(newsock, &info); 210 if (status != PJ_SUCCESS) { 211 app_perror("...ERROR pj_ssl_sock_get_info()", status); 212 goto on_return; 213 } 214 215 pj_sockaddr_print(src_addr, buf, sizeof(buf), 1); 216 PJ_LOG(3, ("", "...Accepted connection from %s", buf)); 217 218 if (st->is_verbose) 219 dump_ssl_info(&info); 240 220 241 221 /* Start reading data */ … … 461 441 param.timeout.sec = 0; 462 442 param.timeout.msec = ms_timeout; 443 param.proto = PJ_SSL_SOCK_PROTO_SSL23; 463 444 pj_time_val_normalize(¶m.timeout); 464 445 … … 513 494 514 495 static int echo_test(pj_ssl_sock_proto srv_proto, pj_ssl_sock_proto cli_proto, 515 pj_ssl_cipher srv_cipher, pj_ssl_cipher cli_cipher) 496 pj_ssl_cipher srv_cipher, pj_ssl_cipher cli_cipher, 497 pj_bool_t req_client_cert, pj_bool_t client_provide_cert) 516 498 { 517 499 pj_pool_t *pool = NULL; … … 534 516 } 535 517 536 /* Set cert */ 518 pj_ssl_sock_param_default(¶m); 519 param.cb.on_accept_complete = &ssl_on_accept_complete; 520 param.cb.on_connect_complete = &ssl_on_connect_complete; 521 param.cb.on_data_read = &ssl_on_data_read; 522 param.cb.on_data_sent = &ssl_on_data_sent; 523 param.ioqueue = ioqueue; 524 param.ciphers = ciphers; 525 526 /* Init default bind address */ 527 { 528 pj_str_t tmp_st; 529 pj_sockaddr_init(PJ_AF_INET, &addr, pj_strset2(&tmp_st, "127.0.0.1"), 0); 530 } 531 532 /* === SERVER === */ 533 param.proto = srv_proto; 534 param.user_data = &state_serv; 535 param.ciphers_num = (srv_cipher == -1)? 0 : 1; 536 param.require_client_cert = req_client_cert; 537 ciphers[0] = srv_cipher; 538 539 state_serv.pool = pool; 540 state_serv.echo = PJ_TRUE; 541 state_serv.is_server = PJ_TRUE; 542 state_serv.is_verbose = PJ_TRUE; 543 544 status = pj_ssl_sock_create(pool, ¶m, &ssock_serv); 545 if (status != PJ_SUCCESS) { 546 goto on_return; 547 } 548 549 /* Set server cert */ 537 550 { 538 551 pj_str_t tmp1, tmp2, tmp3, tmp4; … … 547 560 goto on_return; 548 561 } 549 } 550 551 pj_ssl_sock_param_default(¶m); 552 param.cb.on_accept_complete = &ssl_on_accept_complete; 553 param.cb.on_connect_complete = &ssl_on_connect_complete; 554 param.cb.on_data_read = &ssl_on_data_read; 555 param.cb.on_data_sent = &ssl_on_data_sent; 556 param.ioqueue = ioqueue; 557 param.ciphers = ciphers; 558 559 /* Init default bind address */ 560 { 561 pj_str_t tmp_st; 562 pj_sockaddr_init(PJ_AF_INET, &addr, pj_strset2(&tmp_st, "127.0.0.1"), 0); 563 } 564 565 /* SERVER */ 566 param.proto = srv_proto; 567 param.user_data = &state_serv; 568 param.ciphers_num = (srv_cipher == -1)? 0 : 1; 569 ciphers[0] = srv_cipher; 570 571 state_serv.pool = pool; 572 state_serv.echo = PJ_TRUE; 573 state_serv.is_server = PJ_TRUE; 574 state_serv.is_verbose = PJ_TRUE; 575 576 status = pj_ssl_sock_create(pool, ¶m, &ssock_serv); 577 if (status != PJ_SUCCESS) { 578 goto on_return; 579 } 580 581 status = pj_ssl_sock_set_certificate(ssock_serv, pool, cert); 582 if (status != PJ_SUCCESS) { 583 goto on_return; 562 563 status = pj_ssl_sock_set_certificate(ssock_serv, pool, cert); 564 if (status != PJ_SUCCESS) { 565 goto on_return; 566 } 584 567 } 585 568 … … 597 580 } 598 581 599 /* CLIENT*/582 /* === CLIENT === */ 600 583 param.proto = cli_proto; 601 584 param.user_data = &state_cli; … … 624 607 if (status != PJ_SUCCESS) { 625 608 goto on_return; 609 } 610 611 /* Set cert for client */ 612 { 613 614 if (!client_provide_cert) { 615 pj_str_t tmp1, tmp2; 616 617 pj_strset2(&tmp1, (char*)CERT_CA_FILE); 618 pj_strset2(&tmp2, NULL); 619 status = pj_ssl_cert_load_from_files(pool, 620 &tmp1, &tmp2, &tmp2, &tmp2, 621 &cert); 622 if (status != PJ_SUCCESS) { 623 goto on_return; 624 } 625 } 626 627 status = pj_ssl_sock_set_certificate(ssock_cli, pool, cert); 628 if (status != PJ_SUCCESS) { 629 goto on_return; 630 } 626 631 } 627 632 … … 1014 1019 state_cli = pj_pool_calloc(pool, clients, sizeof(struct test_state)); 1015 1020 1021 /* Get start timestamp */ 1022 pj_gettimeofday(&start); 1023 1016 1024 /* Setup clients */ 1017 1025 for (i = 0; i < clients; ++i) { … … 1065 1073 } 1066 1074 1067 /* Get start timestamp */1068 pj_gettimeofday(&start);1069 1070 1075 /* Wait until everything has been sent/received or error */ 1071 1076 while (clients_num) … … 1151 1156 PJ_LOG(3,("", "..echo test w/ TLSv1 and TLS_RSA_WITH_DES_CBC_SHA cipher")); 1152 1157 ret = echo_test(PJ_SSL_SOCK_PROTO_TLS1, PJ_SSL_SOCK_PROTO_TLS1, 1153 TLS_RSA_WITH_DES_CBC_SHA, TLS_RSA_WITH_DES_CBC_SHA); 1158 TLS_RSA_WITH_DES_CBC_SHA, TLS_RSA_WITH_DES_CBC_SHA, 1159 PJ_FALSE, PJ_FALSE); 1154 1160 if (ret != 0) 1155 1161 return ret; … … 1157 1163 PJ_LOG(3,("", "..echo test w/ SSLv23 and TLS_RSA_WITH_AES_256_CBC_SHA cipher")); 1158 1164 ret = echo_test(PJ_SSL_SOCK_PROTO_SSL23, PJ_SSL_SOCK_PROTO_SSL23, 1159 TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA); 1165 TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, 1166 PJ_FALSE, PJ_FALSE); 1160 1167 if (ret != 0) 1161 1168 return ret; … … 1163 1170 PJ_LOG(3,("", "..echo test w/ incompatible proto")); 1164 1171 ret = echo_test(PJ_SSL_SOCK_PROTO_TLS1, PJ_SSL_SOCK_PROTO_SSL3, 1165 TLS_RSA_WITH_DES_CBC_SHA, TLS_RSA_WITH_DES_CBC_SHA); 1172 TLS_RSA_WITH_DES_CBC_SHA, TLS_RSA_WITH_DES_CBC_SHA, 1173 PJ_FALSE, PJ_FALSE); 1166 1174 if (ret == 0) 1167 1175 return PJ_EBUG; … … 1169 1177 PJ_LOG(3,("", "..echo test w/ incompatible ciphers")); 1170 1178 ret = echo_test(PJ_SSL_SOCK_PROTO_DEFAULT, PJ_SSL_SOCK_PROTO_DEFAULT, 1171 TLS_RSA_WITH_DES_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA); 1179 TLS_RSA_WITH_DES_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, 1180 PJ_FALSE, PJ_FALSE); 1172 1181 if (ret == 0) 1173 1182 return PJ_EBUG; 1183 1184 PJ_LOG(3,("", "..echo test w/ client cert required but not provided")); 1185 ret = echo_test(PJ_SSL_SOCK_PROTO_DEFAULT, PJ_SSL_SOCK_PROTO_DEFAULT, 1186 TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, 1187 PJ_TRUE, PJ_FALSE); 1188 if (ret == 0) 1189 return PJ_EBUG; 1190 1191 PJ_LOG(3,("", "..echo test w/ client cert required and provided")); 1192 ret = echo_test(PJ_SSL_SOCK_PROTO_DEFAULT, PJ_SSL_SOCK_PROTO_DEFAULT, 1193 TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, 1194 PJ_TRUE, PJ_TRUE); 1195 if (ret != 0) 1196 return ret; 1174 1197 1175 1198 PJ_LOG(3,("", "..client non-SSL (handshake timeout 5 secs)")); -
pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c
r3093 r3106 2789 2789 2790 2790 /* 2791 * Transport status notification 2792 */ 2793 static pj_bool_t on_transport_state(pjsip_transport *tp, pj_uint32_t state, 2794 const pjsip_transport_state_info *info) 2795 { 2796 char host_port[128]; 2797 2798 pj_ansi_snprintf(host_port, sizeof(host_port), "[%.*s:%d]", 2799 (int)tp->remote_name.host.slen, 2800 tp->remote_name.host.ptr, 2801 tp->remote_name.port); 2802 2803 if (state & PJSIP_TP_STATE_CONNECTED) { 2804 PJ_LOG(3,(THIS_FILE, "SIP transport %s is connected to %s", 2805 tp->type_name, host_port)); 2806 } 2807 else if (state & PJSIP_TP_STATE_ACCEPTED) { 2808 PJ_LOG(3,(THIS_FILE, "SIP transport %s accepted %s", 2809 tp->type_name, host_port)); 2810 } 2811 else if (state & PJSIP_TP_STATE_DISCONNECTED) { 2812 char buf[100]; 2813 2814 snprintf(buf, sizeof(buf), "SIP transport %s is disconnected from %s", 2815 tp->type_name, host_port); 2816 pjsua_perror(THIS_FILE, buf, info->status); 2817 } 2818 else if (state & PJSIP_TP_STATE_REJECTED) { 2819 char buf[100]; 2820 2821 snprintf(buf, sizeof(buf), "SIP transport %s rejected %s", 2822 tp->type_name, host_port); 2823 pjsua_perror(THIS_FILE, buf, info->status); 2824 } 2825 2826 #if defined(PJSIP_HAS_TLS_TRANSPORT) && PJSIP_HAS_TLS_TRANSPORT!=0 2827 2828 if (!pj_ansi_stricmp(tp->type_name, "tls") && info->ext_info && 2829 (state == PJSIP_TP_STATE_CONNECTED || 2830 (state & PJSIP_TP_STATE_TLS_VERIF_ERROR))) 2831 { 2832 pjsip_tls_state_info *tls_info = (pjsip_tls_state_info*)info->ext_info; 2833 pj_ssl_sock_info *ssl_sock_info = (pj_ssl_sock_info*) 2834 tls_info->ssl_sock_info; 2835 char buf[2048]; 2836 const char *verif_msgs[32]; 2837 unsigned verif_msg_cnt; 2838 2839 /* Dump server TLS certificate */ 2840 pj_ssl_cert_info_dump(ssl_sock_info->remote_cert_info, " ", 2841 buf, sizeof(buf)); 2842 PJ_LOG(4,(THIS_FILE, "TLS cert info of %s:\n%s", host_port, buf)); 2843 2844 /* Dump server TLS certificate verification result */ 2845 verif_msg_cnt = PJ_ARRAY_SIZE(verif_msgs); 2846 pj_ssl_cert_verify_error_st(ssl_sock_info->verify_status, 2847 verif_msgs, &verif_msg_cnt); 2848 PJ_LOG(3,(THIS_FILE, "TLS cert verification result of %s : %s", 2849 host_port, 2850 (verif_msg_cnt == 1? verif_msgs[0]:""))); 2851 if (verif_msg_cnt > 1) { 2852 unsigned i; 2853 for (i = 0; i < verif_msg_cnt; ++i) 2854 PJ_LOG(3,(THIS_FILE, "- %s", verif_msgs[i])); 2855 } 2856 2857 if (state & PJSIP_TP_STATE_TLS_VERIF_ERROR && 2858 !app_config.udp_cfg.tls_setting.verify_server) 2859 { 2860 PJ_LOG(3,(THIS_FILE, "PJSUA is configured to ignore TLS cert " 2861 "verification errors")); 2862 } 2863 } 2864 2865 #endif 2866 return PJ_TRUE; 2867 } 2868 2869 /* 2791 2870 * Print buddy list. 2792 2871 */ … … 4384 4463 app_config.cfg.cb.on_nat_detect = &on_nat_detect; 4385 4464 app_config.cfg.cb.on_mwi_info = &on_mwi_info; 4465 app_config.cfg.cb.on_transport_state = &on_transport_state; 4386 4466 4387 4467 /* Set sound device latency */ -
pjproject/trunk/pjsip-apps/src/symbian_ua/ua.cpp
r2999 r3106 271 271 } 272 272 273 /* 274 * Transport status notification 275 */ 276 static pj_bool_t on_transport_state(pjsip_transport *tp, pj_uint32_t state, 277 const pjsip_transport_state_info *info) 278 { 279 char host_port[128]; 280 281 pj_ansi_snprintf(host_port, sizeof(host_port), "[%.*s:%d]", 282 (int)tp->remote_name.host.slen, 283 tp->remote_name.host.ptr, 284 tp->remote_name.port); 285 286 if (state & PJSIP_TP_STATE_CONNECTED) { 287 PJ_LOG(3,(THIS_FILE, "SIP transport %s is connected to %s", 288 tp->type_name, host_port)); 289 } 290 else if (state & PJSIP_TP_STATE_ACCEPTED) { 291 PJ_LOG(3,(THIS_FILE, "SIP transport %s accepted %s", 292 tp->type_name, host_port)); 293 } 294 else if (state & PJSIP_TP_STATE_DISCONNECTED) { 295 char buf[100]; 296 297 snprintf(buf, sizeof(buf), "SIP transport %s is disconnected from %s", 298 tp->type_name, host_port); 299 pjsua_perror(THIS_FILE, buf, info->status); 300 } 301 else if (state & PJSIP_TP_STATE_REJECTED) { 302 char buf[100]; 303 304 snprintf(buf, sizeof(buf), "SIP transport %s rejected %s", 305 tp->type_name, host_port); 306 pjsua_perror(THIS_FILE, buf, info->status); 307 } 308 309 #if defined(PJSIP_HAS_TLS_TRANSPORT) && PJSIP_HAS_TLS_TRANSPORT!=0 310 311 if (!pj_ansi_stricmp(tp->type_name, "tls") && info->ext_info && 312 (state == PJSIP_TP_STATE_CONNECTED || 313 (state & PJSIP_TP_STATE_TLS_VERIF_ERROR))) 314 { 315 pjsip_tls_state_info *tls_info = (pjsip_tls_state_info*)info->ext_info; 316 pj_ssl_sock_info *ssl_sock_info = (pj_ssl_sock_info*) 317 tls_info->ssl_sock_info; 318 char buf[2048]; 319 320 /* Dump server TLS certificate */ 321 pj_ssl_cert_info_dump(ssl_sock_info->remote_cert_info, " ", 322 buf, sizeof(buf)); 323 PJ_LOG(4,(THIS_FILE, "TLS cert info of %s:\n%s", host_port, buf)); 324 } 325 326 #endif 327 return PJ_TRUE; 328 } 329 273 330 274 331 //#include<e32debug.h> … … 331 388 cfg.cb.on_call_replaced = &on_call_replaced; 332 389 cfg.cb.on_nat_detect = &on_nat_detect; 390 cfg.cb.on_transport_state = &on_transport_state; 333 391 334 392 if (SIP_PROXY) { … … 1055 1113 1056 1114 // Initialize RSocketServ 1057 if ((err=aSocketServer.Connect( )) != KErrNone)1115 if ((err=aSocketServer.Connect(32)) != KErrNone) 1058 1116 return PJ_STATUS_FROM_OS(err); 1059 1117 -
pjproject/trunk/pjsip-apps/src/symbian_ua_gui/group/symbian_ua_gui.mmp
r2821 r3106 42 42 LIBRARY ecom.lib inetprotutil.lib http.lib esock.lib 43 43 LIBRARY charconv.lib estlib.lib 44 LIBRARY securesocket.lib x509.lib crypto.lib x500.lib 44 45 45 46 // Ordering static libs based on dependencies, most to least dependent, -
pjproject/trunk/pjsip-apps/src/symbian_ua_gui/src/symbian_ua.cpp
r2394 r3106 264 264 265 265 // Initialize RSocketServ 266 if ((err=aSocketServer.Connect( )) != KErrNone)266 if ((err=aSocketServer.Connect(32)) != KErrNone) 267 267 return PJ_STATUS_FROM_OS(err); 268 268 -
pjproject/trunk/pjsip/include/pjsip/sip_endpoint.h
r2394 r3106 373 373 374 374 375 /** 376 * Find a SIP transport suitable for sending SIP message to the specified 377 * address by also considering the outgoing SIP message data. If transport 378 * selector ("sel") is set, then the function will check if the transport 379 * selected is suitable to send requests to the specified address. 380 * 381 * @see pjsip_tpmgr_acquire_transport 382 * 383 * @param endpt The SIP endpoint instance. 384 * @param type The type of transport to be acquired. 385 * @param remote The remote address to send message to. 386 * @param addr_len Length of the remote address. 387 * @param sel Optional pointer to transport selector instance which is 388 * used to find explicit transport, if required. 389 * @param tdata Optional pointer to SIP message data to be sent. 390 * @param p_tp Pointer to receive the transport instance, if one is found. 391 * 392 * @return PJ_SUCCESS on success, or the appropriate error code. 393 */ 394 PJ_DECL(pj_status_t) 395 pjsip_endpt_acquire_transport2(pjsip_endpoint *endpt, 396 pjsip_transport_type_e type, 397 const pj_sockaddr_t *remote, 398 int addr_len, 399 const pjsip_tpselector *sel, 400 pjsip_tx_data *tdata, 401 pjsip_transport **p_tp); 402 403 375 404 /***************************************************************************** 376 405 * -
pjproject/trunk/pjsip/include/pjsip/sip_transport.h
r3077 r3106 541 541 struct 542 542 { 543 /** Server name. 544 */ 545 pj_str_t name; 546 543 547 /** Server addresses resolved. 544 548 */ … … 688 692 */ 689 693 long type; 694 695 /** 696 * Hash of host name. 697 */ 698 pj_uint32_t hname; 690 699 691 700 /** … … 919 928 920 929 /** 921 * Create new outbound connection. 930 * Create new outbound connection suitable for sending SIP message 931 * to specified remote address. 922 932 * Note that the factory is responsible for both creating the 923 933 * transport and registering it to the transport manager. … … 929 939 int addr_len, 930 940 pjsip_transport **transport); 941 942 /** 943 * Create new outbound connection suitable for sending SIP message 944 * to specified remote address by also considering outgoing SIP 945 * message data. 946 * Note that the factory is responsible for both creating the 947 * transport and registering it to the transport manager. 948 */ 949 pj_status_t (*create_transport2)(pjsip_tpfactory *factory, 950 pjsip_tpmgr *mgr, 951 pjsip_endpoint *endpt, 952 const pj_sockaddr *rem_addr, 953 int addr_len, 954 pjsip_tx_data *tdata, 955 pjsip_transport **transport); 931 956 932 957 /** … … 1099 1124 const pjsip_tpselector *sel, 1100 1125 pjsip_transport **tp); 1126 1127 /** 1128 * Find suitable transport for sending SIP message to specified remote 1129 * destination by also considering the outgoing SIP message. If no suitable 1130 * transport is found, a new one will be created. 1131 * 1132 * This is an internal function since normally application doesn't have access 1133 * to transport manager. Application should use pjsip_endpt_acquire_transport() 1134 * instead. 1135 * 1136 * @param mgr The transport manager instance. 1137 * @param type The type of transport to be acquired. 1138 * @param remote The remote address to send message to. 1139 * @param addr_len Length of the remote address. 1140 * @param sel Optional pointer to transport selector instance which is 1141 * used to find explicit transport, if required. 1142 * @param tdata Optional pointer to data to be sent. 1143 * @param tp Pointer to receive the transport instance, if one is found. 1144 * 1145 * @return PJ_SUCCESS on success, or the appropriate error code. 1146 */ 1147 PJ_DECL(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr, 1148 pjsip_transport_type_e type, 1149 const pj_sockaddr_t *remote, 1150 int addr_len, 1151 const pjsip_tpselector *sel, 1152 pjsip_tx_data *tdata, 1153 pjsip_transport **tp); 1101 1154 1102 1155 /** … … 1188 1241 pjsip_tp_send_callback cb); 1189 1242 1243 1244 /** 1245 * Enumeration of transport state types. 1246 */ 1247 typedef enum pjsip_transport_state_type { 1248 1249 /** Transport connected. */ 1250 PJSIP_TP_STATE_CONNECTED = (1 << 0), 1251 1252 /** Transport accepted. */ 1253 PJSIP_TP_STATE_ACCEPTED = (1 << 1), 1254 1255 /** Transport disconnected. */ 1256 PJSIP_TP_STATE_DISCONNECTED = (1 << 2), 1257 1258 /** Incoming connection rejected. */ 1259 PJSIP_TP_STATE_REJECTED = (1 << 3), 1260 1261 /** TLS verification error. */ 1262 PJSIP_TP_STATE_TLS_VERIF_ERROR = (1 << 8) 1263 1264 } pjsip_transport_state_type; 1265 1266 1267 /** 1268 * Structure of transport state info. 1269 */ 1270 typedef struct pjsip_transport_state_info { 1271 /** 1272 * The last error code related to the transport state. 1273 */ 1274 pj_status_t status; 1275 1276 /** 1277 * Optional extended info, the content is specific for each transport type. 1278 */ 1279 void *ext_info; 1280 } pjsip_transport_state_info; 1281 1282 1283 /** 1284 * Type of callback to receive transport state notifications, such as 1285 * transport connected, disconnected or TLS verification error. 1286 * 1287 * @param tp The transport instance. 1288 * @param state The transport state, this may contain single or 1289 * combination of transport state types defined in 1290 * #pjsip_transport_state_type. 1291 * @param info The transport state info. 1292 * 1293 * @return When TLS verification fails and peer verification in 1294 * #pjsip_tls_setting is not set, application may return 1295 * PJ_TRUE to ignore the verification result and continue 1296 * using the transport. On other cases, this return value 1297 * is currently not used and will be ignored. 1298 */ 1299 typedef pj_bool_t (*pjsip_tp_state_callback)( 1300 pjsip_transport *tp, 1301 pj_uint32_t state, 1302 const pjsip_transport_state_info *info); 1303 1304 1305 /** 1306 * Setting callback of transport state notification. The caller will be 1307 * notified whenever the state of transport is changed. The type of 1308 * events are defined in #pjsip_transport_state_type. 1309 * 1310 * @param mgr Transport manager. 1311 * @param cb Callback to be called to notify caller about transport 1312 * status changing. 1313 * 1314 * @return PJ_SUCCESS on success, or the appropriate error code. 1315 */ 1316 PJ_DECL(pj_status_t) pjsip_tpmgr_set_status_cb(pjsip_tpmgr *mgr, 1317 pjsip_tp_state_callback *cb); 1318 1319 1320 /** 1321 * Getting the callback of transport state notification. 1322 * 1323 * @param mgr Transport manager. 1324 * 1325 * @return The transport state callback or NULL if it is not set. 1326 */ 1327 PJ_DECL(pjsip_tp_state_callback*) pjsip_tpmgr_get_status_cb( 1328 const pjsip_tpmgr *mgr); 1329 1330 1190 1331 /** 1191 1332 * @} -
pjproject/trunk/pjsip/include/pjsip/sip_transport_tls.h
r2998 r3106 27 27 28 28 #include <pjsip/sip_transport.h> 29 #include <pj/ssl_sock.h> 29 30 #include <pj/string.h> 30 31 #include <pj/sock_qos.h> … … 122 123 123 124 /** 124 * When PJSIP is acting as a client (outgoing TLS connections), 125 * it will always receive a certificate from the peer. 126 * If \a verify_server is disabled (set to zero), PJSIP will not 127 * verifiy the certificate and allows TLS connections to servers 128 * which do not present a valid certificate. 129 * If \a tls_verify_server is non-zero, PJSIP verifies the server 130 * certificate and will close the TLS connection if the server 131 * certificate is not valid. 132 * 133 * This setting corresponds to OpenSSL SSL_VERIFY_PEER flag. 134 * Default value is zero. 125 * Specifies the action when verification of server TLS certificate 126 * resulting errors: 127 * - If \a verify_server is disabled (set to PJ_FALSE), TLS transport 128 * will just notify the application via #pjsip_tp_state_callback with 129 * state (PJSIP_TP_STATE_CONNECTED | PJSIP_TP_STATE_TLS_VERIF_ERROR) 130 * whenever there is any TLS verification error, the return value of 131 * the callback will be used to decide whether transport should be 132 * shutdown. 133 * - If \a verify_server is enabled (set to PJ_TRUE), TLS transport 134 * will be shutdown and application will be notified with state 135 * (PJSIP_TP_STATE_DISCONNECTED | PJSIP_TP_STATE_TLS_VERIF_ERROR) 136 * whenever there is any TLS verification error. 137 * 138 * When the verification resulting success, application will be notified 139 * via #pjsip_tp_state_callback with state PJSIP_TP_STATE_CONNECTED. 140 * 141 * Default value is PJ_FALSE. 135 142 */ 136 143 pj_bool_t verify_server; 137 144 138 145 /** 139 * When acting as server (incoming TLS connections), setting 140 * \a verify_client to non-zero will cause the transport to activate 141 * peer verification upon receiving incoming TLS connection. 142 * 143 * This setting corresponds to OpenSSL SSL_VERIFY_PEER flag. 144 * Default value is zero. 146 * Specifies the action when verification of server TLS certificate 147 * resulting errors: 148 * - If \a verify_client is disabled (set to PJ_FALSE), TLS transport 149 * will just notify the application via #pjsip_tp_state_callback with 150 * state (PJSIP_TP_STATE_ACCEPTED | PJSIP_TP_STATE_TLS_VERIF_ERROR) 151 * whenever there is any TLS verification error, the return value of 152 * the callback will be used to decide whether transport should be 153 * shutdown. 154 * - If \a verify_client is enabled (set to PJ_TRUE), TLS transport 155 * will be shutdown and application will be notified with state 156 * (PJSIP_TP_STATE_REJECTED | PJSIP_TP_STATE_TLS_VERIF_ERROR) 157 * whenever there is any TLS verification error. 158 * 159 * When the verification resulting success, application will be notified 160 * via #pjsip_tp_state_callback with state PJSIP_TP_STATE_ACCEPTED. 161 * 162 * Default value is PJ_FALSE. 145 163 */ 146 164 pj_bool_t verify_client; … … 151 169 * 152 170 * This setting corresponds to SSL_VERIFY_FAIL_IF_NO_PEER_CERT flag. 153 * Default value is zero.171 * Default value is PJ_FALSE. 154 172 */ 155 173 pj_bool_t require_client_cert; … … 189 207 190 208 } pjsip_tls_setting; 209 210 211 /** 212 * This structure defines transport state extended info specifically for 213 * TLS transport. 214 */ 215 typedef struct pjsip_tls_state_info 216 { 217 /** 218 * SSL socket info. 219 */ 220 pj_ssl_sock_info *ssl_sock_info; 221 222 } pjsip_tls_state_info; 191 223 192 224 -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
r3078 r3106 844 844 void (*on_mwi_info)(pjsua_acc_id acc_id, pjsua_mwi_info *mwi_info); 845 845 846 /** 847 * This callback is called when transport state is changed. See also 848 * #pjsip_tp_state_callback. 849 * 850 * @param tp The transport instance. 851 * @param state The transport state, this may contain single or 852 * combination of transport state types defined in 853 * #pjsip_transport_state_type. 854 * @param info The transport state info. 855 * 856 * @return When TLS verification fails and peer verification in 857 * #pjsip_tls_setting is not set, application may return 858 * PJ_TRUE to ignore the verification result and continue 859 * using the transport. On other cases, this return value 860 * is currently not used and will be ignored. 861 */ 862 pj_bool_t (*on_transport_state)(pjsip_transport *tp, pj_uint32_t state, 863 const pjsip_transport_state_info *info); 864 846 865 } pjsua_callback; 847 866 -
pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c
r2394 r3106 1076 1076 1077 1077 /* 1078 * Find/create transport. 1079 */ 1080 PJ_DEF(pj_status_t) pjsip_endpt_acquire_transport2(pjsip_endpoint *endpt, 1081 pjsip_transport_type_e type, 1082 const pj_sockaddr_t *remote, 1083 int addr_len, 1084 const pjsip_tpselector *sel, 1085 pjsip_tx_data *tdata, 1086 pjsip_transport **transport) 1087 { 1088 return pjsip_tpmgr_acquire_transport2(endpt->transport_mgr, type, remote, 1089 addr_len, sel, tdata, transport); 1090 } 1091 1092 1093 /* 1078 1094 * Report error. 1079 1095 */ -
pjproject/trunk/pjsip/src/pjsip/sip_transport.c
r3077 r3106 90 90 void (*on_rx_msg)(pjsip_endpoint*, pj_status_t, pjsip_rx_data*); 91 91 pj_status_t (*on_tx_msg)(pjsip_endpoint*, pjsip_tx_data*); 92 pjsip_tp_state_callback *tp_state_cb; 93 void *tp_state_user_data; 92 94 }; 93 95 … … 865 867 * Register to hash table (see Trac ticket #42). 866 868 */ 867 key_len = sizeof(tp->key.type) + tp->addr_len;869 key_len = sizeof(tp->key.type) + sizeof(tp->key.hname) + tp->addr_len; 868 870 pj_lock_acquire(mgr->lock); 869 871 … … 915 917 * Unregister from hash table (see Trac ticket #42). 916 918 */ 917 key_len = sizeof(tp->key.type) + tp->addr_len;919 key_len = sizeof(tp->key.type) + sizeof(tp->key.hname) + tp->addr_len; 918 920 hval = 0; 919 921 entry = pj_hash_get(mgr->table, &tp->key, key_len, &hval); … … 1503 1505 pjsip_transport **tp) 1504 1506 { 1507 return pjsip_tpmgr_acquire_transport2(mgr, type, remote, addr_len, sel, 1508 NULL, tp); 1509 } 1510 1511 /* 1512 * pjsip_tpmgr_acquire_transport2() 1513 * 1514 * Get transport suitable to communicate to remote. Create a new one 1515 * if necessary. 1516 */ 1517 PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr, 1518 pjsip_transport_type_e type, 1519 const pj_sockaddr_t *remote, 1520 int addr_len, 1521 const pjsip_tpselector *sel, 1522 pjsip_tx_data *tdata, 1523 pjsip_transport **tp) 1524 { 1505 1525 pjsip_tpfactory *factory; 1506 1526 pj_status_t status; … … 1572 1592 pjsip_transport *transport; 1573 1593 1594 /* 1595 * Find factory that can create such transport. 1596 */ 1597 factory = mgr->factory_list.next; 1598 while (factory != &mgr->factory_list) { 1599 if (factory->type == type) 1600 break; 1601 factory = factory->next; 1602 } 1603 if (factory == &mgr->factory_list) 1604 factory = NULL; 1605 1574 1606 pj_bzero(&key, sizeof(key)); 1575 key_len = sizeof(key.type) + addr_len;1607 key_len = sizeof(key.type) + sizeof(key.hname) + addr_len; 1576 1608 1577 1609 /* First try to get exact destination. */ 1578 1610 key.type = type; 1579 1611 pj_memcpy(&key.rem_addr, remote, addr_len); 1612 if (factory && factory->create_transport2 && 1613 tdata && tdata->dest_info.name.slen) 1614 { 1615 /* Only include hostname hash in the key when the factory support 1616 * create_transport2() and tdata is supplied. 1617 */ 1618 key.hname = pj_hash_calc_tolower(0, 1619 (char*)tdata->dest_info.name.ptr, 1620 &tdata->dest_info.name); 1621 } 1580 1622 1581 1623 transport = (pjsip_transport*) 1582 1624 pj_hash_get(mgr->table, &key, key_len, NULL); 1625 1583 1626 if (transport == NULL) { 1584 1627 unsigned flag = pjsip_transport_get_flag_from_type(type); 1585 1628 const pj_sockaddr *remote_addr = (const pj_sockaddr*)remote; 1629 1586 1630 1587 1631 /* Ignore address for loop transports. */ … … 1592 1636 1593 1637 pj_bzero(addr, addr_len); 1594 key_len = sizeof(key.type) + addr_len;1638 key_len = sizeof(key.type) + sizeof(key.hname) + addr_len; 1595 1639 transport = (pjsip_transport*) 1596 1640 pj_hash_get(mgr->table, &key, key_len, NULL); … … 1605 1649 addr->addr.sa_family = remote_addr->addr.sa_family; 1606 1650 1607 key_len = sizeof(key.type) + addr_len;1651 key_len = sizeof(key.type) + sizeof(key.hname) + addr_len; 1608 1652 transport = (pjsip_transport*) 1609 1653 pj_hash_get(mgr->table, &key, key_len, NULL); … … 1625 1669 /* 1626 1670 * Transport not found! 1627 * Find factory that can create such transport.1628 1671 */ 1629 factory = mgr->factory_list.next; 1630 while (factory != &mgr->factory_list) { 1631 if (factory->type == type) 1632 break; 1633 factory = factory->next; 1634 } 1635 1636 if (factory == &mgr->factory_list) { 1672 if (NULL == factory) { 1637 1673 /* No factory can create the transport! */ 1638 1674 pj_lock_release(mgr->lock); … … 1640 1676 return PJSIP_EUNSUPTRANSPORT; 1641 1677 } 1642 1643 1678 } 1644 1679 … … 1647 1682 1648 1683 /* Request factory to create transport. */ 1649 status = factory->create_transport(factory, mgr, mgr->endpt, 1650 (const pj_sockaddr*) remote, addr_len, 1651 tp); 1684 if (factory->create_transport2) { 1685 status = factory->create_transport2(factory, mgr, mgr->endpt, 1686 (const pj_sockaddr*) remote, 1687 addr_len, tdata, tp); 1688 } else { 1689 status = factory->create_transport(factory, mgr, mgr->endpt, 1690 (const pj_sockaddr*) remote, 1691 addr_len, tp); 1692 } 1652 1693 if (status == PJ_SUCCESS) { 1653 1694 PJ_ASSERT_ON_FAIL(tp!=NULL, … … 1712 1753 } 1713 1754 1755 PJ_DEF(pj_status_t) pjsip_tpmgr_set_status_cb(pjsip_tpmgr *mgr, 1756 pjsip_tp_state_callback *cb) 1757 { 1758 PJ_ASSERT_RETURN(mgr, PJ_EINVAL); 1759 1760 mgr->tp_state_cb = cb; 1761 1762 return PJ_SUCCESS; 1763 } 1764 1765 PJ_DEF(pjsip_tp_state_callback*) pjsip_tpmgr_get_status_cb( 1766 const pjsip_tpmgr *mgr) 1767 { 1768 PJ_ASSERT_RETURN(mgr, NULL); 1769 1770 return mgr->tp_state_cb; 1771 } -
pjproject/trunk/pjsip/src/pjsip/sip_transport_tcp.c
r3035 r3106 166 166 host_port->port = pj_sockaddr_get_port(addr); 167 167 } 168 169 170 static void tcp_init_shutdown(struct tcp_transport *tcp, pj_status_t status) 171 { 172 pjsip_tp_state_callback *state_cb; 173 174 if (tcp->close_reason == PJ_SUCCESS) 175 tcp->close_reason = status; 176 177 if (tcp->base.is_shutdown) 178 return; 179 180 /* Notify application of transport disconnected state */ 181 state_cb = pjsip_tpmgr_get_status_cb(tcp->base.tpmgr); 182 if (state_cb) { 183 pjsip_transport_state_info state_info; 184 185 pj_bzero(&state_info, sizeof(state_info)); 186 state_info.status = tcp->close_reason; 187 (*state_cb)(&tcp->base, PJSIP_TP_STATE_DISCONNECTED, &state_info); 188 } 189 190 /* We can not destroy the transport since high level objects may 191 * still keep reference to this transport. So we can only 192 * instruct transport manager to gracefully start the shutdown 193 * procedure for this transport. 194 */ 195 pjsip_transport_shutdown(&tcp->base); 196 } 197 168 198 169 199 /* … … 922 952 struct tcp_transport *tcp; 923 953 char addr[PJ_INET6_ADDRSTRLEN+10]; 954 pjsip_tp_state_callback *state_cb; 924 955 pj_status_t status; 925 956 … … 967 998 pj_gettimeofday(&tcp->last_activity); 968 999 } 1000 1001 /* Notify application of transport state accepted */ 1002 state_cb = pjsip_tpmgr_get_status_cb(tcp->base.tpmgr); 1003 if (state_cb) { 1004 pjsip_transport_state_info state_info; 1005 1006 pj_bzero(&state_info, sizeof(state_info)); 1007 (*state_cb)(&tcp->base, PJSIP_TP_STATE_ACCEPTED, &state_info); 1008 } 969 1009 } 970 1010 } … … 1014 1054 status = (bytes_sent == 0) ? PJ_RETURN_OS_ERROR(OSERR_ENOTCONN) : 1015 1055 -bytes_sent; 1016 if (tcp->close_reason==PJ_SUCCESS) tcp->close_reason = status; 1017 pjsip_transport_shutdown(&tcp->base);1056 1057 tcp_init_shutdown(tcp, status); 1018 1058 1019 1059 return PJ_FALSE; … … 1110 1150 if (status == PJ_SUCCESS) 1111 1151 status = PJ_RETURN_OS_ERROR(OSERR_ENOTCONN); 1112 if (tcp->close_reason==PJ_SUCCESS) tcp->close_reason = status; 1113 pjsip_transport_shutdown(&tcp->base);1152 1153 tcp_init_shutdown(tcp, status); 1114 1154 } 1115 1155 } … … 1200 1240 PJ_LOG(4,(tcp->base.obj_name, "TCP connection closed")); 1201 1241 1202 /* We can not destroy the transport since high level objects may 1203 * still keep reference to this transport. So we can only 1204 * instruct transport manager to gracefully start the shutdown 1205 * procedure for this transport. 1206 */ 1207 if (tcp->close_reason==PJ_SUCCESS) 1208 tcp->close_reason = status; 1209 pjsip_transport_shutdown(&tcp->base); 1242 tcp_init_shutdown(tcp, status); 1210 1243 1211 1244 return PJ_FALSE; … … 1229 1262 pj_sockaddr_in addr; 1230 1263 int addrlen; 1264 1265 pjsip_tp_state_callback *state_cb; 1231 1266 1232 1267 tcp = (struct tcp_transport*) pj_activesock_get_user_data(asock); … … 1253 1288 } 1254 1289 1255 /* We can not destroy the transport since high level objects may 1256 * still keep reference to this transport. So we can only 1257 * instruct transport manager to gracefully start the shutdown 1258 * procedure for this transport. 1259 */ 1260 if (tcp->close_reason==PJ_SUCCESS) tcp->close_reason = status; 1261 pjsip_transport_shutdown(&tcp->base); 1262 return PJ_FALSE; 1290 tcp_init_shutdown(tcp, status); 1263 1291 } 1264 1292 … … 1294 1322 status = tcp_start_read(tcp); 1295 1323 if (status != PJ_SUCCESS) { 1296 /* We can not destroy the transport since high level objects may 1297 * still keep reference to this transport. So we can only 1298 * instruct transport manager to gracefully start the shutdown 1299 * procedure for this transport. 1300 */ 1301 if (tcp->close_reason==PJ_SUCCESS) tcp->close_reason = status; 1302 pjsip_transport_shutdown(&tcp->base); 1324 tcp_init_shutdown(tcp, status); 1303 1325 return PJ_FALSE; 1326 } 1327 1328 /* Notify application of transport state connected */ 1329 state_cb = pjsip_tpmgr_get_status_cb(tcp->base.tpmgr); 1330 if (state_cb) { 1331 pjsip_transport_state_info state_info; 1332 1333 pj_bzero(&state_info, sizeof(state_info)); 1334 (*state_cb)(&tcp->base, PJSIP_TP_STATE_CONNECTED, &state_info); 1304 1335 } 1305 1336 … … 1359 1390 tcp_perror(tcp->base.obj_name, 1360 1391 "Error sending keep-alive packet", status); 1361 pjsip_transport_shutdown(&tcp->base);1392 tcp_init_shutdown(tcp, status); 1362 1393 return; 1363 1394 } -
pjproject/trunk/pjsip/src/pjsip/sip_transport_tls.c
r3039 r3106 25 25 #include <pj/ssl_sock.h> 26 26 #include <pj/assert.h> 27 #include <pj/hash.h> 27 28 #include <pj/lock.h> 28 29 #include <pj/log.h> … … 81 82 pjsip_transport base; 82 83 pj_bool_t is_server; 84 pj_str_t remote_name; 83 85 84 86 pj_bool_t is_registered; … … 87 89 pj_ssl_sock_t *ssock; 88 90 pj_bool_t has_pending_connect; 91 pj_bool_t verify_server; 89 92 90 93 /* Keep-alive timer. */ … … 136 139 const pj_sockaddr *rem_addr, 137 140 int addr_len, 141 pjsip_tx_data *tdata, 138 142 pjsip_transport **transport); 139 143 … … 145 149 const pj_sockaddr_in *local, 146 150 const pj_sockaddr_in *remote, 151 const pj_str_t *remote_name, 147 152 struct tls_transport **p_tls); 148 153 … … 169 174 } 170 175 176 177 static void tls_init_shutdown(struct tls_transport *tls, pj_status_t status) 178 { 179 pjsip_tp_state_callback *state_cb; 180 181 if (tls->close_reason == PJ_SUCCESS) 182 tls->close_reason = status; 183 184 if (tls->base.is_shutdown) 185 return; 186 187 /* Notify application of transport disconnected state */ 188 state_cb = pjsip_tpmgr_get_status_cb(tls->base.tpmgr); 189 if (state_cb) { 190 pjsip_transport_state_info state_info; 191 192 pj_bzero(&state_info, sizeof(state_info)); 193 state_info.status = tls->close_reason; 194 (*state_cb)(&tls->base, PJSIP_TP_STATE_DISCONNECTED, &state_info); 195 } 196 197 /* We can not destroy the transport since high level objects may 198 * still keep reference to this transport. So we can only 199 * instruct transport manager to gracefully start the shutdown 200 * procedure for this transport. 201 */ 202 pjsip_transport_shutdown(&tls->base); 203 } 171 204 172 205 … … 244 277 ssock_param.ioqueue = pjsip_endpt_get_ioqueue(endpt); 245 278 ssock_param.require_client_cert = listener->tls_setting.require_client_cert; 246 ssock_param.server_name = listener->tls_setting.server_name;247 279 ssock_param.timeout = listener->tls_setting.timeout; 248 280 ssock_param.user_data = listener; 249 ssock_param.verify_peer = listener->tls_setting.verify_client; 281 ssock_param.verify_peer = PJ_FALSE; /* avoid SSL socket closing the socket 282 * due to verification error */ 250 283 if (ssock_param.send_buffer_size < PJSIP_MAX_PKT_LEN) 251 284 ssock_param.send_buffer_size = PJSIP_MAX_PKT_LEN; … … 372 405 listener->endpt = endpt; 373 406 listener->tpmgr = pjsip_endpt_get_tpmgr(endpt); 374 listener->factory.create_transport = lis_create_transport;407 listener->factory.create_transport2 = lis_create_transport; 375 408 listener->factory.destroy = lis_destroy; 376 409 listener->is_registered = PJ_TRUE; … … 481 514 const pj_sockaddr_in *local, 482 515 const pj_sockaddr_in *remote, 516 const pj_str_t *remote_name, 483 517 struct tls_transport **p_tls) 484 518 { … … 502 536 tls = PJ_POOL_ZALLOC_T(pool, struct tls_transport); 503 537 tls->is_server = is_server; 538 tls->verify_server = listener->tls_setting.verify_server; 504 539 pj_list_init(&tls->delayed_list); 505 540 tls->base.pool = pool; … … 518 553 } 519 554 555 if (remote_name) 556 pj_strdup(pool, &tls->remote_name, remote_name); 557 520 558 tls->base.key.type = PJSIP_TRANSPORT_TLS; 521 559 pj_memcpy(&tls->base.key.rem_addr, remote, sizeof(pj_sockaddr_in)); 560 tls->base.key.hname = pj_hash_calc_tolower(0, (char*)tls->remote_name.ptr, 561 &tls->remote_name); 522 562 tls->base.type_name = "tls"; 523 563 tls->base.flag = pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_TLS); … … 770 810 const pj_sockaddr *rem_addr, 771 811 int addr_len, 812 pjsip_tx_data *tdata, 772 813 pjsip_transport **p_transport) 773 814 { … … 778 819 pj_ssl_sock_param ssock_param; 779 820 pj_sockaddr_in local_addr; 821 pj_str_t remote_name; 780 822 pj_status_t status; 781 823 … … 794 836 POOL_TP_INIT, POOL_TP_INC); 795 837 PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM); 838 839 /* Get remote host name from tdata */ 840 if (tdata) 841 remote_name = tdata->dest_info.name; 842 else 843 pj_bzero(&remote_name, sizeof(remote_name)); 796 844 797 845 /* Build SSL socket param */ … … 802 850 ssock_param.async_cnt = 1; 803 851 ssock_param.ioqueue = pjsip_endpt_get_ioqueue(listener->endpt); 804 PJ_TODO(set_proper_servername_based_on_target);805 852 PJ_TODO(synchronize_tls_cipher_type_with_ssl_sock_cipher_type); 806 ssock_param.server_name = listener->tls_setting.server_name;853 ssock_param.server_name = remote_name; 807 854 ssock_param.timeout = listener->tls_setting.timeout; 808 855 ssock_param.user_data = NULL; /* pending, must be set later */ 809 ssock_param.verify_peer = listener->tls_setting.verify_server; 856 ssock_param.verify_peer = PJ_FALSE; /* avoid SSL socket closing the socket 857 * due to verification error */ 810 858 if (ssock_param.send_buffer_size < PJSIP_MAX_PKT_LEN) 811 859 ssock_param.send_buffer_size = PJSIP_MAX_PKT_LEN; … … 851 899 /* Create the transport descriptor */ 852 900 status = tls_create(listener, pool, ssock, PJ_FALSE, &local_addr, 853 (pj_sockaddr_in*)rem_addr, & tls);901 (pj_sockaddr_in*)rem_addr, &remote_name, &tls); 854 902 if (status != PJ_SUCCESS) 855 903 return status; … … 929 977 struct tls_listener *listener; 930 978 struct tls_transport *tls; 979 pj_ssl_sock_info ssl_info; 931 980 char addr[PJ_INET6_ADDRSTRLEN+10]; 932 981 pj_status_t status; 982 983 pjsip_tp_state_callback *state_cb; 984 pj_bool_t tls_verif_ignored; 933 985 934 986 PJ_UNUSED_ARG(src_addr_len); … … 947 999 new_ssock)); 948 1000 1001 /* Retrieve SSL socket info, close the socket if this is failed 1002 * as the SSL socket info availability is rather critical here. 1003 */ 1004 status = pj_ssl_sock_get_info(new_ssock, &ssl_info); 1005 if (status != PJ_SUCCESS) { 1006 pj_ssl_sock_close(new_ssock); 1007 return PJ_TRUE; 1008 } 1009 949 1010 /* 950 1011 * Incoming connection! … … 953 1014 status = tls_create( listener, NULL, new_ssock, PJ_TRUE, 954 1015 (const pj_sockaddr_in*)&listener->factory.local_addr, 955 (const pj_sockaddr_in*)src_addr, &tls);1016 (const pj_sockaddr_in*)src_addr, NULL, &tls); 956 1017 957 if (status == PJ_SUCCESS) { 958 /* Set the "pending" SSL socket user data */ 959 pj_ssl_sock_set_user_data(new_ssock, tls); 960 961 status = tls_start_read(tls); 962 if (status != PJ_SUCCESS) { 963 PJ_LOG(3,(tls->base.obj_name, "New transport cancelled")); 964 tls_destroy(&tls->base, status); 1018 if (status != PJ_SUCCESS) 1019 return PJ_TRUE; 1020 1021 /* Set the "pending" SSL socket user data */ 1022 pj_ssl_sock_set_user_data(new_ssock, tls); 1023 1024 tls_verif_ignored = !listener->tls_setting.verify_client; 1025 1026 /* Notify transport state to application */ 1027 state_cb = pjsip_tpmgr_get_status_cb(tls->base.tpmgr); 1028 if (state_cb) { 1029 pjsip_transport_state_info state_info; 1030 pjsip_tls_state_info tls_info; 1031 pj_uint32_t tp_state = 0; 1032 1033 /* Init transport state notification callback */ 1034 pj_bzero(&tls_info, sizeof(tls_info)); 1035 pj_bzero(&state_info, sizeof(state_info)); 1036 1037 /* Set transport state based on verification status */ 1038 if (ssl_info.verify_status) { 1039 state_info.status = PJSIP_TLS_EACCEPT; 1040 tp_state |= PJSIP_TP_STATE_TLS_VERIF_ERROR; 1041 if (listener->tls_setting.verify_client) 1042 tp_state |= PJSIP_TP_STATE_REJECTED; 1043 else 1044 tp_state |= PJSIP_TP_STATE_ACCEPTED; 965 1045 } else { 966 /* Start keep-alive timer */ 967 if (PJSIP_TCP_KEEP_ALIVE_INTERVAL) { 968 pj_time_val delay = {PJSIP_TCP_KEEP_ALIVE_INTERVAL, 0}; 969 pjsip_endpt_schedule_timer(listener->endpt, 970 &tls->ka_timer, 971 &delay); 972 tls->ka_timer.id = PJ_TRUE; 973 pj_gettimeofday(&tls->last_activity); 974 } 1046 tp_state |= PJSIP_TP_STATE_ACCEPTED; 1047 } 1048 1049 tls_info.ssl_sock_info = &ssl_info; 1050 state_info.ext_info = &tls_info; 1051 1052 tls_verif_ignored = (*state_cb)(&tls->base, tp_state, &state_info); 1053 } 1054 1055 /* Transport should be destroyed when there is TLS verification error 1056 * and application doesn't want to ignore it. 1057 */ 1058 if (ssl_info.verify_status && 1059 (listener->tls_setting.verify_client || !tls_verif_ignored)) 1060 { 1061 tls_destroy(&tls->base, PJSIP_TLS_EACCEPT); 1062 return PJ_TRUE; 1063 } 1064 1065 status = tls_start_read(tls); 1066 if (status != PJ_SUCCESS) { 1067 PJ_LOG(3,(tls->base.obj_name, "New transport cancelled")); 1068 tls_init_shutdown(tls, status); 1069 tls_destroy(&tls->base, status); 1070 } else { 1071 /* Start keep-alive timer */ 1072 if (PJSIP_TCP_KEEP_ALIVE_INTERVAL) { 1073 pj_time_val delay = {PJSIP_TCP_KEEP_ALIVE_INTERVAL, 0}; 1074 pjsip_endpt_schedule_timer(listener->endpt, 1075 &tls->ka_timer, 1076 &delay); 1077 tls->ka_timer.id = PJ_TRUE; 1078 pj_gettimeofday(&tls->last_activity); 975 1079 } 976 1080 } … … 1020 1124 status = (bytes_sent == 0) ? PJ_RETURN_OS_ERROR(OSERR_ENOTCONN) : 1021 1125 -bytes_sent; 1022 if (tls->close_reason==PJ_SUCCESS) tls->close_reason = status; 1023 pjsip_transport_shutdown(&tls->base);1126 1127 tls_init_shutdown(tls, status); 1024 1128 1025 1129 return PJ_FALSE; … … 1116 1220 if (status == PJ_SUCCESS) 1117 1221 status = PJ_RETURN_OS_ERROR(OSERR_ENOTCONN); 1118 if (tls->close_reason==PJ_SUCCESS) tls->close_reason = status; 1119 pjsip_transport_shutdown(&tls->base);1222 1223 tls_init_shutdown(tls, status); 1120 1224 } 1121 1225 } … … 1205 1309 /* Transport is closed */ 1206 1310 PJ_LOG(4,(tls->base.obj_name, "TLS connection closed")); 1207 1208 /* We can not destroy the transport since high level objects may 1209 * still keep reference to this transport. So we can only 1210 * instruct transport manager to gracefully start the shutdown 1211 * procedure for this transport. 1212 */ 1213 if (tls->close_reason==PJ_SUCCESS) 1214 tls->close_reason = status; 1215 pjsip_transport_shutdown(&tls->base); 1311 1312 tls_init_shutdown(tls, status); 1216 1313 1217 1314 return PJ_FALSE; … … 1233 1330 { 1234 1331 struct tls_transport *tls; 1235 pj_ssl_sock_info info; 1236 1332 pj_ssl_sock_info ssl_info; 1333 pj_sockaddr_in addr, *tp_addr; 1334 1335 pjsip_tp_state_callback *state_cb; 1336 pj_bool_t tls_verif_ignored; 1337 1237 1338 tls = (struct tls_transport*) pj_ssl_sock_get_user_data(ssock); 1238 1339 … … 1255 1356 } 1256 1357 1257 /* We can not destroy the transport since high level objects may1258 * still keep reference to this transport. So we can only 1259 * instruct transport manager to gracefully start the shutdown 1260 * procedure for this transport. 1261 */ 1262 if (tls->close_reason==PJ_SUCCESS) tls->close_reason = status; 1263 pjsip_transport_shutdown(&tls->base);1264 return PJ_FALSE; 1265 } 1358 goto on_error; 1359 } 1360 1361 /* Retrieve SSL socket info, shutdown the transport if this is failed 1362 * as the SSL socket info availability is rather critical here. 1363 */ 1364 status = pj_ssl_sock_get_info(tls->ssock, &ssl_info); 1365 if (status != PJ_SUCCESS) 1366 goto on_error; 1266 1367 1267 1368 /* Update (again) local address, just in case local address currently … … 1269 1370 * on some systems, like old Win32 probably?). 1270 1371 */ 1271 1272 /* Retrieve the bound address */ 1273 status = pj_ssl_sock_get_info(tls->ssock, &info); 1274 if (status == PJ_SUCCESS) { 1275 pj_sockaddr_in addr; 1276 pj_sockaddr_in *tp_addr = (pj_sockaddr_in*)&tls->base.local_addr; 1277 1278 pj_sockaddr_cp((pj_sockaddr_t*)&addr, (pj_sockaddr_t*)&info.local_addr); 1279 if (tp_addr->sin_addr.s_addr != addr.sin_addr.s_addr) { 1280 tp_addr->sin_addr.s_addr = addr.sin_addr.s_addr; 1281 tp_addr->sin_port = addr.sin_port; 1282 sockaddr_to_host_port(tls->base.pool, &tls->base.local_name, 1283 tp_addr); 1372 tp_addr = (pj_sockaddr_in*)&tls->base.local_addr; 1373 pj_sockaddr_cp((pj_sockaddr_t*)&addr, 1374 (pj_sockaddr_t*)&ssl_info.local_addr); 1375 if (tp_addr->sin_addr.s_addr != addr.sin_addr.s_addr) { 1376 tp_addr->sin_addr.s_addr = addr.sin_addr.s_addr; 1377 tp_addr->sin_port = addr.sin_port; 1378 sockaddr_to_host_port(tls->base.pool, &tls->base.local_name, 1379 tp_addr); 1380 } 1381 1382 /* Server identity verification based on server certificate. */ 1383 if (ssl_info.remote_cert_info->version) { 1384 pj_str_t *remote_name; 1385 pj_ssl_cert_info *serv_cert = ssl_info.remote_cert_info; 1386 pj_bool_t matched = PJ_FALSE; 1387 unsigned i; 1388 1389 /* Remote name may be hostname or IP address */ 1390 if (tls->remote_name.slen) 1391 remote_name = &tls->remote_name; 1392 else 1393 remote_name = &tls->base.remote_name.host; 1394 1395 /* Start matching remote name with SubjectAltName fields of 1396 * server certificate. 1397 */ 1398 for (i = 0; i < serv_cert->subj_alt_name.cnt && !matched; ++i) { 1399 pj_str_t *cert_name = &serv_cert->subj_alt_name.entry[i].name; 1400 1401 switch (serv_cert->subj_alt_name.entry[i].type) { 1402 case PJ_SSL_CERT_NAME_DNS: 1403 case PJ_SSL_CERT_NAME_IP: 1404 matched = !pj_stricmp(remote_name, cert_name); 1405 break; 1406 case PJ_SSL_CERT_NAME_URI: 1407 if (pj_strnicmp2(cert_name, "sip:", 4) == 0 || 1408 pj_strnicmp2(cert_name, "sips:", 5) == 0) 1409 { 1410 pj_str_t host_part; 1411 char *p; 1412 1413 p = pj_strchr(cert_name, ':') + 1; 1414 pj_strset(&host_part, p, cert_name->slen - 1415 (p - cert_name->ptr)); 1416 matched = !pj_stricmp(remote_name, &host_part); 1417 } 1418 break; 1419 default: 1420 break; 1421 } 1284 1422 } 1285 } 1423 1424 /* When still not matched or no SubjectAltName fields in server 1425 * certificate, try with Common Name of Subject field. 1426 */ 1427 if (!matched) { 1428 matched = !pj_stricmp(remote_name, &serv_cert->subject.cn); 1429 } 1430 1431 if (!matched) 1432 ssl_info.verify_status |= PJ_SSL_CERT_EIDENTITY_NOT_MATCH; 1433 } 1434 1435 tls_verif_ignored = !tls->verify_server; 1436 1437 /* Notify transport state to application */ 1438 state_cb = pjsip_tpmgr_get_status_cb(tls->base.tpmgr); 1439 if (state_cb) { 1440 pjsip_transport_state_info state_info; 1441 pjsip_tls_state_info tls_info; 1442 pj_uint32_t tp_state = 0; 1443 1444 /* Init transport state notification callback */ 1445 pj_bzero(&state_info, sizeof(state_info)); 1446 pj_bzero(&tls_info, sizeof(tls_info)); 1447 1448 /* Set transport state info */ 1449 state_info.ext_info = &tls_info; 1450 tls_info.ssl_sock_info = &ssl_info; 1451 1452 /* Set transport state based on verification status */ 1453 if (ssl_info.verify_status) { 1454 state_info.status = PJSIP_TLS_ECONNECT; 1455 tp_state |= PJSIP_TP_STATE_TLS_VERIF_ERROR; 1456 if (tls->verify_server) 1457 tp_state |= PJSIP_TP_STATE_DISCONNECTED; 1458 else 1459 tp_state |= PJSIP_TP_STATE_CONNECTED; 1460 } else { 1461 tp_state |= PJSIP_TP_STATE_CONNECTED; 1462 } 1463 1464 tls_verif_ignored = (*state_cb)(&tls->base, tp_state, &state_info); 1465 } 1466 1467 /* Transport should be shutdown when there is TLS verification error 1468 * and application doesn't want to ignore it. 1469 */ 1470 if (ssl_info.verify_status && 1471 (tls->verify_server || !tls_verif_ignored)) 1472 { 1473 if (tls->close_reason == PJ_SUCCESS) 1474 tls->close_reason = PJSIP_TLS_ECONNECT; 1475 pjsip_transport_shutdown(&tls->base); 1476 return PJ_FALSE; 1477 } 1478 1479 /* Mark that pending connect() operation has completed. */ 1480 tls->has_pending_connect = PJ_FALSE; 1286 1481 1287 1482 PJ_LOG(4,(tls->base.obj_name, … … 1294 1489 tls->base.remote_name.port)); 1295 1490 1296 /* Mark that pending connect() operation has completed. */1297 tls->has_pending_connect = PJ_FALSE;1298 1299 1491 /* Start pending read */ 1300 1492 status = tls_start_read(tls); 1301 if (status != PJ_SUCCESS) { 1302 /* We can not destroy the transport since high level objects may 1303 * still keep reference to this transport. So we can only 1304 * instruct transport manager to gracefully start the shutdown 1305 * procedure for this transport. 1306 */ 1307 if (tls->close_reason==PJ_SUCCESS) tls->close_reason = status; 1308 pjsip_transport_shutdown(&tls->base); 1309 return PJ_FALSE; 1310 } 1493 if (status != PJ_SUCCESS) 1494 goto on_error; 1311 1495 1312 1496 /* Flush all pending send operations */ … … 1323 1507 1324 1508 return PJ_TRUE; 1509 1510 on_error: 1511 tls_init_shutdown(tls, status); 1512 1513 return PJ_FALSE; 1325 1514 } 1326 1515 … … 1366 1555 tls_perror(tls->base.obj_name, 1367 1556 "Error sending keep-alive packet", status); 1368 pjsip_transport_shutdown(&tls->base); 1557 1558 tls_init_shutdown(tls, status); 1369 1559 return; 1370 1560 } -
pjproject/trunk/pjsip/src/pjsip/sip_util.c
r3069 r3106 779 779 pjsip_hdr_clone(cancel_tdata->pool, req_tdata->saved_strict_route); 780 780 } 781 782 /* Copy the destination host name from the original request */ 783 pj_strdup(cancel_tdata->pool, &cancel_tdata->dest_info.name, 784 &req_tdata->dest_info.name); 781 785 782 786 /* Finally copy the destination info from the original request */ … … 1135 1139 1136 1140 /* Acquire transport. */ 1137 status = pjsip_endpt_acquire_transport (stateless_data->endpt,1141 status = pjsip_endpt_acquire_transport2(stateless_data->endpt, 1138 1142 cur_addr_type, 1139 1143 cur_addr, 1140 1144 cur_addr_len, 1141 1145 &tdata->tp_sel, 1146 tdata, 1142 1147 &stateless_data->cur_transport); 1143 1148 if (status != PJ_SUCCESS) { … … 1320 1325 */ 1321 1326 if (tdata->dest_info.addr.count == 0) { 1327 /* Copy the destination host name to TX data */ 1328 pj_strdup(tdata->pool, &tdata->dest_info.name, &dest_info.addr.host); 1329 1322 1330 pjsip_endpt_resolve( endpt, tdata->pool, &dest_info, stateless_data, 1323 1331 &stateless_send_resolver_callback); … … 1466 1474 pjsip_tpselector_add_ref(sraw_data->sel); 1467 1475 } 1476 1477 /* Copy the destination host name to TX data */ 1478 pj_strdup(tdata->pool, &tdata->dest_info.name, &dest_info.addr.host); 1468 1479 1469 1480 /* Resolve destination host. … … 1623 1634 1624 1635 /* Acquire transport. */ 1625 status = pjsip_endpt_acquire_transport (send_state->endpt,1636 status = pjsip_endpt_acquire_transport2(send_state->endpt, 1626 1637 addr->entry[0].type, 1627 1638 &addr->entry[0].addr, 1628 1639 addr->entry[0].addr_len, 1629 1640 &send_state->tdata->tp_sel, 1641 send_state->tdata, 1630 1642 &send_state->cur_transport); 1631 1643 if (status != PJ_SUCCESS) { … … 1703 1715 } 1704 1716 } else { 1717 /* Copy the destination host name to TX data */ 1718 pj_strdup(tdata->pool, &tdata->dest_info.name, 1719 &res_addr->dst_host.addr.host); 1720 1705 1721 pjsip_endpt_resolve(endpt, tdata->pool, &res_addr->dst_host, 1706 1722 send_state, &send_response_resolver_cb); -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
r3021 r3106 1811 1811 * Create TLS transport. 1812 1812 */ 1813 /*1814 * Create TCP transport.1815 */1816 1813 pjsua_transport_config config; 1817 1814 pjsip_host_port a_name; … … 1868 1865 } 1869 1866 1867 /* Set transport state callback */ 1868 if (pjsua_var.ua_cfg.cb.on_transport_state) { 1869 pjsip_tpmgr_set_status_cb(pjsip_endpt_get_tpmgr(pjsua_var.endpt), 1870 &pjsua_var.ua_cfg.cb.on_transport_state); 1871 } 1870 1872 1871 1873 /* Return the ID */
Note: See TracChangeset
for help on using the changeset viewer.